diff --git a/.env b/.env new file mode 100644 index 0000000..a3a2e5a --- /dev/null +++ b/.env @@ -0,0 +1,5 @@ +ENV_HOST=localhost +PORT=3000 +SQL_HASH=D3f@ult5QLh@SH +SQL_USER=swg +SQL_PASS=password diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..336cb81 --- /dev/null +++ b/app.js @@ -0,0 +1,203 @@ +require('dotenv').config(); +const express = require("express"); +const bodyParser = require("body-parser"); +const timediff = require('timediff'); +const crypto = require('crypto'); +const path = require('path'); +const http = require('http'); + +const CONFIG = require('./config.json'); +const database = require("./database.js"); + +const Discord = require('discord.js'); + +const port = process.env.PORT; +const host = process.env.ENV_HOST; +// --------------------------------------------------------------- + +const client = new Discord.Client(); + +var app = express(); +const server = http.createServer(app); +app.use(bodyParser.json()); +app.use(express.json()); +app.use(bodyParser.urlencoded({ extended: true })); +app.use('/', express.static(__dirname + '/public')); + + +// --------------------------------------------------------------- + +function getHash(string, salt) { + var hash = crypto.createHash('sha1').update(string + salt).digest(); + var salt = Buffer.from(salt, "utf8") + return Buffer.concat([hash, salt]).toString('base64'); +} + +function dateFromUTSC(utscTime) { + var d = new Date(0); + d.setUTCSeconds(utscTime); + return d; +} + +function readableTimeDiff(timeDiff) { + var result = ""; + if (timeDiff.days > 0) result += timeDiff.days + " days, "; + if (timeDiff.hours > 0) result += timeDiff.hours + " hours, "; + if (timeDiff.minutes > 0) result += timeDiff.minutes + " minutes, "; + return result + timeDiff.seconds + " seconds"; +} + +// --------------------------------------------------------------- +//Test +//TBD + +app.post("/api/auth", function (req, res) { + var login = req.body; + + console.log("New Login: \t" + + "User: " + login.user_name + ", " + + "IP: " + login.ip); + + var loginHandler = function (err, user) { + if (user !== undefined && user !== null) { + if (user.password_hash === getHash(login.user_password, user.password_salt)) { + res.send({ message: 'success' }); + } else { + res.send({ message: 'Invalid password' }); + } + } else { + if (CONFIG.autoRegistration) { + database.createUser(login.user_name, getHash(login.user_password, process.env.SQL_HASH), "TODO:email", loginHandler); + } else { + res.send({ message: 'Unknown username' }); + } + } + } + + database.getUser(login.user_name, loginHandler); +}); + +app.post("/api/createUser", function (req, res) { + //TODO: implement + res.json('success'); +}); + +var clusters = {}; + +app.post("/api/sendMetrics", function (req, res) { + var metrics = req.body; + clusterName = metrics.clusterName; + + var cluster = clusters[clusterName]; + if (cluster === undefined) { + cluster = {} + clusters[clusterName] = cluster; + clusters[clusterName].clusterStartTime = Date.now(); + cluster.clusterUptime = { "days": 0, "hours": 0, "minutes": 0, "seconds": 0 }; + } + + cluster.clusterStatus = "N/A"; + cluster.clusterLastLoad = { "days": 0, "hours": 0, "minutes": 0, "seconds": 0 }; + cluster.clusterPopulation = metrics.totalPlayerCount; + cluster.clusterLastUpdate = Date.now(); + + if (clusters[clusterName].clusterStartTime == null) { + cluster.clusterStartTime = Date.now(); + } + + if (metrics.timeClusterWentIntoLoadingState > metrics.lastLoadingStateTime) { + cluster.clusterStatus = "Loading"; + } + else if (metrics.lastLoadingStateTime > 0) { + cluster.clusterStatus = "Online"; + var lastLoadDate = dateFromUTSC(metrics.lastLoadingStateTime); + cluster.clusterLastLoad = timediff(lastLoadDate, Date.now(), 'DHmS'); + } + else { + clusters[clusterName].clusterStatus = "Offline"; + cluster.clusterStartTime = null; + console.log("offline"); + } + + console.log("New Metrics: \t" + + "Cluster: " + clusterName + ", " + + "Status: " + cluster.clusterStatus + ", " + + "Players: " + cluster.clusterPopulation + ", " + + "Last Load: " + readableTimeDiff(cluster.clusterLastLoad) + " ago, " + + "Uptime: " + readableTimeDiff(cluster.clusterUptime)); + + res.json('success'); +}); + +// --------------------------------------------------------------- + +if (CONFIG.discordBot) { + + // Status checker + setInterval(function () { + for (var clusterName in clusters) { + let cluster = clusters[clusterName]; + // if we haven't received an update in twice as long as the interval, the server isn't responding + if (Date.now() - cluster.clusterLastUpdate > (CONFIG.discordStatusInterval * 2 * 1000)) { + cluster.clusterStatus = "Offline"; + cluster.clusterLastLoad = { "days": 0, "hours": 0, "minutes": 0, "seconds": 0 }; + cluster.clusterUptime = { "days": 0, "hours": 0, "minutes": 0, "seconds": 0 }; + cluster.clusterPopulation = 0; + cluster.clusterStartTime = null; + } else { + cluster.clusterUptime = timediff(cluster.clusterStartTime, Date.now(), 'DHmS'); + } + } + }, 5 * 1000) + + client.on('ready', () => { + var channel = client.channels.find("name", CONFIG.discordBotChannelName); + setInterval(function () { + for (var clusterName in clusters) { + let cluster = clusters[clusterName]; + channel.sendMessage( + "**Cluster** `" + clusterName + "` " + + "**Status** `" + cluster.clusterStatus + "` " + + "**Players** `" + cluster.clusterPopulation + "` " + + "**Last Load** `" + readableTimeDiff(cluster.clusterLastLoad) + " ago` " + + "**Uptime** `" + readableTimeDiff(cluster.clusterUptime) + "` "); + } + }, CONFIG.discordStatusInterval * 1000) + }); + + + client.login(CONFIG.discordBotToken); +} + +// --------------------------------------------------------------- + +if (CONFIG.restartServer) { + var cp = require("child_process"); + + setInterval(function () { + var cluster = clusters[CONFIG.restartClusterName]; + if (cluster !== undefined) { + if (cluster.clusterStatus === "Offline") { + console.log("[****] Restarting server!!!"); + cp.exec(CONFIG.restartCommand, { cwd: CONFIG.restartWorkingPath }, function (error, stdout, stderr) { }); + if (CONFIG.discordBot) { + var channel = client.channels.find("name", CONFIG.discordBotChannelName); + channel.sendMessage("@here **Restarting cluster `" + CONFIG.restartClusterName + "` due to detected offline status!**"); + } + } + } else { + console.log("[****] Starting server!!!"); + cp.exec(CONFIG.restartCommand, { cwd: CONFIG.restartWorkingPath }, function (error, stdout, stderr) { }); + } + }, 60 * 1000) +} + +// --------------------------------------------------------------- + +app.get('/*', function (req, res) { + res.sendFile(path.join(__dirname + '/public/index.html')); +}); + +server.listen(port, host, () => { + console.log(`Web Server Listening on ${host}:${port}`); +}); \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..f28b183 --- /dev/null +++ b/config.json @@ -0,0 +1,13 @@ +{ + "dbHost": "127.0.0.1", + "dbName": "swg", + "autoRegistration": true, + "discordBot": true, + "discordBotToken": "token", + "discordBotChannelName": "channelName", + "discordStatusInterval": 30, + "restartServer": true, + "restartClusterName": "SWG Server Name", + "restartWorkingPath": "/home/user/swg-main/", + "restartCommand": "./start_server.sh" +} \ No newline at end of file diff --git a/database.js b/database.js new file mode 100644 index 0000000..8bc2fa4 --- /dev/null +++ b/database.js @@ -0,0 +1,36 @@ +(function () { + var exports = module.exports = {}; + + const CONFIG = require('./config.json'); + const mysql = require('mysql'); + require('dotenv').config(); + + var con = mysql.createConnection({ + host: CONFIG.dbHost, + database: CONFIG.dbName, + user: process.env.SQL_USER, + password: process.env.SQL_PASS + }); + + // callback = function(err, user) + module.exports.getUser = function (username, callback) { + var sql = "SELECT * FROM user_account WHERE username = " + mysql.escape(username); + con.query(sql, function (err, result) { + if (err == null) { + var user = (result.length >= 1 ? result[0] : null); + callback(err, user); + } else { + console.log(err); + } + }); + } + + // callback = function(err, user) + module.exports.createUser = function (username, password, email, callback) { + var user = { username: username, password_hash: password, password_salt: process.env.SQL_HASH, accesslevel: 'standard' } + con.query("INSERT INTO user_account SET ?", user, function (err, result) { + if (err) throw err; + module.exports.getUser(username, callback); + }); + } +}()); \ No newline at end of file diff --git a/html/!!!!README 1st!!!! b/html/!!!!README 1st!!!! deleted file mode 100644 index 51ca287..0000000 --- a/html/!!!!README 1st!!!! +++ /dev/null @@ -1,46 +0,0 @@ - -SWG NGE Server Webpage v1.01 - - - -All Star Wars background pictures, music, and logos are registered trademarks and copyright of LucasArts and Disney. We do not recieve original credit for those trademarks and copyrights in anyway, shape, or form. - - - -Modified Webpage: - -I modified the webpage to add backgrounds, music(at main page), extra links, Server Online/Offline Status at Main Page (currently cant find correct port number for $portg but Login Server Status is working. If you accidently delete the port number for the Login Status, it is 10666. just put that in $portl if needed. If someone happens to find the correct port with no errors or crashes, please let us know with the correct port number). - -Currently I have no mysql database and oracle database experience to configure and modify the database for the Number of Players Online status so please let me know if you got this configured and how and what you did. - -Make sure to change the IP addresses in webpage code (not counting 127.0.0.1 in Server Status), to current IP address of VM in lower left corner of VM screen. Bring up a web browser and type in the address bar: http://(your.VM.Address.here) without the (). Then you can refresh the page when you change any of the webpage code. - - -FORUMS PAGE -------------------------------- -MyBB v1.8.12 - -I have also included a MyBB forums for the site as well. You will also have to add a mySQL database section for the forums before you can install it. - -Copy and paste this link in your browser for MyBB setup instructions and make sure to follow them correctly: https://docs.mybb.com/1.8/install/ - -You will need to register a seperate account for the forums. - - - - -May the Force Be With You. - ------------------------------------------------------------------ - -v1.01 UPDATE: 9/10/2017 - -1.)Fixed a few links on index.php and 1 link on addnewuser.php: - - a.)index.php: links for home, forums, and Register for an Account on index.php now have "/index.php", "/forums/index.php", and "/addnewuser.php" instead of http://192.168.1.XXX or http://localhost. Now user wont have to set addresses for webpage - - b.) addnewuser.php> fixed "Home" link on addnewuser.php. Instead of it being http://localhost/index.php or http://192.168.1.XXX, it is now /index.php. Now user wont have to set addresses for webpage - -2.) Reconfigured index.php coding to bring the main page up to top of page and menu on left side of page to be the top-left instead of at midd to bottom of page due to html body coding - - diff --git a/html/addnewuser.php b/html/addnewuser.php deleted file mode 100644 index d8917ba..0000000 --- a/html/addnewuser.php +++ /dev/null @@ -1,80 +0,0 @@ - - - - -Create a New Account - - - - - - - - -

Home

- - -

REGISTER AN ACCOUNT

- - - - - - - - - - - - - - - - -
Account Name
Password
Confirm Password
Access Level
- - -
- - diff --git a/html/auth.php b/html/auth.php deleted file mode 100644 index a3762ce..0000000 --- a/html/auth.php +++ /dev/null @@ -1,41 +0,0 @@ -query("SELECT * FROM user_account WHERE username = '$username'") or die(mysql_error()); - $no_of_rows = $result->num_rows; - if ($no_of_rows > 0) { - $result = $result->fetch_array(); - $salt = $result['password_salt']; - $stored_hash = $result['password_hash']; - $hashtest = checkhashSSHA($salt, $password); - if ($hashtest == $stored_hash) { - return $result; - } - } - else { - return false; - } -} - -function checkhashSSHA($salt, $password) { - $hash = base64_encode(sha1($password . $salt, true) . $salt); - return $hash; -} - -$username = $mysqli->real_escape_string($_POST['user_name']); -$password = $mysqli->real_escape_string($_POST['user_password']); -$user = getUserByEmailAndPassword($username, $password); -if ($user != false) { - if($user['accesslevel'] == "banned") { - $response['message'] = "Account banned"; - } else { - $response['message'] = "success"; - } -} -else { - $response['message'] = "Account does not exist or password was incorrect"; -} -echo json_encode($response); -?> diff --git a/html/create_database_table.sql b/html/create_database_table.sql deleted file mode 100644 index e8e164b..0000000 --- a/html/create_database_table.sql +++ /dev/null @@ -1,38 +0,0 @@ -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- -------------------------------------------------------- - --- --- Table structure for table `user_account` --- - -CREATE TABLE `user_account` ( - `user_id` int(11) NOT NULL, - `accesslevel` varchar(255) NOT NULL, - `username` varchar(255) NOT NULL, - `password_salt` varchar(255) NOT NULL, - `password_hash` varchar(255) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- --- Indexes for table `user_account` --- -ALTER TABLE `user_account` - ADD UNIQUE KEY `user_id` (`user_id`), - ADD UNIQUE KEY `username` (`username`); - --- --- AUTO_INCREMENT for table `user_account` --- -ALTER TABLE `user_account` - MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/html/forums/admin/backups/.htaccess b/html/forums/admin/backups/.htaccess deleted file mode 100644 index 9532873..0000000 --- a/html/forums/admin/backups/.htaccess +++ /dev/null @@ -1,7 +0,0 @@ - - Order deny,allow - Deny from all - - - Require all denied - \ No newline at end of file diff --git a/html/forums/admin/backups/index.html b/html/forums/admin/backups/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/backups/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/inc/class_form.php b/html/forums/admin/inc/class_form.php deleted file mode 100644 index ece99d7..0000000 --- a/html/forums/admin/inc/class_form.php +++ /dev/null @@ -1,1068 +0,0 @@ -\n"; - $form .= $this->generate_hidden_field("my_post_key", $mybb->post_code)."\n"; - if($return == false) - { - echo $form; - } - else - { - $this->_return = true; - $this->construct_return = $form; - } - } - - /** - * Generate and return a hidden field. - * - * @param string $name The name of the hidden field. - * @param string $value The value of the hidden field. - * @param array $options Optional array of options (id) - * @return string The generated hidden - */ - function generate_hidden_field($name, $value, $options=array()) - { - $input = ""; - $textarea .= htmlspecialchars_uni($value); - $textarea .= ""; - return $textarea; - } - - /** - * Generate a radio button. - * - * @param string $name The name of the radio button. - * @param string $value The value of the radio button - * @param string $label The label of the radio button if there is one. - * @param array $options Array of options for the radio button (id, class, checked) - * @return string The generated radio button. - */ - function generate_radio_button($name, $value="", $label="", $options=array()) - { - $input = " val format. - * @param string|array $selected Either a string containing the selected item or an array containing multiple selected items (options['multiple'] must be true) - * @param array $options Array of options for the select box (multiple, class, id, size) - * @return string The select box. - */ - function generate_select_box($name, $option_list, $selected=array(), $options=array()) - { - if(!isset($options['multiple'])) - { - $select = "\n"; - return $select; - } - - /** - * Generate a forum selection box. - * - * @param string $name The name of the selection box. - * @param array|string $selected Array/string of the selected items. - * @param array Array of options (pid, main_option, multiple, depth) - * @param boolean|int $is_first Is this our first iteration of this function? - * @return string The built select box. - */ - function generate_forum_select($name, $selected, $options=array(), $is_first=1) - { - global $fselectcache, $forum_cache, $selectoptions; - - if(!$selectoptions) - { - $selectoptions = ''; - } - - if(!isset($options['depth'])) - { - $options['depth'] = 0; - } - - $options['depth'] = (int)$options['depth']; - - if(!isset($options['pid'])) - { - $options['pid'] = 0; - } - - $pid = (int)$options['pid']; - - if(!is_array($fselectcache)) - { - if(!is_array($forum_cache)) - { - $forum_cache = cache_forums(); - } - - foreach($forum_cache as $fid => $forum) - { - $fselectcache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; - } - } - - if($options['main_option'] && $is_first) - { - $select_add = ''; - if($selected == -1) - { - $select_add = " selected=\"selected\""; - } - - $selectoptions .= "\n"; - } - - if(isset($fselectcache[$pid])) - { - foreach($fselectcache[$pid] as $main) - { - foreach($main as $forum) - { - if($forum['fid'] != "0" && $forum['linkto'] == '') - { - $select_add = ''; - - if(!empty($selected) && ($forum['fid'] == $selected || (is_array($selected) && in_array($forum['fid'], $selected)))) - { - $select_add = " selected=\"selected\""; - } - - $sep = ''; - if(isset($options['depth'])) - { - $sep = str_repeat(" ", $options['depth']); - } - - $style = ""; - if($forum['active'] == 0) - { - $style = " style=\"font-style: italic;\""; - } - - $selectoptions .= "\n"; - - if($forum_cache[$forum['fid']]) - { - $options['depth'] += 5; - $options['pid'] = $forum['fid']; - $this->generate_forum_select($forum['fid'], $selected, $options, 0); - $options['depth'] -= 5; - } - } - } - } - } - - if($is_first == 1) - { - if(!isset($options['multiple'])) - { - $select = "read('usergroups'); - - if(!is_array($selected)) - { - $selected = array($selected); - } - - foreach($groups_cache as $group) - { - $selected_add = ""; - - - if(in_array($group['gid'], $selected)) - { - $selected_add = " selected=\"selected\""; - } - - $select .= ""; - } - - $select .= ""; - - return $select; - } - - /** - * Generate a submit button. - * - * @param string $value The value for the submit button. - * @param array $options Array of options for the submit button (class, id, name, dsiabled, onclick) - * @return string The generated submit button. - */ - function generate_submit_button($value, $options=array()) - { - $input = "generate_radio_button($name, $yes_value, $lang->yes, $yes_options); - $no = $this->generate_radio_button($name, $no_value, $lang->no, $no_options); - return $yes." ".$no; - } - - /** - * Generate an on/off radio button choice. - * - * @param string $name The name of the on/off choice field. - * @param int $value The value that should be checked. - * @param boolean $int Using integers for the checkbox? - * @param array $on_options Array of options for the on checkbox (@see generate_radio_button) - * @param array $off_options Array of options for the off checkbox (@see generate_radio_button) - * @return string The generated on/off radio button. - */ - function generate_on_off_radio($name, $value=1, $int=true, $on_options=array(), $off_options = array()) - { - global $lang; - - // Checked status - if($value == "off" || (int) $value !== 1) - { - $off_checked = 1; - $on_checked = 0; - } - else - { - $on_checked = 1; - $off_checked = 0; - } - // Element value - if($int == true) - { - $on_value = 1; - $off_value = 0; - } - else - { - $on_value = "on"; - $off_value = "off"; - } - - // Set the options straight - if(!isset($on_options['class'])) - { - $on_options['class'] = ''; - } - - if(!isset($off_options['class'])) - { - $off_options['class'] = ''; - } - - $on_options['class'] = "radio_on ".$on_options['class']; - $on_options['checked'] = $on_checked; - $off_options['class'] = "radio_off ".$off_options['class']; - $off_options['checked'] = $off_checked; - - $on = $this->generate_radio_button($name, $on_value, $lang->on, $on_options); - $off = $this->generate_radio_button($name, $off_value, $lang->off, $off_options); - return $on." ".$off; - } - - /** - * @param string $name - * @param int $day - * @param int $month - * @param int $year - * - * @return string - */ - function generate_date_select($name, $day=0,$month=0,$year=0) - { - global $lang; - - $months = array( - 1 => $lang->january, - 2 => $lang->february, - 3 => $lang->march, - 4 => $lang->april, - 5 => $lang->may, - 6 => $lang->june, - 7 => $lang->july, - 8 => $lang->august, - 9 => $lang->september, - 10 => $lang->october, - 11 => $lang->november, - 12 => $lang->december, - ); - - // Construct option list for days - $days = array(); - for($i = 1; $i <= 31; ++$i) - { - $days[$i] = $i; - } - - if(!$day) - { - $day = date("j", TIME_NOW); - } - - if(!$month) - { - $month = date("n", TIME_NOW); - } - - if(!$year) - { - $year = date("Y", TIME_NOW); - } - - $built = $this->generate_select_box($name.'_day', $days, (int)$day, array('id' => $name.'_day'))."   "; - $built .= $this->generate_select_box($name.'_month', $months, (int)$month, array('id' => $name.'_month'))."   "; - $built .= $this->generate_numeric_field($name.'_year', $year, array('id' => $name.'_year', 'style' => 'width: 100px;', 'min' => 0)); - return $built; - } - - /** - * Output a row of buttons in a wrapped container. - * - * @param array $buttons Array of the buttons (html) to output. - * @return string The submit wrapper (optional) - */ - function output_submit_wrapper($buttons) - { - global $plugins; - $buttons = $plugins->run_hooks("admin_form_output_submit_wrapper", $buttons); - $return = "
\n"; - foreach($buttons as $button) - { - $return .= $button." \n"; - } - $return .= "
\n"; - if($this->_return == false) - { - echo $return; - } - else - { - return $return; - } - } - - /** - * Finish up a form. - * - * @return string The ending form tag (optional) - */ - function end() - { - global $plugins; - $plugins->run_hooks("admin_form_end", $this); - if($this->_return == false) - { - echo ""; - } - else - { - return ""; - } - } -} - -/** - * Generate a form container. - */ -class DefaultFormContainer -{ - /** @var Table */ - private $_container; - /** @var string */ - public $_title; - - /** - * Initialise the new form container. - * - * @param string $title The title of the form container - * @param string $extra_class An additional class to apply if we have one. - */ - function __construct($title='', $extra_class='') - { - $this->_container = new Table; - $this->extra_class = $extra_class; - $this->_title = $title; - } - - /** - * Output a header row of the form container. - * - * @param string $title The header row label. - * @param array $extra Array of extra information for this header cell (class, style, colspan, width) - */ - function output_row_header($title, $extra=array()) - { - $this->_container->construct_header($title, $extra); - } - - /** - * Output a row of the form container. - * - * @param string $title The title of the row. - * @param string $description The description of the row/field. - * @param string $content The HTML content to show in the row. - * @param string $label_for The ID of the control this row should be a label for. - * @param array $options Array of options for the row cell. - * @param array $row_options Array of options for the row container. - */ - function output_row($title, $description="", $content="", $label_for="", $options=array(), $row_options=array()) - { - global $plugins; - $pluginargs = array( - 'title' => &$title, - 'description' => &$description, - 'content' => &$content, - 'label_for' => &$label_for, - 'options' => &$options, - 'row_options' => &$row_options, - 'this' => &$this - ); - - $plugins->run_hooks("admin_formcontainer_output_row", $pluginargs); - - $row = $for = ''; - if($label_for != '') - { - $for = " for=\"{$label_for}\""; - } - - if($title) - { - $row = "{$title}"; - } - - if($description != '') - { - $row .= "\n
{$description}
\n"; - } - - $row .= "
{$content}
\n"; - - $this->_container->construct_cell($row, $options); - - if(!isset($options['skip_construct'])) - { - $this->_container->construct_row($row_options); - } - } - - /** - * Output a row cell for a table based form row. - * - * @param string $data The data to show in the cell. - * @param array $options Array of options for the cell (optional). - */ - function output_cell($data, $options=array()) - { - $this->_container->construct_cell($data, $options); - } - - /** - * Build a row for the table based form row. - * - * @param array $extra Array of extra options for the cell (optional). - */ - function construct_row($extra=array()) - { - $this->_container->construct_row($extra); - } - - /** - * return the cells of a row for the table based form row. - * - * @param string $row_id The id of the row. - * @param boolean $return Whether or not to return or echo the resultant contents. - * @return string The output of the row cells (optional). - */ - function output_row_cells($row_id, $return=false) - { - if(!$return) - { - echo $this->_container->output_row_cells($row_id, $return); - } - else - { - return $this->_container->output_row_cells($row_id, $return); - } - } - - /** - * Count the number of rows in the form container. Useful for displaying a 'no rows' message. - * - * @return int The number of rows in the form container. - */ - function num_rows() - { - return $this->_container->num_rows(); - } - - /** - * Output the end of the form container row. - * - * @param boolean $return Whether or not to return or echo the resultant contents. - * @return string The output of the form container (optional). - */ - function end($return=false) - { - global $plugins; - - $hook = array( - 'return' => &$return, - 'this' => &$this - ); - - $plugins->run_hooks("admin_formcontainer_end", $hook); - if($return == true) - { - return $this->_container->output($this->_title, 1, "general form_container {$this->extra_class}", true); - } - else - { - echo $this->_container->output($this->_title, 1, "general form_container {$this->extra_class}", false); - } - } -} diff --git a/html/forums/admin/inc/class_page.php b/html/forums/admin/inc/class_page.php deleted file mode 100644 index 15806cd..0000000 --- a/html/forums/admin/inc/class_page.php +++ /dev/null @@ -1,1230 +0,0 @@ - tags. - */ - public $extra_header = ""; - - /** - * @var string Any additional messages to add after the flash messages are shown. - */ - public $extra_messages = array(); - - /** - * @var string Show a post verify error - */ - public $show_post_verify_error = ''; - - /** - * Output the page header. - * - * @param string $title The title of the page. - */ - function output_header($title="") - { - global $mybb, $admin_session, $lang, $plugins; - - $args = array( - 'this' => &$this, - 'title' => &$title, - ); - - $plugins->run_hooks("admin_page_output_header", $args); - - if(!$title) - { - $title = $lang->mybb_admin_panel; - } - - $rtl = ""; - if($lang->settings['rtl'] == 1) - { - $rtl = " dir=\"rtl\""; - } - - echo "\n"; - echo "\n"; - echo "\n"; - echo " ".$title."\n"; - echo " \n"; - echo " \n"; - echo " style."/main.css?ver=1804\" type=\"text/css\" />\n"; - echo " style."/modal.css\" type=\"text/css\" />\n"; - - // Load stylesheet for this module if it has one - if(file_exists(MYBB_ADMIN_DIR."styles/{$this->style}/{$this->active_module}.css")) - { - echo " style}/{$this->active_module}.css\" type=\"text/css\" />\n"; - } - - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - - // Stop JS elements showing while page is loading (JS supported browsers only) - echo " \n"; - echo " \n"; - - echo " \n"; - echo $this->extra_header; - echo "\n"; - echo "\n"; - echo "
\n"; - echo "

{$lang->mybb_admin_cp}

\n"; - $username = htmlspecialchars_uni($mybb->user['username']); - echo " \n"; - echo $this->_build_menu(); - echo "
\n"; - echo "
\n"; - echo $this->submenu; - echo $this->sidebar; - echo "
\n"; - echo "
\n"; - echo "
\n"; - echo $this->_generate_breadcrumb(); - echo "
\n"; - echo "
\n"; - if(isset($admin_session['data']['flash_message']) && $admin_session['data']['flash_message']) - { - $message = $admin_session['data']['flash_message']['message']; - $type = $admin_session['data']['flash_message']['type']; - echo "
\n"; - echo "{$message}\n"; - echo "
\n"; - update_admin_session('flash_message', ''); - } - - if(!empty($this->extra_messages) && is_array($this->extra_messages)) - { - foreach($this->extra_messages as $message) - { - switch($message['type']) - { - case 'success': - case 'error': - echo "
\n"; - echo "{$message['message']}\n"; - echo "
\n"; - break; - default: - $this->output_error($message['message']); - break; - } - } - } - - if($this->show_post_verify_error == true) - { - $this->output_error($lang->invalid_post_verify_key); - } - } - - /** - * Output the page footer. - * - * @param bool $quit - */ - function output_footer($quit=true) - { - global $mybb, $maintimer, $db, $lang, $plugins; - - $args = array( - 'this' => &$this, - 'quit' => &$quit, - ); - - $plugins->run_hooks("admin_page_output_footer", $args); - - $memory_usage = get_friendly_size(get_memory_usage()); - - $totaltime = format_time_duration($maintimer->stop()); - $querycount = $db->query_count; - - if(my_strpos(getenv("REQUEST_URI"), "?")) - { - $debuglink = htmlspecialchars_uni(getenv("REQUEST_URI")) . "&debug=1#footer"; - } - else - { - $debuglink = htmlspecialchars_uni(getenv("REQUEST_URI")) . "?debug=1#footer"; - } - - echo "
\n"; - echo "
\n"; - echo "
"; - echo "
"; - echo "
\n"; - echo "

".$lang->sprintf($lang->generated_in, $totaltime, $debuglink, $querycount, $memory_usage)."

Powered By MyBB, © 2002-".COPY_YEAR." MyBB Group.

\n"; - if($mybb->debug_mode) - { - echo $db->explain; - } - echo "
\n"; - echo "\n"; - echo "\n"; - - if($quit != false) - { - exit; - } - } - - /** - * Add an item to the page breadcrumb trail. - * - * @param string $name The name of the item to add. - * @param string $url The URL to the item we're adding (if there is one) - */ - function add_breadcrumb_item($name, $url="") - { - $this->_breadcrumb_trail[] = array("name" => $name, "url" => $url); - } - - /** - * Generate a breadcrumb trail. - * - * @return bool|string - */ - function _generate_breadcrumb() - { - if(!is_array($this->_breadcrumb_trail)) - { - return false; - } - $trail = ""; - foreach($this->_breadcrumb_trail as $key => $crumb) - { - if(isset($this->_breadcrumb_trail[$key+1])) - { - $trail .= "".$crumb['name'].""; - if(isset($this->_breadcrumb_trail[$key+2])) - { - $trail .= " » "; - } - } - else - { - $trail .= "".$crumb['name'].""; - } - } - return $trail; - } - - /** - * Output a success message. - * - * @param string $message The message to output. - */ - function output_success($message) - { - echo "
{$message}
\n"; - } - - /** - * Output an alert/warning message. - * - * @param string $message The message to output. - * @param string $id The ID of the alert/warning (optional) - */ - function output_alert($message, $id="") - { - if($id) - { - $id = " id=\"{$id}\""; - } - echo "
{$message}
\n"; - } - - /** - * Output an inline message. - * - * @param string $message The message to output. - */ - function output_inline_message($message) - { - echo "
{$message}
\n"; - } - - /** - * Output a single error message. - * - * @param string $error The message to output. - */ - function output_error($error) - { - echo "
\n"; - echo "{$error}\n"; - echo "
\n"; - } - - /** - * Output one or more inline error messages. - * - * @param array $errors Array of error messages to output. - */ - function output_inline_error($errors) - { - global $lang; - - if(!is_array($errors)) - { - $errors = array($errors); - } - echo "
\n"; - echo "

{$lang->encountered_errors}

\n"; - echo "
    \n"; - foreach($errors as $error) - { - echo "
  • {$error}
  • \n"; - } - echo "
\n"; - echo "
\n"; - } - - /** - * Generate the login page. - * - * @param string $message The any message to output on the page if there is one. - * @param string $class The class name of the message (defaults to success) - */ - function show_login($message="", $class="success") - { - global $plugins, $lang, $cp_style, $mybb; - - $args = array( - 'this' => &$this, - 'message' => &$message, - 'class' => &$class - ); - - $plugins->run_hooks('admin_page_show_login_start', $args); - - $copy_year = COPY_YEAR; - - $login_container_width = ""; - $login_label_width = ""; - - // If the language string for "Username" is too cramped then use this to define how much larger you want the gap to be (in px) - if(isset($lang->login_field_width)) - { - $login_label_width = " style=\"width: ".((int)$lang->login_field_width+100)."px;\""; - $login_container_width = " style=\"width: ".(410+((int)$lang->login_field_width))."px;\""; - } - - $login_page .= << - - -{$lang->mybb_admin_login} - - - - - - - - - -
- -
-

{$lang->please_login}

-EOF; - if($message) - { - $login_page .= "

{$message}

"; - } - // Make query string nice and pretty so that user can go to his/her preferred destination - $query_string = ''; - if($_SERVER['QUERY_STRING']) - { - $query_string = '?'.preg_replace('#adminsid=(.{32})#i', '', $_SERVER['QUERY_STRING']); - $query_string = preg_replace('#my_post_key=(.{32})#i', '', $query_string); - $query_string = str_replace('action=logout', '', $query_string); - $query_string = preg_replace('#&+#', '&', $query_string); - $query_string = str_replace('?&', '?', $query_string); - $query_string = htmlspecialchars_uni($query_string); - } - switch($mybb->settings['username_method']) - { - case 0: - $lang_username = $lang->username; - break; - case 1: - $lang_username = $lang->username1; - break; - case 2: - $lang_username = $lang->username2; - break; - default: - $lang_username = $lang->username; - break; - } - - // Secret PIN - global $config; - if(isset($config['secret_pin']) && $config['secret_pin'] != '') - { - $secret_pin = "
-
"; - } - else - { - $secret_pin = ''; - } - - $login_lang_string = $lang->enter_username_and_password; - - switch($mybb->settings['username_method']) - { - case 0: // Username only - $login_lang_string = $lang->sprintf($login_lang_string, $lang->login_username); - break; - case 1: // Email only - $login_lang_string = $lang->sprintf($login_lang_string, $lang->login_email); - break; - case 2: // Username and email - default: - $login_lang_string = $lang->sprintf($login_lang_string, $lang->login_username_and_password); - break; - } - - $_SERVER['PHP_SELF'] = htmlspecialchars_uni($_SERVER['PHP_SELF']); - - $login_page .= <<{$login_lang_string}

-
-
- -
- -
- -
-
- {$secret_pin} -
-

- - {$lang->lost_password} - - - - -

-
-
-
- - -EOF; - - $args = array( - 'this' => &$this, - 'login_page' => &$login_page - ); - - $plugins->run_hooks('admin_page_show_login_end', $args); - - echo $login_page; - exit; - } - - function show_2fa() - { - global $lang, $cp_style, $mybb; - - $mybb2fa_page = << - - -{$lang->my2fa} - - - - - - - - - -
- -
-

{$lang->my2fa}

-EOF; - // Make query string nice and pretty so that user can go to his/her preferred destination - $query_string = ''; - if($_SERVER['QUERY_STRING']) - { - $query_string = '?'.preg_replace('#adminsid=(.{32})#i', '', $_SERVER['QUERY_STRING']); - $query_string = preg_replace('#my_post_key=(.{32})#i', '', $query_string); - $query_string = str_replace('action=logout', '', $query_string); - $query_string = preg_replace('#&+#', '&', $query_string); - $query_string = str_replace('?&', '?', $query_string); - $query_string = htmlspecialchars_uni($query_string); - } - $mybb2fa_page .= <<{$lang->my2fa_code}

-
-
-
-
-
-

- - -

-
-
-
- - -EOF; - echo $mybb2fa_page; - exit; - } - - /** - * Generate the lockout page - * - */ - function show_lockedout() - { - global $lang, $mybb, $cp_style; - - $copy_year = COPY_YEAR; - $allowed_attempts = (int)$mybb->settings['maxloginattempts']; - $lockedout_message = $lang->sprintf($lang->error_mybb_admin_lockedout_message, $allowed_attempts); - - print << - - -{$lang->mybb_admin_cp} - {$lang->error_mybb_admin_lockedout} - - - - - -
- -
-

{$lang->error_mybb_admin_lockedout}

-
{$lockedout_message}
-
-
- - -EOF; - exit; - } - - /** - * Generate the lockout unlock page - * - * @param string $message The any message to output on the page if there is one. - * @param string $class The class name of the message (defaults to success) - */ - function show_lockout_unlock($message="", $class="success") - { - global $lang, $mybb, $cp_style; - - $copy_year = COPY_YEAR; - switch($mybb->settings['username_method']) - { - case 0: - $lang_username = $lang->username; - break; - case 1: - $lang_username = $lang->username1; - break; - case 2: - $lang_username = $lang->username2; - break; - default: - $lang_username = $lang->username; - break; - } - - if($message) - { - $message = "

{$message}

"; - } - - print << - - -{$lang->mybb_admin_cp} - {$lang->lockout_unlock} - - - - - -
- -
-

{$lang->lockout_unlock}

- {$message} -

{$lang->enter_username_and_token}

-
-
- -
- -
- -
-
-
-

- - {$lang->lost_password} - - - - -

-
-
-
- - -EOF; - exit; - } - - /** - * Add an item to the primary navigation menu. - * - * @param string $title The title of the menu item. - * @param string $id The ID of the menu item. This should correspond with the module the menu will run. - * @param string $link The link to follow when the menu item is clicked. - * @param int $order The display order of the menu item. Lower display order means closer to start of the menu. - * @param array $submenu Array of sub menu items if there are any. - */ - function add_menu_item($title, $id, $link, $order=10, $submenu=array()) - { - $this->_menu[$order][] = array( - "title" => $title, - "id" => $id, - "link" => $link, - "submenu" => $submenu - ); - } - - /** - * Build the actual navigation menu. - * - * @return bool|string - */ - function _build_menu() - { - if(!is_array($this->_menu)) - { - return false; - } - $build_menu = "
\n
    \n"; - ksort($this->_menu); - foreach($this->_menu as $items) - { - foreach($items as $menu_item) - { - $menu_item['link'] = htmlspecialchars_uni($menu_item['link']); - if($menu_item['id'] == $this->active_module) - { - $sub_menu = $menu_item['submenu']; - $sub_menu_title = $menu_item['title']; - $build_menu .= "
  • {$menu_item['title']}
  • \n"; - - } - else - { - $build_menu .= "
  • {$menu_item['title']}
  • \n"; - } - } - } - $build_menu .= "
\n
"; - - if($sub_menu) - { - $this->_build_submenu($sub_menu_title, $sub_menu); - } - return $build_menu; - } - - /** - * Build a navigation sub menu if we have one. - * - * @param string $title A title for the sub menu. - * @param array $items Array of items for the sub menu. - */ - function _build_submenu($title, $items) - { - if(is_array($items)) - { - $sidebar = new sideBarItem($title); - $sidebar->add_menu_items($items, $this->active_action); - $this->submenu .= $sidebar->get_markup(); - } - } - - /** - * Output a Javascript based tab control on to the page. - * - * @param array $tabs Array of tabs in name => title format. Name should correspond to the name of a DIV containing the tab content. - * @param boolean $observe_onload Whether or not to run the event onload or instantly - * @param string $id The ID to use for the tabs for if you run multiple instances of the tabbing control in one html page - */ - function output_tab_control($tabs=array(), $observe_onload=true, $id="tabs") - { - global $plugins; - $tabs = $plugins->run_hooks("admin_page_output_tab_control_start", $tabs); - echo "
    \n"; - $tab_count = count($tabs); - $done = 1; - foreach($tabs as $anchor => $title) - { - $class = ""; - if($tab_count == $done) - { - $class .= " last"; - } - if($done == 1) - { - $class .= " first"; - } - ++$done; - echo "
  • {$title}
  • \n"; - } - echo "
\n"; - $plugins->run_hooks("admin_page_output_tab_control_end", $tabs); - } - - /** - * Output a series of primary navigation tabs for swithcing between items within a particular module/action. - * - * @param array $tabs Nested array of tabs containing possible keys of align, link_target, link, title. - * @param string $active The name of the active tab. Corresponds with the key of each tab item. - */ - function output_nav_tabs($tabs=array(), $active='') - { - global $plugins; - $tabs = $plugins->run_hooks("admin_page_output_nav_tabs_start", $tabs); - echo "
"; - echo "\t
    \n"; - foreach($tabs as $id => $tab) - { - $class = ''; - if($id == $active) - { - $class = ' active'; - } - if(isset($tab['align']) == "right") - { - $class .= " right"; - } - $target = ''; - if(isset($tab['link_target'])) - { - $target = " target=\"{$tab['link_target']}\""; - } - if(!isset($tab['link'])) - { - $tab['link'] = ''; - } - echo "\t\t
  • {$tab['title']}
  • \n"; - $target = ''; - } - echo "\t
\n"; - if($tabs[$active]['description']) - { - echo "\t
{$tabs[$active]['description']}
\n"; - } - echo "
"; - $arguments = array('tabs' => $tabs, 'active' => $active); - $plugins->run_hooks("admin_page_output_nav_tabs_end", $arguments); - } - - /** - * Output a page asking if a user wishes to continue performing a specific action. - * - * @param string $url The URL to be forwarded to. - * @param string $message The confirmation message to output. - * @param string $title The title to use in the output header - */ - function output_confirm_action($url, $message="", $title="") - { - global $lang, $plugins; - - $args = array( - 'this' => &$this, - 'url' => &$url, - 'message' => &$message, - 'title' => &$title, - ); - - $plugins->run_hooks('admin_page_output_confirm_action', $args); - - if(!$message) - { - $message = $lang->confirm_action; - } - $this->output_header($title); - $form = new Form($url, 'post'); - - echo "
\n"; - echo "

{$message}

\n"; - echo "
\n"; - echo "

\n"; - echo $form->generate_submit_button($lang->yes, array('class' => 'button_yes')); - echo $form->generate_submit_button($lang->no, array("name" => "no", 'class' => 'button_no')); - echo "

\n"; - echo "
\n"; - - $form->end(); - $this->output_footer(); - } - - /** - * Build a clickable MyCode editor for the Admin CP. - * - * @param string $bind The ID of the textarea to bind the editor to. - * @param string $editor_language The language string for the editor. - * @param bool $smilies Whether or not smilies should be included - * @return string The build MyCode editor Javascript. - */ - function build_codebuttons_editor($bind, $editor_language, $smilies) - { - global $lang, $mybb, $smiliecache, $cache; - - // Smilies - $emoticon = ""; - $emoticons_enabled = "false"; - if($smilies) - { - if($mybb->settings['smilieinserter'] && $mybb->settings['smilieinsertercols'] && $mybb->settings['smilieinsertertot']) - { - $emoticon = ",emoticon"; - } - $emoticons_enabled = "true"; - - if(!$smiliecount) - { - $smilie_cache = $cache->read("smilies"); - $smiliecount = count($smilie_cache); - } - - if(!$smiliecache) - { - if(!is_array($smilie_cache)) - { - $smilie_cache = $cache->read("smilies"); - } - foreach($smilie_cache as $smilie) - { - $smilie['image'] = str_replace("{theme}", "images", $smilie['image']); - $smiliecache[$smilie['sid']] = $smilie; - } - } - - unset($smilie); - - if(is_array($smiliecache)) - { - reset($smiliecache); - - $dropdownsmilies = $moresmilies = $hiddensmilies = ""; - $i = 0; - - foreach($smiliecache as $smilie) - { - $finds = explode("\n", $smilie['find']); - $finds_count = count($finds); - - // Only show the first text to replace in the box - $find = str_replace(array('\\', '"'), array('\\\\', '\"'), htmlspecialchars_uni($finds[0])); - $image = str_replace(array('\\', '"'), array('\\\\', '\"'), htmlspecialchars_uni($smilie['image'])); - if(substr($image, 0, 4) != "http") - { - $image = $mybb->settings['bburl']."/".$image; - } - - if(!$mybb->settings['smilieinserter'] || !$mybb->settings['smilieinsertercols'] || !$mybb->settings['smilieinsertertot'] || !$smilie['showclickable']) - { - $hiddensmilies .= '"'.$find.'": "'.$image.'",'; - } - elseif($i < $mybb->settings['smilieinsertertot']) - { - $dropdownsmilies .= '"'.$find.'": "'.$image.'",'; - ++$i; - } - else - { - $moresmilies .= '"'.$find.'": "'.$image.'",'; - } - - for($j = 1; $j < $finds_count; ++$j) - { - $find = str_replace(array('\\', '"'), array('\\\\', '\"'), htmlspecialchars_uni($finds[$j])); - $hiddensmilies .= '"'.$find.'": "'.$image.'",'; - } - } - } - } - - $basic1 = $basic2 = $align = $font = $size = $color = $removeformat = $email = $link = $list = $code = $sourcemode = ""; - - if($mybb->settings['allowbasicmycode'] == 1) - { - $basic1 = "bold,italic,underline,strike|"; - $basic2 = "horizontalrule,"; - } - - if($mybb->settings['allowalignmycode'] == 1) - { - $align = "left,center,right,justify|"; - } - - if($mybb->settings['allowfontmycode'] == 1) - { - $font = "font,"; - } - - if($mybb->settings['allowsizemycode'] == 1) - { - $size = "size,"; - } - - if($mybb->settings['allowcolormycode'] == 1) - { - $color = "color,"; - } - - if($mybb->settings['allowfontmycode'] == 1 || $mybb->settings['allowsizemycode'] == 1 || $mybb->settings['allowcolormycode'] == 1) - { - $removeformat = "removeformat|"; - } - - if($mybb->settings['allowemailmycode'] == 1) - { - $email = "email,"; - } - - if($mybb->settings['allowlinkmycode'] == 1) - { - $link = "link,unlink"; - } - - if($mybb->settings['allowlistmycode'] == 1) - { - $list = "bulletlist,orderedlist|"; - } - - if($mybb->settings['allowcodemycode'] == 1) - { - $code = "code,php,"; - } - - if($mybb->user['sourceeditor'] == 1) - { - $sourcemode = "MyBBEditor.sourceMode(true);"; - } - - return << -var partialmode = {$mybb->settings['partialmode']}, -opt_editor = { - plugins: "bbcode,undo", - style: "../jscripts/sceditor/textarea_styles/jquery.sceditor.mybb.css", - rtl: {$lang->settings['rtl']}, - locale: "mybblang", - enablePasteFiltering: true, - autoUpdate: true, - emoticonsEnabled: {$emoticons_enabled}, - emoticons: { - // Emoticons to be included in the dropdown - dropdown: { - {$dropdownsmilies} - }, - // Emoticons to be included in the more section - more: { - {$moresmilies} - }, - // Emoticons that are not shown in the dropdown but will still be converted. Can be used for things like aliases - hidden: { - {$hiddensmilies} - } - }, - emoticonsCompat: true, - toolbar: "{$basic1}{$align}{$font}{$size}{$color}{$removeformat}{$basic2}image,{$email}{$link}|video{$emoticon}|{$list}{$code}quote|maximize,source", -}; -{$editor_language} -$(function() { - $("#{$bind}").sceditor(opt_editor); - - MyBBEditor = $("#{$bind}").sceditor("instance"); - {$sourcemode} -}); - -EOF; - } -} - -/** - * A class for generating side bar blocks. - */ -class DefaultSidebarItem -{ - /** - * @var string The title of the side bar block. - */ - private $_title; - - /** - * @var string The contents of the side bar block. - */ - private $_contents; - - /** - * Constructor. Set the title of the side bar block. - * - * @param string $title The title of the side bar block. - */ - function __construct($title="") - { - $this->_title = $title; - } - - /** - * Add menus item to the side bar block. - * - * @param array $items Array of menu items to add. Each menu item should be a nested array of id, link and title. - * @param string $active The ID of the active menu item if there is one. - */ - function add_menu_items($items, $active) - { - global $run_module; - - $this->_contents = "
    "; - foreach($items as $item) - { - if(!check_admin_permissions(array("module" => $run_module, "action" => $item['id']), false)) - { - continue; - } - - $class = ""; - if($item['id'] == $active) - { - $class = "active"; - } - $item['link'] = htmlspecialchars_uni($item['link']); - $this->_contents .= "
  • {$item['title']}
  • \n"; - } - $this->_contents .= "
"; - } - - /** - * Sets custom html to the contents variable - * - * @param string $html The custom html to set - */ - function set_contents($html) - { - $this->_contents = $html; - } - - /** - * Fetch the HTML markup for the side bar box. - * - * @return string - */ - function get_markup() - { - $markup = "
\n"; - $markup .= "
{$this->_title}
\n"; - if($this->_contents) - { - $markup .= $this->_contents; - } - $markup .= "
\n"; - return $markup; - } -} - -/** - * Generate a Javascript based popup menu. - */ -class DefaultPopupMenu -{ - /** - * @var string The title of the popup menu to be shown on the button. - */ - private $_title; - - /** - * @var string The ID of this popup menu. Must be unique. - */ - private $_id; - - /** - * @var string Built HTML for the items in the popup menu. - */ - private $_items; - - /** - * Initialise a new popup menu. - * - * @var string $id The ID of the popup menu. - * @var string $title The title of the popup menu. - */ - function __construct($id, $title='') - { - $this->_id = $id; - $this->_title = $title; - } - - /** - * Add an item to the popup menu. - * - * @param string $text The title of this item. - * @param string $link The page this item should link to. - * @param string $onclick The onclick event handler if we have one. - */ - function add_item($text, $link, $onclick='') - { - if($onclick) - { - $onclick = " onclick=\"{$onclick}\""; - } - $this->_items .= "\n"; - } - - /** - * Fetch the contents of the popup menu. - * - * @return string The popup menu. - */ - function fetch() - { - $popup = "
_id}_popup\">\n{$this->_items}
\n"; - if($this->_title) - { - $popup .= "_id}\" class=\"popup_button\">{$this->_title}\n"; - } - $popup .= "\n"; - return $popup; - } - - /** - * Outputs a popup menu to the browser. - */ - function output() - { - echo $this->fetch(); - } -} diff --git a/html/forums/admin/inc/class_table.php b/html/forums/admin/inc/class_table.php deleted file mode 100644 index ff33251..0000000 --- a/html/forums/admin/inc/class_table.php +++ /dev/null @@ -1,291 +0,0 @@ -_cells[] = array("data" => $data, "extra" => $extra); - } - - /** - * Construct a row from the earlier defined constructed cells for the table. - * - * @param array $extra Array of extra information about this row (class, id) - */ - function construct_row($extra = array()) - { - $i = 1; - $cells = ''; - - // We construct individual cells here - foreach($this->_cells as $key => $cell) - { - $cells .= "\t\t\t_cells[$key+1])) - { - $cell['extra']['class'] .= " last"; - } - if($i == 2) - { - $cell['extra']['class'] .= " alt_col"; - $i = 0; - } - $i++; - if($cell['extra']['class']) - { - $cells .= " class=\"".trim($cell['extra']['class'])."\""; - } - if(isset($cell['extra']['style'])) - { - $cells .= " style=\"".$cell['extra']['style']."\""; - } - if(isset($cell['extra']['id'])) - { - $cells .= " id=\"".$cell['extra']['id']."\""; - } - if(isset($cell['extra']['colspan']) && $cell['extra']['colspan'] > 1) - { - $cells .= " colspan=\"".$cell['extra']['colspan']."\""; - } - if(isset($cell['extra']['rowspan']) && $cell['extra']['rowspan'] > 1) - { - $cells .= " rowspan=\"".$cell['extra']['rowspan']."\""; - } - if(isset($cell['extra']['width'])) - { - $cells .= " width=\"".$cell['extra']['width']."\""; - } - $cells .= ">"; - $cells .= $cell['data']; - $cells .= "\n"; - } - $data['cells'] = $cells; - $data['extra'] = $extra; - $this->_rows[] = $data; - - $this->_cells = array(); - } - - /** - * return the cells of a row for the table based row. - * - * @param string $row_id The id of the row you want to give it. - * @param boolean $return Whether or not to return or echo the resultant contents. - * @return string The output of the row cells (optional). - */ - function output_row_cells($row_id, $return=false) - { - $row = $this->_rows[$row_id]['cells']; - - if(!$return) - { - echo $row; - } - else - { - return $row; - } - } - - /** - * Count the number of rows in the table. Useful for displaying a 'no rows' message. - * - * @return int The number of rows in the table. - */ - function num_rows() - { - return count($this->_rows); - } - - /** - * Construct a header cell for this table. - * - * @param string $data The HTML content for this header cell. - * @param array $extra Array of extra information for this header cell (class, style, colspan, width) - */ - function construct_header($data, $extra=array()) - { - $this->_headers[] = array("data" => $data, "extra" => $extra); - } - - /** - * Output this table to the browser. - * - * @param string $heading The heading for this table. - * @param int $border The border width for this table. - * @param string $class The class for this table. - * @param boolean $return Whether or not to return or echo the resultant contents. - * @return string The output of the row cells (optional). - */ - function output($heading="", $border=1, $class="general", $return=false) - { - if($return == true) - { - return $this->construct_html($heading, $border, $class); - } - else - { - echo $this->construct_html($heading, $border, $class); - } - } - - /** - * Fetch the built HTML for this table. - * - * @param string $heading The heading for this table. - * @param int $border The border width for this table. - * @param string $class The class for this table. - * @param string $table_id The id for this table. - * @return string The built HTML. - */ - function construct_html($heading="", $border=1, $class=null, $table_id="") - { - $table = ''; - if($border == 1) - { - $table .= "
\n"; - if($heading != "") - { - $table .= "
".$heading."
\n"; - } - } - $table .= "\n"; - if($this->_headers) - { - $table .= "\t\n"; - $table .= "\t\t\n"; - foreach($this->_headers as $key => $data) - { - $table .= "\t\t\t_headers[$key+1])) - { - $data['extra']['class'] .= " last"; - } - if(isset($data['extra']['class'])) - { - $table .= " class=\"".$data['extra']['class']."\""; - } - if(isset($data['extra']['style'])) - { - $table .= " style=\"".$data['extra']['style']."\""; - } - if(isset($data['extra']['width'])) - { - $table .= " width=\"".$data['extra']['width']."\""; - } - if(isset($data['extra']['colspan']) && $data['extra']['colspan'] > 1) - { - $table .= " colspan=\"".$data['extra']['colspan']."\""; - } - $table .= ">".$data['data']."\n"; - } - $table .= "\t\t\n"; - $table .= "\t\n"; - } - $table .= "\t\n"; - $i = 1; - foreach($this->_rows as $key => $table_row) - { - $table .= "\t\t_rows[$key+1])) - { - $table_row['extra']['class'] .= " last"; - } - if($i == 2 && !isset($table_row['extra']['no_alt_row'])) - { - $table_row['extra']['class'] .= " alt_row"; - $i = 0; - } - $i++; - if($table_row['extra']['class']) - { - $table .= " class=\"".trim($table_row['extra']['class'])."\""; - } - $table .= ">\n"; - $table .= $table_row['cells']; - $table .= "\t\t\n"; - } - $table .= "\t\n"; - $table .= "\n"; - // Clean up - $this->_cells = $this->_rows = $this->_headers = array(); - if($border == 1) - { - $table .= "
"; - } - return $table; - } -} diff --git a/html/forums/admin/inc/functions.php b/html/forums/admin/inc/functions.php deleted file mode 100644 index 295c3e0..0000000 --- a/html/forums/admin/inc/functions.php +++ /dev/null @@ -1,803 +0,0 @@ - (int)$mybb->user['uid'], - "ipaddress" => $db->escape_binary(my_inet_pton(get_ip())), - "dateline" => TIME_NOW, - "module" => $db->escape_string($mybb->get_input('module')), - "action" => $db->escape_string($mybb->get_input('action')), - "data" => $db->escape_string(@my_serialize($data)) - ); - - $db->insert_query("adminlog", $log_entry); -} - -/** - * Redirects the current user to a specified URL. - * - * @param string $url The URL to redirect to - */ -function admin_redirect($url) -{ - if(!headers_sent()) - { - $url = str_replace("&", "&", $url); - header("Location: $url"); - } - else - { - echo ""; - } - exit; -} - -/** - * Updates an administration session data array. - * - * @param string $name The name of the item in the data session to update - * @param mixed $value The value - */ -function update_admin_session($name, $value) -{ - global $db, $admin_session; - - $admin_session['data'][$name] = $value; - $updated_session = array( - "data" => $db->escape_string(@my_serialize($admin_session['data'])) - ); - $db->update_query("adminsessions", $updated_session, "sid='{$admin_session['sid']}'"); -} - -/** - * Saves a "flash message" for the current user to be shown on their next page visit. - * - * @param string $message The message to show - * @param string $type The type of message to be shown (success|error) - */ -function flash_message($message, $type='') -{ - $flash = array('message' => $message, 'type' => $type); - update_admin_session('flash_message', $flash); -} - -/** - * Draw pagination for pages in the Admin CP. - * - * @param int $page The current page we're on - * @param int $per_page The number of items per page - * @param int $total_items The total number of items in this collection - * @param string $url The URL for pagination of this collection - * @return string The built pagination - */ -function draw_admin_pagination($page, $per_page, $total_items, $url) -{ - global $mybb, $lang; - - if($total_items <= $per_page) - { - return ''; - } - - $pages = ceil($total_items / $per_page); - - $pagination = "
{$lang->pages}: \n"; - - if($page > 1) - { - $prev = $page-1; - $prev_page = fetch_page_url($url, $prev); - $pagination .= "« {$lang->previous} \n"; - } - - // Maximum number of "page bits" to show - if(!$mybb->settings['maxmultipagelinks']) - { - $mybb->settings['maxmultipagelinks'] = 5; - } - - $max_links = $mybb->settings['maxmultipagelinks']; - - $from = $page-floor($mybb->settings['maxmultipagelinks']/2); - $to = $page+floor($mybb->settings['maxmultipagelinks']/2); - - if($from <= 0) - { - $from = 1; - $to = $from+$max_links-1; - } - - if($to > $pages) - { - $to = $pages; - $from = $pages-$max_links+1; - if($from <= 0) - { - $from = 1; - } - } - - if($to == 0) - { - $to = $pages; - } - - if($from > 2) - { - $first = fetch_page_url($url, 1); - $pagination .= "page} 1\" class=\"pagination_first\">1 ... "; - } - - for($i = $from; $i <= $to; ++$i) - { - $page_url = fetch_page_url($url, $i); - if($page == $i) - { - $pagination .= "{$i} \n"; - } - else - { - $pagination .= "page} {$i}\">{$i} \n"; - } - } - - if($to < $pages) - { - $last = fetch_page_url($url, $pages); - $pagination .= "... page} {$pages}\" class=\"pagination_last\">{$pages}"; - } - - if($page < $pages) - { - $next = $page+1; - $next_page = fetch_page_url($url, $next); - $pagination .= " {$lang->next} »\n"; - } - $pagination .= "
\n"; - return $pagination; -} - -/** - * Builds a CSV parent list for a particular forum. - * - * @param int $fid The forum ID - * @param string $navsep Optional separator - defaults to comma for CSV list - * @return string The built parent list - */ -function make_parent_list($fid, $navsep=",") -{ - global $pforumcache, $db; - - if(!$pforumcache) - { - $query = $db->simple_select("forums", "name, fid, pid", "", array("order_by" => "disporder, pid")); - while($forum = $db->fetch_array($query)) - { - $pforumcache[$forum['fid']][$forum['pid']] = $forum; - } - } - - reset($pforumcache); - reset($pforumcache[$fid]); - - foreach($pforumcache[$fid] as $key => $forum) - { - if($fid == $forum['fid']) - { - if($pforumcache[$forum['pid']]) - { - $navigation = make_parent_list($forum['pid'], $navsep).$navigation; - } - - if($navigation) - { - $navigation .= $navsep; - } - $navigation .= $forum['fid']; - } - } - return $navigation; -} - -/** - * @param int $fid - */ -function save_quick_perms($fid) -{ - global $db, $inherit, $canview, $canpostthreads, $canpostreplies, $canpostpolls, $canpostattachments, $cache; - - $permission_fields = array(); - - $field_list = $db->show_fields_from("forumpermissions"); - foreach($field_list as $field) - { - if(strpos($field['Field'], 'can') !== false || strpos($field['Field'], 'mod') !== false) - { - $permission_fields[$field['Field']] = 1; - } - } - - // "Can Only View Own Threads" and "Can Only Reply Own Threads" permissions are forum permission only options - $usergroup_permission_fields = $permission_fields; - unset($usergroup_permission_fields['canonlyviewownthreads']); - unset($usergroup_permission_fields['canonlyreplyownthreads']); - - $query = $db->simple_select("usergroups", "gid"); - while($usergroup = $db->fetch_array($query)) - { - $query2 = $db->simple_select("forumpermissions", $db->escape_string(implode(',', array_keys($permission_fields))), "fid='{$fid}' AND gid='{$usergroup['gid']}'", array('limit' => 1)); - $existing_permissions = $db->fetch_array($query2); - - if(!$existing_permissions) - { - $query2 = $db->simple_select("usergroups", $db->escape_string(implode(',', array_keys($usergroup_permission_fields))), "gid='{$usergroup['gid']}'", array('limit' => 1)); - $existing_permissions = $db->fetch_array($query2); - } - - // Delete existing permissions - $db->delete_query("forumpermissions", "fid='{$fid}' AND gid='{$usergroup['gid']}'"); - - // Only insert the new ones if we're using custom permissions - if($inherit[$usergroup['gid']] != 1) - { - if($canview[$usergroup['gid']] == 1) - { - $pview = 1; - } - else - { - $pview = 0; - } - - if($canpostthreads[$usergroup['gid']] == 1) - { - $pthreads = 1; - } - else - { - $pthreads = 0; - } - - if($canpostreplies[$usergroup['gid']] == 1) - { - $preplies = 1; - } - else - { - $preplies = 0; - } - - if($canpostpolls[$usergroup['gid']] == 1) - { - $ppolls = 1; - } - else - { - $ppolls = 0; - } - - if(!$preplies && !$pthreads) - { - $ppost = 0; - } - else - { - $ppost = 1; - } - - $insertquery = array( - "fid" => (int)$fid, - "gid" => (int)$usergroup['gid'], - "canview" => (int)$pview, - "canpostthreads" => (int)$pthreads, - "canpostreplys" => (int)$preplies, - "canpostpolls" => (int)$ppolls, - ); - - foreach($permission_fields as $field => $value) - { - if(array_key_exists($field, $insertquery)) - { - continue; - } - - $insertquery[$db->escape_string($field)] = (int)$existing_permissions[$field]; - } - - $db->insert_query("forumpermissions", $insertquery); - } - } - $cache->update_forumpermissions(); -} - -/** - * Checks if a particular user has the necessary permissions to access a particular page. - * - * @param array $action Array containing module and action to check for - * @param bool $error - * @return bool - */ -function check_admin_permissions($action, $error = true) -{ - global $mybb, $page, $lang, $modules_dir; - - if(is_super_admin($mybb->user['uid'])) - { - return true; - } - - require_once $modules_dir."/".$action['module']."/module_meta.php"; - if(function_exists($action['module']."_admin_permissions")) - { - $func = $action['module']."_admin_permissions"; - $permissions = $func(); - if($permissions['permissions'][$action['action']] && $mybb->admin['permissions'][$action['module']][$action['action']] != 1) - { - if($error) - { - $page->output_header($lang->access_denied); - $page->add_breadcrumb_item($lang->access_denied, "index.php?module=home-index"); - $page->output_error("{$lang->access_denied}
  • {$lang->access_denied_desc}
"); - $page->output_footer(); - exit; - } - else - { - return false; - } - } - } - - return true; -} - -/** - * Fetches the list of administrator permissions for a particular user or group - * - * @param int $get_uid The user ID to fetch permissions for - * @param int $get_gid The (optional) group ID to fetch permissions for - * @return array Array of permissions for specified user or group - */ -function get_admin_permissions($get_uid=0, $get_gid=0) -{ - global $db, $mybb; - - // Set UID and GID if none - $uid = $get_uid; - $gid = $get_gid; - - $gid_array = array(); - - if($uid === 0) - { - $uid = $mybb->user['uid']; - } - - if(!$gid) - { - // Prepare user's groups since the group isn't specified - $gid_array[] = (-1) * (int)$mybb->user['usergroup']; - - if($mybb->user['additionalgroups']) - { - $additional_groups = explode(',', $mybb->user['additionalgroups']); - - if(!empty($additional_groups)) - { - // Make sure gids are negative - foreach($additional_groups as $g) - { - $gid_array[] = (-1) * abs($g); - } - } - } - } - else - { - // Group is specified - // Make sure gid is negative - $gid_array[] = (-1) * abs($gid); - } - - // What are we trying to find? - if($get_gid && !$get_uid) - { - // A group only - - $options = array( - "order_by" => "uid", - "order_dir" => "ASC", - "limit" => "1" - ); - $query = $db->simple_select("adminoptions", "permissions", "(uid='-{$get_gid}' OR uid='0') AND permissions != ''", $options); - return my_unserialize($db->fetch_field($query, "permissions")); - } - else - { - // A user and/or group - - $options = array( - "order_by" => "uid", - "order_dir" => "DESC" - ); - - // Prepare user's groups into SQL format - $group_sql = ''; - foreach($gid_array as $gid) - { - $group_sql .= " OR uid='{$gid}'"; - } - - $perms_group = array(); - $query = $db->simple_select("adminoptions", "permissions, uid", "(uid='{$uid}'{$group_sql}) AND permissions != ''", $options); - while($perm = $db->fetch_array($query)) - { - $perm['permissions'] = my_unserialize($perm['permissions']); - - // Sorting out which permission is which - if($perm['uid'] > 0) - { - $perms_user = $perm; - return $perms_user['permissions']; - } - elseif($perm['uid'] < 0) - { - $perms_group[] = $perm['permissions']; - } - else - { - $perms_def = $perm['permissions']; - } - } - - // Figure out group permissions...ugh. - foreach($perms_group as $gperms) - { - if(!isset($final_group_perms)) - { - // Use this group as the base for admin group permissions - $final_group_perms = $gperms; - continue; - } - - // Loop through each specific permission to find the highest permission - foreach($gperms as $perm_name => $perm_value) - { - if($final_group_perms[$perm_name] != '1' && $perm_value == '1') - { - $final_group_perms[$perm_name] = '1'; - } - } - } - - // Send specific user, or group permissions before default. - // If user's permission are explicitly set, they've already been returned above. - if(isset($final_group_perms)) - { - return $final_group_perms; - } - else - { - return $perms_def; - } - } -} - -/** - * Fetch the iconv/mb encoding for a particular MySQL encoding - * - * @param string $mysql_encoding The MySQL encoding - * @return string The iconv/mb encoding - */ -function fetch_iconv_encoding($mysql_encoding) -{ - $mysql_encoding = explode("_", $mysql_encoding); - switch($mysql_encoding[0]) - { - case "utf8": - return "utf-8"; - break; - case "latin1": - return "iso-8859-1"; - break; - default: - return $mysql_encoding[0]; - } -} - -/** - * Adds/Updates a Page/Tab to the permissions array in the adminoptions table - * - * @param string $tab The name of the tab that is being affected - * @param string $page The name of the page being affected (optional - if not specified, will affect everything under the specified tab) - * @param integer $default Default permissions for the page (1 for allowed - 0 for disallowed - -1 to remove) - */ -function change_admin_permission($tab, $page="", $default=1) -{ - global $db; - - $query = $db->simple_select("adminoptions", "uid, permissions", "permissions != ''"); - while($adminoption = $db->fetch_array($query)) - { - $adminoption['permissions'] = my_unserialize($adminoption['permissions']); - - if($default == -1) - { - if(!empty($page)) - { - unset($adminoption['permissions'][$tab][$page]); - } - else - { - unset($adminoption['permissions'][$tab]); - } - } - else - { - if(!empty($page)) - { - if($adminoption['uid'] == 0) - { - $adminoption['permissions'][$tab][$page] = 0; - } - else - { - $adminoption['permissions'][$tab][$page] = $default; - } - } - else - { - if($adminoption['uid'] == 0) - { - $adminoption['permissions'][$tab]['tab'] = 0; - } - else - { - $adminoption['permissions'][$tab]['tab'] = $default; - } - } - } - - $db->update_query("adminoptions", array('permissions' => $db->escape_string(my_serialize($adminoption['permissions']))), "uid='{$adminoption['uid']}'"); - } -} - -/** - * Checks if we have had too many attempts at logging into the ACP - * - * @param integer $uid The uid of the admin to check - * @param boolean $return_num Return an array of the number of attempts and expiry time? (default false) - * @return mixed Return an array if the second parameter is true, boolean otherwise. - */ -function login_attempt_check_acp($uid=0, $return_num=false) -{ - global $db, $mybb; - - $attempts['loginattempts'] = 0; - - if($uid > 0) - { - $query = $db->simple_select("adminoptions", "loginattempts, loginlockoutexpiry", "uid='".(int)$uid."'", 1); - $attempts = $db->fetch_array($query); - } - - if($attempts['loginattempts'] <= 0) - { - return false; - } - - if($mybb->settings['maxloginattempts'] > 0 && $attempts['loginattempts'] >= $mybb->settings['maxloginattempts']) - { - // Has the expiry dateline been set yet? - if($attempts['loginlockoutexpiry'] == 0 && $return_num == false) - { - $db->update_query("adminoptions", array("loginlockoutexpiry" => TIME_NOW+((int)$mybb->settings['loginattemptstimeout']*60)), "uid='".(int)$uid."'"); - } - - // Are we returning the # of login attempts? - if($return_num == true) - { - return $attempts; - } - // Otherwise are we still locked out? - else if($attempts['loginlockoutexpiry'] > TIME_NOW) - { - return true; - } - } - - return false; -} - -/** - * Checks whether the administrator is on a mobile device - * - * @param string $useragent The useragent to be checked - * @return boolean A true/false depending on if the administrator is on a mobile - */ -function is_mobile($useragent) -{ - return preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i", $useragent); -} - -/** - * Checks whether there are any 'security' issues in templates via complex syntax - * - * @param string $template The template to be scanned - * @return boolean A true/false depending on if an issue was detected - */ -function check_template($template) -{ - // Check to see if our database password is in the template - if(preg_match('#\$config\[(([\'|"]database[\'|"])|([^\'"].*?))\]\[(([\'|"](database|hostname|password|table_prefix|username)[\'|"])|([^\'"].*?))\]#i', $template)) - { - return true; - } - - // System calls via backtick - if(preg_match('#\$\s*\{#', $template)) - { - return true; - } - - // Any other malicious acts? - // Courtesy of ZiNgA BuRgA - if(preg_match("~\\{\\$.+?\\}~s", preg_replace('~\\{\\$+[a-zA-Z_][a-zA-Z_0-9]*((?:-\\>|\\:\\:)\\$*[a-zA-Z_][a-zA-Z_0-9]*|\\[\s*\\$*([\'"]?)[a-zA-Z_ 0-9 ]+\\2\\]\s*)*\\}~', '', $template))) - { - return true; - } - - return false; -} - -/** - * Provides a function to entirely delete a user's posts, and find the threads attached to them - * - * @param integer $uid The uid of the user - * @param int $date A UNIX timestamp to delete posts that are older - * @return array An array of threads to delete, threads/forums to recount - */ -function delete_user_posts($uid, $date) -{ - global $db; - $uid = (int)$uid; - - // Build an array of posts to delete - $postcache = array(); - $query = $db->simple_select("posts", "pid", "uid = '".$uid."' AND dateline < '".$date."'"); - while($post = $db->fetch_array($query)) - { - $postcache[] = $post['pid']; - } - - if(!$db->num_rows($query)) - { - return false; - } - elseif(!empty($postcache)) - { - // Let's start deleting posts - $user_posts = implode(",", $postcache); - $query = $db->query(" - SELECT p.pid, p.visible, f.usepostcounts, t.tid AS thread, t.firstpost, t.fid AS forum - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.pid IN ({$user_posts}) - "); - - $post_count = 0; // Collect the post number to deduct from the user's postcount - $thread_list = array(); - $forum_list = array(); - $delete_thread_list = array(); - if(!$db->num_rows($query)) - { - return false; - } - else - { - while($post = $db->fetch_array($query)) - { - if($post['usepostcounts'] != 0 && $post['visible'] != 0) - { - ++$post_count; - } - - if($post['pid'] == $post['firstpost']) - { - $delete_thread_list[] = $post['thread']; - } - - if(!in_array($post['thread'], $thread_list) && !in_array($post['thread'], $delete_thread_list)) - { - $thread_list[] = $post['thread']; // Threads that have been affected by this action, that aren't marked to be deleted - } - if(!in_array($post['forum'], $forum_list)) - { - $forum_list[] = $post['forum']; // Forums that have been affected, too - } - - // Remove the attachments to this post, then delete the post - remove_attachments($post['pid']); - $db->delete_query("posts", "pid = '".$post['pid']."'"); - $db->delete_query("pollvotes", "pid = '".$post['pid']."'"); // Delete pollvotes attached to this post - } - - $db->update_query("users", array("postnum" => "postnum-".$post_count.""), "uid='".$uid."'", 1, true); - - $to_return = array( - 'to_delete' => $delete_thread_list, - 'thread_update' => $thread_list, - 'forum_update' => $forum_list - ); - - return $to_return; - } - } -} - -/** - * Prints a selection JavaScript code for selectable groups/forums fields. - */ -function print_selection_javascript() -{ - static $already_printed = false; - - if($already_printed) - { - return; - } - - $already_printed = true; - - echo ""; -} diff --git a/html/forums/admin/inc/functions_themes.php b/html/forums/admin/inc/functions_themes.php deleted file mode 100644 index ea2a27f..0000000 --- a/html/forums/admin/inc/functions_themes.php +++ /dev/null @@ -1,1602 +0,0 @@ -get_tree(); - - if(!is_array($tree) || !is_array($tree['theme'])) - { - return -1; - } - - $theme = $tree['theme']; - - // Do we have MyBB 1.2 template's we're importing? - $css_120 = ""; - - if(isset($theme['cssbits']) && is_array($theme['cssbits'])) - { - $cssbits = kill_tags($theme['cssbits']); - - foreach($cssbits as $name => $values) - { - $css_120 .= "{$name} {\n"; - foreach($values as $property => $value) - { - if(is_array($value)) - { - $property = str_replace('_', ':', $property); - - $css_120 .= "}\n{$name} {$property} {\n"; - foreach($value as $property2 => $value2) - { - $css_120 .= "\t{$property2}: {$value2}\n"; - } - } - else - { - $css_120 .= "\t{$property}: {$value}\n"; - } - } - $css_120 .= "}\n"; - } - } - - if(isset($theme['themebits']) && is_array($theme['themebits'])) - { - $themebits = kill_tags($theme['themebits']); - - $theme['properties']['tag'] = 'properties'; - - foreach($themebits as $name => $value) - { - if($name == "extracss") - { - $css_120 .= $value; - continue; - } - - $theme['properties'][$name] = $value; - } - } - - if($css_120) - { - $css_120 = upgrade_css_120_to_140($css_120); - $theme['stylesheets']['tag'] = 'stylesheets'; - $theme['stylesheets']['stylesheet'][0]['tag'] = 'stylesheet'; - $theme['stylesheets']['stylesheet'][0]['attributes'] = array('name' => 'global.css', 'version' => $mybb->version_code); - $theme['stylesheets']['stylesheet'][0]['value'] = $css_120; - - unset($theme['cssbits']); - unset($theme['themebits']); - } - - if(is_array($theme['properties'])) - { - foreach($theme['properties'] as $property => $value) - { - if($property == "tag" || $property == "value") - { - continue; - } - - if($property == 'colors' || $property == 'disporder') - { - $data = my_unserialize($value['value']); - - if(!is_array($data)) - { - // Bad data? - continue; - } - - $value['value'] = $data; - } - - $properties[$property] = $value['value']; - } - } - - if(empty($mybb->input['name'])) - { - $name = $theme['attributes']['name']; - } - else - { - $name = $mybb->input['name']; - } - $version = $theme['attributes']['version']; - - $query = $db->simple_select("themes", "tid", "name='".$db->escape_string($name)."'", array("limit" => 1)); - $existingtheme = $db->fetch_array($query); - if(!empty($options['force_name_check']) && $existingtheme['tid']) - { - return -3; - } - else if($existingtheme['tid']) - { - $options['tid'] = $existingtheme['tid']; - } - - if($mybb->version_code != $version && $options['version_compat'] != 1) - { - return -2; - } - - // Do we have any templates to insert? - if(!empty($theme['templates']['template']) && empty($options['no_templates'])) - { - if($options['templateset']) - { - $sid = $options['templateset']; - } - else - { - $sid = $db->insert_query("templatesets", array('title' => $db->escape_string($name)." Templates")); - } - - $templates = $theme['templates']['template']; - if(is_array($templates)) - { - // Theme only has one custom template - if(array_key_exists("attributes", $templates)) - { - $templates = array($templates); - } - } - - $security_check = false; - $templatecache = array(); - foreach($templates as $template) - { - if(check_template($template['value'])) - { - $security_check = true; - break; - } - - $templatecache[] = array( - "title" => $db->escape_string($template['attributes']['name']), - "template" => $db->escape_string($template['value']), - "sid" => $db->escape_string($sid), - "version" => $db->escape_string($template['attributes']['version']), - "dateline" => TIME_NOW - ); - } - - if($security_check == true) - { - return -4; - } - - foreach($templatecache as $template) - { - // PostgreSQL causes apache to stop sending content sometimes and - // causes the page to stop loading during many queries all at one time - if($db->engine == "pgsql") - { - echo " "; - flush(); - } - - $db->insert_query("templates", $template); - } - - $properties['templateset'] = $sid; - } - - // Not overriding an existing theme - if(empty($options['tid'])) - { - // Insert the theme - if(!isset($options['parent'])) - { - $options['parent'] = 0; - } - $theme_id = build_new_theme($name, $properties, $options['parent']); - } - // Overriding an existing - delete refs. - else - { - $db->delete_query("themestylesheets", "tid='{$options['tid']}'"); - $db->update_query("themes", array("properties" => $db->escape_string(my_serialize($properties))), "tid='{$options['tid']}'"); - $theme_id = $options['tid']; - } - - // If we have any stylesheets, process them - if(!empty($theme['stylesheets']['stylesheet']) && empty($options['no_stylesheets'])) - { - // Are we dealing with a single stylesheet? - if(isset($theme['stylesheets']['stylesheet']['tag'])) - { - // Trick the system into thinking we have a good array =P - $theme['stylesheets']['stylesheet'] = array($theme['stylesheets']['stylesheet']); - } - - // Retrieve a list of inherited stylesheets - $query = $db->simple_select("themes", "stylesheets", "tid = '{$theme_id}'"); - if($db->num_rows($query)) - { - $inherited_stylesheets = my_unserialize($db->fetch_field($query, "stylesheets")); - - if(is_array($inherited_stylesheets['inherited'])) - { - $loop = 1; - foreach($inherited_stylesheets['inherited'] as $action => $stylesheets) - { - foreach($stylesheets as $filename => $stylesheet) - { - if($properties['disporder'][basename($filename)]) - { - continue; - } - - $properties['disporder'][basename($filename)] = $loop; - ++$loop; - } - } - } - } - - $loop = 1; - foreach($theme['stylesheets']['stylesheet'] as $stylesheet) - { - if(substr($stylesheet['attributes']['name'], -4) != ".css") - { - continue; - } - - if(empty($stylesheet['attributes']['lastmodified'])) - { - $stylesheet['attributes']['lastmodified'] = TIME_NOW; - } - - if(empty($stylesheet['attributes']['disporder'])) - { - $stylesheet['attributes']['disporder'] = $loop; - } - - if(empty($stylesheet['attributes']['attachedto'])) - { - $stylesheet['attributes']['attachedto'] = ''; - } - - $properties['disporder'][$stylesheet['attributes']['name']] = $stylesheet['attributes']['disporder']; - - $new_stylesheet = array( - "name" => $db->escape_string($stylesheet['attributes']['name']), - "tid" => $theme_id, - "attachedto" => $db->escape_string($stylesheet['attributes']['attachedto']), - "stylesheet" => $db->escape_string($stylesheet['value']), - "lastmodified" => (int)$stylesheet['attributes']['lastmodified'], - "cachefile" => $db->escape_string($stylesheet['attributes']['name']) - ); - $sid = $db->insert_query("themestylesheets", $new_stylesheet); - $css_url = "css.php?stylesheet={$sid}"; - $cached = cache_stylesheet($theme_id, $stylesheet['attributes']['name'], $stylesheet['value']); - if($cached) - { - $css_url = $cached; - } - - $attachedto = $stylesheet['attributes']['attachedto']; - if(!$attachedto) - { - $attachedto = "global"; - } - - // private.php?compose,folders|usercp.php,global|global - $attachedto = explode("|", $attachedto); - foreach($attachedto as $attached_file) - { - $attached_actions = explode(",", $attached_file); - $attached_file = array_shift($attached_actions); - if(count($attached_actions) == 0) - { - $attached_actions = array("global"); - } - - foreach($attached_actions as $action) - { - $theme_stylesheets[$attached_file][$action][] = $css_url; - } - } - - ++$loop; - } - // Now we have our list of built stylesheets, save them - $updated_theme = array( - "stylesheets" => $db->escape_string(my_serialize($theme_stylesheets)) - ); - - if(is_array($properties['disporder'])) - { - asort($properties['disporder'], SORT_NUMERIC); - - // Because inherited stylesheets can mess this up - $loop = 1; - $orders = array(); - foreach($properties['disporder'] as $filename => $order) - { - $orders[$filename] = $loop; - ++$loop; - } - - $properties['disporder'] = $orders; - $updated_theme['properties'] = $db->escape_string(my_serialize($properties)); - } - - $db->update_query("themes", $updated_theme, "tid='{$theme_id}'"); - } - - update_theme_stylesheet_list($theme_id); - - // And done? - return $theme_id; -} - -/** - * Parse theme variables in a specific string. - * - * @param string $string The string to parse variables for - * @param array $variables Array of variables - * @return string Parsed string with variables replaced - */ -function parse_theme_variables($string, $variables=array()) -{ - $find = array(); - $replace = array(); - foreach(array_keys($variables) as $variable) - { - $find[] = "{{$variable}}"; - $replace[] = $variables[$variable]; - } - return str_replace($find, $replace, $string); -} - -/** - * Caches a stylesheet to the file system. - * - * @param string $tid The theme ID this stylesheet belongs to. - * @param string $filename The name of the stylesheet. - * @param string $stylesheet The contents of the stylesheet. - * - * @return string The cache file path. - */ -function cache_stylesheet($tid, $filename, $stylesheet) -{ - global $mybb; - - $filename = basename($filename); - $tid = (int) $tid; - $theme_directory = "cache/themes/theme{$tid}"; - - // If we're in safe mode save to the main theme folder by default - if($mybb->safemode) - { - $theme_directory = "cache/themes"; - $filename = $tid."_".$filename; - } - // Does our theme directory exist? Try and create it. - elseif(!is_dir(MYBB_ROOT . $theme_directory)) - { - if(!@mkdir(MYBB_ROOT . $theme_directory)) - { - $theme_directory = "cache/themes"; - $filename = $tid."_".$filename; - } - else - { - // Add in empty index.html! - $fp = @fopen(MYBB_ROOT . $theme_directory."/index.html", "w"); - @fwrite($fp, ""); - @fclose($fp); - - } - } - - $theme_vars = array( - "theme" => $theme_directory - ); - $stylesheet = parse_theme_variables($stylesheet, $theme_vars); - $stylesheet = preg_replace_callback("#url\((\"|'|)(.*)\\1\)#", create_function('$matches', 'return fix_css_urls($matches[2]);'), $stylesheet); - - $fp = @fopen(MYBB_ROOT . "{$theme_directory}/{$filename}", "wb"); - if(!$fp) - { - return false; - } - - @fwrite($fp, $stylesheet); - @fclose($fp); - - $stylesheet_min = minify_stylesheet($stylesheet); - $filename_min = str_replace('.css', '.min.css', $filename); - $fp_min = @fopen(MYBB_ROOT . "{$theme_directory}/{$filename_min}", "wb"); - if(!$fp_min) - { - return false; - } - @fwrite($fp_min, $stylesheet_min); - @fclose($fp_min); - - copy_file_to_cdn(MYBB_ROOT . "{$theme_directory}/{$filename}"); - copy_file_to_cdn(MYBB_ROOT . "{$theme_directory}/{$filename_min}"); - - return "{$theme_directory}/{$filename}"; -} - -/** - * Minify a stylesheet to remove comments, linebreaks, whitespace, - * unnecessary semicolons, and prefers #rgb over #rrggbb. - * - * @param $stylesheet string The stylesheet in it's untouched form. - * @return string The minified stylesheet - */ -function minify_stylesheet($stylesheet) -{ - // Remove comments. - $stylesheet = preg_replace('@/\*.*?\*/@s', '', $stylesheet); - // Remove whitespace around symbols. - $stylesheet = preg_replace('@\s*([{}:;,])\s*@', '\1', $stylesheet); - // Remove unnecessary semicolons. - $stylesheet = preg_replace('@;}@', '}', $stylesheet); - // Replace #rrggbb with #rgb when possible. - $stylesheet = preg_replace('@#([a-f0-9])\1([a-f0-9])\2([a-f0-9])\3@i','#\1\2\3',$stylesheet); - $stylesheet = trim($stylesheet); - return $stylesheet; -} - -/** - * @param array $stylesheet - * - * @return bool - */ -function resync_stylesheet($stylesheet) -{ - global $db; - - // Try and fix any missing cache file names - if(!$stylesheet['cachefile'] && $stylesheet['name']) - { - $stylesheet['cachefile'] = $stylesheet['name']; - $db->update_query("themestylesheets", array('cachefile' => $db->escape_string($stylesheet['name'])), "sid='{$stylesheet['sid']}'"); - } - - // Still don't have the cache file name or is it not a flat file? Return false - if(!$stylesheet['cachefile'] || strpos($stylesheet['cachefile'], 'css.php') !== false) - { - return false; - } - - if(!file_exists(MYBB_ROOT."cache/themes/theme{$stylesheet['tid']}/{$stylesheet['name']}") && !file_exists(MYBB_ROOT."cache/themes/{$stylesheet['tid']}_{$stylesheet['name']}")) - { - if(cache_stylesheet($stylesheet['tid'], $stylesheet['cachefile'], $stylesheet['stylesheet']) !== false) - { - $db->update_query("themestylesheets", array('cachefile' => $db->escape_string($stylesheet['name'])), "sid='{$stylesheet['sid']}'"); - - update_theme_stylesheet_list($stylesheet['tid']); - - if($stylesheet['sid'] != 1) - { - $db->update_query("themestylesheets", array('lastmodified' => TIME_NOW), "sid='{$stylesheet['sid']}'"); - } - } - - return true; - } - - return false; -} - -/** - * @param string $url - * - * @return string - */ -function fix_css_urls($url) -{ - if(!preg_match("#^([a-z0-9]+\:|/)#i", $url) && strpos($url, "../../../") === false) - { - return "url(../../../{$url})"; - } - else - { - return "url({$url})"; - } -} - -/** - * @param string $url - * - * @return string - */ -function unfix_css_urls($url) -{ - return str_replace("../../../", "", $url); -} - -/** - * Build a theme based on the specified parameters. - * - * @param string $name The name of the theme - * @param array $properties Array of theme properties (if blank, inherits from parent) - * @param int $parent The parent ID for this theme (defaults to Master) - * @return int The new theme ID - */ -function build_new_theme($name, $properties=null, $parent=1) -{ - global $db; - - $new_theme = array( - "name" => $db->escape_string($name), - "pid" => (int)$parent, - "def" => 0, - "allowedgroups" => "all", - "properties" => "", - "stylesheets" => "" - ); - $tid = $db->insert_query("themes", $new_theme); - - $inherited_properties = false; - $stylesheets = array(); - if($parent > 0) - { - $query = $db->simple_select("themes", "*", "tid='".(int)$parent."'"); - $parent_theme = $db->fetch_array($query); - if(count($properties) == 0 || !is_array($properties)) - { - $parent_properties = my_unserialize($parent_theme['properties']); - if(!empty($parent_properties)) - { - foreach($parent_properties as $property => $value) - { - if($property == "inherited") - { - continue; - } - - $properties[$property] = $value; - if(!empty($parent_properties['inherited'][$property])) - { - $properties['inherited'][$property] = $parent_properties['inherited'][$property]; - } - else - { - $properties['inherited'][$property] = $parent; - } - } - $inherited_properties = true; - } - } - - $parent_stylesheets = my_unserialize($parent_theme['stylesheets']); - if(!empty($parent_stylesheets)) - { - foreach($parent_stylesheets as $location => $value) - { - if($location == "inherited") - { - continue; - } - - foreach($value as $action => $sheets) - { - foreach($sheets as $stylesheet) - { - $stylesheets[$location][$action][] = $stylesheet; - $inherited_check = "{$location}_{$action}"; - if(!empty($parent_stylesheets['inherited'][$inherited_check][$stylesheet])) - { - $stylesheets['inherited'][$inherited_check][$stylesheet] = $parent_stylesheets['inherited'][$inherited_check][$stylesheet]; - } - else - { - $stylesheets['inherited'][$inherited_check][$stylesheet] = $parent; - } - } - } - } - } - } - - if(!$inherited_properties) - { - $theme_vars = array( - "theme" => "cache/themes/theme{$tid}" - ); - $properties['logo'] = parse_theme_variables($properties['logo'], $theme_vars); - } - if(!empty($stylesheets)) - { - $updated_theme['stylesheets'] = $db->escape_string(my_serialize($stylesheets)); - } - $updated_theme['properties'] = $db->escape_string(my_serialize($properties)); - - if(count($updated_theme) > 0) - { - $db->update_query("themes", $updated_theme, "tid='{$tid}'"); - } - - return $tid; -} - -/** - * Generates an array from an incoming CSS file. - * - * @param string $css The incoming CSS - * @return array Parsed CSS file as array, false on failure - */ -function css_to_array($css) -{ - // Normalise line breaks - $css = str_replace(array("\r\n", "\n", "\r"), "\n", $css); - - /** - * Play with the css a little - just to ensure we can parse it - * - * This essentially adds line breaks before and after each } not inside a string - * so it's parsed correctly below - */ - $stripped_css = preg_replace('#(?\*\.\#\,\s\(\)\|~|@\^]+)(\s*)\{(.*?)\}\n#msi', $stripped_css, $matches, PREG_PATTERN_ORDER); - $total = count($matches[1]); - - $parsed_css = array(); - - for($i=0; $i < $total; $i++) - { - $name = $description = ''; - $class_name = $matches[3][$i]; - $class_name = trim($class_name); - $comments = $matches[1][$i]; - preg_match_all("#Name:(.*)#i", $comments, $name_match); - if(isset($name_match[count($name_match)-1][0])) - { - $name = trim($name_match[count($name_match)-1][0]); - } - preg_match_all("#Description:(.*)#i", $comments, $description_match); - if(isset($description_match[count($description_match)-1][0])) - { - $description = trim($description_match[count($description_match)-1][0]); - } - $class_id = md5($class_name); - if(isset($already_parsed[$class_id])) - { - $already_parsed[$class_id]++; - $class_id .= "_".$already_parsed[$class_id]; - } - else - { - $already_parsed[$class_id] = 1; - } - $values = trim($matches[5][$i]); - $values = preg_replace("#/\*(.*?)\*/#s", "", $values); - $parsed_css[$class_id] = array("class_name" => $class_name, "name" => $name, "description" => $description, "values" => $values); - } - - return $parsed_css; -} - -/** - * @param array|string $css - * @param int $selected_item - * - * @return string - */ -function get_selectors_as_options($css, $selected_item=null) -{ - $select = ""; - - if(!is_array($css)) - { - $css = css_to_array($css); - } - - $selected = false; - - if(is_array($css)) - { - uasort($css, "css_selectors_sort_cmp"); - - foreach($css as $id => $css_array) - { - if(!$css_array['name']) - { - $css_array['name'] = $css_array['class_name']; - } - - if($selected_item == $id || (!$selected_item && !$selected)) - { - $select .= "\n"; - $selected = true; - } - else - { - $select .= "\n"; - } - } - } - return $select; -} - -/** - * @param array $a - * @param array $b - * - * @return int - */ -function css_selectors_sort_cmp($a, $b) -{ - if(!$a['name']) - { - $a['name'] = $a['class_name']; - } - - if(!$b['name']) - { - $b['name'] = $b['class_name']; - } - return strcmp($a['name'], $b['name']); -} - -/** - * @param array|string $css - * @param string $id - * - * @return array|bool - */ -function get_css_properties($css, $id) -{ - if(!is_array($css)) - { - $css = css_to_array($css); - } - - if(!isset($css[$id])) - { - return false; - } - return parse_css_properties($css[$id]['values']); -} - -/** - * Parses CSS supported properties and returns them as an array. - * - * @param string $values Value of CSS properties from within class or selector - * @return array Array of CSS properties - */ -function parse_css_properties($values) -{ - $css_bits = array(); - - if(!$values) - { - return null; - } - - $values = explode(";", $values); - foreach($values as $value) - { - $value = trim($value); - if(!$value) continue; - list($property, $css_value) = explode(":", $value, 2); - $property = trim($property); - switch(strtolower($property)) - { - case "background": - case "color": - case "width": - case "font-family": - case "font-size": - case "font-weight": - case "font-style": - case "text-decoration": - $css_bits[$property] = trim($css_value); - break; - default: - $css_bits['extra'] .= "{$property}: ".trim($css_value).";\n"; - - } - } - return $css_bits; -} - -/** - * Inserts an incoming string of CSS in to an already defined document. If the class ID is not found, the CSS is appended to the file. - * - * @param string $new_css CSS we wish to insert at this location. - * @param string $selector The selector for this piece of CSS. - * @param string $css The existing CSS if we have any. - * @param string $class_id (Optional) The optional friendly class id value just incase the CSS is not found in the file. - * - * @return string The altered CSS. - */ -function insert_into_css($new_css, $selector="", $css="", $class_id="") -{ - $new_css = str_replace(array("\r\n", "\n", "\r"), "\n", $new_css); - - $generated_css = ''; - - // Build the new CSS properties list - $new_css = explode("\n", $new_css); - foreach($new_css as $css_line) - { - $generated_css .= "\t".trim($css_line)."\n"; - } - - $parsed_css = array(); - - // Parse out the CSS - if($css) - { - $parsed_css = css_to_array($css); - } - - if(!$class_id) - { - $class_id = $parsed_css[$selector]['class_name']; - } - - // The specified class ID cannot be found, add CSS to end of file - if(!$css || !$parsed_css[$selector]) - { - return $css."{$class_id}\n{\n{$generated_css}\n}\n\n"; - } - // Valid CSS, swap out old, swap in new - else - { - $css = str_replace(array("\r\n", "\n", "\r"), "\n", $css); - $css = preg_replace('#(?\*\.\#\,\s\(\)\|~\^]+)(\s*)\{(\n*)#isu", "\n$1 {\n", $css); - $css = preg_replace("#\s{1,}\{#", " {", $css); - $existing_block = $parsed_css[$selector]; - - $break = strrpos($selector, "_"); - $actual_occurance = 0; - if($break !== false) - { - $actual_occurance = (int)substr($selector, ($break+1)); - } - - if(!$actual_occurance) - { - $actual_occurance = 1; - } - - $occurance = 1; - $pos = 0; - do - { - $pos = strpos($css, "\n".$existing_block['class_name']." {", $pos); - if($pos === false) - { - break; - } - if($occurance == $actual_occurance) - { - // This is the part we want to replace, now we need to fetch the opening & closing braces - $opening = strpos($css, "{", $pos); - $closing = strpos($css, "}", $pos); - $css = substr_replace($css, "\n".$generated_css."\n", $opening+1, $closing-$opening-1); - break; - } - ++$occurance; - ++$pos; - } while($occurance <= $actual_occurance); - } - $css = preg_replace("#{\n*#s", "{\n", $css); - $css = preg_replace("#\s*\}\s*#", "\n}\n\n", $css); - return $css; -} - -/** - * @param array $stylesheet - * @param int $tid - * - * @return bool|int - */ -function copy_stylesheet_to_theme($stylesheet, $tid) -{ - global $db; - - $stylesheet['tid'] = $tid; - unset($stylesheet['sid']); - - $new_stylesheet = array(); - foreach($stylesheet as $key => $value) - { - if(!is_numeric($key)) - { - $new_stylesheet[$db->escape_string($key)] = $db->escape_string($value); - } - } - - $sid = $db->insert_query("themestylesheets", $new_stylesheet); - - return $sid; -} - -/** - * @param int $tid - * @param bool|array $theme - * @param bool $update_disporders - * - * @return bool - */ -function update_theme_stylesheet_list($tid, $theme = false, $update_disporders = true) -{ - global $mybb, $db, $cache, $plugins; - - $stylesheets = array(); - - $child_list = make_child_theme_list($tid); - $parent_list = make_parent_theme_list($tid); - - if(!is_array($parent_list)) - { - return false; - } - - $tid_list = implode(',', $parent_list); - - // Get our list of stylesheets - $query = $db->simple_select("themestylesheets", "*", "tid IN ({$tid_list})", array('order_by' => 'tid', 'order_dir' => 'desc')); - while($stylesheet = $db->fetch_array($query)) - { - if(empty($stylesheets[$stylesheet['name']])) - { - if($stylesheet['tid'] != $tid) - { - $stylesheet['inherited'] = $stylesheet['tid']; - } - - $stylesheets[$stylesheet['name']] = $stylesheet; - } - } - - $theme_stylesheets = array(); - - foreach($stylesheets as $name => $stylesheet) - { - $sid = $stylesheet['sid']; - $css_url = "css.php?stylesheet={$sid}"; - - foreach($parent_list as $theme_id) - { - if($mybb->settings['usecdn'] && !empty($mybb->settings['cdnpath'])) - { - $cdnpath = rtrim($mybb->settings['cdnpath'], '/\\').'/'; - if(file_exists($cdnpath."cache/themes/theme{$theme_id}/{$stylesheet['name']}") && filemtime( - $cdnpath."cache/themes/theme{$theme_id}/{$stylesheet['name']}" - ) >= $stylesheet['lastmodified'] - ) - { - $css_url = "cache/themes/theme{$theme_id}/{$stylesheet['name']}"; - break; - } - } - else - { - if(file_exists(MYBB_ROOT."cache/themes/theme{$theme_id}/{$stylesheet['name']}") && filemtime( - MYBB_ROOT."cache/themes/theme{$theme_id}/{$stylesheet['name']}" - ) >= $stylesheet['lastmodified'] - ) - { - $css_url = "cache/themes/theme{$theme_id}/{$stylesheet['name']}"; - break; - } - } - } - - if(is_object($plugins)) - { - $plugins->run_hooks('update_theme_stylesheet_list_set_css_url', $css_url); - } - - $attachedto = $stylesheet['attachedto']; - if(!$attachedto) - { - $attachedto = "global"; - } - // private.php?compose,folders|usercp.php,global|global - $attachedto = explode("|", $attachedto); - foreach($attachedto as $attached_file) - { - $attached_actions = array(); - if(strpos($attached_file, '?') !== false) - { - $attached_file = explode('?', $attached_file); - $attached_actions = explode(",", $attached_file[1]); - $attached_file = $attached_file[0]; - } - - if(count($attached_actions) == 0) - { - $attached_actions = array("global"); - } - - foreach($attached_actions as $action) - { - $theme_stylesheets[$attached_file][$action][] = $css_url; - - if(!empty($stylesheet['inherited'])) - { - $theme_stylesheets['inherited']["{$attached_file}_{$action}"][$css_url] = $stylesheet['inherited']; - } - } - } - } - - // Now we have our list of built stylesheets, save them - $updated_theme = array( - "stylesheets" => $db->escape_string(my_serialize($theme_stylesheets)) - ); - - // Do we have a theme present? If so, update the stylesheet display orders - if($update_disporders) - { - if(!is_array($theme) || !$theme) - { - $theme_cache = cache_themes(); - $theme = $theme_cache[$tid]; - } - - $orders = $orphaned_stylesheets = array(); - $properties = $theme['properties']; - - if(!is_array($properties)) - { - $properties = my_unserialize($theme['properties']); - } - - $max_disporder = 0; - - foreach($stylesheets as $stylesheet) - { - if(!isset($properties['disporder'][$stylesheet['name']])) - { - $orphaned_stylesheets[] = $stylesheet['name']; - continue; - } - - if($properties['disporder'][$stylesheet['name']] > $max_disporder) - { - $max_disporder = $properties['disporder'][$stylesheet['name']]; - } - - $orders[$stylesheet['name']] = $properties['disporder'][$stylesheet['name']]; - } - - if(!empty($orphaned_stylesheets)) - { - $loop = $max_disporder + 1; - $max_disporder = $loop; - foreach($orphaned_stylesheets as $stylesheet) - { - $orders[$stylesheet] = $loop; - ++$loop; - } - } - - asort($orders); - $properties['disporder'] = $orders; - $updated_theme['properties'] = $db->escape_string(my_serialize($properties)); - } - - $db->update_query("themes", $updated_theme, "tid = '{$tid}'"); - - // Do we have any children themes that need updating too? - if(count($child_list) > 0) - { - foreach($child_list as $id) - { - update_theme_stylesheet_list($id, false, $update_disporders); - } - } - - $cache->update_default_theme(); - - return true; -} - -/** - * @param int $tid - * - * @return array|bool - */ -function make_parent_theme_list($tid) -{ - static $themes_by_parent; - - $themes = array(); - if(!is_array($themes_by_parent)) - { - $theme_cache = cache_themes(); - foreach($theme_cache as $key => $theme) - { - if($key == "default") - { - continue; - } - - $themes_by_parent[$theme['tid']][$theme['pid']] = $theme; - } - } - - if(!isset($themes_by_parent[$tid]) || !is_array($themes_by_parent[$tid])) - { - return false; - } - - reset($themes_by_parent); - reset($themes_by_parent[$tid]); - - $themes = array(); - - foreach($themes_by_parent[$tid] as $key => $theme) - { - $themes[] = $theme['tid']; - $parents = make_parent_theme_list($theme['pid']); - - if(is_array($parents)) - { - $themes = array_merge($themes, $parents); - } - } - - return $themes; -} - -/** - * @param int $tid - * - * @return array|null - */ -function make_child_theme_list($tid) -{ - static $themes_by_child; - - $themes = array(); - if(!is_array($themes_by_child)) - { - $theme_cache = cache_themes(); - foreach($theme_cache as $key => $theme) - { - if($key == "default") - { - continue; - } - - $themes_by_child[$theme['pid']][$theme['tid']] = $theme; - } - } - - if(!isset($themes_by_child[$tid]) || !is_array($themes_by_child[$tid])) - { - return null; - } - - $themes = array(); - - foreach($themes_by_child[$tid] as $theme) - { - $themes[] = $theme['tid']; - $children = make_child_theme_list($theme['tid']); - - if(is_array($children)) - { - $themes = array_merge($themes, $children); - } - } - - return $themes; -} - -/** - * @return array - */ -function cache_themes() -{ - global $db, $theme_cache; - - if(empty($theme_cache) || !is_array($theme_cache)) - { - $query = $db->simple_select("themes", "*", "", array('order_by' => "pid, name")); - while($theme = $db->fetch_array($query)) - { - $theme['properties'] = my_unserialize($theme['properties']); - $theme['stylesheets'] = my_unserialize($theme['stylesheets']); - $theme_cache[$theme['tid']] = $theme; - - if($theme['def'] == 1) - { - $theme_cache['default'] = $theme['tid']; - } - } - } - - // Do we have no themes assigned as default? - if(empty($theme_cache['default'])) - { - $theme_cache['default'] = 1; - } - - return $theme_cache; -} - -/** - * @param int $parent - * @param int $depth - */ -function build_theme_list($parent=0, $depth=0) -{ - global $mybb, $db, $table, $lang, $page; // Global $table is bad, but it will have to do for now - static $theme_cache; - - $padding = $depth*20; // Padding - - if(!is_array($theme_cache)) - { - $themes = cache_themes(); - $query = $db->simple_select("users", "style, COUNT(uid) AS users", "", array('group_by' => 'style')); - while($user_themes = $db->fetch_array($query)) - { - if($user_themes['style'] == 0) - { - $user_themes['style'] = $themes['default']; - } - - if($themes[$user_themes['style']]['users'] > 0) - { - $themes[$user_themes['style']]['users'] += (int)$user_themes['users']; - } - else - { - $themes[$user_themes['style']]['users'] = (int)$user_themes['users']; - } - } - - // Restrucure the theme array to something we can "loop-de-loop" with - foreach($themes as $key => $theme) - { - if($key == "default") - { - continue; - } - - $theme_cache[$theme['pid']][$theme['tid']] = $theme; - } - $theme_cache['num_themes'] = count($themes); - unset($themes); - } - - if(!is_array($theme_cache[$parent])) - { - return; - } - - foreach($theme_cache[$parent] as $theme) - { - $popup = new PopupMenu("theme_{$theme['tid']}", $lang->options); - if($theme['tid'] > 1) - { - $popup->add_item($lang->edit_theme, "index.php?module=style-themes&action=edit&tid={$theme['tid']}"); - $theme['name'] = "".htmlspecialchars_uni($theme['name']).""; - - // We must have at least the master and 1 other active theme - if($theme_cache['num_themes'] > 2) - { - $popup->add_item($lang->delete_theme, "index.php?module=style-themes&action=delete&tid={$theme['tid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_theme_deletion}')"); - } - - if($theme['def'] != 1) - { - $popup->add_item($lang->set_as_default, "index.php?module=style-themes&action=set_default&tid={$theme['tid']}&my_post_key={$mybb->post_code}"); - $set_default = "post_code}\">style}/images/icons/make_default.png\" alt=\"{$lang->set_as_default}\" style=\"vertical-align: middle;\" title=\"{$lang->set_as_default}\" />"; - } - else - { - $set_default = "style}/images/icons/default.png\" alt=\"{$lang->default_theme}\" style=\"vertical-align: middle;\" title=\"{$lang->default_theme}\" />"; - } - $popup->add_item($lang->force_on_users, "index.php?module=style-themes&action=force&tid={$theme['tid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_theme_forced}')"); - } - $popup->add_item($lang->export_theme, "index.php?module=style-themes&action=export&tid={$theme['tid']}"); - $popup->add_item($lang->duplicate_theme, "index.php?module=style-themes&action=duplicate&tid={$theme['tid']}"); - $table->construct_cell("
{$set_default}
{$theme['name']}
"); - $table->construct_cell(my_number_format($theme['users']), array("class" => "align_center")); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - $table->construct_row(); - - // Fetch & build any child themes - build_theme_list($theme['tid'], ++$depth); - } -} - -/** - * returns an array which can be sent to generate_select_box() - * - * @param int $ignoretid - * @param int $parent - * @param int $depth - * - * @return null|string - */ -function build_theme_array($ignoretid = null, $parent=0, $depth=0) -{ - global $list; - static $theme_cache; - - if(!is_array($theme_cache)) - { - $themes = cache_themes(); - // Restrucure the theme array to something we can "loop-de-loop" with - foreach($themes as $key => $theme) - { - if($key == "default") - { - continue; - } - - $theme_cache[$theme['pid']][$theme['tid']] = $theme; - } - unset($theme); - } - - if(!is_array($theme_cache[$parent]) || $ignoretid === $parent) - { - return null; - } - - foreach($theme_cache[$parent] as $theme) - { - if($ignoretid === $theme['tid']) - { - continue; - } - - $list[$theme['tid']] = str_repeat("--", $depth).$theme['name']; - // Fetch & build any child themes - build_theme_array($ignoretid, $theme['tid'], $depth+1); - } - - if(!$parent) - { - return $list; - } -} - -/** - * @param array $theme - * - * @return array|bool - */ -function fetch_theme_stylesheets($theme) -{ - // Fetch list of all of the stylesheets for this theme - $file_stylesheets = my_unserialize($theme['stylesheets']); - - if(!is_array($file_stylesheets)) - { - return false; - } - - $stylesheets = array(); - $inherited_load = array(); - - // Now we loop through the list of stylesheets for each file - foreach($file_stylesheets as $file => $action_stylesheet) - { - if($file == 'inherited') - { - continue; - } - - foreach($action_stylesheet as $action => $style) - { - foreach($style as $stylesheet2) - { - $stylesheets[$stylesheet2]['applied_to'][$file][] = $action; - if(is_array($file_stylesheets['inherited'][$file."_".$action]) && in_array($stylesheet2, array_keys($file_stylesheets['inherited'][$file."_".$action]))) - { - $stylesheets[$stylesheet2]['inherited'] = $file_stylesheets['inherited'][$file."_".$action]; - foreach($file_stylesheets['inherited'][$file."_".$action] as $value) - { - $inherited_load[] = $value; - } - } - } - } - } - - foreach($stylesheets as $file => $stylesheet2) - { - if(is_array($stylesheet2['inherited'])) - { - foreach($stylesheet2['inherited'] as $inherited_file => $tid) - { - $stylesheet2['inherited'][basename($inherited_file)] = $tid; - unset($stylesheet2['inherited'][$inherited_file]); - } - } - - $stylesheets[basename($file)] = $stylesheet2; - unset($stylesheets[$file]); - } - - return $stylesheets; -} - -/** - * @param string $css - * - * @return string - */ -function upgrade_css_120_to_140($css) -{ - // Update our CSS to the new stuff in 1.4 - $parsed_css = css_to_array($css); - - if(!is_array($parsed_css)) - { - return ""; - } - - foreach($parsed_css as $class_id => $array) - { - $parsed_css[$class_id]['values'] = str_replace('#eea8a1', '#ffdde0', $array['values']); - $parsed_css[$class_id]['values'] = str_replace('font-family: Verdana;', 'font-family: Verdana, Arial, Sans-Serif;', $array['values']); - - switch($array['class_name']) - { - case '.bottommenu': - $parsed_css[$class_id]['values'] = str_replace('padding: 6px;', 'padding: 10px;', $array['values']); - break; - case '.expcolimage': - $parsed_css[$class_id]['values'] .= "\n\tmargin-top: 2px;"; - break; - case '.toolbar_normal': - case '.toolbar_hover': - case '.toolbar_clicked': - case '.pagenav': - case '.pagenavbit': - case '.pagenavbit a': - case '.pagenavcurrent': - case '.quote_header': - case '.quote_body': - case '.code_header': - case '.code_body': - case '.usercpnav': - case '.usercpnav li': - case '.usercpnav .pmfolders': - unset($parsed_css[$class_id]); - break; - default: - } - } - - $to_add = array( - md5('.trow_selected td') => array("class_name" => '.trow_selected td', "values" => 'background: #FFFBD9;'), - md5('blockquote') => array("class_name" => 'blockquote', "values" => "border: 1px solid #ccc;\n\tmargin: 0;\n\tbackground: #fff;\n\tpadding: 4px;"), - md5('blockquote cite') => array("class_name" => 'blockquote cite', "values" => "font-weight: bold;\n\tborder-bottom: 1px solid #ccc;\n\tfont-style: normal;\n\tdisplay: block;\n\tmargin: 4px 0;"), - md5('blockquote cite span') => array("class_name" => 'blockquote cite span', "values" => "float: right;\n\tfont-weight: normal;"), - md5('.codeblock') => array("class_name" => '.codeblock', "values" => "background: #fff;\n\tborder: 1px solid #ccc;\n\tpadding: 4px;"), - md5('.codeblock .title') => array("class_name" => '.codeblock .title', "values" => "border-bottom: 1px solid #ccc;\n\tfont-weight: bold;\n\tmargin: 4px 0;"), - md5('.codeblock code') => array("class_name" => '.codeblock code', "values" => "overflow: auto;\n\theight: auto;\n\tmax-height: 200px;\n\tdisplay: block;\n\tfont-family: Monaco, Consolas, Courier, monospace;\n\tfont-size: 13px;"), - md5('.subject_new') => array("class_name" => '.subject_new', "values" => "font-weight: bold;"), - md5('.highlight') => array("class_name" => '.highlight', "values" => "background: #FFFFCC;\n\tpadding: 3px;"), - md5('.pm_alert') => array("class_name" => '.pm_alert', "values" => "background: #FFF6BF;\n\tborder: 1px solid #FFD324;\n\ttext-align: center;\n\tpadding: 5px 20px;\n\tfont-size: 11px;"), - md5('.red_alert') => array("class_name" => '.red_alert', "values" => "background: #FBE3E4;\n\tborder: 1px solid #A5161A;\n\tcolor: #A5161A;\n\ttext-align: center;\n\tpadding: 5px 20px;\n\tfont-size: 11px;"), - md5('.high_warning') => array("class_name" => '.high_warning', "values" => "color: #CC0000;"), - md5('.moderate_warning') => array("class_name" => '.moderate_warning', "values" => "color: #F3611B;"), - md5('.low_warning') => array("class_name" => '.low_warning', "values" => "color: #AE5700;"), - md5('div.error') => array("class_name" => 'div.error', "values" => "padding: 5px 10px;\n\tborder-top: 2px solid #FFD324;\n\tborder-bottom: 2px solid #FFD324;\n\tbackground: #FFF6BF\n\tfont-size: 12px;"), - md5('.high_warning') => array("class_name" => '.high_warning', "values" => "color: #CC0000;"), - md5('.moderate_warning') => array("class_name" => '.moderate_warning', "values" => "color: #F3611B;"), - md5('.low_warning') => array("class_name" => '.low_warning', "values" => "color: #AE5700;"), - md5('div.error') => array("class_name" => 'div.error', "values" => "padding: 5px 10px;\n\tborder-top: 2px solid #FFD324;\n\tborder-bottom: 2px solid #FFD324;\n\tbackground: #FFF6BF;\n\tfont-size: 12px;"), - md5('div.error p') => array("class_name" => 'div.error p', "values" => "margin: 0;\n\tcolor: #000;\n\tfont-weight: normal;"), - md5('div.error p em') => array("class_name" => 'div.error p em', "values" => "font-style: normal;\n\tfont-weight: bold;\n\tpadding-left: 24px;\n\tdisplay: block;\n\tcolor: #C00;\n\tbackground: url({$mybb->settings['bburl']}/images/error.png) no-repeat 0;"), - md5('div.error.ul') => array("class_name" => 'div.error.ul', "values" => "margin-left: 24px;"), - md5('.online') => array("class_name" => '.online', "values" => "color: #15A018;"), - md5('.offline') => array("class_name" => '.offline', "values" => "color: #C7C7C7;"), - md5('.pagination') => array("class_name" => '.pagination', "values" => "font-size: 11px;\n\tpadding-top: 10px;\n\tmargin-bottom: 5px;"), - md5('.tfoot .pagination, .tcat .pagination') => array("class_name" => '.tfoot .pagination, .tcat .pagination', "values" => "padding-top: 0;"), - md5('.pagination .pages') => array("class_name" => '.pagination .pages', "values" => "font-weight: bold;"), - md5('.pagination .pagination_current, .pagination a') => array("class_name" => '.pagination .pagination_current, .pagination a', "values" => "padding: 2px 6px;\n\tmargin-bottom: 3px;"), - md5('.pagination a') => array("class_name" => '.pagination a', "values" => "border: 1px solid #81A2C4;"), - md5('.pagination .pagination_current') => array("class_name" => '.pagination .pagination_current', "values" => "background: #F5F5F5;\n\tborder: 1px solid #81A2C4;\n\tfont-weight: bold;"), - md5('.pagination a:hover') => array("class_name" => '.pagination a:hover', "values" => "background: #F5F5F5;\n\ttext-decoration: none;"), - md5('.thread_legend, .thread_legend dd') => array("class_name" => '.thread_legend, .thread_legend dd', "values" => "margin: 0;\n\tpadding: 0;"), - md5('.thread_legend dd') => array("class_name" => '.thread_legend dd', "values" => "padding-bottom: 4px;\n\tmargin-right: 15px;"), - md5('.thread_legend img') => array("class_name" => '.thread_legend img', "values" => "margin-right: 4px;\n\tvertical-align: bottom;"), - md5('.forum_legend, .forum_legend dt, .forum_legend dd') => array("class_name" => '.forum_legend, .forum_legend dt, .forum_legend dd', "values" => "margin: 0;\n\tpadding: 0;"), - md5('.forum_legend dd') => array("class_name" => '.forum_legend dd', "values" => "float: left;\n\tmargin-right: 10px;"), - md5('.forum_legend dt') => array("class_name" => '.forum_legend dt', "values" => "margin-right: 10px;\n\tfloat: left;"), - md5('.success_message') => array("class_name" => '.success_message', "values" => "color: #00b200;\n\tfont-weight: bold;\n\tfont-size: 10px;\n\tmargin-bottom: 10px;"), - md5('.error_message') => array("class_name" => '.error_message', "values" => "color: #C00;\n\tfont-weight: bold;\n\tfont-size: 10px;\n\tmargin-bottom: 10px;"), - md5('.post_body') => array("class_name" => '.post_body', "values" => "padding: 5px;"), - md5('.post_content') => array("class_name" => '.post_content', "values" => "padding: 5px 10px;"), - md5('.invalid_field') => array("class_name" => '.invalid_field', "values" => "border: 1px solid #f30;\n\tcolor: #f30;"), - md5('.valid_field') => array("class_name" => '.valid_field', "values" => "border: 1px solid #0c0;"), - md5('.validation_error') => array("class_name" => '.validation_error', "values" => "background: url(images/invalid.png) no-repeat center left;\n\tcolor: #f30;\n\tmargin: 5px 0;\n\tpadding: 5px;\n\tfont-weight: bold;\n\tfont-size: 11px;\n\tpadding-left: 22px;"), - md5('.validation_success') => array("class_name" => '.validation_success', "values" => "background: url(images/valid.png) no-repeat center left;\n\tcolor: #00b200;\n\tmargin: 5px 0;\n\tpadding: 5px;\n\tfont-weight: bold;\n\tfont-size: 11px;\n\tpadding-left: 22px;"), - md5('.validation_loading') => array("class_name" => '.validation_loading', "values" => "background: url(images/spinner.gif) no-repeat center left;\n\tcolor: #555;\n\tmargin: 5px 0;\n\tpadding: 5px;\n\tfont-weight: bold;\n\tfont-size: 11px;\n\tpadding-left: 22px;"), - ); - - $already_parsed = array(); - - foreach($to_add as $class_id => $array) - { - if($already_parsed[$class_id]) - { - $already_parsed[$class_id]++; - $class_id .= "_".$already_parsed[$class_id]; - } - else - { - $already_parsed[$class_id] = 1; - } - - $array['name'] = ""; - $array['description'] = ""; - - $parsed_css[$class_id] = $array; - } - - $theme = array( - 'css' => '', - ); - - $css = ""; - foreach($parsed_css as $class_id => $array) - { - if($array['name'] || $array['description']) - { - $theme['css'] .= "/* "; - if($array['name']) - { - $array['css'] .= "Name: {$array['name']}"; - - if($array['description']) - { - $array['css'] .= "\n"; - } - } - - if($array['description']) - { - $array['css'] .= "Description: {$array['description']}"; - } - - $array['css'] .= " */\n"; - } - - $css .= "{$array['class_name']} {\n\t{$array['values']}\n}\n"; - } - - return $css; -} diff --git a/html/forums/admin/inc/functions_view_manager.php b/html/forums/admin/inc/functions_view_manager.php deleted file mode 100644 index 8ba4c6d..0000000 --- a/html/forums/admin/inc/functions_view_manager.php +++ /dev/null @@ -1,674 +0,0 @@ - $lang->views, - 'link' => "{$base_url}&action=views", - 'description' => $lang->views_desc - ); - - $sub_tabs['create_view'] = array( - 'title' => $lang->create_new_view, - 'link' => "{$base_url}&action=views&do=add", - 'description' => $lang->create_new_view_desc - ); - - $page->add_breadcrumb_item($lang->view_manager, 'index.php?module=user-users&action=views'); - - // Lang strings should be in global lang file - - if($mybb->input['do'] == "set_default") - { - $query = $db->simple_select("adminviews", "vid, uid, visibility", "vid='".$mybb->get_input('vid', MyBB::INPUT_INT)."'"); - $admin_view = $db->fetch_array($query); - - if(!$admin_view['vid'] || $admin_view['visibility'] == 1 && $mybb->user['uid'] != $admin_view['uid']) - { - flash_message($lang->error_invalid_admin_view, 'error'); - admin_redirect($base_url."&action=views"); - } - set_default_view($type, $admin_view['vid']); - flash_message($lang->succuss_view_set_as_default, 'success'); - admin_redirect($base_url."&action=views"); - } - - if($mybb->input['do'] == "add") - { - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_view_title; - } - if($mybb->input['fields_js']) - { - $mybb->input['fields'] = explode(",", $mybb->input['fields_js']); - } - if(count($mybb->input['fields']) <= 0) - { - $errors[] = $lang->error_no_view_fields; - } - - if($mybb->get_input('perpage', MyBB::INPUT_INT) <= 0) - { - $errors[] = $lang->error_invalid_view_perpage; - } - - if(!in_array($mybb->input['sortby'], array_keys($sort_options))) - { - $errors[] = $lang->error_invalid_view_sortby; - } - - if($mybb->input['sortorder'] != "asc" && $mybb->input['sortorder'] != "desc") - { - $errors[] = $lang->error_invalid_view_sortorder; - } - - if($mybb->input['visibility'] == 0) - { - $mybb->input['visibility'] = 2; - } - - if(!$errors) - { - $new_view = array( - "uid" => $mybb->user['uid'], - "title" => $db->escape_string($mybb->input['title']), - "type" => $type, - "visibility" => $mybb->get_input('visibility', MyBB::INPUT_INT), - "fields" => $db->escape_string(my_serialize($mybb->input['fields'])), - "conditions" => $db->escape_string(my_serialize($mybb->input['conditions'])), - "custom_profile_fields" => $db->escape_string(my_serialize($mybb->input['profile_fields'])), - "sortby" => $db->escape_string($mybb->input['sortby']), - "sortorder" => $db->escape_string($mybb->input['sortorder']), - "perpage" => $mybb->get_input('perpage', MyBB::INPUT_INT), - "view_type" => $db->escape_string($mybb->input['view_type']) - ); - - $vid = $db->insert_query("adminviews", $new_view); - - if($mybb->input['isdefault']) - { - set_default_view($type, $vid); - } - flash_message($lang->success_view_created, "success"); - admin_redirect($base_url."&vid={$vid}"); - } - } - else - { - $mybb->input = array_merge($mybb->input, array('perpage' => 20)); - } - - // Write in our JS based field selector - $page->extra_header .= "\n"; - - $page->add_breadcrumb_item($lang->create_new_view); - $page->output_header($lang->create_new_view); - - $form = new Form($base_url."&action=views&do=add", "post"); - - $page->output_nav_tabs($sub_tabs, 'create_view'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer($lang->create_new_view); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - - if($mybb->input['visibility'] == 2) - { - $visibility_public_checked = true; - } - else - { - $visibility_private_checked = true; - } - - $visibility_options = array( - $form->generate_radio_button("visibility", "1", "{$lang->private} - {$lang->private_desc}", array("checked" => $visibility_private_checked)), - $form->generate_radio_button("visibility", "2", "{$lang->public} - {$lang->public_desc}", array("checked" => $visibility_public_checked)) - ); - $form_container->output_row($lang->visibility, "", implode("
", $visibility_options)); - - $form_container->output_row($lang->set_as_default_view, "", $form->generate_yes_no_radio("isdefault", $mybb->input['isdefault'], array('yes' => 1, 'no' => 0))); - - if(count($sort_options) > 0) - { - $sort_directions = array( - "asc" => $lang->ascending, - "desc" => $lang->descending - ); - $form_container->output_row($lang->sort_results_by, "", $form->generate_select_box('sortby', $sort_options, $mybb->input['sortby'], array('id' => 'sortby'))." {$lang->in} ".$form->generate_select_box('sortorder', $sort_directions, $mybb->input['sortorder'], array('id' => 'sortorder')), 'sortby'); - } - - $form_container->output_row($lang->results_per_page, "", $form->generate_numeric_field('perpage', $mybb->input['perpage'], array('id' => 'perpage', 'min' => 1)), 'perpage'); - - if($type == "user") - { - $form_container->output_row($lang->display_results_as, "", $form->generate_radio_button('view_type', 'table', $lang->table, array('checked' => ($mybb->input['view_type'] != "card" ? true : false)))."
".$form->generate_radio_button('view_type', 'card', $lang->business_card, array('checked' => ($mybb->input['view_type'] == "card" ? true : false)))); - } - - $form_container->end(); - - $field_select .= "
\n"; - $field_select .= "
{$lang->enabled}
    \n"; - if(is_array($mybb->input['fields'])) - { - foreach($mybb->input['fields'] as $field) - { - if($fields[$field]) - { - $field_select .= "
  • • {$fields[$field]['title']}
  • "; - $active[$field] = 1; - } - } - } - $field_select .= "
\n"; - $field_select .= "
{$lang->disabled}
    \n"; - foreach($fields as $key => $field) - { - if($active[$key]) - { - continue; - } - $field_select .= "
  • • {$field['title']}
  • "; - } - $field_select .= "
\n"; - $field_select .= $form->generate_hidden_field("fields_js", @implode(",", @array_keys($active)), array('id' => 'fields_js')); - $field_select = str_replace("'", "\\'", $field_select); - $field_select = str_replace("\n", "", $field_select); - - $field_select = "\n"; - - foreach($fields as $key => $field) - { - $field_options[$key] = $field['title']; - } - - $field_select .= "\n"; - - $form_container = new FormContainer($lang->fields_to_show); - $form_container->output_row($lang->fields_to_show_desc, $description, $field_select); - $form_container->end(); - - // Build the search conditions - if(function_exists($conditions_callback)) - { - $conditions_callback($mybb->input, $form); - } - - $buttons[] = $form->generate_submit_button($lang->save_view); - $form->output_submit_wrapper($buttons); - - $form->end(); - $page->output_footer(); - } - else if($mybb->input['do'] == "edit") - { - $query = $db->simple_select("adminviews", "*", "vid='".$mybb->get_input('vid', MyBB::INPUT_INT)."'"); - $admin_view = $db->fetch_array($query); - - // Does the view not exist? - if(!$admin_view['vid'] || $admin_view['visibility'] == 1 && $mybb->user['uid'] != $admin_view['uid']) - { - flash_message($lang->error_invalid_admin_view, 'error'); - admin_redirect($base_url."&action=views"); - } - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_view_title; - } - if($mybb->input['fields_js']) - { - $mybb->input['fields'] = explode(",", $mybb->input['fields_js']); - } - - if(count($mybb->input['fields']) <= 0) - { - $errors[] = $lang->error_no_view_fields; - } - - if($mybb->get_input('perpage', MyBB::INPUT_INT) <= 0) - { - $errors[] = $lang->error_invalid_view_perpage; - } - - if(!in_array($mybb->input['sortby'], array_keys($sort_options))) - { - $errors[] = $lang->error_invalid_view_sortby; - } - - if($mybb->input['sortorder'] != "asc" && $mybb->input['sortorder'] != "desc") - { - $errors[] = $lang->error_invalid_view_sortorder; - } - - if($mybb->input['visibility'] == 0) - { - $mybb->input['visibility'] = 2; - } - - if(!$errors) - { - $updated_view = array( - "title" => $db->escape_string($mybb->input['title']), - "type" => $type, - "visibility" => $mybb->get_input('visibility', MyBB::INPUT_INT), - "fields" => $db->escape_string(my_serialize($mybb->input['fields'])), - "conditions" => $db->escape_string(my_serialize($mybb->input['conditions'])), - "custom_profile_fields" => $db->escape_string(my_serialize($mybb->input['profile_fields'])), - "sortby" => $db->escape_string($mybb->input['sortby']), - "sortorder" => $db->escape_string($mybb->input['sortorder']), - "perpage" => $mybb->get_input('perpage', MyBB::INPUT_INT), - "view_type" => $db->escape_string($mybb->input['view_type']) - ); - $db->update_query("adminviews", $updated_view, "vid='{$admin_view['vid']}'"); - - if($mybb->input['isdefault']) - { - set_default_view($type, $admin_view['vid']); - } - - flash_message($lang->success_view_updated, "success"); - admin_redirect($base_url."&vid={$admin_view['vid']}"); - } - } - - // Write in our JS based field selector - $page->extra_header .= "\n"; - - $page->add_breadcrumb_item($lang->edit_view); - $page->output_header($lang->edit_view); - - $form = new Form($base_url."&action=views&do=edit&vid={$admin_view['vid']}", "post"); - - $sub_tabs = array(); - $sub_tabs['edit_view'] = array( - 'title' => $lang->edit_view, - 'link' => $base_url."&action=views&do=edit&vid={$admin_view['vid']}", - 'description' => $lang->edit_view_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_view'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $admin_view['conditions'] = my_unserialize($admin_view['conditions']); - $admin_view['fields'] = my_unserialize($admin_view['fields']); - $admin_view['profile_fields'] = my_unserialize($admin_view['custom_profile_fields']); - $mybb->input = array_merge($mybb->input, $admin_view); - - $mybb->input['isdefault'] = 0; - $default_view = fetch_default_view($type); - - if($default_view == $admin_view['vid']) - { - $mybb->input['isdefault'] = 1; - } - } - - $form_container = new FormContainer($lang->edit_view); - $form_container->output_row($lang->view." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - - if($mybb->input['visibility'] == 2) - { - $visibility_public_checked = true; - } - else - { - $visibility_private_checked = true; - } - - $visibility_options = array( - $form->generate_radio_button("visibility", "1", "{$lang->private} - {$lang->private_desc}", array("checked" => $visibility_private_checked)), - $form->generate_radio_button("visibility", "2", "{$lang->public} - {$lang->public_desc}", array("checked" => $visibility_public_checked)) - ); - $form_container->output_row($lang->visibility, "", implode("
", $visibility_options)); - - $form_container->output_row($lang->set_as_default_view, "", $form->generate_yes_no_radio("isdefault", $mybb->input['isdefault'], array('yes' => 1, 'no' => 0))); - - if(count($sort_options) > 0) - { - $sort_directions = array( - "asc" => $lang->ascending, - "desc" => $lang->descending - ); - $form_container->output_row($lang->sort_results_by, "", $form->generate_select_box('sortby', $sort_options, $mybb->input['sortby'], array('id' => 'sortby'))." {$lang->in} ".$form->generate_select_box('sortorder', $sort_directions, $mybb->input['sortorder'], array('id' => 'sortorder')), 'sortby'); - } - - $form_container->output_row($lang->results_per_page, "", $form->generate_numeric_field('perpage', $mybb->input['perpage'], array('id' => 'perpage', 'min' => 1)), 'perpage'); - - if($type == "user") - { - $form_container->output_row($lang->display_results_as, "", $form->generate_radio_button('view_type', 'table', $lang->table, array('checked' => ($mybb->input['view_type'] != "card" ? true : false)))."
".$form->generate_radio_button('view_type', 'card', $lang->business_card, array('checked' => ($mybb->input['view_type'] == "card" ? true : false)))); - } - - $form_container->end(); - - $field_select .= "
\n"; - $field_select .= "
{$lang->enabled}
    \n"; - if(is_array($mybb->input['fields'])) - { - foreach($mybb->input['fields'] as $field) - { - if($fields[$field]) - { - $field_select .= "
  • • {$fields[$field]['title']}
  • "; - $active[$field] = 1; - } - } - } - $field_select .= "
\n"; - $field_select .= "
{$lang->disabled}
    \n"; - if(is_array($fields)) - { - foreach($fields as $key => $field) - { - if($active[$key]) - { - continue; - } - $field_select .= "
  • • {$field['title']}
  • "; - } - } - $field_select .= "
\n"; - $field_select .= $form->generate_hidden_field("fields_js", @implode(",", @array_keys($active)), array('id' => 'fields_js')); - $field_select = str_replace("'", "\\'", $field_select); - $field_select = str_replace("\n", "", $field_select); - - $field_select = "\n"; - - foreach($fields as $key => $field) - { - $field_options[$key] = $field['title']; - } - - $field_select .= "\n"; - - $form_container = new FormContainer($lang->fields_to_show); - $form_container->output_row($lang->fields_to_show_desc, $description, $field_select); - $form_container->end(); - - // Build the search conditions - if(function_exists($conditions_callback)) - { - $conditions_callback($mybb->input, $form); - } - - $buttons[] = $form->generate_submit_button($lang->save_view); - $form->output_submit_wrapper($buttons); - - $form->end(); - $page->output_footer(); - } - - else if($mybb->input['do'] == "delete") - { - if($mybb->input['no']) - { - admin_redirect($base_url."&action=views"); - } - - $query = $db->simple_select("adminviews", "COUNT(vid) as views"); - $views = $db->fetch_field($query, "views"); - - if($views == 0) - { - flash_message($lang->error_cannot_delete_view, 'error'); - admin_redirect($base_url."&action=views"); - } - - $vid = $mybb->get_input('vid', MyBB::INPUT_INT); - $query = $db->simple_select("adminviews", "vid, uid, visibility", "vid = '{$vid}'"); - $admin_view = $db->fetch_array($query); - - if($vid == 1 || !$admin_view['vid'] || $admin_view['visibility'] == 1 && $mybb->user['uid'] != $admin_view['uid']) - { - flash_message($lang->error_invalid_view_delete, 'error'); - admin_redirect($base_url."&action=views"); - } - - if($mybb->request_method == "post") - { - $db->delete_query("adminviews", "vid='{$admin_view['vid']}'"); - flash_message($lang->success_view_deleted, 'success'); - admin_redirect($base_url."&action=views"); - } - else - { - $page->output_confirm_action($base_url."&action=views&do=delete&vid={$admin_view['vid']}", $lang->confirm_view_deletion); - } - } - - // Export views - else if($mybb->input['do'] == "export") - { - $xml = "\n"; - $xml = "version_code."\" exported=\"".TIME_NOW."\">\n"; - - if($mybb->input['type']) - { - $type_where = "type='".$db->escape_string($mybb->input['type'])."'"; - } - - $query = $db->simple_select("adminviews", "*", $type_where); - while($admin_view = $db->fetch_array($query)) - { - $fields = my_unserialize($admin_view['fields']); - $conditions = my_unserialize($admin_view['conditions']); - - $admin_view['title'] = str_replace(']]>', ']]]]>', $admin_view['title']); - $admin_view['sortby'] = str_replace(']]>', ']]]]>', $admin_view['sortby']); - $admin_view['sortorder'] = str_replace(']]>', ']]]]>', $admin_view['sortorder']); - $admin_view['view_type'] = str_replace(']]>', ']]]]>', $admin_view['view_type']); - - $xml .= "\t\n"; - $xml .= "\t\t<![CDATA[{$admin_view['title']}]]>\n"; - $xml .= "\t\t\n"; - foreach($fields as $field) - { - $xml .= "\t\t\t\n"; - } - $xml .= "\t\t\n"; - $xml .= "\t\t\n"; - foreach($conditions as $name => $condition) - { - if(!$conditions) continue; - if(is_array($condition)) - { - $condition = my_serialize($condition); - $is_serialized = " is_serialized=\"1\""; - } - $condition = str_replace(']]>', ']]]]>', $condition); - $xml .= "\t\t\t\n"; - } - $xml .= "\t\t\n"; - $xml .= "\t\t\n"; - $xml .= "\t\t\n"; - $xml .= "\t\t\n"; - $xml .= "\t\t\n"; - $xml .= "\t\n"; - } - $xml .= "\n"; - $mybb->settings['bbname'] = urlencode($mybb->settings['bbname']); - header("Content-disposition: filename=".$mybb->settings['bbname']."-views.xml"); - header("Content-Length: ".my_strlen($xml)); - header("Content-type: unknown/unknown"); - header("Pragma: no-cache"); - header("Expires: 0"); - echo $xml; - exit; - } - - // Generate a listing of all current views - else - { - $page->output_header($lang->view_manager); - - $page->output_nav_tabs($sub_tabs, 'views'); - - $table = new Table; - $table->construct_header($lang->view); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - $default_view = fetch_default_view($type); - - $query = $db->simple_select("adminviews", "COUNT(vid) as views"); - $views = $db->fetch_field($query, "views"); - - $query = $db->query(" - SELECT v.*, u.username - FROM ".TABLE_PREFIX."adminviews v - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=v.uid) - WHERE v.visibility='2' OR (v.visibility='1' AND v.uid='{$mybb->user['uid']}') - ORDER BY title - "); - while($view = $db->fetch_array($query)) - { - $created = ""; - if($view['uid'] == 0) - { - $view_type = "default"; - $default_class = "grey"; - } - else if($view['visibility'] == 2) - { - $view_type = "group"; - if($view['username']) - { - $username = htmlspecialchars_uni($view['username']); - $created = "
{$lang->created_by} {$username}"; - } - } - else - { - $view_type = "user"; - } - - $default_add = ''; - if($default_view == $view['vid']) - { - $default_add = " ({$lang->default})"; - } - - $title_string = "view_title_{$view['vid']}"; - - if($lang->$title_string) - { - $view['title'] = $lang->$title_string; - } - - $table->construct_cell("
style}/images/icons/{$view_type}.png\" title=\"".$lang->sprintf($lang->this_is_a_view, $view_type)."\" alt=\"{$view_type}\" />
{$view['title']}{$default_add}{$created}
"); - - $popup = new PopupMenu("view_{$view['vid']}", $lang->options); - $popup->add_item($lang->edit_view, "{$base_url}&action=views&do=edit&vid={$view['vid']}"); - if($view['vid'] != $default_view) - { - $popup->add_item($lang->set_as_default, "{$base_url}&action=views&do=set_default&vid={$view['vid']}"); - } - - if($views > 1 && $view['vid'] != 1) - { - $popup->add_item($lang->delete_view, "{$base_url}&action=views&do=delete&vid={$view['vid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_view_deletion}')"); - } - $controls = $popup->fetch(); - $table->construct_cell($controls, array("class" => "align_center")); - $table->construct_row(); - } - - $table->output($lang->view); - - echo << -
-{$lang->legend} -{$lang->default} {$lang->default_view_desc}
-{$lang->public} {$lang->public_view_desc}
-{$lang->private} {$lang->private_view_desc}
-LEGEND; - $page->output_footer(); - } -} - -function set_default_view($type, $vid) -{ - global $mybb, $db; - - $query = $db->simple_select("adminoptions", "defaultviews", "uid='{$mybb->user['uid']}'"); - $default_views = my_unserialize($db->fetch_field($query, "defaultviews")); - if(!$db->num_rows($query)) - { - $create = true; - } - $default_views[$type] = $vid; - $default_views = my_serialize($default_views); - $updated_admin = array("defaultviews" => $db->escape_string($default_views)); - - if($create == true) - { - $updated_admin['uid'] = $mybb->user['uid']; - $updated_admin['notes'] = ''; - $updated_admin['permissions'] = ''; - $db->insert_query("adminoptions", $updated_admin); - } - else - { - $db->update_query("adminoptions", $updated_admin, "uid='{$mybb->user['uid']}'"); - } -} - -/** - * @param string $type - * - * @return bool|array - */ -function fetch_default_view($type) -{ - global $mybb, $db; - $query = $db->simple_select("adminoptions", "defaultviews", "uid='{$mybb->user['uid']}'"); - $default_views = my_unserialize($db->fetch_field($query, "defaultviews")); - if(!is_array($default_views)) - { - return false; - } - return $default_views[$type]; -} diff --git a/html/forums/admin/inc/index.html b/html/forums/admin/inc/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/inc/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/index.php b/html/forums/admin/index.php deleted file mode 100644 index 41b6a6a..0000000 --- a/html/forums/admin/index.php +++ /dev/null @@ -1,822 +0,0 @@ -settings['cookiepath'] = substr($loc, 0, strrpos($loc, "/{$config['admin_dir']}/"))."/{$config['admin_dir']}/"; - -if(!isset($cp_language)) -{ - if(!file_exists(MYBB_ROOT."inc/languages/".$mybb->settings['cplanguage']."/admin/home_dashboard.lang.php")) - { - $mybb->settings['cplanguage'] = "english"; - } - $lang->set_language($mybb->settings['cplanguage'], "admin"); -} - -// Load global language phrases -$lang->load("global"); -$lang->load("messages", true); - -if(function_exists('mb_internal_encoding') && !empty($lang->settings['charset'])) -{ - @mb_internal_encoding($lang->settings['charset']); -} - -header("Content-type: text/html; charset={$lang->settings['charset']}"); - -$time = TIME_NOW; -$errors = null; - -if(is_dir(MYBB_ROOT."install") && !file_exists(MYBB_ROOT."install/lock")) -{ - $mybb->trigger_generic_error("install_directory"); -} - -$ip_address = get_ip(); -unset($user); - -// Load Admin CP style -if(!isset($cp_style)) -{ - if(!empty($mybb->settings['cpstyle']) && file_exists(MYBB_ADMIN_DIR."/styles/".$mybb->settings['cpstyle']."/main.css")) - { - $cp_style = $mybb->settings['cpstyle']; - } - else - { - $cp_style = "default"; - } -} - -$default_page = new DefaultPage; - -$logged_out = false; -$fail_check = 0; -$post_verify = true; - -foreach(array('action', 'do', 'module') as $input) -{ - if(!isset($mybb->input[$input])) - { - $mybb->input[$input] = ''; - } -} - -if($mybb->input['action'] == "unlock") -{ - $user = array(); - $error = ''; - - $plugins->run_hooks("admin_unlock_start"); - - if($mybb->input['username']) - { - $user = get_user_by_username($mybb->input['username'], array('fields' => '*')); - - if(!$user['uid']) - { - $error = $lang->error_invalid_username; - } - } - else if($mybb->input['uid']) - { - $user = get_user($mybb->input['uid']); - if(!$user['uid']) - { - $error = $lang->error_invalid_uid; - } - } - - // Do we have the token? If so let's process it - if($mybb->input['token'] && $user['uid']) - { - $query = $db->simple_select("awaitingactivation", "COUNT(aid) AS num", "uid='".(int)$user['uid']."' AND code='".$db->escape_string($mybb->input['token'])."' AND type='l'"); - - $plugins->run_hooks("admin_unlock_end"); - - // If we're good to go - if($db->fetch_field($query, "num") > 0) - { - $db->delete_query("awaitingactivation", "uid='".(int)$user['uid']."' AND code='".$db->escape_string($mybb->input['token'])."' AND type='l'"); - $db->update_query("adminoptions", array('loginlockoutexpiry' => 0, 'loginattempts' => 0), "uid='".(int)$user['uid']."'"); - - admin_redirect("index.php"); - } - else - { - $error = $lang->error_invalid_token; - } - } - - $default_page->show_lockout_unlock($error, 'error'); -} -elseif($mybb->input['do'] == "login") -{ - $plugins->run_hooks("admin_login"); - - // We have an adminsid cookie? - if(isset($mybb->cookies['adminsid'])) - { - // Check admin session - $query = $db->simple_select("adminsessions", "sid", "sid='".$db->escape_string($mybb->cookies['adminsid'])."'"); - $admin_session = $db->fetch_field($query, 'sid'); - - // Session found: redirect to index - if($admin_session) - { - admin_redirect("index.php"); - } - } - - require_once MYBB_ROOT."inc/datahandlers/login.php"; - $loginhandler = new LoginDataHandler("get"); - - // Determine login method - $login_lang_string = $lang->error_invalid_username_password; - switch($mybb->settings['username_method']) - { - case 0: // Username only - $login_lang_string = $lang->sprintf($login_lang_string, $lang->login_username); - break; - case 1: // Email only - $login_lang_string = $lang->sprintf($login_lang_string, $lang->login_email); - break; - case 2: // Username and email - default: - $login_lang_string = $lang->sprintf($login_lang_string, $lang->login_username_and_password); - break; - } - - // Validate PIN first - if(!empty($config['secret_pin']) && (empty($mybb->input['pin']) || $mybb->input['pin'] != $config['secret_pin'])) - { - $login_user = get_user_by_username($mybb->input['username'], array('fields' => array('email', 'username'))); - - $plugins->run_hooks("admin_login_incorrect_pin"); - - if($login_user['uid'] > 0) - { - $db->update_query("adminoptions", array("loginattempts" => "loginattempts+1"), "uid='".(int)$login_user['uid']."'", '', true); - } - - $loginattempts = login_attempt_check_acp($login_user['uid'], true); - - // Have we attempted too many times? - if($loginattempts['loginattempts'] > 0) - { - // Have we set an expiry yet? - if($loginattempts['loginlockoutexpiry'] == 0) - { - $db->update_query("adminoptions", array("loginlockoutexpiry" => TIME_NOW+((int)$mybb->settings['loginattemptstimeout']*60)), "uid='".(int)$login_user['uid']."'"); - } - - // Did we hit lockout for the first time? Send the unlock email to the administrator - if($loginattempts['loginattempts'] == $mybb->settings['maxloginattempts']) - { - $db->delete_query("awaitingactivation", "uid='".(int)$login_user['uid']."' AND type='l'"); - $lockout_array = array( - "uid" => $login_user['uid'], - "dateline" => TIME_NOW, - "code" => random_str(), - "type" => "l" - ); - $db->insert_query("awaitingactivation", $lockout_array); - - $subject = $lang->sprintf($lang->locked_out_subject, $mybb->settings['bbname']); - $message = $lang->sprintf($lang->locked_out_message, htmlspecialchars_uni($mybb->input['username']), $mybb->settings['bbname'], $mybb->settings['maxloginattempts'], $mybb->settings['bburl'], $mybb->config['admin_dir'], $lockout_array['code'], $lockout_array['uid']); - my_mail($login_user['email'], $subject, $message); - } - - log_admin_action(array( - 'type' => 'admin_locked_out', - 'uid' => (int)$login_user['uid'], - 'username' => $login_user['username'], - ) - ); - - $default_page->show_lockedout(); - } - else - { - $default_page->show_login($login_lang_string, "error"); - } - } - - $loginhandler->set_data(array( - 'username' => $mybb->input['username'], - 'password' => $mybb->input['password'] - )); - - if($loginhandler->validate_login() == true) - { - $mybb->user = get_user($loginhandler->login_data['uid']); - } - - if($mybb->user['uid']) - { - if(login_attempt_check_acp($mybb->user['uid']) == true) - { - log_admin_action(array( - 'type' => 'admin_locked_out', - 'uid' => (int)$mybb->user['uid'], - 'username' => $mybb->user['username'], - ) - ); - - $default_page->show_lockedout(); - } - - $plugins->run_hooks("admin_login_success"); - - $db->delete_query("adminsessions", "uid='{$mybb->user['uid']}'"); - - $sid = md5(random_str(50)); - - $useragent = $_SERVER['HTTP_USER_AGENT']; - if(my_strlen($useragent) > 200) - { - $useragent = my_substr($useragent, 0, 200); - } - - // Create a new admin session for this user - $admin_session = array( - "sid" => $sid, - "uid" => $mybb->user['uid'], - "loginkey" => $mybb->user['loginkey'], - "ip" => $db->escape_binary(my_inet_pton(get_ip())), - "dateline" => TIME_NOW, - "lastactive" => TIME_NOW, - "data" => my_serialize(array()), - "useragent" => $db->escape_string($useragent), - ); - $db->insert_query("adminsessions", $admin_session); - $admin_session['data'] = array(); - - // Only reset the loginattempts when we're really logged in and the user doesn't need to enter a 2fa code - $query = $db->simple_select("adminoptions", "authsecret", "uid='{$mybb->user['uid']}'"); - $admin_options = $db->fetch_array($query); - if(empty($admin_options['authsecret'])) - { - $db->update_query("adminoptions", array("loginattempts" => 0, "loginlockoutexpiry" => 0), "uid='{$mybb->user['uid']}'"); - } - - my_setcookie("adminsid", $sid, '', true); - my_setcookie('acploginattempts', 0); - $post_verify = false; - - $mybb->request_method = "get"; - - if(!empty($mybb->input['module'])) - { - // $query_string should contain the module - $query_string = '?module='.htmlspecialchars_uni($mybb->input['module']); - - // Now we look for any paramters passed in $_SERVER['QUERY_STRING'] - if($_SERVER['QUERY_STRING']) - { - $qstring = '?'.preg_replace('#adminsid=(.{32})#i', '', $_SERVER['QUERY_STRING']); - $qstring = str_replace('action=logout', '', $qstring); - $qstring = preg_replace('#&+#', '&', $qstring); - $qstring = str_replace('?&', '?', $qstring); - - // So what do we do? We know that parameters are devided by ampersands - // That means we must get to work! - $parameters = explode('&', $qstring); - - // Remove our first member if it's for the module - if(substr($parameters[0], 0, 8) == '?module=') - { - unset($parameters[0]); - } - - foreach($parameters as $key => $param) - { - $params = explode("=", $param); - - $query_string .= '&'.htmlspecialchars_uni($params[0])."=".htmlspecialchars_uni($params[1]); - } - } - - admin_redirect("index.php".$query_string); - } - } - else - { - $login_user = get_user_by_username($mybb->input['username'], array('fields' => array('email', 'username'))); - - $plugins->run_hooks("admin_login_fail"); - - if($login_user['uid'] > 0) - { - $db->update_query("adminoptions", array("loginattempts" => "loginattempts+1"), "uid='".(int)$login_user['uid']."'", '', true); - } - - $loginattempts = login_attempt_check_acp($login_user['uid'], true); - - // Have we attempted too many times? - if($loginattempts['loginattempts'] > 0) - { - // Have we set an expiry yet? - if($loginattempts['loginlockoutexpiry'] == 0) - { - $db->update_query("adminoptions", array("loginlockoutexpiry" => TIME_NOW+((int)$mybb->settings['loginattemptstimeout']*60)), "uid='".(int)$login_user['uid']."'"); - } - - $plugins->run_hooks("admin_login_lockout"); - - // Did we hit lockout for the first time? Send the unlock email to the administrator - if($loginattempts['loginattempts'] == $mybb->settings['maxloginattempts']) - { - $db->delete_query("awaitingactivation", "uid='".(int)$login_user['uid']."' AND type='l'"); - $lockout_array = array( - "uid" => $login_user['uid'], - "dateline" => TIME_NOW, - "code" => random_str(), - "type" => "l" - ); - $db->insert_query("awaitingactivation", $lockout_array); - - $subject = $lang->sprintf($lang->locked_out_subject, $mybb->settings['bbname']); - $message = $lang->sprintf($lang->locked_out_message, htmlspecialchars_uni($mybb->input['username']), $mybb->settings['bbname'], $mybb->settings['maxloginattempts'], $mybb->settings['bburl'], $mybb->config['admin_dir'], $lockout_array['code'], $lockout_array['uid']); - my_mail($login_user['email'], $subject, $message); - } - - log_admin_action(array( - 'type' => 'admin_locked_out', - 'uid' => (int)$login_user['uid'], - 'username' => $login_user['username'], - ) - ); - - $default_page->show_lockedout(); - } - - $fail_check = 1; - } -} -else -{ - // No admin session - show message on the login screen - if(!isset($mybb->cookies['adminsid'])) - { - $login_message = ""; - } - // Otherwise, check admin session - else - { - $query = $db->simple_select("adminsessions", "*", "sid='".$db->escape_string($mybb->cookies['adminsid'])."'"); - $admin_session = $db->fetch_array($query); - - // No matching admin session found - show message on login screen - if(!$admin_session['sid']) - { - $login_message = $lang->error_invalid_admin_session; - } - else - { - $admin_session['data'] = my_unserialize($admin_session['data']); - - // Fetch the user from the admin session - $mybb->user = get_user($admin_session['uid']); - - // Login key has changed - force logout - if(!$mybb->user['uid'] || $mybb->user['loginkey'] !== $admin_session['loginkey']) - { - unset($mybb->user); - } - else - { - // Admin CP sessions 2 hours old are expired - if($admin_session['lastactive'] < TIME_NOW-7200) - { - $login_message = $lang->error_admin_session_expired; - $db->delete_query("adminsessions", "sid='".$db->escape_string($mybb->cookies['adminsid'])."'"); - unset($mybb->user); - } - // If IP matching is set - check IP address against the session IP - else if(ADMIN_IP_SEGMENTS > 0 && strpos($ip_address, ':') === false) - { - $exploded_ip = explode(".", $ip_address); - $exploded_admin_ip = explode(".", my_inet_ntop($admin_session['ip'])); - $matches = 0; - $valid_ip = false; - for($i = 0; $i < ADMIN_IP_SEGMENTS; ++$i) - { - if($exploded_ip[$i] == $exploded_admin_ip[$i]) - { - ++$matches; - } - if($matches == ADMIN_IP_SEGMENTS) - { - $valid_ip = true; - break; - } - } - - // IP doesn't match properly - show message on logon screen - if(!$valid_ip) - { - $login_message = $lang->error_invalid_ip; - unset($mybb->user); - } - } - else if(ADMIN_IPV6_SEGMENTS > 0 && strpos($ip_address, ':') !== false) - { - // Expand IPv6 addresses - $hex = unpack("H*hex", my_inet_pton($ip_address)); - $expanded_ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1); - $hex_admin = unpack("H*hex", $admin_session['ip']); - $expanded_admin_ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex_admin['hex']), 0, -1); - - $exploded_ip = explode(":", $expanded_ip); - $exploded_admin_ip = explode(":", $expanded_admin_ip); - $matches = 0; - $valid_ip = false; - for($i = 0; $i < ADMIN_IPV6_SEGMENTS; ++$i) - { - if($exploded_ip[$i] == $exploded_admin_ip[$i]) - { - ++$matches; - } - if($matches == ADMIN_IPV6_SEGMENTS) - { - $valid_ip = true; - break; - } - } - - // IP doesn't match properly - show message on logon screen - if(!$valid_ip) - { - $login_message = $lang->error_invalid_ip; - unset($mybb->user); - } - } - } - } - } -} - -if($mybb->input['action'] == "logout" && $mybb->user) -{ - $plugins->run_hooks("admin_logout"); - - if(verify_post_check($mybb->input['my_post_key'])) - { - $db->delete_query("adminsessions", "sid='".$db->escape_string($mybb->cookies['adminsid'])."'"); - my_unsetcookie('adminsid'); - $logged_out = true; - } -} - -if(!isset($mybb->user['usergroup'])) -{ - $mybbgroups = 1; -} -else -{ - $mybbgroups = $mybb->user['usergroup'].",".$mybb->user['additionalgroups']; -} -$mybb->usergroup = usergroup_permissions($mybbgroups); - -$is_super_admin = is_super_admin($mybb->user['uid']); - -if($mybb->usergroup['cancp'] != 1 && !$is_super_admin || !$mybb->user['uid']) -{ - $uid = 0; - if(isset($mybb->user['uid'])) - { - $uid = (int)$mybb->user['uid']; - } - $db->delete_query("adminsessions", "uid = '{$uid}'"); - unset($mybb->user); - my_unsetcookie('adminsid'); -} - -if(!empty($mybb->user['uid'])) -{ - $query = $db->simple_select("adminoptions", "*", "uid='".$mybb->user['uid']."'"); - $admin_options = $db->fetch_array($query); - - if(!empty($admin_options['cplanguage']) && file_exists(MYBB_ROOT."inc/languages/".$admin_options['cplanguage']."/admin/home_dashboard.lang.php")) - { - $cp_language = $admin_options['cplanguage']; - $lang->set_language($cp_language, "admin"); - $lang->load("global"); // Reload global language vars - $lang->load("messages", true); - } - - if(!empty($admin_options['cpstyle']) && file_exists(MYBB_ADMIN_DIR."/styles/{$admin_options['cpstyle']}/main.css")) - { - $cp_style = $admin_options['cpstyle']; - } - - // Update the session information in the DB - if($admin_session['sid']) - { - $db->update_query("adminsessions", array('lastactive' => TIME_NOW, 'ip' => $db->escape_binary(my_inet_pton(get_ip()))), "sid='".$db->escape_string($admin_session['sid'])."'"); - } - - // Fetch administrator permissions - $mybb->admin['permissions'] = get_admin_permissions($mybb->user['uid']); -} - -// Include the layout generation class overrides for this style -if(file_exists(MYBB_ADMIN_DIR."/styles/{$cp_style}/style.php")) -{ - require_once MYBB_ADMIN_DIR."/styles/{$cp_style}/style.php"; -} - -// Check if any of the layout generation classes we can override exist in the style file -$classes = array( - "Page" => "DefaultPage", - "SidebarItem" => "DefaultSidebarItem", - "PopupMenu" => "DefaultPopupMenu", - "Table" => "DefaultTable", - "Form" => "DefaultForm", - "FormContainer" => "DefaultFormContainer" -); -foreach($classes as $style_name => $default_name) -{ - // Style does not have this layout generation class, create it - if(!class_exists($style_name)) - { - eval("class {$style_name} extends {$default_name} { }"); - } -} - -$page = new Page; -$page->style = $cp_style; - -// Do not have a valid Admin user, throw back to login page. -if(!isset($mybb->user['uid']) || $logged_out == true) -{ - if($logged_out == true) - { - $page->show_login($lang->success_logged_out); - } - elseif($fail_check == 1) - { - $page->show_login($login_lang_string, "error"); - } - else - { - // If we have this error while retreiving it from an AJAX request, then send back a nice error - if(isset($mybb->input['ajax']) && $mybb->input['ajax'] == 1) - { - echo json_encode(array("errors" => array("login"))); - exit; - } - $page->show_login($login_message, "error"); - } -} - -// Time to check for Two-Factor Authentication -// First: are we trying to verify a code? -if($mybb->input['do'] == "do_2fa" && $mybb->request_method == "post") -{ - // Test whether it's a recovery code - $recovery = false; - $codes = my_unserialize($admin_options['recovery_codes']); - if(!empty($codes) && in_array($mybb->get_input('code'), $codes)) - { - $recovery = true; - $ncodes = array_diff($codes, array($mybb->input['code'])); // Removes our current code from the codes array - $db->update_query("adminoptions", array("recovery_codes" => $db->escape_string(my_serialize($ncodes))), "uid='{$mybb->user['uid']}'"); - - if(count($ncodes) == 0) - { - flash_message($lang->my2fa_no_codes, "error"); - } - } - - // Validate the code - require_once MYBB_ROOT."inc/3rdparty/2fa/GoogleAuthenticator.php"; - $auth = new PHPGangsta_GoogleAuthenticator; - - $test = $auth->verifyCode($admin_options['authsecret'], $mybb->get_input('code')); - - // Either the code was okay or it was a recovery code - if($test === true || $recovery === true) - { - // Correct code -> session authenticated - $db->update_query("adminsessions", array("authenticated" => 1), "sid='".$db->escape_string($mybb->cookies['adminsid'])."'"); - $admin_session['authenticated'] = 1; - $db->update_query("adminoptions", array("loginattempts" => 0, "loginlockoutexpiry" => 0), "uid='{$mybb->user['uid']}'"); - my_setcookie('acploginattempts', 0); - // post would result in an authorization code mismatch error - $mybb->request_method = "get"; - } - else - { - // Wrong code -> close session (aka logout) - $db->delete_query("adminsessions", "sid='".$db->escape_string($mybb->cookies['adminsid'])."'"); - my_unsetcookie('adminsid'); - - // Now test whether we need to lock this guy completly - $db->update_query("adminoptions", array("loginattempts" => "loginattempts+1"), "uid='{$mybb->user['uid']}'", '', true); - - $loginattempts = login_attempt_check_acp($mybb->user['uid'], true); - - // Have we attempted too many times? - if($loginattempts['loginattempts'] > 0) - { - // Have we set an expiry yet? - if($loginattempts['loginlockoutexpiry'] == 0) - { - $db->update_query("adminoptions", array("loginlockoutexpiry" => TIME_NOW+((int)$mybb->settings['loginattemptstimeout']*60)), "uid='{$mybb->user['uid']}'"); - } - - // Did we hit lockout for the first time? Send the unlock email to the administrator - if($loginattempts['loginattempts'] == $mybb->settings['maxloginattempts']) - { - $db->delete_query("awaitingactivation", "uid='{$mybb->user['uid']}' AND type='l'"); - $lockout_array = array( - "uid" => $mybb->user['uid'], - "dateline" => TIME_NOW, - "code" => random_str(), - "type" => "l" - ); - $db->insert_query("awaitingactivation", $lockout_array); - - $subject = $lang->sprintf($lang->locked_out_subject, $mybb->settings['bbname']); - $message = $lang->sprintf($lang->locked_out_message, htmlspecialchars_uni($mybb->user['username']), $mybb->settings['bbname'], $mybb->settings['maxloginattempts'], $mybb->settings['bburl'], $mybb->config['admin_dir'], $lockout_array['code'], $lockout_array['uid']); - my_mail($mybb->user['email'], $subject, $message); - } - - log_admin_action(array( - 'type' => 'admin_locked_out', - 'uid' => $mybb->user['uid'], - 'username' => $mybb->user['username'], - ) - ); - - $page->show_lockedout(); - } - - // Still here? Show a custom login page - $page->show_login($lang->my2fa_failed, "error"); - } -} - -// Show our 2FA page -if(!empty($admin_options['authsecret']) && $admin_session['authenticated'] != 1) -{ - $page->show_2fa(); -} - -$page->add_breadcrumb_item($lang->home, "index.php"); - -// Begin dealing with the modules -$modules_dir = MYBB_ADMIN_DIR."modules"; -$dir = opendir($modules_dir); -while(($module = readdir($dir)) !== false) -{ - if(is_dir($modules_dir."/".$module) && !in_array($module, array(".", "..")) && file_exists($modules_dir."/".$module."/module_meta.php")) - { - require_once $modules_dir."/".$module."/module_meta.php"; - - // Need to always load it for admin permissions / quick access - $lang->load($module."_module_meta", false, true); - - $has_permission = false; - if(function_exists($module."_admin_permissions")) - { - if(isset($mybb->admin['permissions'][$module]) || $is_super_admin == true) - { - $has_permission = true; - } - } - // This module doesn't support permissions - else - { - $has_permission = true; - } - - // Do we have permissions to run this module (Note: home is accessible by all) - if($module == "home" || $has_permission == true) - { - $meta_function = $module."_meta"; - $initialized = $meta_function(); - if($initialized == true) - { - $modules[$module] = 1; - } - } - else - { - $modules[$module] = 0; - } - } -} - -$modules = $plugins->run_hooks("admin_tabs", $modules); - -closedir($dir); - -if(strpos($mybb->input['module'], "/") !== false) -{ - $current_module = explode("/", $mybb->input['module'], 2); -} -else -{ - $current_module = explode("-", $mybb->input['module'], 2); -} - -if(!isset($current_module[1])) -{ - $current_module[1] = 'home'; -} - -if($mybb->input['module'] && isset($modules[$current_module[0]])) -{ - $run_module = $current_module[0]; -} -else -{ - $run_module = "home"; -} - -$action_handler = $run_module."_action_handler"; -$action_file = $action_handler($current_module[1]); - -// Set our POST validation code here -$mybb->post_code = generate_post_check(); - -if($run_module != "home") -{ - check_admin_permissions(array('module' => $page->active_module, 'action' => $page->active_action)); -} - -// Only POST actions with a valid post code can modify information. Here we check if the incoming request is a POST and if that key is valid. -$post_check_ignores = array( - "example/page" => array("action") -); // An array of modules/actions to ignore POST checks for. - -if($mybb->request_method == "post") -{ - if(in_array($mybb->input['module'], $post_check_ignores)) - { - $k = array_search($mybb->input['module'], $post_check_ignores); - if(in_array($mybb->input['action'], $post_check_ignores[$k])) - { - $post_verify = false; - } - } - - if($post_verify == true) - { - // If the post key does not match we switch the action to GET and set a message to show the user - if(!isset($mybb->input['my_post_key']) || $mybb->post_code !== $mybb->input['my_post_key']) - { - $mybb->request_method = "get"; - $page->show_post_verify_error = true; - } - } -} - -$lang->load("{$run_module}_{$page->active_action}", false, true); - -$plugins->run_hooks("admin_load"); - -require $modules_dir."/".$run_module."/".$action_file; - diff --git a/html/forums/admin/jscripts/admincp.js b/html/forums/admin/jscripts/admincp.js deleted file mode 100644 index 7d4d810..0000000 --- a/html/forums/admin/jscripts/admincp.js +++ /dev/null @@ -1,23 +0,0 @@ -var AdminCP = { - init: function() - { - }, - - deleteConfirmation: function(element, message) - { - if(!element) return false; - confirmReturn = confirm(message); - if(confirmReturn == true) - { - form = $("
", { method: "post", action: element.href, style: "display: none;" }); - $("body").append(form); - form.submit(); - } - return false; - } -}; - -$(function() -{ - AdminCP.init(); -}); \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/LICENSE b/html/forums/admin/jscripts/codemirror/LICENSE deleted file mode 100644 index 3c454bd..0000000 --- a/html/forums/admin/jscripts/codemirror/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2014 by Marijn Haverbeke and others - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/html/forums/admin/jscripts/codemirror/addon/dialog/dialog-mybb.css b/html/forums/admin/jscripts/codemirror/addon/dialog/dialog-mybb.css deleted file mode 100644 index 6d2c0ea..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/dialog/dialog-mybb.css +++ /dev/null @@ -1,32 +0,0 @@ -.CodeMirror-dialog { - position: absolute; - left: 0; right: 0; - background: #1F4661; - z-index: 15; - padding: .1em .8em; - overflow: hidden; - color: #fff; -} - -.CodeMirror-dialog-top { - border-bottom: 1px solid #3E7087; - top: 0; -} - -.CodeMirror-dialog-bottom { - border-top: 1px solid #3E7087; - bottom: 0; -} - -.CodeMirror-dialog input { - border: none; - outline: none; - background: transparent; - width: 20em; - color: inherit; - font-family: monospace; -} - -.CodeMirror-dialog button { - font-size: 70%; -} diff --git a/html/forums/admin/jscripts/codemirror/addon/dialog/dialog.css b/html/forums/admin/jscripts/codemirror/addon/dialog/dialog.css deleted file mode 100644 index 43e1212..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/dialog/dialog.css +++ /dev/null @@ -1,32 +0,0 @@ -.CodeMirror-dialog { - position: absolute; - left: 0; right: 0; - background: white; - z-index: 15; - padding: .1em .8em; - overflow: hidden; - color: #333; -} - -.CodeMirror-dialog-top { - border-bottom: 1px solid #eee; - top: 0; -} - -.CodeMirror-dialog-bottom { - border-top: 1px solid #eee; - bottom: 0; -} - -.CodeMirror-dialog input { - border: none; - outline: none; - background: transparent; - width: 20em; - color: inherit; - font-family: monospace; -} - -.CodeMirror-dialog button { - font-size: 70%; -} diff --git a/html/forums/admin/jscripts/codemirror/addon/dialog/dialog.js b/html/forums/admin/jscripts/codemirror/addon/dialog/dialog.js deleted file mode 100644 index e0e8ad4..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/dialog/dialog.js +++ /dev/null @@ -1,155 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Open simple dialogs on top of an editor. Relies on dialog.css. - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - function dialogDiv(cm, template, bottom) { - var wrap = cm.getWrapperElement(); - var dialog; - dialog = wrap.appendChild(document.createElement("div")); - if (bottom) - dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; - else - dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; - - if (typeof template == "string") { - dialog.innerHTML = template; - } else { // Assuming it's a detached DOM element. - dialog.appendChild(template); - } - return dialog; - } - - function closeNotification(cm, newVal) { - if (cm.state.currentNotificationClose) - cm.state.currentNotificationClose(); - cm.state.currentNotificationClose = newVal; - } - - CodeMirror.defineExtension("openDialog", function(template, callback, options) { - if (!options) options = {}; - - closeNotification(this, null); - - var dialog = dialogDiv(this, template, options.bottom); - var closed = false, me = this; - function close(newVal) { - if (typeof newVal == 'string') { - inp.value = newVal; - } else { - if (closed) return; - closed = true; - dialog.parentNode.removeChild(dialog); - me.focus(); - - if (options.onClose) options.onClose(dialog); - } - } - - var inp = dialog.getElementsByTagName("input")[0], button; - if (inp) { - if (options.value) { - inp.value = options.value; - inp.select(); - } - - if (options.onInput) - CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); - if (options.onKeyUp) - CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); - - CodeMirror.on(inp, "keydown", function(e) { - if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } - if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { - inp.blur(); - CodeMirror.e_stop(e); - close(); - } - if (e.keyCode == 13) callback(inp.value, e); - }); - - if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); - - inp.focus(); - } else if (button = dialog.getElementsByTagName("button")[0]) { - CodeMirror.on(button, "click", function() { - close(); - me.focus(); - }); - - if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); - - button.focus(); - } - return close; - }); - - CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) { - closeNotification(this, null); - var dialog = dialogDiv(this, template, options && options.bottom); - var buttons = dialog.getElementsByTagName("button"); - var closed = false, me = this, blurring = 1; - function close() { - if (closed) return; - closed = true; - dialog.parentNode.removeChild(dialog); - me.focus(); - } - buttons[0].focus(); - for (var i = 0; i < buttons.length; ++i) { - var b = buttons[i]; - (function(callback) { - CodeMirror.on(b, "click", function(e) { - CodeMirror.e_preventDefault(e); - close(); - if (callback) callback(me); - }); - })(callbacks[i]); - CodeMirror.on(b, "blur", function() { - --blurring; - setTimeout(function() { if (blurring <= 0) close(); }, 200); - }); - CodeMirror.on(b, "focus", function() { ++blurring; }); - } - }); - - /* - * openNotification - * Opens a notification, that can be closed with an optional timer - * (default 5000ms timer) and always closes on click. - * - * If a notification is opened while another is opened, it will close the - * currently opened one and open the new one immediately. - */ - CodeMirror.defineExtension("openNotification", function(template, options) { - closeNotification(this, close); - var dialog = dialogDiv(this, template, options && options.bottom); - var closed = false, doneTimer; - var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; - - function close() { - if (closed) return; - closed = true; - clearTimeout(doneTimer); - dialog.parentNode.removeChild(dialog); - } - - CodeMirror.on(dialog, 'click', function(e) { - CodeMirror.e_preventDefault(e); - close(); - }); - - if (duration) - doneTimer = setTimeout(close, duration); - - return close; - }); -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/dialog/index.html b/html/forums/admin/jscripts/codemirror/addon/dialog/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/dialog/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/addon/fold/brace-fold.js b/html/forums/admin/jscripts/codemirror/addon/fold/brace-fold.js deleted file mode 100644 index 1605f6c..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/fold/brace-fold.js +++ /dev/null @@ -1,105 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.registerHelper("fold", "brace", function(cm, start) { - var line = start.line, lineText = cm.getLine(line); - var startCh, tokenType; - - function findOpening(openCh) { - for (var at = start.ch, pass = 0;;) { - var found = at <= 0 ? -1 : lineText.lastIndexOf(openCh, at - 1); - if (found == -1) { - if (pass == 1) break; - pass = 1; - at = lineText.length; - continue; - } - if (pass == 1 && found < start.ch) break; - tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1)); - if (!/^(comment|string)/.test(tokenType)) return found + 1; - at = found - 1; - } - } - - var startToken = "{", endToken = "}", startCh = findOpening("{"); - if (startCh == null) { - startToken = "[", endToken = "]"; - startCh = findOpening("["); - } - - if (startCh == null) return; - var count = 1, lastLine = cm.lastLine(), end, endCh; - outer: for (var i = line; i <= lastLine; ++i) { - var text = cm.getLine(i), pos = i == line ? startCh : 0; - for (;;) { - var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos); - if (nextOpen < 0) nextOpen = text.length; - if (nextClose < 0) nextClose = text.length; - pos = Math.min(nextOpen, nextClose); - if (pos == text.length) break; - if (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == tokenType) { - if (pos == nextOpen) ++count; - else if (!--count) { end = i; endCh = pos; break outer; } - } - ++pos; - } - } - if (end == null || line == end && endCh == startCh) return; - return {from: CodeMirror.Pos(line, startCh), - to: CodeMirror.Pos(end, endCh)}; -}); - -CodeMirror.registerHelper("fold", "import", function(cm, start) { - function hasImport(line) { - if (line < cm.firstLine() || line > cm.lastLine()) return null; - var start = cm.getTokenAt(CodeMirror.Pos(line, 1)); - if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1)); - if (start.type != "keyword" || start.string != "import") return null; - // Now find closing semicolon, return its position - for (var i = line, e = Math.min(cm.lastLine(), line + 10); i <= e; ++i) { - var text = cm.getLine(i), semi = text.indexOf(";"); - if (semi != -1) return {startCh: start.end, end: CodeMirror.Pos(i, semi)}; - } - } - - var start = start.line, has = hasImport(start), prev; - if (!has || hasImport(start - 1) || ((prev = hasImport(start - 2)) && prev.end.line == start - 1)) - return null; - for (var end = has.end;;) { - var next = hasImport(end.line + 1); - if (next == null) break; - end = next.end; - } - return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end}; -}); - -CodeMirror.registerHelper("fold", "include", function(cm, start) { - function hasInclude(line) { - if (line < cm.firstLine() || line > cm.lastLine()) return null; - var start = cm.getTokenAt(CodeMirror.Pos(line, 1)); - if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1)); - if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8; - } - - var start = start.line, has = hasInclude(start); - if (has == null || hasInclude(start - 1) != null) return null; - for (var end = start;;) { - var next = hasInclude(end + 1); - if (next == null) break; - ++end; - } - return {from: CodeMirror.Pos(start, has + 1), - to: cm.clipPos(CodeMirror.Pos(end))}; -}); - -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/fold/comment-fold.js b/html/forums/admin/jscripts/codemirror/addon/fold/comment-fold.js deleted file mode 100644 index b75db7e..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/fold/comment-fold.js +++ /dev/null @@ -1,57 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.registerGlobalHelper("fold", "comment", function(mode) { - return mode.blockCommentStart && mode.blockCommentEnd; -}, function(cm, start) { - var mode = cm.getModeAt(start), startToken = mode.blockCommentStart, endToken = mode.blockCommentEnd; - if (!startToken || !endToken) return; - var line = start.line, lineText = cm.getLine(line); - - var startCh; - for (var at = start.ch, pass = 0;;) { - var found = at <= 0 ? -1 : lineText.lastIndexOf(startToken, at - 1); - if (found == -1) { - if (pass == 1) return; - pass = 1; - at = lineText.length; - continue; - } - if (pass == 1 && found < start.ch) return; - if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1)))) { - startCh = found + startToken.length; - break; - } - at = found - 1; - } - - var depth = 1, lastLine = cm.lastLine(), end, endCh; - outer: for (var i = line; i <= lastLine; ++i) { - var text = cm.getLine(i), pos = i == line ? startCh : 0; - for (;;) { - var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos); - if (nextOpen < 0) nextOpen = text.length; - if (nextClose < 0) nextClose = text.length; - pos = Math.min(nextOpen, nextClose); - if (pos == text.length) break; - if (pos == nextOpen) ++depth; - else if (!--depth) { end = i; endCh = pos; break outer; } - ++pos; - } - } - if (end == null || line == end && endCh == startCh) return; - return {from: CodeMirror.Pos(line, startCh), - to: CodeMirror.Pos(end, endCh)}; -}); - -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/fold/foldcode.js b/html/forums/admin/jscripts/codemirror/addon/fold/foldcode.js deleted file mode 100644 index 62911f9..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/fold/foldcode.js +++ /dev/null @@ -1,149 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function doFold(cm, pos, options, force) { - if (options && options.call) { - var finder = options; - options = null; - } else { - var finder = getOption(cm, options, "rangeFinder"); - } - if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0); - var minSize = getOption(cm, options, "minFoldSize"); - - function getRange(allowFolded) { - var range = finder(cm, pos); - if (!range || range.to.line - range.from.line < minSize) return null; - var marks = cm.findMarksAt(range.from); - for (var i = 0; i < marks.length; ++i) { - if (marks[i].__isFold && force !== "fold") { - if (!allowFolded) return null; - range.cleared = true; - marks[i].clear(); - } - } - return range; - } - - var range = getRange(true); - if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) { - pos = CodeMirror.Pos(pos.line - 1, 0); - range = getRange(false); - } - if (!range || range.cleared || force === "unfold") return; - - var myWidget = makeWidget(cm, options); - CodeMirror.on(myWidget, "mousedown", function(e) { - myRange.clear(); - CodeMirror.e_preventDefault(e); - }); - var myRange = cm.markText(range.from, range.to, { - replacedWith: myWidget, - clearOnEnter: true, - __isFold: true - }); - myRange.on("clear", function(from, to) { - CodeMirror.signal(cm, "unfold", cm, from, to); - }); - CodeMirror.signal(cm, "fold", cm, range.from, range.to); - } - - function makeWidget(cm, options) { - var widget = getOption(cm, options, "widget"); - if (typeof widget == "string") { - var text = document.createTextNode(widget); - widget = document.createElement("span"); - widget.appendChild(text); - widget.className = "CodeMirror-foldmarker"; - } - return widget; - } - - // Clumsy backwards-compatible interface - CodeMirror.newFoldFunction = function(rangeFinder, widget) { - return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); }; - }; - - // New-style interface - CodeMirror.defineExtension("foldCode", function(pos, options, force) { - doFold(this, pos, options, force); - }); - - CodeMirror.defineExtension("isFolded", function(pos) { - var marks = this.findMarksAt(pos); - for (var i = 0; i < marks.length; ++i) - if (marks[i].__isFold) return true; - }); - - CodeMirror.commands.toggleFold = function(cm) { - cm.foldCode(cm.getCursor()); - }; - CodeMirror.commands.fold = function(cm) { - cm.foldCode(cm.getCursor(), null, "fold"); - }; - CodeMirror.commands.unfold = function(cm) { - cm.foldCode(cm.getCursor(), null, "unfold"); - }; - CodeMirror.commands.foldAll = function(cm) { - cm.operation(function() { - for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) - cm.foldCode(CodeMirror.Pos(i, 0), null, "fold"); - }); - }; - CodeMirror.commands.unfoldAll = function(cm) { - cm.operation(function() { - for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) - cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold"); - }); - }; - - CodeMirror.registerHelper("fold", "combine", function() { - var funcs = Array.prototype.slice.call(arguments, 0); - return function(cm, start) { - for (var i = 0; i < funcs.length; ++i) { - var found = funcs[i](cm, start); - if (found) return found; - } - }; - }); - - CodeMirror.registerHelper("fold", "auto", function(cm, start) { - var helpers = cm.getHelpers(start, "fold"); - for (var i = 0; i < helpers.length; i++) { - var cur = helpers[i](cm, start); - if (cur) return cur; - } - }); - - var defaultOptions = { - rangeFinder: CodeMirror.fold.auto, - widget: "\u2194", - minFoldSize: 0, - scanUp: false - }; - - CodeMirror.defineOption("foldOptions", null); - - function getOption(cm, options, name) { - if (options && options[name] !== undefined) - return options[name]; - var editorOptions = cm.options.foldOptions; - if (editorOptions && editorOptions[name] !== undefined) - return editorOptions[name]; - return defaultOptions[name]; - } - - CodeMirror.defineExtension("foldOption", function(options, name) { - return getOption(this, options, name); - }); -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/fold/foldgutter.css b/html/forums/admin/jscripts/codemirror/addon/fold/foldgutter.css deleted file mode 100644 index 3655e7d..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/fold/foldgutter.css +++ /dev/null @@ -1,20 +0,0 @@ -.CodeMirror-foldmarker { - color: blue; - text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px; - font-family: arial; - line-height: .3; - cursor: pointer; -} -.CodeMirror-foldgutter { - width: .7em; -} -.CodeMirror-foldgutter-open, -.CodeMirror-foldgutter-folded { - cursor: pointer; -} -.CodeMirror-foldgutter-open:after { - content: "\25BE"; -} -.CodeMirror-foldgutter-folded:after { - content: "\25B8"; -} diff --git a/html/forums/admin/jscripts/codemirror/addon/fold/foldgutter.js b/html/forums/admin/jscripts/codemirror/addon/fold/foldgutter.js deleted file mode 100644 index 3359476..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/fold/foldgutter.js +++ /dev/null @@ -1,136 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("./foldcode")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "./foldcode"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineOption("foldGutter", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) { - cm.clearGutter(cm.state.foldGutter.options.gutter); - cm.state.foldGutter = null; - cm.off("gutterClick", onGutterClick); - cm.off("change", onChange); - cm.off("viewportChange", onViewportChange); - cm.off("fold", onFold); - cm.off("unfold", onFold); - cm.off("swapDoc", updateInViewport); - } - if (val) { - cm.state.foldGutter = new State(parseOptions(val)); - updateInViewport(cm); - cm.on("gutterClick", onGutterClick); - cm.on("change", onChange); - cm.on("viewportChange", onViewportChange); - cm.on("fold", onFold); - cm.on("unfold", onFold); - cm.on("swapDoc", updateInViewport); - } - }); - - var Pos = CodeMirror.Pos; - - function State(options) { - this.options = options; - this.from = this.to = 0; - } - - function parseOptions(opts) { - if (opts === true) opts = {}; - if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter"; - if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open"; - if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded"; - return opts; - } - - function isFolded(cm, line) { - var marks = cm.findMarksAt(Pos(line)); - for (var i = 0; i < marks.length; ++i) - if (marks[i].__isFold && marks[i].find().from.line == line) return true; - } - - function marker(spec) { - if (typeof spec == "string") { - var elt = document.createElement("div"); - elt.className = spec + " CodeMirror-guttermarker-subtle"; - return elt; - } else { - return spec.cloneNode(true); - } - } - - function updateFoldInfo(cm, from, to) { - var opts = cm.state.foldGutter.options, cur = from; - var minSize = cm.foldOption(opts, "minFoldSize"); - var func = cm.foldOption(opts, "rangeFinder"); - cm.eachLine(from, to, function(line) { - var mark = null; - if (isFolded(cm, cur)) { - mark = marker(opts.indicatorFolded); - } else { - var pos = Pos(cur, 0); - var range = func && func(cm, pos); - if (range && range.to.line - range.from.line >= minSize) - mark = marker(opts.indicatorOpen); - } - cm.setGutterMarker(line, opts.gutter, mark); - ++cur; - }); - } - - function updateInViewport(cm) { - var vp = cm.getViewport(), state = cm.state.foldGutter; - if (!state) return; - cm.operation(function() { - updateFoldInfo(cm, vp.from, vp.to); - }); - state.from = vp.from; state.to = vp.to; - } - - function onGutterClick(cm, line, gutter) { - var opts = cm.state.foldGutter.options; - if (gutter != opts.gutter) return; - cm.foldCode(Pos(line, 0), opts.rangeFinder); - } - - function onChange(cm) { - var state = cm.state.foldGutter, opts = cm.state.foldGutter.options; - state.from = state.to = 0; - clearTimeout(state.changeUpdate); - state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600); - } - - function onViewportChange(cm) { - var state = cm.state.foldGutter, opts = cm.state.foldGutter.options; - clearTimeout(state.changeUpdate); - state.changeUpdate = setTimeout(function() { - var vp = cm.getViewport(); - if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) { - updateInViewport(cm); - } else { - cm.operation(function() { - if (vp.from < state.from) { - updateFoldInfo(cm, vp.from, state.from); - state.from = vp.from; - } - if (vp.to > state.to) { - updateFoldInfo(cm, state.to, vp.to); - state.to = vp.to; - } - }); - } - }, opts.updateViewportTimeSpan || 400); - } - - function onFold(cm, from) { - var state = cm.state.foldGutter, line = from.line; - if (line >= state.from && line < state.to) - updateFoldInfo(cm, line, line + 1); - } -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/fold/indent-fold.js b/html/forums/admin/jscripts/codemirror/addon/fold/indent-fold.js deleted file mode 100644 index e29f15e..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/fold/indent-fold.js +++ /dev/null @@ -1,44 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.registerHelper("fold", "indent", function(cm, start) { - var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line); - if (!/\S/.test(firstLine)) return; - var getIndent = function(line) { - return CodeMirror.countColumn(line, null, tabSize); - }; - var myIndent = getIndent(firstLine); - var lastLineInFold = null; - // Go through lines until we find a line that definitely doesn't belong in - // the block we're folding, or to the end. - for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) { - var curLine = cm.getLine(i); - var curIndent = getIndent(curLine); - if (curIndent > myIndent) { - // Lines with a greater indent are considered part of the block. - lastLineInFold = i; - } else if (!/\S/.test(curLine)) { - // Empty lines might be breaks within the block we're trying to fold. - } else { - // A non-empty line at an indent equal to or less than ours marks the - // start of another block. - break; - } - } - if (lastLineInFold) return { - from: CodeMirror.Pos(start.line, firstLine.length), - to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length) - }; -}); - -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/fold/index.html b/html/forums/admin/jscripts/codemirror/addon/fold/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/fold/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/addon/fold/markdown-fold.js b/html/forums/admin/jscripts/codemirror/addon/fold/markdown-fold.js deleted file mode 100644 index ce84c94..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/fold/markdown-fold.js +++ /dev/null @@ -1,49 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.registerHelper("fold", "markdown", function(cm, start) { - var maxDepth = 100; - - function isHeader(lineNo) { - var tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0)); - return tokentype && /\bheader\b/.test(tokentype); - } - - function headerLevel(lineNo, line, nextLine) { - var match = line && line.match(/^#+/); - if (match && isHeader(lineNo)) return match[0].length; - match = nextLine && nextLine.match(/^[=\-]+\s*$/); - if (match && isHeader(lineNo + 1)) return nextLine[0] == "=" ? 1 : 2; - return maxDepth; - } - - var firstLine = cm.getLine(start.line), nextLine = cm.getLine(start.line + 1); - var level = headerLevel(start.line, firstLine, nextLine); - if (level === maxDepth) return undefined; - - var lastLineNo = cm.lastLine(); - var end = start.line, nextNextLine = cm.getLine(end + 2); - while (end < lastLineNo) { - if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break; - ++end; - nextLine = nextNextLine; - nextNextLine = cm.getLine(end + 2); - } - - return { - from: CodeMirror.Pos(start.line, firstLine.length), - to: CodeMirror.Pos(end, cm.getLine(end).length) - }; -}); - -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/fold/xml-fold.js b/html/forums/admin/jscripts/codemirror/addon/fold/xml-fold.js deleted file mode 100644 index 504727f..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/fold/xml-fold.js +++ /dev/null @@ -1,182 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var Pos = CodeMirror.Pos; - function cmp(a, b) { return a.line - b.line || a.ch - b.ch; } - - var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; - var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; - var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g"); - - function Iter(cm, line, ch, range) { - this.line = line; this.ch = ch; - this.cm = cm; this.text = cm.getLine(line); - this.min = range ? range.from : cm.firstLine(); - this.max = range ? range.to - 1 : cm.lastLine(); - } - - function tagAt(iter, ch) { - var type = iter.cm.getTokenTypeAt(Pos(iter.line, ch)); - return type && /\btag\b/.test(type); - } - - function nextLine(iter) { - if (iter.line >= iter.max) return; - iter.ch = 0; - iter.text = iter.cm.getLine(++iter.line); - return true; - } - function prevLine(iter) { - if (iter.line <= iter.min) return; - iter.text = iter.cm.getLine(--iter.line); - iter.ch = iter.text.length; - return true; - } - - function toTagEnd(iter) { - for (;;) { - var gt = iter.text.indexOf(">", iter.ch); - if (gt == -1) { if (nextLine(iter)) continue; else return; } - if (!tagAt(iter, gt + 1)) { iter.ch = gt + 1; continue; } - var lastSlash = iter.text.lastIndexOf("/", gt); - var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt)); - iter.ch = gt + 1; - return selfClose ? "selfClose" : "regular"; - } - } - function toTagStart(iter) { - for (;;) { - var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1; - if (lt == -1) { if (prevLine(iter)) continue; else return; } - if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; } - xmlTagStart.lastIndex = lt; - iter.ch = lt; - var match = xmlTagStart.exec(iter.text); - if (match && match.index == lt) return match; - } - } - - function toNextTag(iter) { - for (;;) { - xmlTagStart.lastIndex = iter.ch; - var found = xmlTagStart.exec(iter.text); - if (!found) { if (nextLine(iter)) continue; else return; } - if (!tagAt(iter, found.index + 1)) { iter.ch = found.index + 1; continue; } - iter.ch = found.index + found[0].length; - return found; - } - } - function toPrevTag(iter) { - for (;;) { - var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1; - if (gt == -1) { if (prevLine(iter)) continue; else return; } - if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; } - var lastSlash = iter.text.lastIndexOf("/", gt); - var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt)); - iter.ch = gt + 1; - return selfClose ? "selfClose" : "regular"; - } - } - - function findMatchingClose(iter, tag) { - var stack = []; - for (;;) { - var next = toNextTag(iter), end, startLine = iter.line, startCh = iter.ch - (next ? next[0].length : 0); - if (!next || !(end = toTagEnd(iter))) return; - if (end == "selfClose") continue; - if (next[1]) { // closing tag - for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) { - stack.length = i; - break; - } - if (i < 0 && (!tag || tag == next[2])) return { - tag: next[2], - from: Pos(startLine, startCh), - to: Pos(iter.line, iter.ch) - }; - } else { // opening tag - stack.push(next[2]); - } - } - } - function findMatchingOpen(iter, tag) { - var stack = []; - for (;;) { - var prev = toPrevTag(iter); - if (!prev) return; - if (prev == "selfClose") { toTagStart(iter); continue; } - var endLine = iter.line, endCh = iter.ch; - var start = toTagStart(iter); - if (!start) return; - if (start[1]) { // closing tag - stack.push(start[2]); - } else { // opening tag - for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == start[2]) { - stack.length = i; - break; - } - if (i < 0 && (!tag || tag == start[2])) return { - tag: start[2], - from: Pos(iter.line, iter.ch), - to: Pos(endLine, endCh) - }; - } - } - } - - CodeMirror.registerHelper("fold", "xml", function(cm, start) { - var iter = new Iter(cm, start.line, 0); - for (;;) { - var openTag = toNextTag(iter), end; - if (!openTag || iter.line != start.line || !(end = toTagEnd(iter))) return; - if (!openTag[1] && end != "selfClose") { - var start = Pos(iter.line, iter.ch); - var close = findMatchingClose(iter, openTag[2]); - return close && {from: start, to: close.from}; - } - } - }); - CodeMirror.findMatchingTag = function(cm, pos, range) { - var iter = new Iter(cm, pos.line, pos.ch, range); - if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return; - var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch); - var start = end && toTagStart(iter); - if (!end || !start || cmp(iter, pos) > 0) return; - var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]}; - if (end == "selfClose") return {open: here, close: null, at: "open"}; - - if (start[1]) { // closing tag - return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"}; - } else { // opening tag - iter = new Iter(cm, to.line, to.ch, range); - return {open: here, close: findMatchingClose(iter, start[2]), at: "open"}; - } - }; - - CodeMirror.findEnclosingTag = function(cm, pos, range) { - var iter = new Iter(cm, pos.line, pos.ch, range); - for (;;) { - var open = findMatchingOpen(iter); - if (!open) break; - var forward = new Iter(cm, pos.line, pos.ch, range); - var close = findMatchingClose(forward, open.tag); - if (close) return {open: open, close: close}; - } - }; - - // Used by addon/edit/closetag.js - CodeMirror.scanForClosingTag = function(cm, pos, name, end) { - var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null); - return findMatchingClose(iter, name); - }; -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/index.html b/html/forums/admin/jscripts/codemirror/addon/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/addon/search/index.html b/html/forums/admin/jscripts/codemirror/addon/search/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/search/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/addon/search/match-highlighter.js b/html/forums/admin/jscripts/codemirror/addon/search/match-highlighter.js deleted file mode 100644 index e9a2272..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/search/match-highlighter.js +++ /dev/null @@ -1,128 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Highlighting text that matches the selection -// -// Defines an option highlightSelectionMatches, which, when enabled, -// will style strings that match the selection throughout the -// document. -// -// The option can be set to true to simply enable it, or to a -// {minChars, style, wordsOnly, showToken, delay} object to explicitly -// configure it. minChars is the minimum amount of characters that should be -// selected for the behavior to occur, and style is the token style to -// apply to the matches. This will be prefixed by "cm-" to create an -// actual CSS class name. If wordsOnly is enabled, the matches will be -// highlighted only if the selected text is a word. showToken, when enabled, -// will cause the current token to be highlighted when nothing is selected. -// delay is used to specify how much time to wait, in milliseconds, before -// highlighting the matches. - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var DEFAULT_MIN_CHARS = 2; - var DEFAULT_TOKEN_STYLE = "matchhighlight"; - var DEFAULT_DELAY = 100; - var DEFAULT_WORDS_ONLY = false; - - function State(options) { - if (typeof options == "object") { - this.minChars = options.minChars; - this.style = options.style; - this.showToken = options.showToken; - this.delay = options.delay; - this.wordsOnly = options.wordsOnly; - } - if (this.style == null) this.style = DEFAULT_TOKEN_STYLE; - if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS; - if (this.delay == null) this.delay = DEFAULT_DELAY; - if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY; - this.overlay = this.timeout = null; - } - - CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) { - var over = cm.state.matchHighlighter.overlay; - if (over) cm.removeOverlay(over); - clearTimeout(cm.state.matchHighlighter.timeout); - cm.state.matchHighlighter = null; - cm.off("cursorActivity", cursorActivity); - } - if (val) { - cm.state.matchHighlighter = new State(val); - highlightMatches(cm); - cm.on("cursorActivity", cursorActivity); - } - }); - - function cursorActivity(cm) { - var state = cm.state.matchHighlighter; - clearTimeout(state.timeout); - state.timeout = setTimeout(function() {highlightMatches(cm);}, state.delay); - } - - function highlightMatches(cm) { - cm.operation(function() { - var state = cm.state.matchHighlighter; - if (state.overlay) { - cm.removeOverlay(state.overlay); - state.overlay = null; - } - if (!cm.somethingSelected() && state.showToken) { - var re = state.showToken === true ? /[\w$]/ : state.showToken; - var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start; - while (start && re.test(line.charAt(start - 1))) --start; - while (end < line.length && re.test(line.charAt(end))) ++end; - if (start < end) - cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style)); - return; - } - var from = cm.getCursor("from"), to = cm.getCursor("to"); - if (from.line != to.line) return; - if (state.wordsOnly && !isWord(cm, from, to)) return; - var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, ""); - if (selection.length >= state.minChars) - cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style)); - }); - } - - function isWord(cm, from, to) { - var str = cm.getRange(from, to); - if (str.match(/^\w+$/) !== null) { - if (from.ch > 0) { - var pos = {line: from.line, ch: from.ch - 1}; - var chr = cm.getRange(pos, from); - if (chr.match(/\W/) === null) return false; - } - if (to.ch < cm.getLine(from.line).length) { - var pos = {line: to.line, ch: to.ch + 1}; - var chr = cm.getRange(to, pos); - if (chr.match(/\W/) === null) return false; - } - return true; - } else return false; - } - - function boundariesAround(stream, re) { - return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) && - (stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos))); - } - - function makeOverlay(query, hasBoundary, style) { - return {token: function(stream) { - if (stream.match(query) && - (!hasBoundary || boundariesAround(stream, hasBoundary))) - return style; - stream.next(); - stream.skipTo(query.charAt(0)) || stream.skipToEnd(); - }}; - } -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/search/matchesonscrollbar.css b/html/forums/admin/jscripts/codemirror/addon/search/matchesonscrollbar.css deleted file mode 100644 index 77efb38..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/search/matchesonscrollbar.css +++ /dev/null @@ -1,8 +0,0 @@ -.CodeMirror-search-match { - background: gold; - border-top: 1px solid orange; - border-bottom: 1px solid orange; - -moz-box-sizing: border-box; - box-sizing: border-box; - opacity: .5; -} diff --git a/html/forums/admin/jscripts/codemirror/addon/search/matchesonscrollbar.js b/html/forums/admin/jscripts/codemirror/addon/search/matchesonscrollbar.js deleted file mode 100644 index 937d3f7..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/search/matchesonscrollbar.js +++ /dev/null @@ -1,90 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, className) { - return new SearchAnnotation(this, query, caseFold, className); - }); - - function SearchAnnotation(cm, query, caseFold, className) { - this.cm = cm; - this.annotation = cm.annotateScrollbar(className || "CodeMirror-search-match"); - this.query = query; - this.caseFold = caseFold; - this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1}; - this.matches = []; - this.update = null; - - this.findMatches(); - this.annotation.update(this.matches); - - var self = this; - cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); }); - } - - var MAX_MATCHES = 1000; - - SearchAnnotation.prototype.findMatches = function() { - if (!this.gap) return; - for (var i = 0; i < this.matches.length; i++) { - var match = this.matches[i]; - if (match.from.line >= this.gap.to) break; - if (match.to.line >= this.gap.from) this.matches.splice(i--, 1); - } - var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold); - while (cursor.findNext()) { - var match = {from: cursor.from(), to: cursor.to()}; - if (match.from.line >= this.gap.to) break; - this.matches.splice(i++, 0, match); - if (this.matches.length > MAX_MATCHES) break; - } - this.gap = null; - }; - - function offsetLine(line, changeStart, sizeChange) { - if (line <= changeStart) return line; - return Math.max(changeStart, line + sizeChange); - } - - SearchAnnotation.prototype.onChange = function(change) { - var startLine = change.from.line; - var endLine = CodeMirror.changeEnd(change).line; - var sizeChange = endLine - change.to.line; - if (this.gap) { - this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line); - this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line); - } else { - this.gap = {from: change.from.line, to: endLine + 1}; - } - - if (sizeChange) for (var i = 0; i < this.matches.length; i++) { - var match = this.matches[i]; - var newFrom = offsetLine(match.from.line, startLine, sizeChange); - if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch); - var newTo = offsetLine(match.to.line, startLine, sizeChange); - if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch); - } - clearTimeout(this.update); - var self = this; - this.update = setTimeout(function() { self.updateAfterChange(); }, 250); - }; - - SearchAnnotation.prototype.updateAfterChange = function() { - this.findMatches(); - this.annotation.update(this.matches); - }; - - SearchAnnotation.prototype.clear = function() { - this.cm.off("change", this.changeHandler); - this.annotation.clear(); - }; -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/search/search.js b/html/forums/admin/jscripts/codemirror/addon/search/search.js deleted file mode 100644 index 0251067..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/search/search.js +++ /dev/null @@ -1,164 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Define search commands. Depends on dialog.js or another -// implementation of the openDialog method. - -// Replace works a little oddly -- it will do the replace on the next -// Ctrl-G (or whatever is bound to findNext) press. You prevent a -// replace by making sure the match is no longer selected when hitting -// Ctrl-G. - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - function searchOverlay(query, caseInsensitive) { - if (typeof query == "string") - query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g"); - else if (!query.global) - query = new RegExp(query.source, query.ignoreCase ? "gi" : "g"); - - return {token: function(stream) { - query.lastIndex = stream.pos; - var match = query.exec(stream.string); - if (match && match.index == stream.pos) { - stream.pos += match[0].length; - return "searching"; - } else if (match) { - stream.pos = match.index; - } else { - stream.skipToEnd(); - } - }}; - } - - function SearchState() { - this.posFrom = this.posTo = this.query = null; - this.overlay = null; - } - function getSearchState(cm) { - return cm.state.search || (cm.state.search = new SearchState()); - } - function queryCaseInsensitive(query) { - return typeof query == "string" && query == query.toLowerCase(); - } - function getSearchCursor(cm, query, pos) { - // Heuristic: if the query string is all lowercase, do a case insensitive search. - return cm.getSearchCursor(query, pos, queryCaseInsensitive(query)); - } - function dialog(cm, text, shortText, deflt, f) { - if (cm.openDialog) cm.openDialog(text, f, {value: deflt}); - else f(prompt(shortText, deflt)); - } - function confirmDialog(cm, text, shortText, fs) { - if (cm.openConfirm) cm.openConfirm(text, fs); - else if (confirm(shortText)) fs[0](); - } - function parseQuery(query) { - var isRE = query.match(/^\/(.*)\/([a-z]*)$/); - if (isRE) { - try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); } - catch(e) {} // Not a regular expression after all, do a string search - } - if (typeof query == "string" ? query == "" : query.test("")) - query = /x^/; - return query; - } - var queryDialog = - 'Search: (Use /re/ syntax for regexp search)'; - function doSearch(cm, rev) { - var state = getSearchState(cm); - if (state.query) return findNext(cm, rev); - dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) { - cm.operation(function() { - if (!query || state.query) return; - state.query = parseQuery(query); - cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); - state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query)); - cm.addOverlay(state.overlay); - if (cm.showMatchesOnScrollbar) { - if (state.annotate) { state.annotate.clear(); state.annotate = null; } - state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query)); - } - state.posFrom = state.posTo = cm.getCursor(); - findNext(cm, rev); - }); - }); - } - function findNext(cm, rev) {cm.operation(function() { - var state = getSearchState(cm); - var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo); - if (!cursor.find(rev)) { - cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0)); - if (!cursor.find(rev)) return; - } - cm.setSelection(cursor.from(), cursor.to()); - cm.scrollIntoView({from: cursor.from(), to: cursor.to()}); - state.posFrom = cursor.from(); state.posTo = cursor.to(); - });} - function clearSearch(cm) {cm.operation(function() { - var state = getSearchState(cm); - if (!state.query) return; - state.query = null; - cm.removeOverlay(state.overlay); - if (state.annotate) { state.annotate.clear(); state.annotate = null; } - });} - - var replaceQueryDialog = - 'Replace: (Use /re/ syntax for regexp search)'; - var replacementQueryDialog = 'With: '; - var doReplaceConfirm = "Replace? "; - function replace(cm, all) { - if (cm.getOption("readOnly")) return; - dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) { - if (!query) return; - query = parseQuery(query); - dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) { - if (all) { - cm.operation(function() { - for (var cursor = getSearchCursor(cm, query); cursor.findNext();) { - if (typeof query != "string") { - var match = cm.getRange(cursor.from(), cursor.to()).match(query); - cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];})); - } else cursor.replace(text); - } - }); - } else { - clearSearch(cm); - var cursor = getSearchCursor(cm, query, cm.getCursor()); - var advance = function() { - var start = cursor.from(), match; - if (!(match = cursor.findNext())) { - cursor = getSearchCursor(cm, query); - if (!(match = cursor.findNext()) || - (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return; - } - cm.setSelection(cursor.from(), cursor.to()); - cm.scrollIntoView({from: cursor.from(), to: cursor.to()}); - confirmDialog(cm, doReplaceConfirm, "Replace?", - [function() {doReplace(match);}, advance]); - }; - var doReplace = function(match) { - cursor.replace(typeof query == "string" ? text : - text.replace(/\$(\d)/g, function(_, i) {return match[i];})); - advance(); - }; - advance(); - } - }); - }); - } - - CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);}; - CodeMirror.commands.findNext = doSearch; - CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);}; - CodeMirror.commands.clearSearch = clearSearch; - CodeMirror.commands.replace = replace; - CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);}; -}); diff --git a/html/forums/admin/jscripts/codemirror/addon/search/searchcursor.js b/html/forums/admin/jscripts/codemirror/addon/search/searchcursor.js deleted file mode 100644 index 55c108b..0000000 --- a/html/forums/admin/jscripts/codemirror/addon/search/searchcursor.js +++ /dev/null @@ -1,189 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - var Pos = CodeMirror.Pos; - - function SearchCursor(doc, query, pos, caseFold) { - this.atOccurrence = false; this.doc = doc; - if (caseFold == null && typeof query == "string") caseFold = false; - - pos = pos ? doc.clipPos(pos) : Pos(0, 0); - this.pos = {from: pos, to: pos}; - - // The matches method is filled in based on the type of query. - // It takes a position and a direction, and returns an object - // describing the next occurrence of the query, or null if no - // more matches were found. - if (typeof query != "string") { // Regexp match - if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g"); - this.matches = function(reverse, pos) { - if (reverse) { - query.lastIndex = 0; - var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start; - for (;;) { - query.lastIndex = cutOff; - var newMatch = query.exec(line); - if (!newMatch) break; - match = newMatch; - start = match.index; - cutOff = match.index + (match[0].length || 1); - if (cutOff == line.length) break; - } - var matchLen = (match && match[0].length) || 0; - if (!matchLen) { - if (start == 0 && line.length == 0) {match = undefined;} - else if (start != doc.getLine(pos.line).length) { - matchLen++; - } - } - } else { - query.lastIndex = pos.ch; - var line = doc.getLine(pos.line), match = query.exec(line); - var matchLen = (match && match[0].length) || 0; - var start = match && match.index; - if (start + matchLen != line.length && !matchLen) matchLen = 1; - } - if (match && matchLen) - return {from: Pos(pos.line, start), - to: Pos(pos.line, start + matchLen), - match: match}; - }; - } else { // String query - var origQuery = query; - if (caseFold) query = query.toLowerCase(); - var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;}; - var target = query.split("\n"); - // Different methods for single-line and multi-line queries - if (target.length == 1) { - if (!query.length) { - // Empty string would match anything and never progress, so - // we define it to match nothing instead. - this.matches = function() {}; - } else { - this.matches = function(reverse, pos) { - if (reverse) { - var orig = doc.getLine(pos.line).slice(0, pos.ch), line = fold(orig); - var match = line.lastIndexOf(query); - if (match > -1) { - match = adjustPos(orig, line, match); - return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)}; - } - } else { - var orig = doc.getLine(pos.line).slice(pos.ch), line = fold(orig); - var match = line.indexOf(query); - if (match > -1) { - match = adjustPos(orig, line, match) + pos.ch; - return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)}; - } - } - }; - } - } else { - var origTarget = origQuery.split("\n"); - this.matches = function(reverse, pos) { - var last = target.length - 1; - if (reverse) { - if (pos.line - (target.length - 1) < doc.firstLine()) return; - if (fold(doc.getLine(pos.line).slice(0, origTarget[last].length)) != target[target.length - 1]) return; - var to = Pos(pos.line, origTarget[last].length); - for (var ln = pos.line - 1, i = last - 1; i >= 1; --i, --ln) - if (target[i] != fold(doc.getLine(ln))) return; - var line = doc.getLine(ln), cut = line.length - origTarget[0].length; - if (fold(line.slice(cut)) != target[0]) return; - return {from: Pos(ln, cut), to: to}; - } else { - if (pos.line + (target.length - 1) > doc.lastLine()) return; - var line = doc.getLine(pos.line), cut = line.length - origTarget[0].length; - if (fold(line.slice(cut)) != target[0]) return; - var from = Pos(pos.line, cut); - for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln) - if (target[i] != fold(doc.getLine(ln))) return; - if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return; - return {from: from, to: Pos(ln, origTarget[last].length)}; - } - }; - } - } - } - - SearchCursor.prototype = { - findNext: function() {return this.find(false);}, - findPrevious: function() {return this.find(true);}, - - find: function(reverse) { - var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to); - function savePosAndFail(line) { - var pos = Pos(line, 0); - self.pos = {from: pos, to: pos}; - self.atOccurrence = false; - return false; - } - - for (;;) { - if (this.pos = this.matches(reverse, pos)) { - this.atOccurrence = true; - return this.pos.match || true; - } - if (reverse) { - if (!pos.line) return savePosAndFail(0); - pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length); - } - else { - var maxLine = this.doc.lineCount(); - if (pos.line == maxLine - 1) return savePosAndFail(maxLine); - pos = Pos(pos.line + 1, 0); - } - } - }, - - from: function() {if (this.atOccurrence) return this.pos.from;}, - to: function() {if (this.atOccurrence) return this.pos.to;}, - - replace: function(newText) { - if (!this.atOccurrence) return; - var lines = CodeMirror.splitLines(newText); - this.doc.replaceRange(lines, this.pos.from, this.pos.to); - this.pos.to = Pos(this.pos.from.line + lines.length - 1, - lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0)); - } - }; - - // Maps a position in a case-folded line back to a position in the original line - // (compensating for codepoints increasing in number during folding) - function adjustPos(orig, folded, pos) { - if (orig.length == folded.length) return pos; - for (var pos1 = Math.min(pos, orig.length);;) { - var len1 = orig.slice(0, pos1).toLowerCase().length; - if (len1 < pos) ++pos1; - else if (len1 > pos) --pos1; - else return pos1; - } - } - - CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) { - return new SearchCursor(this.doc, query, pos, caseFold); - }); - CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) { - return new SearchCursor(this, query, pos, caseFold); - }); - - CodeMirror.defineExtension("selectMatches", function(query, caseFold) { - var ranges = [], next; - var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold); - while (next = cur.findNext()) { - if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break; - ranges.push({anchor: cur.from(), head: cur.to()}); - } - if (ranges.length) - this.setSelections(ranges, 0); - }); -}); diff --git a/html/forums/admin/jscripts/codemirror/index.html b/html/forums/admin/jscripts/codemirror/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/lib/codemirror.css b/html/forums/admin/jscripts/codemirror/lib/codemirror.css deleted file mode 100644 index 8cecd76..0000000 --- a/html/forums/admin/jscripts/codemirror/lib/codemirror.css +++ /dev/null @@ -1,309 +0,0 @@ -/* BASICS */ - -.CodeMirror { - /* Set height, width, borders, and global font properties here */ - font-family: monospace; - height: 300px; -} - -/* PADDING */ - -.CodeMirror-lines { - padding: 4px 0; /* Vertical padding around content */ -} -.CodeMirror pre { - padding: 0 4px; /* Horizontal padding of content */ -} - -.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - background-color: white; /* The little square between H and V scrollbars */ -} - -/* GUTTER */ - -.CodeMirror-gutters { - border-right: 1px solid #ddd; - background-color: #f7f7f7; - white-space: nowrap; -} -.CodeMirror-linenumbers {} -.CodeMirror-linenumber { - padding: 0 3px 0 5px; - min-width: 20px; - text-align: right; - color: #999; - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -.CodeMirror-guttermarker { color: black; } -.CodeMirror-guttermarker-subtle { color: #999; } - -/* CURSOR */ - -.CodeMirror div.CodeMirror-cursor { - border-left: 1px solid black; -} -/* Shown when moving in bi-directional text */ -.CodeMirror div.CodeMirror-secondarycursor { - border-left: 1px solid silver; -} -.CodeMirror.cm-fat-cursor div.CodeMirror-cursor { - width: auto; - border: 0; - background: #7e7; -} -.CodeMirror.cm-fat-cursor div.CodeMirror-cursors { - z-index: 1; -} - -.cm-animate-fat-cursor { - width: auto; - border: 0; - -webkit-animation: blink 1.06s steps(1) infinite; - -moz-animation: blink 1.06s steps(1) infinite; - animation: blink 1.06s steps(1) infinite; -} -@-moz-keyframes blink { - 0% { background: #7e7; } - 50% { background: none; } - 100% { background: #7e7; } -} -@-webkit-keyframes blink { - 0% { background: #7e7; } - 50% { background: none; } - 100% { background: #7e7; } -} -@keyframes blink { - 0% { background: #7e7; } - 50% { background: none; } - 100% { background: #7e7; } -} - -/* Can style cursor different in overwrite (non-insert) mode */ -div.CodeMirror-overwrite div.CodeMirror-cursor {} - -.cm-tab { display: inline-block; text-decoration: inherit; } - -.CodeMirror-ruler { - border-left: 1px solid #ccc; - position: absolute; -} - -/* DEFAULT THEME */ - -.cm-s-default .cm-keyword {color: #708;} -.cm-s-default .cm-atom {color: #219;} -.cm-s-default .cm-number {color: #164;} -.cm-s-default .cm-def {color: #00f;} -.cm-s-default .cm-variable, -.cm-s-default .cm-punctuation, -.cm-s-default .cm-property, -.cm-s-default .cm-operator {} -.cm-s-default .cm-variable-2 {color: #05a;} -.cm-s-default .cm-variable-3 {color: #085;} -.cm-s-default .cm-comment {color: #a50;} -.cm-s-default .cm-string {color: #a11;} -.cm-s-default .cm-string-2 {color: #f50;} -.cm-s-default .cm-meta {color: #555;} -.cm-s-default .cm-qualifier {color: #555;} -.cm-s-default .cm-builtin {color: #30a;} -.cm-s-default .cm-bracket {color: #997;} -.cm-s-default .cm-tag {color: #170;} -.cm-s-default .cm-attribute {color: #00c;} -.cm-s-default .cm-header {color: blue;} -.cm-s-default .cm-quote {color: #090;} -.cm-s-default .cm-hr {color: #999;} -.cm-s-default .cm-link {color: #00c;} - -.cm-negative {color: #d44;} -.cm-positive {color: #292;} -.cm-header, .cm-strong {font-weight: bold;} -.cm-em {font-style: italic;} -.cm-link {text-decoration: underline;} -.cm-strikethrough {text-decoration: line-through;} - -.cm-s-default .cm-error {color: #f00;} -.cm-invalidchar {color: #f00;} - -/* Default styles for common addons */ - -div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} -div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} -.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } -.CodeMirror-activeline-background {background: #e8f2ff;} - -/* STOP */ - -/* The rest of this file contains styles related to the mechanics of - the editor. You probably shouldn't touch them. */ - -.CodeMirror { - line-height: 1; - position: relative; - overflow: hidden; - background: white; - color: black; -} - -.CodeMirror-scroll { - overflow: scroll !important; /* Things will break if this is overridden */ - /* 30px is the magic margin used to hide the element's real scrollbars */ - /* See overflow: hidden in .CodeMirror */ - margin-bottom: -30px; margin-right: -30px; - padding-bottom: 30px; - height: 100%; - outline: none; /* Prevent dragging from highlighting the element */ - position: relative; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -.CodeMirror-sizer { - position: relative; - border-right: 30px solid transparent; - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -/* The fake, visible scrollbars. Used to force redraw during scrolling - before actuall scrolling happens, thus preventing shaking and - flickering artifacts. */ -.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - position: absolute; - z-index: 6; - display: none; -} -.CodeMirror-vscrollbar { - right: 0; top: 0; - overflow-x: hidden; - overflow-y: scroll; -} -.CodeMirror-hscrollbar { - bottom: 0; left: 0; - overflow-y: hidden; - overflow-x: scroll; -} -.CodeMirror-scrollbar-filler { - right: 0; bottom: 0; -} -.CodeMirror-gutter-filler { - left: 0; bottom: 0; -} - -.CodeMirror-gutters { - position: absolute; left: 0; top: 0; - z-index: 3; -} -.CodeMirror-gutter { - white-space: normal; - height: 100%; - -moz-box-sizing: content-box; - box-sizing: content-box; - display: inline-block; - margin-bottom: -30px; - /* Hack to make IE7 behave */ - *zoom:1; - *display:inline; -} -.CodeMirror-gutter-wrapper { - position: absolute; - z-index: 4; - height: 100%; -} -.CodeMirror-gutter-elt { - position: absolute; - cursor: default; - z-index: 4; -} - -.CodeMirror-lines { - cursor: text; - min-height: 1px; /* prevents collapsing before first draw */ -} -.CodeMirror pre { - /* Reset some styles that the rest of the page might have set */ - -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; - border-width: 0; - background: transparent; - font-family: inherit; - font-size: inherit; - margin: 0; - white-space: pre; - word-wrap: normal; - line-height: inherit; - color: inherit; - z-index: 2; - position: relative; - overflow: visible; -} -.CodeMirror-wrap pre { - word-wrap: break-word; - white-space: pre-wrap; - word-break: normal; -} - -.CodeMirror-linebackground { - position: absolute; - left: 0; right: 0; top: 0; bottom: 0; - z-index: 0; -} - -.CodeMirror-linewidget { - position: relative; - z-index: 2; - overflow: auto; -} - -.CodeMirror-widget {} - -.CodeMirror-measure { - position: absolute; - width: 100%; - height: 0; - overflow: hidden; - visibility: hidden; -} -.CodeMirror-measure pre { position: static; } - -.CodeMirror div.CodeMirror-cursor { - position: absolute; - border-right: none; - width: 0; -} - -div.CodeMirror-cursors { - visibility: hidden; - position: relative; - z-index: 3; -} -.CodeMirror-focused div.CodeMirror-cursors { - visibility: visible; -} - -.CodeMirror-selected { background: #d9d9d9; } -.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } -.CodeMirror-crosshair { cursor: crosshair; } - -.cm-searching { - background: #ffa; - background: rgba(255, 255, 0, .4); -} - -/* IE7 hack to prevent it from returning funny offsetTops on the spans */ -.CodeMirror span { *vertical-align: text-bottom; } - -/* Used to force a border model for a node */ -.cm-force-border { padding-right: .1px; } - -@media print { - /* Hide the cursor when printing */ - .CodeMirror div.CodeMirror-cursors { - visibility: hidden; - } -} - -/* See issue #2901 */ -.cm-tab-wrap-hack:after { content: ''; } - -/* Help users use markselection to safely style text background */ -span.CodeMirror-selectedtext { background: none; } diff --git a/html/forums/admin/jscripts/codemirror/lib/codemirror.js b/html/forums/admin/jscripts/codemirror/lib/codemirror.js deleted file mode 100644 index 03a34db..0000000 --- a/html/forums/admin/jscripts/codemirror/lib/codemirror.js +++ /dev/null @@ -1,8045 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// This is CodeMirror (http://codemirror.net), a code editor -// implemented in JavaScript on top of the browser's DOM. -// -// You can find some technical background for some of the code below -// at http://marijnhaverbeke.nl/blog/#cm-internals . - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - module.exports = mod(); - else if (typeof define == "function" && define.amd) // AMD - return define([], mod); - else // Plain browser env - this.CodeMirror = mod(); -})(function() { - "use strict"; - - // BROWSER SNIFFING - - // Kludges for bugs and behavior differences that can't be feature - // detected are enabled based on userAgent etc sniffing. - - var gecko = /gecko\/\d/i.test(navigator.userAgent); - // ie_uptoN means Internet Explorer version N or lower - var ie_upto10 = /MSIE \d/.test(navigator.userAgent); - var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent); - var ie = ie_upto10 || ie_11up; - var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]); - var webkit = /WebKit\//.test(navigator.userAgent); - var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent); - var chrome = /Chrome\//.test(navigator.userAgent); - var presto = /Opera\//.test(navigator.userAgent); - var safari = /Apple Computer/.test(navigator.vendor); - var khtml = /KHTML\//.test(navigator.userAgent); - var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent); - var phantom = /PhantomJS/.test(navigator.userAgent); - - var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent); - // This is woefully incomplete. Suggestions for alternative methods welcome. - var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent); - var mac = ios || /Mac/.test(navigator.platform); - var windows = /win/i.test(navigator.platform); - - var presto_version = presto && navigator.userAgent.match(/Version\/(\d*\.\d*)/); - if (presto_version) presto_version = Number(presto_version[1]); - if (presto_version && presto_version >= 15) { presto = false; webkit = true; } - // Some browsers use the wrong event properties to signal cmd/ctrl on OS X - var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); - var captureRightClick = gecko || (ie && ie_version >= 9); - - // Optimize some code when these features are not used. - var sawReadOnlySpans = false, sawCollapsedSpans = false; - - // EDITOR CONSTRUCTOR - - // A CodeMirror instance represents an editor. This is the object - // that user code is usually dealing with. - - function CodeMirror(place, options) { - if (!(this instanceof CodeMirror)) return new CodeMirror(place, options); - - this.options = options = options ? copyObj(options) : {}; - // Determine effective options based on given values and defaults. - copyObj(defaults, options, false); - setGuttersForLineNumbers(options); - - var doc = options.value; - if (typeof doc == "string") doc = new Doc(doc, options.mode); - this.doc = doc; - - var display = this.display = new Display(place, doc); - display.wrapper.CodeMirror = this; - updateGutters(this); - themeChanged(this); - if (options.lineWrapping) - this.display.wrapper.className += " CodeMirror-wrap"; - if (options.autofocus && !mobile) focusInput(this); - initScrollbars(this); - - this.state = { - keyMaps: [], // stores maps added by addKeyMap - overlays: [], // highlighting overlays, as added by addOverlay - modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info - overwrite: false, focused: false, - suppressEdits: false, // used to disable editing during key handlers when in readOnly mode - pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in readInput - draggingText: false, - highlight: new Delayed(), // stores highlight worker timeout - keySeq: null // Unfinished key sequence - }; - - // Override magic textarea content restore that IE sometimes does - // on our hidden textarea on reload - if (ie && ie_version < 11) setTimeout(bind(resetInput, this, true), 20); - - registerEventHandlers(this); - ensureGlobalHandlers(); - - startOperation(this); - this.curOp.forceUpdate = true; - attachDoc(this, doc); - - if ((options.autofocus && !mobile) || activeElt() == display.input) - setTimeout(bind(onFocus, this), 20); - else - onBlur(this); - - for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt)) - optionHandlers[opt](this, options[opt], Init); - maybeUpdateLineNumberWidth(this); - for (var i = 0; i < initHooks.length; ++i) initHooks[i](this); - endOperation(this); - // Suppress optimizelegibility in Webkit, since it breaks text - // measuring on line wrapping boundaries. - if (webkit && options.lineWrapping && - getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") - display.lineDiv.style.textRendering = "auto"; - } - - // DISPLAY CONSTRUCTOR - - // The display handles the DOM integration, both for input reading - // and content drawing. It holds references to DOM nodes and - // display-related state. - - function Display(place, doc) { - var d = this; - - // The semihidden textarea that is focused when the editor is - // focused, and receives input. - var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none"); - // The textarea is kept positioned near the cursor to prevent the - // fact that it'll be scrolled into view on input from scrolling - // our fake cursor out of view. On webkit, when wrap=off, paste is - // very slow. So make the area wide instead. - if (webkit) input.style.width = "1000px"; - else input.setAttribute("wrap", "off"); - // If border: 0; -- iOS fails to open keyboard (issue #1287) - if (ios) input.style.border = "1px solid black"; - input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false"); - - // Wraps and hides input textarea - d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); - // Covers bottom-right square when both scrollbars are present. - d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); - d.scrollbarFiller.setAttribute("not-content", "true"); - // Covers bottom of gutter when coverGutterNextToScrollbar is on - // and h scrollbar is present. - d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); - d.gutterFiller.setAttribute("not-content", "true"); - // Will contain the actual code, positioned to cover the viewport. - d.lineDiv = elt("div", null, "CodeMirror-code"); - // Elements are added to these to represent selection and cursors. - d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); - d.cursorDiv = elt("div", null, "CodeMirror-cursors"); - // A visibility: hidden element used to find the size of things. - d.measure = elt("div", null, "CodeMirror-measure"); - // When lines outside of the viewport are measured, they are drawn in this. - d.lineMeasure = elt("div", null, "CodeMirror-measure"); - // Wraps everything that needs to exist inside the vertically-padded coordinate system - d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], - null, "position: relative; outline: none"); - // Moved around its parent to cover visible view. - d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative"); - // Set to the height of the document, allowing scrolling. - d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); - d.sizerWidth = null; - // Behavior of elts with overflow: auto and padding is - // inconsistent across browsers. This is used to ensure the - // scrollable area is big enough. - d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); - // Will contain the gutters, if any. - d.gutters = elt("div", null, "CodeMirror-gutters"); - d.lineGutter = null; - // Actual scrollable element. - d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); - d.scroller.setAttribute("tabIndex", "-1"); - // The element in which the editor lives. - d.wrapper = elt("div", [d.inputDiv, d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); - - // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) - if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } - // Needed to hide big blue blinking cursor on Mobile Safari - if (ios) input.style.width = "0px"; - if (!webkit) d.scroller.draggable = true; - // Needed to handle Tab key in KHTML - if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; } - - if (place) { - if (place.appendChild) place.appendChild(d.wrapper); - else place(d.wrapper); - } - - // Current rendered range (may be bigger than the view window). - d.viewFrom = d.viewTo = doc.first; - d.reportedViewFrom = d.reportedViewTo = doc.first; - // Information about the rendered lines. - d.view = []; - d.renderedView = null; - // Holds info about a single rendered line when it was rendered - // for measurement, while not in view. - d.externalMeasured = null; - // Empty space (in pixels) above the view - d.viewOffset = 0; - d.lastWrapHeight = d.lastWrapWidth = 0; - d.updateLineNumbers = null; - - d.nativeBarWidth = d.barHeight = d.barWidth = 0; - d.scrollbarsClipped = false; - - // Used to only resize the line number gutter when necessary (when - // the amount of lines crosses a boundary that makes its width change) - d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; - // See readInput and resetInput - d.prevInput = ""; - // Set to true when a non-horizontal-scrolling line widget is - // added. As an optimization, line widget aligning is skipped when - // this is false. - d.alignWidgets = false; - // Flag that indicates whether we expect input to appear real soon - // now (after some event like 'keypress' or 'input') and are - // polling intensively. - d.pollingFast = false; - // Self-resetting timeout for the poller - d.poll = new Delayed(); - - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; - - // Tracks when resetInput has punted to just putting a short - // string into the textarea instead of the full selection. - d.inaccurateSelection = false; - - // Tracks the maximum line length so that the horizontal scrollbar - // can be kept static when scrolling. - d.maxLine = null; - d.maxLineLength = 0; - d.maxLineChanged = false; - - // Used for measuring wheel scrolling granularity - d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; - - // True when shift is held down. - d.shift = false; - - // Used to track whether anything happened since the context menu - // was opened. - d.selForContextMenu = null; - } - - // STATE UPDATES - - // Used to get the editor into a consistent state again when options change. - - function loadMode(cm) { - cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption); - resetModeState(cm); - } - - function resetModeState(cm) { - cm.doc.iter(function(line) { - if (line.stateAfter) line.stateAfter = null; - if (line.styles) line.styles = null; - }); - cm.doc.frontier = cm.doc.first; - startWorker(cm, 100); - cm.state.modeGen++; - if (cm.curOp) regChange(cm); - } - - function wrappingChanged(cm) { - if (cm.options.lineWrapping) { - addClass(cm.display.wrapper, "CodeMirror-wrap"); - cm.display.sizer.style.minWidth = ""; - cm.display.sizerWidth = null; - } else { - rmClass(cm.display.wrapper, "CodeMirror-wrap"); - findMaxLine(cm); - } - estimateLineHeights(cm); - regChange(cm); - clearCaches(cm); - setTimeout(function(){updateScrollbars(cm);}, 100); - } - - // Returns a function that estimates the height of a line, to use as - // first approximation until the line becomes visible (and is thus - // properly measurable). - function estimateHeight(cm) { - var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; - var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); - return function(line) { - if (lineIsHidden(cm.doc, line)) return 0; - - var widgetsHeight = 0; - if (line.widgets) for (var i = 0; i < line.widgets.length; i++) { - if (line.widgets[i].height) widgetsHeight += line.widgets[i].height; - } - - if (wrapping) - return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th; - else - return widgetsHeight + th; - }; - } - - function estimateLineHeights(cm) { - var doc = cm.doc, est = estimateHeight(cm); - doc.iter(function(line) { - var estHeight = est(line); - if (estHeight != line.height) updateLineHeight(line, estHeight); - }); - } - - function themeChanged(cm) { - cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + - cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); - clearCaches(cm); - } - - function guttersChanged(cm) { - updateGutters(cm); - regChange(cm); - setTimeout(function(){alignHorizontally(cm);}, 20); - } - - // Rebuild the gutter elements, ensure the margin to the left of the - // code matches their width. - function updateGutters(cm) { - var gutters = cm.display.gutters, specs = cm.options.gutters; - removeChildren(gutters); - for (var i = 0; i < specs.length; ++i) { - var gutterClass = specs[i]; - var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)); - if (gutterClass == "CodeMirror-linenumbers") { - cm.display.lineGutter = gElt; - gElt.style.width = (cm.display.lineNumWidth || 1) + "px"; - } - } - gutters.style.display = i ? "" : "none"; - updateGutterSpace(cm); - } - - function updateGutterSpace(cm) { - var width = cm.display.gutters.offsetWidth; - cm.display.sizer.style.marginLeft = width + "px"; - } - - // Compute the character length of a line, taking into account - // collapsed ranges (see markText) that might hide parts, and join - // other lines onto it. - function lineLength(line) { - if (line.height == 0) return 0; - var len = line.text.length, merged, cur = line; - while (merged = collapsedSpanAtStart(cur)) { - var found = merged.find(0, true); - cur = found.from.line; - len += found.from.ch - found.to.ch; - } - cur = line; - while (merged = collapsedSpanAtEnd(cur)) { - var found = merged.find(0, true); - len -= cur.text.length - found.from.ch; - cur = found.to.line; - len += cur.text.length - found.to.ch; - } - return len; - } - - // Find the longest line in the document. - function findMaxLine(cm) { - var d = cm.display, doc = cm.doc; - d.maxLine = getLine(doc, doc.first); - d.maxLineLength = lineLength(d.maxLine); - d.maxLineChanged = true; - doc.iter(function(line) { - var len = lineLength(line); - if (len > d.maxLineLength) { - d.maxLineLength = len; - d.maxLine = line; - } - }); - } - - // Make sure the gutters options contains the element - // "CodeMirror-linenumbers" when the lineNumbers option is true. - function setGuttersForLineNumbers(options) { - var found = indexOf(options.gutters, "CodeMirror-linenumbers"); - if (found == -1 && options.lineNumbers) { - options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]); - } else if (found > -1 && !options.lineNumbers) { - options.gutters = options.gutters.slice(0); - options.gutters.splice(found, 1); - } - } - - // SCROLLBARS - - // Prepare DOM reads needed to update the scrollbars. Done in one - // shot to minimize update/measure roundtrips. - function measureForScrollbars(cm) { - var d = cm.display, gutterW = d.gutters.offsetWidth; - var docH = Math.round(cm.doc.height + paddingVert(cm.display)); - return { - clientHeight: d.scroller.clientHeight, - viewHeight: d.wrapper.clientHeight, - scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, - viewWidth: d.wrapper.clientWidth, - barLeft: cm.options.fixedGutter ? gutterW : 0, - docHeight: docH, - scrollHeight: docH + scrollGap(cm) + d.barHeight, - nativeBarWidth: d.nativeBarWidth, - gutterWidth: gutterW - }; - } - - function NativeScrollbars(place, scroll, cm) { - this.cm = cm; - var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); - var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); - place(vert); place(horiz); - - on(vert, "scroll", function() { - if (vert.clientHeight) scroll(vert.scrollTop, "vertical"); - }); - on(horiz, "scroll", function() { - if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal"); - }); - - this.checkedOverlay = false; - // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). - if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; - } - - NativeScrollbars.prototype = copyObj({ - update: function(measure) { - var needsH = measure.scrollWidth > measure.clientWidth + 1; - var needsV = measure.scrollHeight > measure.clientHeight + 1; - var sWidth = measure.nativeBarWidth; - - if (needsV) { - this.vert.style.display = "block"; - this.vert.style.bottom = needsH ? sWidth + "px" : "0"; - var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); - // A bug in IE8 can cause this value to be negative, so guard it. - this.vert.firstChild.style.height = - Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; - } else { - this.vert.style.display = ""; - this.vert.firstChild.style.height = "0"; - } - - if (needsH) { - this.horiz.style.display = "block"; - this.horiz.style.right = needsV ? sWidth + "px" : "0"; - this.horiz.style.left = measure.barLeft + "px"; - var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); - this.horiz.firstChild.style.width = - (measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; - } else { - this.horiz.style.display = ""; - this.horiz.firstChild.style.width = "0"; - } - - if (!this.checkedOverlay && measure.clientHeight > 0) { - if (sWidth == 0) this.overlayHack(); - this.checkedOverlay = true; - } - - return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}; - }, - setScrollLeft: function(pos) { - if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos; - }, - setScrollTop: function(pos) { - if (this.vert.scrollTop != pos) this.vert.scrollTop = pos; - }, - overlayHack: function() { - var w = mac && !mac_geMountainLion ? "12px" : "18px"; - this.horiz.style.minHeight = this.vert.style.minWidth = w; - var self = this; - var barMouseDown = function(e) { - if (e_target(e) != self.vert && e_target(e) != self.horiz) - operation(self.cm, onMouseDown)(e); - }; - on(this.vert, "mousedown", barMouseDown); - on(this.horiz, "mousedown", barMouseDown); - }, - clear: function() { - var parent = this.horiz.parentNode; - parent.removeChild(this.horiz); - parent.removeChild(this.vert); - } - }, NativeScrollbars.prototype); - - function NullScrollbars() {} - - NullScrollbars.prototype = copyObj({ - update: function() { return {bottom: 0, right: 0}; }, - setScrollLeft: function() {}, - setScrollTop: function() {}, - clear: function() {} - }, NullScrollbars.prototype); - - CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; - - function initScrollbars(cm) { - if (cm.display.scrollbars) { - cm.display.scrollbars.clear(); - if (cm.display.scrollbars.addClass) - rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); - } - - cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) { - cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); - on(node, "mousedown", function() { - if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); - }); - node.setAttribute("not-content", "true"); - }, function(pos, axis) { - if (axis == "horizontal") setScrollLeft(cm, pos); - else setScrollTop(cm, pos); - }, cm); - if (cm.display.scrollbars.addClass) - addClass(cm.display.wrapper, cm.display.scrollbars.addClass); - } - - function updateScrollbars(cm, measure) { - if (!measure) measure = measureForScrollbars(cm); - var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; - updateScrollbarsInner(cm, measure); - for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { - if (startWidth != cm.display.barWidth && cm.options.lineWrapping) - updateHeightsInViewport(cm); - updateScrollbarsInner(cm, measureForScrollbars(cm)); - startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; - } - } - - // Re-synchronize the fake scrollbars with the actual size of the - // content. - function updateScrollbarsInner(cm, measure) { - var d = cm.display; - var sizes = d.scrollbars.update(measure); - - d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; - d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; - - if (sizes.right && sizes.bottom) { - d.scrollbarFiller.style.display = "block"; - d.scrollbarFiller.style.height = sizes.bottom + "px"; - d.scrollbarFiller.style.width = sizes.right + "px"; - } else d.scrollbarFiller.style.display = ""; - if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { - d.gutterFiller.style.display = "block"; - d.gutterFiller.style.height = sizes.bottom + "px"; - d.gutterFiller.style.width = measure.gutterWidth + "px"; - } else d.gutterFiller.style.display = ""; - } - - // Compute the lines that are visible in a given viewport (defaults - // the the current scroll position). viewport may contain top, - // height, and ensure (see op.scrollToPos) properties. - function visibleLines(display, doc, viewport) { - var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; - top = Math.floor(top - paddingTop(display)); - var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; - - var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); - // Ensure is a {from: {line, ch}, to: {line, ch}} object, and - // forces those lines into the viewport (if possible). - if (viewport && viewport.ensure) { - var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; - if (ensureFrom < from) { - from = ensureFrom; - to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); - } else if (Math.min(ensureTo, doc.lastLine()) >= to) { - from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); - to = ensureTo; - } - } - return {from: from, to: Math.max(to, from + 1)}; - } - - // LINE NUMBERS - - // Re-align line numbers and gutter marks to compensate for - // horizontal scrolling. - function alignHorizontally(cm) { - var display = cm.display, view = display.view; - if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return; - var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; - var gutterW = display.gutters.offsetWidth, left = comp + "px"; - for (var i = 0; i < view.length; i++) if (!view[i].hidden) { - if (cm.options.fixedGutter && view[i].gutter) - view[i].gutter.style.left = left; - var align = view[i].alignable; - if (align) for (var j = 0; j < align.length; j++) - align[j].style.left = left; - } - if (cm.options.fixedGutter) - display.gutters.style.left = (comp + gutterW) + "px"; - } - - // Used to ensure that the line number gutter is still the right - // size for the current document size. Returns true when an update - // is needed. - function maybeUpdateLineNumberWidth(cm) { - if (!cm.options.lineNumbers) return false; - var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; - if (last.length != display.lineNumChars) { - var test = display.measure.appendChild(elt("div", [elt("div", last)], - "CodeMirror-linenumber CodeMirror-gutter-elt")); - var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; - display.lineGutter.style.width = ""; - display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding); - display.lineNumWidth = display.lineNumInnerWidth + padding; - display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; - display.lineGutter.style.width = display.lineNumWidth + "px"; - updateGutterSpace(cm); - return true; - } - return false; - } - - function lineNumberFor(options, i) { - return String(options.lineNumberFormatter(i + options.firstLineNumber)); - } - - // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, - // but using getBoundingClientRect to get a sub-pixel-accurate - // result. - function compensateForHScroll(display) { - return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left; - } - - // DISPLAY DRAWING - - function DisplayUpdate(cm, viewport, force) { - var display = cm.display; - - this.viewport = viewport; - // Store some values that we'll need later (but don't want to force a relayout for) - this.visible = visibleLines(display, cm.doc, viewport); - this.editorIsHidden = !display.wrapper.offsetWidth; - this.wrapperHeight = display.wrapper.clientHeight; - this.wrapperWidth = display.wrapper.clientWidth; - this.oldDisplayWidth = displayWidth(cm); - this.force = force; - this.dims = getDimensions(cm); - } - - function maybeClipScrollbars(cm) { - var display = cm.display; - if (!display.scrollbarsClipped && display.scroller.offsetWidth) { - display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; - display.heightForcer.style.height = scrollGap(cm) + "px"; - display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; - display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; - display.scrollbarsClipped = true; - } - } - - // Does the actual updating of the line display. Bails out - // (returning false) when there is nothing to be done and forced is - // false. - function updateDisplayIfNeeded(cm, update) { - var display = cm.display, doc = cm.doc; - - if (update.editorIsHidden) { - resetView(cm); - return false; - } - - // Bail out if the visible area is already rendered and nothing changed. - if (!update.force && - update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && - display.renderedView == display.view && countDirtyView(cm) == 0) - return false; - - if (maybeUpdateLineNumberWidth(cm)) { - resetView(cm); - update.dims = getDimensions(cm); - } - - // Compute a suitable new viewport (from & to) - var end = doc.first + doc.size; - var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); - var to = Math.min(end, update.visible.to + cm.options.viewportMargin); - if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom); - if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo); - if (sawCollapsedSpans) { - from = visualLineNo(cm.doc, from); - to = visualLineEndNo(cm.doc, to); - } - - var different = from != display.viewFrom || to != display.viewTo || - display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; - adjustView(cm, from, to); - - display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); - // Position the mover div to align with the current scroll position - cm.display.mover.style.top = display.viewOffset + "px"; - - var toUpdate = countDirtyView(cm); - if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) - return false; - - // For big changes, we hide the enclosing element during the - // update, since that speeds up the operations on most browsers. - var focused = activeElt(); - if (toUpdate > 4) display.lineDiv.style.display = "none"; - patchDisplay(cm, display.updateLineNumbers, update.dims); - if (toUpdate > 4) display.lineDiv.style.display = ""; - display.renderedView = display.view; - // There might have been a widget with a focused element that got - // hidden or updated, if so re-focus it. - if (focused && activeElt() != focused && focused.offsetHeight) focused.focus(); - - // Prevent selection and cursors from interfering with the scroll - // width and height. - removeChildren(display.cursorDiv); - removeChildren(display.selectionDiv); - display.gutters.style.height = 0; - - if (different) { - display.lastWrapHeight = update.wrapperHeight; - display.lastWrapWidth = update.wrapperWidth; - startWorker(cm, 400); - } - - display.updateLineNumbers = null; - - return true; - } - - function postUpdateDisplay(cm, update) { - var force = update.force, viewport = update.viewport; - for (var first = true;; first = false) { - if (first && cm.options.lineWrapping && update.oldDisplayWidth != displayWidth(cm)) { - force = true; - } else { - force = false; - // Clip forced viewport to actual scrollable area. - if (viewport && viewport.top != null) - viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; - // Updated line heights might result in the drawn area not - // actually covering the viewport. Keep looping until it does. - update.visible = visibleLines(cm.display, cm.doc, viewport); - if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) - break; - } - if (!updateDisplayIfNeeded(cm, update)) break; - updateHeightsInViewport(cm); - var barMeasure = measureForScrollbars(cm); - updateSelection(cm); - setDocumentHeight(cm, barMeasure); - updateScrollbars(cm, barMeasure); - } - - signalLater(cm, "update", cm); - if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { - signalLater(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); - cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; - } - } - - function updateDisplaySimple(cm, viewport) { - var update = new DisplayUpdate(cm, viewport); - if (updateDisplayIfNeeded(cm, update)) { - updateHeightsInViewport(cm); - postUpdateDisplay(cm, update); - var barMeasure = measureForScrollbars(cm); - updateSelection(cm); - setDocumentHeight(cm, barMeasure); - updateScrollbars(cm, barMeasure); - } - } - - function setDocumentHeight(cm, measure) { - cm.display.sizer.style.minHeight = measure.docHeight + "px"; - var total = measure.docHeight + cm.display.barHeight; - cm.display.heightForcer.style.top = total + "px"; - cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px"; - } - - // Read the actual heights of the rendered lines, and update their - // stored heights to match. - function updateHeightsInViewport(cm) { - var display = cm.display; - var prevBottom = display.lineDiv.offsetTop; - for (var i = 0; i < display.view.length; i++) { - var cur = display.view[i], height; - if (cur.hidden) continue; - if (ie && ie_version < 8) { - var bot = cur.node.offsetTop + cur.node.offsetHeight; - height = bot - prevBottom; - prevBottom = bot; - } else { - var box = cur.node.getBoundingClientRect(); - height = box.bottom - box.top; - } - var diff = cur.line.height - height; - if (height < 2) height = textHeight(display); - if (diff > .001 || diff < -.001) { - updateLineHeight(cur.line, height); - updateWidgetHeight(cur.line); - if (cur.rest) for (var j = 0; j < cur.rest.length; j++) - updateWidgetHeight(cur.rest[j]); - } - } - } - - // Read and store the height of line widgets associated with the - // given line. - function updateWidgetHeight(line) { - if (line.widgets) for (var i = 0; i < line.widgets.length; ++i) - line.widgets[i].height = line.widgets[i].node.offsetHeight; - } - - // Do a bulk-read of the DOM positions and sizes needed to draw the - // view, so that we don't interleave reading and writing to the DOM. - function getDimensions(cm) { - var d = cm.display, left = {}, width = {}; - var gutterLeft = d.gutters.clientLeft; - for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { - left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft; - width[cm.options.gutters[i]] = n.clientWidth; - } - return {fixedPos: compensateForHScroll(d), - gutterTotalWidth: d.gutters.offsetWidth, - gutterLeft: left, - gutterWidth: width, - wrapperWidth: d.wrapper.clientWidth}; - } - - // Sync the actual display DOM structure with display.view, removing - // nodes for lines that are no longer in view, and creating the ones - // that are not there yet, and updating the ones that are out of - // date. - function patchDisplay(cm, updateNumbersFrom, dims) { - var display = cm.display, lineNumbers = cm.options.lineNumbers; - var container = display.lineDiv, cur = container.firstChild; - - function rm(node) { - var next = node.nextSibling; - // Works around a throw-scroll bug in OS X Webkit - if (webkit && mac && cm.display.currentWheelTarget == node) - node.style.display = "none"; - else - node.parentNode.removeChild(node); - return next; - } - - var view = display.view, lineN = display.viewFrom; - // Loop over the elements in the view, syncing cur (the DOM nodes - // in display.lineDiv) with the view as we go. - for (var i = 0; i < view.length; i++) { - var lineView = view[i]; - if (lineView.hidden) { - } else if (!lineView.node) { // Not drawn yet - var node = buildLineElement(cm, lineView, lineN, dims); - container.insertBefore(node, cur); - } else { // Already drawn - while (cur != lineView.node) cur = rm(cur); - var updateNumber = lineNumbers && updateNumbersFrom != null && - updateNumbersFrom <= lineN && lineView.lineNumber; - if (lineView.changes) { - if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false; - updateLineForChanges(cm, lineView, lineN, dims); - } - if (updateNumber) { - removeChildren(lineView.lineNumber); - lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); - } - cur = lineView.node.nextSibling; - } - lineN += lineView.size; - } - while (cur) cur = rm(cur); - } - - // When an aspect of a line changes, a string is added to - // lineView.changes. This updates the relevant part of the line's - // DOM structure. - function updateLineForChanges(cm, lineView, lineN, dims) { - for (var j = 0; j < lineView.changes.length; j++) { - var type = lineView.changes[j]; - if (type == "text") updateLineText(cm, lineView); - else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims); - else if (type == "class") updateLineClasses(lineView); - else if (type == "widget") updateLineWidgets(lineView, dims); - } - lineView.changes = null; - } - - // Lines with gutter elements, widgets or a background class need to - // be wrapped, and have the extra elements added to the wrapper div - function ensureLineWrapped(lineView) { - if (lineView.node == lineView.text) { - lineView.node = elt("div", null, null, "position: relative"); - if (lineView.text.parentNode) - lineView.text.parentNode.replaceChild(lineView.node, lineView.text); - lineView.node.appendChild(lineView.text); - if (ie && ie_version < 8) lineView.node.style.zIndex = 2; - } - return lineView.node; - } - - function updateLineBackground(lineView) { - var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; - if (cls) cls += " CodeMirror-linebackground"; - if (lineView.background) { - if (cls) lineView.background.className = cls; - else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } - } else if (cls) { - var wrap = ensureLineWrapped(lineView); - lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); - } - } - - // Wrapper around buildLineContent which will reuse the structure - // in display.externalMeasured when possible. - function getLineContent(cm, lineView) { - var ext = cm.display.externalMeasured; - if (ext && ext.line == lineView.line) { - cm.display.externalMeasured = null; - lineView.measure = ext.measure; - return ext.built; - } - return buildLineContent(cm, lineView); - } - - // Redraw the line's text. Interacts with the background and text - // classes because the mode may output tokens that influence these - // classes. - function updateLineText(cm, lineView) { - var cls = lineView.text.className; - var built = getLineContent(cm, lineView); - if (lineView.text == lineView.node) lineView.node = built.pre; - lineView.text.parentNode.replaceChild(built.pre, lineView.text); - lineView.text = built.pre; - if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { - lineView.bgClass = built.bgClass; - lineView.textClass = built.textClass; - updateLineClasses(lineView); - } else if (cls) { - lineView.text.className = cls; - } - } - - function updateLineClasses(lineView) { - updateLineBackground(lineView); - if (lineView.line.wrapClass) - ensureLineWrapped(lineView).className = lineView.line.wrapClass; - else if (lineView.node != lineView.text) - lineView.node.className = ""; - var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; - lineView.text.className = textClass || ""; - } - - function updateLineGutter(cm, lineView, lineN, dims) { - if (lineView.gutter) { - lineView.node.removeChild(lineView.gutter); - lineView.gutter = null; - } - var markers = lineView.line.gutterMarkers; - if (cm.options.lineNumbers || markers) { - var wrap = ensureLineWrapped(lineView); - var gutterWrap = lineView.gutter = - wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "left: " + - (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + - "px; width: " + dims.gutterTotalWidth + "px"), - lineView.text); - if (lineView.line.gutterClass) - gutterWrap.className += " " + lineView.line.gutterClass; - if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) - lineView.lineNumber = gutterWrap.appendChild( - elt("div", lineNumberFor(cm.options, lineN), - "CodeMirror-linenumber CodeMirror-gutter-elt", - "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: " - + cm.display.lineNumInnerWidth + "px")); - if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) { - var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]; - if (found) - gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " + - dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px")); - } - } - } - - function updateLineWidgets(lineView, dims) { - if (lineView.alignable) lineView.alignable = null; - for (var node = lineView.node.firstChild, next; node; node = next) { - var next = node.nextSibling; - if (node.className == "CodeMirror-linewidget") - lineView.node.removeChild(node); - } - insertLineWidgets(lineView, dims); - } - - // Build a line's DOM representation from scratch - function buildLineElement(cm, lineView, lineN, dims) { - var built = getLineContent(cm, lineView); - lineView.text = lineView.node = built.pre; - if (built.bgClass) lineView.bgClass = built.bgClass; - if (built.textClass) lineView.textClass = built.textClass; - - updateLineClasses(lineView); - updateLineGutter(cm, lineView, lineN, dims); - insertLineWidgets(lineView, dims); - return lineView.node; - } - - // A lineView may contain multiple logical lines (when merged by - // collapsed spans). The widgets for all of them need to be drawn. - function insertLineWidgets(lineView, dims) { - insertLineWidgetsFor(lineView.line, lineView, dims, true); - if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++) - insertLineWidgetsFor(lineView.rest[i], lineView, dims, false); - } - - function insertLineWidgetsFor(line, lineView, dims, allowAbove) { - if (!line.widgets) return; - var wrap = ensureLineWrapped(lineView); - for (var i = 0, ws = line.widgets; i < ws.length; ++i) { - var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget"); - if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true"); - positionLineWidget(widget, node, lineView, dims); - if (allowAbove && widget.above) - wrap.insertBefore(node, lineView.gutter || lineView.text); - else - wrap.appendChild(node); - signalLater(widget, "redraw"); - } - } - - function positionLineWidget(widget, node, lineView, dims) { - if (widget.noHScroll) { - (lineView.alignable || (lineView.alignable = [])).push(node); - var width = dims.wrapperWidth; - node.style.left = dims.fixedPos + "px"; - if (!widget.coverGutter) { - width -= dims.gutterTotalWidth; - node.style.paddingLeft = dims.gutterTotalWidth + "px"; - } - node.style.width = width + "px"; - } - if (widget.coverGutter) { - node.style.zIndex = 5; - node.style.position = "relative"; - if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px"; - } - } - - // POSITION OBJECT - - // A Pos instance represents a position within the text. - var Pos = CodeMirror.Pos = function(line, ch) { - if (!(this instanceof Pos)) return new Pos(line, ch); - this.line = line; this.ch = ch; - }; - - // Compare two positions, return 0 if they are the same, a negative - // number when a is less, and a positive number otherwise. - var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; }; - - function copyPos(x) {return Pos(x.line, x.ch);} - function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; } - function minPos(a, b) { return cmp(a, b) < 0 ? a : b; } - - // SELECTION / CURSOR - - // Selection objects are immutable. A new one is created every time - // the selection changes. A selection is one or more non-overlapping - // (and non-touching) ranges, sorted, and an integer that indicates - // which one is the primary selection (the one that's scrolled into - // view, that getCursor returns, etc). - function Selection(ranges, primIndex) { - this.ranges = ranges; - this.primIndex = primIndex; - } - - Selection.prototype = { - primary: function() { return this.ranges[this.primIndex]; }, - equals: function(other) { - if (other == this) return true; - if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false; - for (var i = 0; i < this.ranges.length; i++) { - var here = this.ranges[i], there = other.ranges[i]; - if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false; - } - return true; - }, - deepCopy: function() { - for (var out = [], i = 0; i < this.ranges.length; i++) - out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); - return new Selection(out, this.primIndex); - }, - somethingSelected: function() { - for (var i = 0; i < this.ranges.length; i++) - if (!this.ranges[i].empty()) return true; - return false; - }, - contains: function(pos, end) { - if (!end) end = pos; - for (var i = 0; i < this.ranges.length; i++) { - var range = this.ranges[i]; - if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) - return i; - } - return -1; - } - }; - - function Range(anchor, head) { - this.anchor = anchor; this.head = head; - } - - Range.prototype = { - from: function() { return minPos(this.anchor, this.head); }, - to: function() { return maxPos(this.anchor, this.head); }, - empty: function() { - return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch; - } - }; - - // Take an unsorted, potentially overlapping set of ranges, and - // build a selection out of it. 'Consumes' ranges array (modifying - // it). - function normalizeSelection(ranges, primIndex) { - var prim = ranges[primIndex]; - ranges.sort(function(a, b) { return cmp(a.from(), b.from()); }); - primIndex = indexOf(ranges, prim); - for (var i = 1; i < ranges.length; i++) { - var cur = ranges[i], prev = ranges[i - 1]; - if (cmp(prev.to(), cur.from()) >= 0) { - var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); - var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; - if (i <= primIndex) --primIndex; - ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); - } - } - return new Selection(ranges, primIndex); - } - - function simpleSelection(anchor, head) { - return new Selection([new Range(anchor, head || anchor)], 0); - } - - // Most of the external API clips given positions to make sure they - // actually exist within the document. - function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));} - function clipPos(doc, pos) { - if (pos.line < doc.first) return Pos(doc.first, 0); - var last = doc.first + doc.size - 1; - if (pos.line > last) return Pos(last, getLine(doc, last).text.length); - return clipToLen(pos, getLine(doc, pos.line).text.length); - } - function clipToLen(pos, linelen) { - var ch = pos.ch; - if (ch == null || ch > linelen) return Pos(pos.line, linelen); - else if (ch < 0) return Pos(pos.line, 0); - else return pos; - } - function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;} - function clipPosArray(doc, array) { - for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]); - return out; - } - - // SELECTION UPDATES - - // The 'scroll' parameter given to many of these indicated whether - // the new cursor position should be scrolled into view after - // modifying the selection. - - // If shift is held or the extend flag is set, extends a range to - // include a given position (and optionally a second position). - // Otherwise, simply returns the range between the given positions. - // Used for cursor motion and such. - function extendRange(doc, range, head, other) { - if (doc.cm && doc.cm.display.shift || doc.extend) { - var anchor = range.anchor; - if (other) { - var posBefore = cmp(head, anchor) < 0; - if (posBefore != (cmp(other, anchor) < 0)) { - anchor = head; - head = other; - } else if (posBefore != (cmp(head, other) < 0)) { - head = other; - } - } - return new Range(anchor, head); - } else { - return new Range(other || head, head); - } - } - - // Extend the primary selection range, discard the rest. - function extendSelection(doc, head, other, options) { - setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options); - } - - // Extend all selections (pos is an array of selections with length - // equal the number of selections) - function extendSelections(doc, heads, options) { - for (var out = [], i = 0; i < doc.sel.ranges.length; i++) - out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null); - var newSel = normalizeSelection(out, doc.sel.primIndex); - setSelection(doc, newSel, options); - } - - // Updates a single range in the selection. - function replaceOneSelection(doc, i, range, options) { - var ranges = doc.sel.ranges.slice(0); - ranges[i] = range; - setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options); - } - - // Reset the selection to a single range. - function setSimpleSelection(doc, anchor, head, options) { - setSelection(doc, simpleSelection(anchor, head), options); - } - - // Give beforeSelectionChange handlers a change to influence a - // selection update. - function filterSelectionChange(doc, sel) { - var obj = { - ranges: sel.ranges, - update: function(ranges) { - this.ranges = []; - for (var i = 0; i < ranges.length; i++) - this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), - clipPos(doc, ranges[i].head)); - } - }; - signal(doc, "beforeSelectionChange", doc, obj); - if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj); - if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1); - else return sel; - } - - function setSelectionReplaceHistory(doc, sel, options) { - var done = doc.history.done, last = lst(done); - if (last && last.ranges) { - done[done.length - 1] = sel; - setSelectionNoUndo(doc, sel, options); - } else { - setSelection(doc, sel, options); - } - } - - // Set a new selection. - function setSelection(doc, sel, options) { - setSelectionNoUndo(doc, sel, options); - addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); - } - - function setSelectionNoUndo(doc, sel, options) { - if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) - sel = filterSelectionChange(doc, sel); - - var bias = options && options.bias || - (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); - setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); - - if (!(options && options.scroll === false) && doc.cm) - ensureCursorVisible(doc.cm); - } - - function setSelectionInner(doc, sel) { - if (sel.equals(doc.sel)) return; - - doc.sel = sel; - - if (doc.cm) { - doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true; - signalCursorActivity(doc.cm); - } - signalLater(doc, "cursorActivity", doc); - } - - // Verify that the selection does not partially select any atomic - // marked ranges. - function reCheckSelection(doc) { - setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll); - } - - // Return a selection that does not partially select any atomic - // ranges. - function skipAtomicInSelection(doc, sel, bias, mayClear) { - var out; - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i]; - var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear); - var newHead = skipAtomic(doc, range.head, bias, mayClear); - if (out || newAnchor != range.anchor || newHead != range.head) { - if (!out) out = sel.ranges.slice(0, i); - out[i] = new Range(newAnchor, newHead); - } - } - return out ? normalizeSelection(out, sel.primIndex) : sel; - } - - // Ensure a given position is not inside an atomic range. - function skipAtomic(doc, pos, bias, mayClear) { - var flipped = false, curPos = pos; - var dir = bias || 1; - doc.cantEdit = false; - search: for (;;) { - var line = getLine(doc, curPos.line); - if (line.markedSpans) { - for (var i = 0; i < line.markedSpans.length; ++i) { - var sp = line.markedSpans[i], m = sp.marker; - if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) && - (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) { - if (mayClear) { - signal(m, "beforeCursorEnter"); - if (m.explicitlyCleared) { - if (!line.markedSpans) break; - else {--i; continue;} - } - } - if (!m.atomic) continue; - var newPos = m.find(dir < 0 ? -1 : 1); - if (cmp(newPos, curPos) == 0) { - newPos.ch += dir; - if (newPos.ch < 0) { - if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1)); - else newPos = null; - } else if (newPos.ch > line.text.length) { - if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0); - else newPos = null; - } - if (!newPos) { - if (flipped) { - // Driven in a corner -- no valid cursor position found at all - // -- try again *with* clearing, if we didn't already - if (!mayClear) return skipAtomic(doc, pos, bias, true); - // Otherwise, turn off editing until further notice, and return the start of the doc - doc.cantEdit = true; - return Pos(doc.first, 0); - } - flipped = true; newPos = pos; dir = -dir; - } - } - curPos = newPos; - continue search; - } - } - } - return curPos; - } - } - - // SELECTION DRAWING - - // Redraw the selection and/or cursor - function drawSelection(cm) { - var display = cm.display, doc = cm.doc, result = {}; - var curFragment = result.cursors = document.createDocumentFragment(); - var selFragment = result.selection = document.createDocumentFragment(); - - for (var i = 0; i < doc.sel.ranges.length; i++) { - var range = doc.sel.ranges[i]; - var collapsed = range.empty(); - if (collapsed || cm.options.showCursorWhenSelecting) - drawSelectionCursor(cm, range, curFragment); - if (!collapsed) - drawSelectionRange(cm, range, selFragment); - } - - // Move the hidden textarea near the cursor to prevent scrolling artifacts - if (cm.options.moveInputWithCursor) { - var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); - var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); - result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, - headPos.top + lineOff.top - wrapOff.top)); - result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, - headPos.left + lineOff.left - wrapOff.left)); - } - - return result; - } - - function showSelection(cm, drawn) { - removeChildrenAndAdd(cm.display.cursorDiv, drawn.cursors); - removeChildrenAndAdd(cm.display.selectionDiv, drawn.selection); - if (drawn.teTop != null) { - cm.display.inputDiv.style.top = drawn.teTop + "px"; - cm.display.inputDiv.style.left = drawn.teLeft + "px"; - } - } - - function updateSelection(cm) { - showSelection(cm, drawSelection(cm)); - } - - // Draws a cursor for the given range - function drawSelectionCursor(cm, range, output) { - var pos = cursorCoords(cm, range.head, "div", null, null, !cm.options.singleCursorHeightPerLine); - - var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); - cursor.style.left = pos.left + "px"; - cursor.style.top = pos.top + "px"; - cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; - - if (pos.other) { - // Secondary cursor, shown when on a 'jump' in bi-directional text - var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); - otherCursor.style.display = ""; - otherCursor.style.left = pos.other.left + "px"; - otherCursor.style.top = pos.other.top + "px"; - otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; - } - } - - // Draws the given range as a highlighted selection - function drawSelectionRange(cm, range, output) { - var display = cm.display, doc = cm.doc; - var fragment = document.createDocumentFragment(); - var padding = paddingH(cm.display), leftSide = padding.left; - var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; - - function add(left, top, width, bottom) { - if (top < 0) top = 0; - top = Math.round(top); - bottom = Math.round(bottom); - fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + - "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) + - "px; height: " + (bottom - top) + "px")); - } - - function drawForLine(line, fromArg, toArg) { - var lineObj = getLine(doc, line); - var lineLen = lineObj.text.length; - var start, end; - function coords(ch, bias) { - return charCoords(cm, Pos(line, ch), "div", lineObj, bias); - } - - iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) { - var leftPos = coords(from, "left"), rightPos, left, right; - if (from == to) { - rightPos = leftPos; - left = right = leftPos.left; - } else { - rightPos = coords(to - 1, "right"); - if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; } - left = leftPos.left; - right = rightPos.right; - } - if (fromArg == null && from == 0) left = leftSide; - if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part - add(left, leftPos.top, null, leftPos.bottom); - left = leftSide; - if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top); - } - if (toArg == null && to == lineLen) right = rightSide; - if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) - start = leftPos; - if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) - end = rightPos; - if (left < leftSide + 1) left = leftSide; - add(left, rightPos.top, right - left, rightPos.bottom); - }); - return {start: start, end: end}; - } - - var sFrom = range.from(), sTo = range.to(); - if (sFrom.line == sTo.line) { - drawForLine(sFrom.line, sFrom.ch, sTo.ch); - } else { - var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); - var singleVLine = visualLine(fromLine) == visualLine(toLine); - var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; - var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; - if (singleVLine) { - if (leftEnd.top < rightStart.top - 2) { - add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); - add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); - } else { - add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); - } - } - if (leftEnd.bottom < rightStart.top) - add(leftSide, leftEnd.bottom, null, rightStart.top); - } - - output.appendChild(fragment); - } - - // Cursor-blinking - function restartBlink(cm) { - if (!cm.state.focused) return; - var display = cm.display; - clearInterval(display.blinker); - var on = true; - display.cursorDiv.style.visibility = ""; - if (cm.options.cursorBlinkRate > 0) - display.blinker = setInterval(function() { - display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; - }, cm.options.cursorBlinkRate); - else if (cm.options.cursorBlinkRate < 0) - display.cursorDiv.style.visibility = "hidden"; - } - - // HIGHLIGHT WORKER - - function startWorker(cm, time) { - if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo) - cm.state.highlight.set(time, bind(highlightWorker, cm)); - } - - function highlightWorker(cm) { - var doc = cm.doc; - if (doc.frontier < doc.first) doc.frontier = doc.first; - if (doc.frontier >= cm.display.viewTo) return; - var end = +new Date + cm.options.workTime; - var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)); - var changedLines = []; - - doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) { - if (doc.frontier >= cm.display.viewFrom) { // Visible - var oldStyles = line.styles; - var highlighted = highlightLine(cm, line, state, true); - line.styles = highlighted.styles; - var oldCls = line.styleClasses, newCls = highlighted.classes; - if (newCls) line.styleClasses = newCls; - else if (oldCls) line.styleClasses = null; - var ischange = !oldStyles || oldStyles.length != line.styles.length || - oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); - for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]; - if (ischange) changedLines.push(doc.frontier); - line.stateAfter = copyState(doc.mode, state); - } else { - processLine(cm, line.text, state); - line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null; - } - ++doc.frontier; - if (+new Date > end) { - startWorker(cm, cm.options.workDelay); - return true; - } - }); - if (changedLines.length) runInOp(cm, function() { - for (var i = 0; i < changedLines.length; i++) - regLineChange(cm, changedLines[i], "text"); - }); - } - - // Finds the line to start with when starting a parse. Tries to - // find a line with a stateAfter, so that it can start with a - // valid state. If that fails, it returns the line with the - // smallest indentation, which tends to need the least context to - // parse correctly. - function findStartLine(cm, n, precise) { - var minindent, minline, doc = cm.doc; - var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); - for (var search = n; search > lim; --search) { - if (search <= doc.first) return doc.first; - var line = getLine(doc, search - 1); - if (line.stateAfter && (!precise || search <= doc.frontier)) return search; - var indented = countColumn(line.text, null, cm.options.tabSize); - if (minline == null || minindent > indented) { - minline = search - 1; - minindent = indented; - } - } - return minline; - } - - function getStateBefore(cm, n, precise) { - var doc = cm.doc, display = cm.display; - if (!doc.mode.startState) return true; - var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter; - if (!state) state = startState(doc.mode); - else state = copyState(doc.mode, state); - doc.iter(pos, n, function(line) { - processLine(cm, line.text, state); - var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo; - line.stateAfter = save ? copyState(doc.mode, state) : null; - ++pos; - }); - if (precise) doc.frontier = pos; - return state; - } - - // POSITION MEASUREMENT - - function paddingTop(display) {return display.lineSpace.offsetTop;} - function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;} - function paddingH(display) { - if (display.cachedPaddingH) return display.cachedPaddingH; - var e = removeChildrenAndAdd(display.measure, elt("pre", "x")); - var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; - var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; - if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data; - return data; - } - - function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; } - function displayWidth(cm) { - return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth; - } - function displayHeight(cm) { - return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight; - } - - // Ensure the lineView.wrapping.heights array is populated. This is - // an array of bottom offsets for the lines that make up a drawn - // line. When lineWrapping is on, there might be more than one - // height. - function ensureLineHeights(cm, lineView, rect) { - var wrapping = cm.options.lineWrapping; - var curWidth = wrapping && displayWidth(cm); - if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { - var heights = lineView.measure.heights = []; - if (wrapping) { - lineView.measure.width = curWidth; - var rects = lineView.text.firstChild.getClientRects(); - for (var i = 0; i < rects.length - 1; i++) { - var cur = rects[i], next = rects[i + 1]; - if (Math.abs(cur.bottom - next.bottom) > 2) - heights.push((cur.bottom + next.top) / 2 - rect.top); - } - } - heights.push(rect.bottom - rect.top); - } - } - - // Find a line map (mapping character offsets to text nodes) and a - // measurement cache for the given line number. (A line view might - // contain multiple lines when collapsed ranges are present.) - function mapFromLineView(lineView, line, lineN) { - if (lineView.line == line) - return {map: lineView.measure.map, cache: lineView.measure.cache}; - for (var i = 0; i < lineView.rest.length; i++) - if (lineView.rest[i] == line) - return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]}; - for (var i = 0; i < lineView.rest.length; i++) - if (lineNo(lineView.rest[i]) > lineN) - return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true}; - } - - // Render a line into the hidden node display.externalMeasured. Used - // when measurement is needed for a line that's not in the viewport. - function updateExternalMeasurement(cm, line) { - line = visualLine(line); - var lineN = lineNo(line); - var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); - view.lineN = lineN; - var built = view.built = buildLineContent(cm, view); - view.text = built.pre; - removeChildrenAndAdd(cm.display.lineMeasure, built.pre); - return view; - } - - // Get a {top, bottom, left, right} box (in line-local coordinates) - // for a given character. - function measureChar(cm, line, ch, bias) { - return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias); - } - - // Find a line view that corresponds to the given line number. - function findViewForLine(cm, lineN) { - if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) - return cm.display.view[findViewIndex(cm, lineN)]; - var ext = cm.display.externalMeasured; - if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) - return ext; - } - - // Measurement can be split in two steps, the set-up work that - // applies to the whole line, and the measurement of the actual - // character. Functions like coordsChar, that need to do a lot of - // measurements in a row, can thus ensure that the set-up work is - // only done once. - function prepareMeasureForLine(cm, line) { - var lineN = lineNo(line); - var view = findViewForLine(cm, lineN); - if (view && !view.text) - view = null; - else if (view && view.changes) - updateLineForChanges(cm, view, lineN, getDimensions(cm)); - if (!view) - view = updateExternalMeasurement(cm, line); - - var info = mapFromLineView(view, line, lineN); - return { - line: line, view: view, rect: null, - map: info.map, cache: info.cache, before: info.before, - hasHeights: false - }; - } - - // Given a prepared measurement object, measures the position of an - // actual character (or fetches it from the cache). - function measureCharPrepared(cm, prepared, ch, bias, varHeight) { - if (prepared.before) ch = -1; - var key = ch + (bias || ""), found; - if (prepared.cache.hasOwnProperty(key)) { - found = prepared.cache[key]; - } else { - if (!prepared.rect) - prepared.rect = prepared.view.text.getBoundingClientRect(); - if (!prepared.hasHeights) { - ensureLineHeights(cm, prepared.view, prepared.rect); - prepared.hasHeights = true; - } - found = measureCharInner(cm, prepared, ch, bias); - if (!found.bogus) prepared.cache[key] = found; - } - return {left: found.left, right: found.right, - top: varHeight ? found.rtop : found.top, - bottom: varHeight ? found.rbottom : found.bottom}; - } - - var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; - - function measureCharInner(cm, prepared, ch, bias) { - var map = prepared.map; - - var node, start, end, collapse; - // First, search the line map for the text node corresponding to, - // or closest to, the target character. - for (var i = 0; i < map.length; i += 3) { - var mStart = map[i], mEnd = map[i + 1]; - if (ch < mStart) { - start = 0; end = 1; - collapse = "left"; - } else if (ch < mEnd) { - start = ch - mStart; - end = start + 1; - } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { - end = mEnd - mStart; - start = end - 1; - if (ch >= mEnd) collapse = "right"; - } - if (start != null) { - node = map[i + 2]; - if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) - collapse = bias; - if (bias == "left" && start == 0) - while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { - node = map[(i -= 3) + 2]; - collapse = "left"; - } - if (bias == "right" && start == mEnd - mStart) - while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { - node = map[(i += 3) + 2]; - collapse = "right"; - } - break; - } - } - - var rect; - if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. - for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned - while (start && isExtendingChar(prepared.line.text.charAt(mStart + start))) --start; - while (mStart + end < mEnd && isExtendingChar(prepared.line.text.charAt(mStart + end))) ++end; - if (ie && ie_version < 9 && start == 0 && end == mEnd - mStart) { - rect = node.parentNode.getBoundingClientRect(); - } else if (ie && cm.options.lineWrapping) { - var rects = range(node, start, end).getClientRects(); - if (rects.length) - rect = rects[bias == "right" ? rects.length - 1 : 0]; - else - rect = nullRect; - } else { - rect = range(node, start, end).getBoundingClientRect() || nullRect; - } - if (rect.left || rect.right || start == 0) break; - end = start; - start = start - 1; - collapse = "right"; - } - if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect); - } else { // If it is a widget, simply get the box for the whole widget. - if (start > 0) collapse = bias = "right"; - var rects; - if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) - rect = rects[bias == "right" ? rects.length - 1 : 0]; - else - rect = node.getBoundingClientRect(); - } - if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { - var rSpan = node.parentNode.getClientRects()[0]; - if (rSpan) - rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; - else - rect = nullRect; - } - - var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; - var mid = (rtop + rbot) / 2; - var heights = prepared.view.measure.heights; - for (var i = 0; i < heights.length - 1; i++) - if (mid < heights[i]) break; - var top = i ? heights[i - 1] : 0, bot = heights[i]; - var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, - right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, - top: top, bottom: bot}; - if (!rect.left && !rect.right) result.bogus = true; - if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } - - return result; - } - - // Work around problem with bounding client rects on ranges being - // returned incorrectly when zoomed on IE10 and below. - function maybeUpdateRectForZooming(measure, rect) { - if (!window.screen || screen.logicalXDPI == null || - screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) - return rect; - var scaleX = screen.logicalXDPI / screen.deviceXDPI; - var scaleY = screen.logicalYDPI / screen.deviceYDPI; - return {left: rect.left * scaleX, right: rect.right * scaleX, - top: rect.top * scaleY, bottom: rect.bottom * scaleY}; - } - - function clearLineMeasurementCacheFor(lineView) { - if (lineView.measure) { - lineView.measure.cache = {}; - lineView.measure.heights = null; - if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++) - lineView.measure.caches[i] = {}; - } - } - - function clearLineMeasurementCache(cm) { - cm.display.externalMeasure = null; - removeChildren(cm.display.lineMeasure); - for (var i = 0; i < cm.display.view.length; i++) - clearLineMeasurementCacheFor(cm.display.view[i]); - } - - function clearCaches(cm) { - clearLineMeasurementCache(cm); - cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; - if (!cm.options.lineWrapping) cm.display.maxLineChanged = true; - cm.display.lineNumChars = null; - } - - function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; } - function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; } - - // Converts a {top, bottom, left, right} box from line-local - // coordinates into another coordinate system. Context may be one of - // "line", "div" (display.lineDiv), "local"/null (editor), "window", - // or "page". - function intoCoordSystem(cm, lineObj, rect, context) { - if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) { - var size = widgetHeight(lineObj.widgets[i]); - rect.top += size; rect.bottom += size; - } - if (context == "line") return rect; - if (!context) context = "local"; - var yOff = heightAtLine(lineObj); - if (context == "local") yOff += paddingTop(cm.display); - else yOff -= cm.display.viewOffset; - if (context == "page" || context == "window") { - var lOff = cm.display.lineSpace.getBoundingClientRect(); - yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); - var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); - rect.left += xOff; rect.right += xOff; - } - rect.top += yOff; rect.bottom += yOff; - return rect; - } - - // Coverts a box from "div" coords to another coordinate system. - // Context may be "window", "page", "div", or "local"/null. - function fromCoordSystem(cm, coords, context) { - if (context == "div") return coords; - var left = coords.left, top = coords.top; - // First move into "page" coordinate system - if (context == "page") { - left -= pageScrollX(); - top -= pageScrollY(); - } else if (context == "local" || !context) { - var localBox = cm.display.sizer.getBoundingClientRect(); - left += localBox.left; - top += localBox.top; - } - - var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); - return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}; - } - - function charCoords(cm, pos, context, lineObj, bias) { - if (!lineObj) lineObj = getLine(cm.doc, pos.line); - return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context); - } - - // Returns a box for a given cursor position, which may have an - // 'other' property containing the position of the secondary cursor - // on a bidi boundary. - function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { - lineObj = lineObj || getLine(cm.doc, pos.line); - if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj); - function get(ch, right) { - var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); - if (right) m.left = m.right; else m.right = m.left; - return intoCoordSystem(cm, lineObj, m, context); - } - function getBidi(ch, partPos) { - var part = order[partPos], right = part.level % 2; - if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) { - part = order[--partPos]; - ch = bidiRight(part) - (part.level % 2 ? 0 : 1); - right = true; - } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) { - part = order[++partPos]; - ch = bidiLeft(part) - part.level % 2; - right = false; - } - if (right && ch == part.to && ch > part.from) return get(ch - 1); - return get(ch, right); - } - var order = getOrder(lineObj), ch = pos.ch; - if (!order) return get(ch); - var partPos = getBidiPartAt(order, ch); - var val = getBidi(ch, partPos); - if (bidiOther != null) val.other = getBidi(ch, bidiOther); - return val; - } - - // Used to cheaply estimate the coordinates for a position. Used for - // intermediate scroll updates. - function estimateCoords(cm, pos) { - var left = 0, pos = clipPos(cm.doc, pos); - if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch; - var lineObj = getLine(cm.doc, pos.line); - var top = heightAtLine(lineObj) + paddingTop(cm.display); - return {left: left, right: left, top: top, bottom: top + lineObj.height}; - } - - // Positions returned by coordsChar contain some extra information. - // xRel is the relative x position of the input coordinates compared - // to the found position (so xRel > 0 means the coordinates are to - // the right of the character position, for example). When outside - // is true, that means the coordinates lie outside the line's - // vertical range. - function PosWithInfo(line, ch, outside, xRel) { - var pos = Pos(line, ch); - pos.xRel = xRel; - if (outside) pos.outside = true; - return pos; - } - - // Compute the character position closest to the given coordinates. - // Input must be lineSpace-local ("div" coordinate system). - function coordsChar(cm, x, y) { - var doc = cm.doc; - y += cm.display.viewOffset; - if (y < 0) return PosWithInfo(doc.first, 0, true, -1); - var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; - if (lineN > last) - return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1); - if (x < 0) x = 0; - - var lineObj = getLine(doc, lineN); - for (;;) { - var found = coordsCharInner(cm, lineObj, lineN, x, y); - var merged = collapsedSpanAtEnd(lineObj); - var mergedPos = merged && merged.find(0, true); - if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) - lineN = lineNo(lineObj = mergedPos.to.line); - else - return found; - } - } - - function coordsCharInner(cm, lineObj, lineNo, x, y) { - var innerOff = y - heightAtLine(lineObj); - var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth; - var preparedMeasure = prepareMeasureForLine(cm, lineObj); - - function getX(ch) { - var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure); - wrongLine = true; - if (innerOff > sp.bottom) return sp.left - adjust; - else if (innerOff < sp.top) return sp.left + adjust; - else wrongLine = false; - return sp.left; - } - - var bidi = getOrder(lineObj), dist = lineObj.text.length; - var from = lineLeft(lineObj), to = lineRight(lineObj); - var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine; - - if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1); - // Do a binary search between these bounds. - for (;;) { - if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { - var ch = x < fromX || x - fromX <= toX - x ? from : to; - var xDiff = x - (ch == from ? fromX : toX); - while (isExtendingChar(lineObj.text.charAt(ch))) ++ch; - var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside, - xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0); - return pos; - } - var step = Math.ceil(dist / 2), middle = from + step; - if (bidi) { - middle = from; - for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1); - } - var middleX = getX(middle); - if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;} - else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;} - } - } - - var measureText; - // Compute the default text height. - function textHeight(display) { - if (display.cachedTextHeight != null) return display.cachedTextHeight; - if (measureText == null) { - measureText = elt("pre"); - // Measure a bunch of lines, for browsers that compute - // fractional heights. - for (var i = 0; i < 49; ++i) { - measureText.appendChild(document.createTextNode("x")); - measureText.appendChild(elt("br")); - } - measureText.appendChild(document.createTextNode("x")); - } - removeChildrenAndAdd(display.measure, measureText); - var height = measureText.offsetHeight / 50; - if (height > 3) display.cachedTextHeight = height; - removeChildren(display.measure); - return height || 1; - } - - // Compute the default character width. - function charWidth(display) { - if (display.cachedCharWidth != null) return display.cachedCharWidth; - var anchor = elt("span", "xxxxxxxxxx"); - var pre = elt("pre", [anchor]); - removeChildrenAndAdd(display.measure, pre); - var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; - if (width > 2) display.cachedCharWidth = width; - return width || 10; - } - - // OPERATIONS - - // Operations are used to wrap a series of changes to the editor - // state in such a way that each change won't have to update the - // cursor and display (which would be awkward, slow, and - // error-prone). Instead, display updates are batched and then all - // combined and executed at once. - - var operationGroup = null; - - var nextOpId = 0; - // Start a new operation. - function startOperation(cm) { - cm.curOp = { - cm: cm, - viewChanged: false, // Flag that indicates that lines might need to be redrawn - startHeight: cm.doc.height, // Used to detect need to update scrollbar - forceUpdate: false, // Used to force a redraw - updateInput: null, // Whether to reset the input textarea - typing: false, // Whether this reset should be careful to leave existing text (for compositing) - changeObjs: null, // Accumulated changes, for firing change events - cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on - cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already - selectionChanged: false, // Whether the selection needs to be redrawn - updateMaxLine: false, // Set when the widest line needs to be determined anew - scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet - scrollToPos: null, // Used to scroll to a specific position - id: ++nextOpId // Unique ID - }; - if (operationGroup) { - operationGroup.ops.push(cm.curOp); - } else { - cm.curOp.ownsGroup = operationGroup = { - ops: [cm.curOp], - delayedCallbacks: [] - }; - } - } - - function fireCallbacksForOps(group) { - // Calls delayed callbacks and cursorActivity handlers until no - // new ones appear - var callbacks = group.delayedCallbacks, i = 0; - do { - for (; i < callbacks.length; i++) - callbacks[i](); - for (var j = 0; j < group.ops.length; j++) { - var op = group.ops[j]; - if (op.cursorActivityHandlers) - while (op.cursorActivityCalled < op.cursorActivityHandlers.length) - op.cursorActivityHandlers[op.cursorActivityCalled++](op.cm); - } - } while (i < callbacks.length); - } - - // Finish an operation, updating the display and signalling delayed events - function endOperation(cm) { - var op = cm.curOp, group = op.ownsGroup; - if (!group) return; - - try { fireCallbacksForOps(group); } - finally { - operationGroup = null; - for (var i = 0; i < group.ops.length; i++) - group.ops[i].cm.curOp = null; - endOperations(group); - } - } - - // The DOM updates done when an operation finishes are batched so - // that the minimum number of relayouts are required. - function endOperations(group) { - var ops = group.ops; - for (var i = 0; i < ops.length; i++) // Read DOM - endOperation_R1(ops[i]); - for (var i = 0; i < ops.length; i++) // Write DOM (maybe) - endOperation_W1(ops[i]); - for (var i = 0; i < ops.length; i++) // Read DOM - endOperation_R2(ops[i]); - for (var i = 0; i < ops.length; i++) // Write DOM (maybe) - endOperation_W2(ops[i]); - for (var i = 0; i < ops.length; i++) // Read DOM - endOperation_finish(ops[i]); - } - - function endOperation_R1(op) { - var cm = op.cm, display = cm.display; - maybeClipScrollbars(cm); - if (op.updateMaxLine) findMaxLine(cm); - - op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || - op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || - op.scrollToPos.to.line >= display.viewTo) || - display.maxLineChanged && cm.options.lineWrapping; - op.update = op.mustUpdate && - new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); - } - - function endOperation_W1(op) { - op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); - } - - function endOperation_R2(op) { - var cm = op.cm, display = cm.display; - if (op.updatedDisplay) updateHeightsInViewport(cm); - - op.barMeasure = measureForScrollbars(cm); - - // If the max line changed since it was last measured, measure it, - // and ensure the document's width matches it. - // updateDisplay_W2 will use these properties to do the actual resizing - if (display.maxLineChanged && !cm.options.lineWrapping) { - op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; - cm.display.sizerWidth = op.adjustWidthTo; - op.barMeasure.scrollWidth = - Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); - op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); - } - - if (op.updatedDisplay || op.selectionChanged) - op.newSelectionNodes = drawSelection(cm); - } - - function endOperation_W2(op) { - var cm = op.cm; - - if (op.adjustWidthTo != null) { - cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; - if (op.maxScrollLeft < cm.doc.scrollLeft) - setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); - cm.display.maxLineChanged = false; - } - - if (op.newSelectionNodes) - showSelection(cm, op.newSelectionNodes); - if (op.updatedDisplay) - setDocumentHeight(cm, op.barMeasure); - if (op.updatedDisplay || op.startHeight != cm.doc.height) - updateScrollbars(cm, op.barMeasure); - - if (op.selectionChanged) restartBlink(cm); - - if (cm.state.focused && op.updateInput) - resetInput(cm, op.typing); - } - - function endOperation_finish(op) { - var cm = op.cm, display = cm.display, doc = cm.doc; - - if (op.updatedDisplay) postUpdateDisplay(cm, op.update); - - // Abort mouse wheel delta measurement, when scrolling explicitly - if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) - display.wheelStartX = display.wheelStartY = null; - - // Propagate the scroll position to the actual DOM scroller - if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) { - doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop)); - display.scrollbars.setScrollTop(doc.scrollTop); - display.scroller.scrollTop = doc.scrollTop; - } - if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) { - doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft)); - display.scrollbars.setScrollLeft(doc.scrollLeft); - display.scroller.scrollLeft = doc.scrollLeft; - alignHorizontally(cm); - } - // If we need to scroll a specific position into view, do so. - if (op.scrollToPos) { - var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), - clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); - if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords); - } - - // Fire events for markers that are hidden/unidden by editing or - // undoing - var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; - if (hidden) for (var i = 0; i < hidden.length; ++i) - if (!hidden[i].lines.length) signal(hidden[i], "hide"); - if (unhidden) for (var i = 0; i < unhidden.length; ++i) - if (unhidden[i].lines.length) signal(unhidden[i], "unhide"); - - if (display.wrapper.offsetHeight) - doc.scrollTop = cm.display.scroller.scrollTop; - - // Fire change events, and delayed event handlers - if (op.changeObjs) - signal(cm, "changes", cm, op.changeObjs); - } - - // Run the given function in an operation - function runInOp(cm, f) { - if (cm.curOp) return f(); - startOperation(cm); - try { return f(); } - finally { endOperation(cm); } - } - // Wraps a function in an operation. Returns the wrapped function. - function operation(cm, f) { - return function() { - if (cm.curOp) return f.apply(cm, arguments); - startOperation(cm); - try { return f.apply(cm, arguments); } - finally { endOperation(cm); } - }; - } - // Used to add methods to editor and doc instances, wrapping them in - // operations. - function methodOp(f) { - return function() { - if (this.curOp) return f.apply(this, arguments); - startOperation(this); - try { return f.apply(this, arguments); } - finally { endOperation(this); } - }; - } - function docMethodOp(f) { - return function() { - var cm = this.cm; - if (!cm || cm.curOp) return f.apply(this, arguments); - startOperation(cm); - try { return f.apply(this, arguments); } - finally { endOperation(cm); } - }; - } - - // VIEW TRACKING - - // These objects are used to represent the visible (currently drawn) - // part of the document. A LineView may correspond to multiple - // logical lines, if those are connected by collapsed ranges. - function LineView(doc, line, lineN) { - // The starting line - this.line = line; - // Continuing lines, if any - this.rest = visualLineContinued(line); - // Number of logical lines in this visual line - this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; - this.node = this.text = null; - this.hidden = lineIsHidden(doc, line); - } - - // Create a range of LineView objects for the given lines. - function buildViewArray(cm, from, to) { - var array = [], nextPos; - for (var pos = from; pos < to; pos = nextPos) { - var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); - nextPos = pos + view.size; - array.push(view); - } - return array; - } - - // Updates the display.view data structure for a given change to the - // document. From and to are in pre-change coordinates. Lendiff is - // the amount of lines added or subtracted by the change. This is - // used for changes that span multiple lines, or change the way - // lines are divided into visual lines. regLineChange (below) - // registers single-line changes. - function regChange(cm, from, to, lendiff) { - if (from == null) from = cm.doc.first; - if (to == null) to = cm.doc.first + cm.doc.size; - if (!lendiff) lendiff = 0; - - var display = cm.display; - if (lendiff && to < display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers > from)) - display.updateLineNumbers = from; - - cm.curOp.viewChanged = true; - - if (from >= display.viewTo) { // Change after - if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) - resetView(cm); - } else if (to <= display.viewFrom) { // Change before - if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { - resetView(cm); - } else { - display.viewFrom += lendiff; - display.viewTo += lendiff; - } - } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap - resetView(cm); - } else if (from <= display.viewFrom) { // Top overlap - var cut = viewCuttingPoint(cm, to, to + lendiff, 1); - if (cut) { - display.view = display.view.slice(cut.index); - display.viewFrom = cut.lineN; - display.viewTo += lendiff; - } else { - resetView(cm); - } - } else if (to >= display.viewTo) { // Bottom overlap - var cut = viewCuttingPoint(cm, from, from, -1); - if (cut) { - display.view = display.view.slice(0, cut.index); - display.viewTo = cut.lineN; - } else { - resetView(cm); - } - } else { // Gap in the middle - var cutTop = viewCuttingPoint(cm, from, from, -1); - var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); - if (cutTop && cutBot) { - display.view = display.view.slice(0, cutTop.index) - .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) - .concat(display.view.slice(cutBot.index)); - display.viewTo += lendiff; - } else { - resetView(cm); - } - } - - var ext = display.externalMeasured; - if (ext) { - if (to < ext.lineN) - ext.lineN += lendiff; - else if (from < ext.lineN + ext.size) - display.externalMeasured = null; - } - } - - // Register a change to a single line. Type must be one of "text", - // "gutter", "class", "widget" - function regLineChange(cm, line, type) { - cm.curOp.viewChanged = true; - var display = cm.display, ext = cm.display.externalMeasured; - if (ext && line >= ext.lineN && line < ext.lineN + ext.size) - display.externalMeasured = null; - - if (line < display.viewFrom || line >= display.viewTo) return; - var lineView = display.view[findViewIndex(cm, line)]; - if (lineView.node == null) return; - var arr = lineView.changes || (lineView.changes = []); - if (indexOf(arr, type) == -1) arr.push(type); - } - - // Clear the view. - function resetView(cm) { - cm.display.viewFrom = cm.display.viewTo = cm.doc.first; - cm.display.view = []; - cm.display.viewOffset = 0; - } - - // Find the view element corresponding to a given line. Return null - // when the line isn't visible. - function findViewIndex(cm, n) { - if (n >= cm.display.viewTo) return null; - n -= cm.display.viewFrom; - if (n < 0) return null; - var view = cm.display.view; - for (var i = 0; i < view.length; i++) { - n -= view[i].size; - if (n < 0) return i; - } - } - - function viewCuttingPoint(cm, oldN, newN, dir) { - var index = findViewIndex(cm, oldN), diff, view = cm.display.view; - if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) - return {index: index, lineN: newN}; - for (var i = 0, n = cm.display.viewFrom; i < index; i++) - n += view[i].size; - if (n != oldN) { - if (dir > 0) { - if (index == view.length - 1) return null; - diff = (n + view[index].size) - oldN; - index++; - } else { - diff = n - oldN; - } - oldN += diff; newN += diff; - } - while (visualLineNo(cm.doc, newN) != newN) { - if (index == (dir < 0 ? 0 : view.length - 1)) return null; - newN += dir * view[index - (dir < 0 ? 1 : 0)].size; - index += dir; - } - return {index: index, lineN: newN}; - } - - // Force the view to cover a given range, adding empty view element - // or clipping off existing ones as needed. - function adjustView(cm, from, to) { - var display = cm.display, view = display.view; - if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { - display.view = buildViewArray(cm, from, to); - display.viewFrom = from; - } else { - if (display.viewFrom > from) - display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); - else if (display.viewFrom < from) - display.view = display.view.slice(findViewIndex(cm, from)); - display.viewFrom = from; - if (display.viewTo < to) - display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); - else if (display.viewTo > to) - display.view = display.view.slice(0, findViewIndex(cm, to)); - } - display.viewTo = to; - } - - // Count the number of lines in the view whose DOM representation is - // out of date (or nonexistent). - function countDirtyView(cm) { - var view = cm.display.view, dirty = 0; - for (var i = 0; i < view.length; i++) { - var lineView = view[i]; - if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty; - } - return dirty; - } - - // INPUT HANDLING - - // Poll for input changes, using the normal rate of polling. This - // runs as long as the editor is focused. - function slowPoll(cm) { - if (cm.display.pollingFast) return; - cm.display.poll.set(cm.options.pollInterval, function() { - readInput(cm); - if (cm.state.focused) slowPoll(cm); - }); - } - - // When an event has just come in that is likely to add or change - // something in the input textarea, we poll faster, to ensure that - // the change appears on the screen quickly. - function fastPoll(cm) { - var missed = false; - cm.display.pollingFast = true; - function p() { - var changed = readInput(cm); - if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);} - else {cm.display.pollingFast = false; slowPoll(cm);} - } - cm.display.poll.set(20, p); - } - - // This will be set to an array of strings when copying, so that, - // when pasting, we know what kind of selections the copied text - // was made out of. - var lastCopied = null; - - // Read input from the textarea, and update the document to match. - // When something is selected, it is present in the textarea, and - // selected (unless it is huge, in which case a placeholder is - // used). When nothing is selected, the cursor sits after previously - // seen text (can be empty), which is stored in prevInput (we must - // not reset the textarea when typing, because that breaks IME). - function readInput(cm) { - var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc; - // Since this is called a *lot*, try to bail out as cheaply as - // possible when it is clear that nothing happened. hasSelection - // will be the case when there is a lot of text in the textarea, - // in which case reading its value would be expensive. - if (!cm.state.focused || (hasSelection(input) && !prevInput) || isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq) - return false; - // See paste handler for more on the fakedLastChar kludge - if (cm.state.pasteIncoming && cm.state.fakedLastChar) { - input.value = input.value.substring(0, input.value.length - 1); - cm.state.fakedLastChar = false; - } - var text = input.value; - // If nothing changed, bail. - if (text == prevInput && !cm.somethingSelected()) return false; - // Work around nonsensical selection resetting in IE9/10, and - // inexplicable appearance of private area unicode characters on - // some key combos in Mac (#2689). - if (ie && ie_version >= 9 && cm.display.inputHasSelection === text || - mac && /[\uf700-\uf7ff]/.test(text)) { - resetInput(cm); - return false; - } - - var withOp = !cm.curOp; - if (withOp) startOperation(cm); - cm.display.shift = false; - - if (text.charCodeAt(0) == 0x200b && doc.sel == cm.display.selForContextMenu && !prevInput) - prevInput = "\u200b"; - // Find the part of the input that is actually new - var same = 0, l = Math.min(prevInput.length, text.length); - while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same; - var inserted = text.slice(same), textLines = splitLines(inserted); - - // When pasing N lines into N selections, insert one line per selection - var multiPaste = null; - if (cm.state.pasteIncoming && doc.sel.ranges.length > 1) { - if (lastCopied && lastCopied.join("\n") == inserted) - multiPaste = doc.sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines); - else if (textLines.length == doc.sel.ranges.length) - multiPaste = map(textLines, function(l) { return [l]; }); - } - - // Normal behavior is to insert the new text into every selection - for (var i = doc.sel.ranges.length - 1; i >= 0; i--) { - var range = doc.sel.ranges[i]; - var from = range.from(), to = range.to(); - // Handle deletion - if (same < prevInput.length) - from = Pos(from.line, from.ch - (prevInput.length - same)); - // Handle overwrite - else if (cm.state.overwrite && range.empty() && !cm.state.pasteIncoming) - to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); - var updateInput = cm.curOp.updateInput; - var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines, - origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"}; - makeChange(cm.doc, changeEvent); - signalLater(cm, "inputRead", cm, changeEvent); - // When an 'electric' character is inserted, immediately trigger a reindent - if (inserted && !cm.state.pasteIncoming && cm.options.electricChars && - cm.options.smartIndent && range.head.ch < 100 && - (!i || doc.sel.ranges[i - 1].head.line != range.head.line)) { - var mode = cm.getModeAt(range.head); - var end = changeEnd(changeEvent); - if (mode.electricChars) { - for (var j = 0; j < mode.electricChars.length; j++) - if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { - indentLine(cm, end.line, "smart"); - break; - } - } else if (mode.electricInput) { - if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch))) - indentLine(cm, end.line, "smart"); - } - } - } - ensureCursorVisible(cm); - cm.curOp.updateInput = updateInput; - cm.curOp.typing = true; - - // Don't leave long text in the textarea, since it makes further polling slow - if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = ""; - else cm.display.prevInput = text; - if (withOp) endOperation(cm); - cm.state.pasteIncoming = cm.state.cutIncoming = false; - return true; - } - - // Reset the input to correspond to the selection (or to be empty, - // when not typing and nothing is selected) - function resetInput(cm, typing) { - if (cm.display.contextMenuPending) return; - var minimal, selected, doc = cm.doc; - if (cm.somethingSelected()) { - cm.display.prevInput = ""; - var range = doc.sel.primary(); - minimal = hasCopyEvent && - (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000); - var content = minimal ? "-" : selected || cm.getSelection(); - cm.display.input.value = content; - if (cm.state.focused) selectInput(cm.display.input); - if (ie && ie_version >= 9) cm.display.inputHasSelection = content; - } else if (!typing) { - cm.display.prevInput = cm.display.input.value = ""; - if (ie && ie_version >= 9) cm.display.inputHasSelection = null; - } - cm.display.inaccurateSelection = minimal; - } - - function focusInput(cm) { - if (cm.options.readOnly != "nocursor" && (!mobile || activeElt() != cm.display.input)) - cm.display.input.focus(); - } - - function ensureFocus(cm) { - if (!cm.state.focused) { focusInput(cm); onFocus(cm); } - } - - function isReadOnly(cm) { - return cm.options.readOnly || cm.doc.cantEdit; - } - - // EVENT HANDLERS - - // Attach the necessary event handlers when initializing the editor - function registerEventHandlers(cm) { - var d = cm.display; - on(d.scroller, "mousedown", operation(cm, onMouseDown)); - // Older IE's will not fire a second mousedown for a double click - if (ie && ie_version < 11) - on(d.scroller, "dblclick", operation(cm, function(e) { - if (signalDOMEvent(cm, e)) return; - var pos = posFromMouse(cm, e); - if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return; - e_preventDefault(e); - var word = cm.findWordAt(pos); - extendSelection(cm.doc, word.anchor, word.head); - })); - else - on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); }); - // Prevent normal selection in the editor (we handle our own) - on(d.lineSpace, "selectstart", function(e) { - if (!eventInWidget(d, e)) e_preventDefault(e); - }); - // Some browsers fire contextmenu *after* opening the menu, at - // which point we can't mess with it anymore. Context menu is - // handled in onMouseDown for these browsers. - if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);}); - - // Sync scrolling between fake scrollbars and real scrollable - // area, ensure viewport is updated when scrolling. - on(d.scroller, "scroll", function() { - if (d.scroller.clientHeight) { - setScrollTop(cm, d.scroller.scrollTop); - setScrollLeft(cm, d.scroller.scrollLeft, true); - signal(cm, "scroll", cm); - } - }); - - // Listen to wheel events in order to try and update the viewport on time. - on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);}); - on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);}); - - // Prevent wrapper from ever scrolling - on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); - - on(d.input, "keyup", function(e) { onKeyUp.call(cm, e); }); - on(d.input, "input", function() { - if (ie && ie_version >= 9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null; - readInput(cm); - }); - on(d.input, "keydown", operation(cm, onKeyDown)); - on(d.input, "keypress", operation(cm, onKeyPress)); - on(d.input, "focus", bind(onFocus, cm)); - on(d.input, "blur", bind(onBlur, cm)); - - function drag_(e) { - if (!signalDOMEvent(cm, e)) e_stop(e); - } - if (cm.options.dragDrop) { - on(d.scroller, "dragstart", function(e){onDragStart(cm, e);}); - on(d.scroller, "dragenter", drag_); - on(d.scroller, "dragover", drag_); - on(d.scroller, "drop", operation(cm, onDrop)); - } - on(d.scroller, "paste", function(e) { - if (eventInWidget(d, e)) return; - cm.state.pasteIncoming = true; - focusInput(cm); - fastPoll(cm); - }); - on(d.input, "paste", function() { - // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206 - // Add a char to the end of textarea before paste occur so that - // selection doesn't span to the end of textarea. - if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) { - var start = d.input.selectionStart, end = d.input.selectionEnd; - d.input.value += "$"; - // The selection end needs to be set before the start, otherwise there - // can be an intermediate non-empty selection between the two, which - // can override the middle-click paste buffer on linux and cause the - // wrong thing to get pasted. - d.input.selectionEnd = end; - d.input.selectionStart = start; - cm.state.fakedLastChar = true; - } - cm.state.pasteIncoming = true; - fastPoll(cm); - }); - - function prepareCopyCut(e) { - if (cm.somethingSelected()) { - lastCopied = cm.getSelections(); - if (d.inaccurateSelection) { - d.prevInput = ""; - d.inaccurateSelection = false; - d.input.value = lastCopied.join("\n"); - selectInput(d.input); - } - } else { - var text = [], ranges = []; - for (var i = 0; i < cm.doc.sel.ranges.length; i++) { - var line = cm.doc.sel.ranges[i].head.line; - var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; - ranges.push(lineRange); - text.push(cm.getRange(lineRange.anchor, lineRange.head)); - } - if (e.type == "cut") { - cm.setSelections(ranges, null, sel_dontScroll); - } else { - d.prevInput = ""; - d.input.value = text.join("\n"); - selectInput(d.input); - } - lastCopied = text; - } - if (e.type == "cut") cm.state.cutIncoming = true; - } - on(d.input, "cut", prepareCopyCut); - on(d.input, "copy", prepareCopyCut); - - // Needed to handle Tab key in KHTML - if (khtml) on(d.sizer, "mouseup", function() { - if (activeElt() == d.input) d.input.blur(); - focusInput(cm); - }); - } - - // Called when the window resizes - function onResize(cm) { - var d = cm.display; - if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth) - return; - // Might be a text scaling operation, clear size caches. - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; - d.scrollbarsClipped = false; - cm.setSize(); - } - - // MOUSE EVENTS - - // Return true when the given mouse event happened in a widget - function eventInWidget(display, e) { - for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { - if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || - (n.parentNode == display.sizer && n != display.mover)) - return true; - } - } - - // Given a mouse event, find the corresponding position. If liberal - // is false, it checks whether a gutter or scrollbar was clicked, - // and returns null if it was. forRect is used by rectangular - // selections, and tries to estimate a character position even for - // coordinates beyond the right of the text. - function posFromMouse(cm, e, liberal, forRect) { - var display = cm.display; - if (!liberal && e_target(e).getAttribute("not-content") == "true") return null; - - var x, y, space = display.lineSpace.getBoundingClientRect(); - // Fails unpredictably on IE[67] when mouse is dragged around quickly. - try { x = e.clientX - space.left; y = e.clientY - space.top; } - catch (e) { return null; } - var coords = coordsChar(cm, x, y), line; - if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { - var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; - coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); - } - return coords; - } - - // A mouse down can be a single click, double click, triple click, - // start of selection drag, start of text drag, new cursor - // (ctrl-click), rectangle drag (alt-drag), or xwin - // middle-click-paste. Or it might be a click on something we should - // not interfere with, such as a scrollbar or widget. - function onMouseDown(e) { - if (signalDOMEvent(this, e)) return; - var cm = this, display = cm.display; - display.shift = e.shiftKey; - - if (eventInWidget(display, e)) { - if (!webkit) { - // Briefly turn off draggability, to allow widgets to do - // normal dragging things. - display.scroller.draggable = false; - setTimeout(function(){display.scroller.draggable = true;}, 100); - } - return; - } - if (clickInGutter(cm, e)) return; - var start = posFromMouse(cm, e); - window.focus(); - - switch (e_button(e)) { - case 1: - if (start) - leftButtonDown(cm, e, start); - else if (e_target(e) == display.scroller) - e_preventDefault(e); - break; - case 2: - if (webkit) cm.state.lastMiddleDown = +new Date; - if (start) extendSelection(cm.doc, start); - setTimeout(bind(focusInput, cm), 20); - e_preventDefault(e); - break; - case 3: - if (captureRightClick) onContextMenu(cm, e); - break; - } - } - - var lastClick, lastDoubleClick; - function leftButtonDown(cm, e, start) { - setTimeout(bind(ensureFocus, cm), 0); - - var now = +new Date, type; - if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) { - type = "triple"; - } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) { - type = "double"; - lastDoubleClick = {time: now, pos: start}; - } else { - type = "single"; - lastClick = {time: now, pos: start}; - } - - var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained; - if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && - type == "single" && (contained = sel.contains(start)) > -1 && - !sel.ranges[contained].empty()) - leftButtonStartDrag(cm, e, start, modifier); - else - leftButtonSelect(cm, e, start, type, modifier); - } - - // Start a text drag. When it ends, see if any dragging actually - // happen, and treat as a click if it didn't. - function leftButtonStartDrag(cm, e, start, modifier) { - var display = cm.display; - var dragEnd = operation(cm, function(e2) { - if (webkit) display.scroller.draggable = false; - cm.state.draggingText = false; - off(document, "mouseup", dragEnd); - off(display.scroller, "drop", dragEnd); - if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { - e_preventDefault(e2); - if (!modifier) - extendSelection(cm.doc, start); - focusInput(cm); - // Work around unexplainable focus problem in IE9 (#2127) - if (ie && ie_version == 9) - setTimeout(function() {document.body.focus(); focusInput(cm);}, 20); - } - }); - // Let the drag handler handle this. - if (webkit) display.scroller.draggable = true; - cm.state.draggingText = dragEnd; - // IE's approach to draggable - if (display.scroller.dragDrop) display.scroller.dragDrop(); - on(document, "mouseup", dragEnd); - on(display.scroller, "drop", dragEnd); - } - - // Normal selection, as opposed to text dragging. - function leftButtonSelect(cm, e, start, type, addNew) { - var display = cm.display, doc = cm.doc; - e_preventDefault(e); - - var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges; - if (addNew && !e.shiftKey) { - ourIndex = doc.sel.contains(start); - if (ourIndex > -1) - ourRange = ranges[ourIndex]; - else - ourRange = new Range(start, start); - } else { - ourRange = doc.sel.primary(); - } - - if (e.altKey) { - type = "rect"; - if (!addNew) ourRange = new Range(start, start); - start = posFromMouse(cm, e, true, true); - ourIndex = -1; - } else if (type == "double") { - var word = cm.findWordAt(start); - if (cm.display.shift || doc.extend) - ourRange = extendRange(doc, ourRange, word.anchor, word.head); - else - ourRange = word; - } else if (type == "triple") { - var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0))); - if (cm.display.shift || doc.extend) - ourRange = extendRange(doc, ourRange, line.anchor, line.head); - else - ourRange = line; - } else { - ourRange = extendRange(doc, ourRange, start); - } - - if (!addNew) { - ourIndex = 0; - setSelection(doc, new Selection([ourRange], 0), sel_mouse); - startSel = doc.sel; - } else if (ourIndex == -1) { - ourIndex = ranges.length; - setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex), - {scroll: false, origin: "*mouse"}); - } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single") { - setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0)); - startSel = doc.sel; - } else { - replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); - } - - var lastPos = start; - function extendTo(pos) { - if (cmp(lastPos, pos) == 0) return; - lastPos = pos; - - if (type == "rect") { - var ranges = [], tabSize = cm.options.tabSize; - var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); - var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); - var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); - for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); - line <= end; line++) { - var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize); - if (left == right) - ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); - else if (text.length > leftPos) - ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); - } - if (!ranges.length) ranges.push(new Range(start, start)); - setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), - {origin: "*mouse", scroll: false}); - cm.scrollIntoView(pos); - } else { - var oldRange = ourRange; - var anchor = oldRange.anchor, head = pos; - if (type != "single") { - if (type == "double") - var range = cm.findWordAt(pos); - else - var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))); - if (cmp(range.anchor, anchor) > 0) { - head = range.head; - anchor = minPos(oldRange.from(), range.anchor); - } else { - head = range.anchor; - anchor = maxPos(oldRange.to(), range.head); - } - } - var ranges = startSel.ranges.slice(0); - ranges[ourIndex] = new Range(clipPos(doc, anchor), head); - setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse); - } - } - - var editorSize = display.wrapper.getBoundingClientRect(); - // Used to ensure timeout re-tries don't fire when another extend - // happened in the meantime (clearTimeout isn't reliable -- at - // least on Chrome, the timeouts still happen even when cleared, - // if the clear happens after their scheduled firing time). - var counter = 0; - - function extend(e) { - var curCount = ++counter; - var cur = posFromMouse(cm, e, true, type == "rect"); - if (!cur) return; - if (cmp(cur, lastPos) != 0) { - ensureFocus(cm); - extendTo(cur); - var visible = visibleLines(display, doc); - if (cur.line >= visible.to || cur.line < visible.from) - setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150); - } else { - var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; - if (outside) setTimeout(operation(cm, function() { - if (counter != curCount) return; - display.scroller.scrollTop += outside; - extend(e); - }), 50); - } - } - - function done(e) { - counter = Infinity; - e_preventDefault(e); - focusInput(cm); - off(document, "mousemove", move); - off(document, "mouseup", up); - doc.history.lastSelOrigin = null; - } - - var move = operation(cm, function(e) { - if (!e_button(e)) done(e); - else extend(e); - }); - var up = operation(cm, done); - on(document, "mousemove", move); - on(document, "mouseup", up); - } - - // Determines whether an event happened in the gutter, and fires the - // handlers for the corresponding event. - function gutterEvent(cm, e, type, prevent, signalfn) { - try { var mX = e.clientX, mY = e.clientY; } - catch(e) { return false; } - if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false; - if (prevent) e_preventDefault(e); - - var display = cm.display; - var lineBox = display.lineDiv.getBoundingClientRect(); - - if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e); - mY -= lineBox.top - display.viewOffset; - - for (var i = 0; i < cm.options.gutters.length; ++i) { - var g = display.gutters.childNodes[i]; - if (g && g.getBoundingClientRect().right >= mX) { - var line = lineAtHeight(cm.doc, mY); - var gutter = cm.options.gutters[i]; - signalfn(cm, type, cm, line, gutter, e); - return e_defaultPrevented(e); - } - } - } - - function clickInGutter(cm, e) { - return gutterEvent(cm, e, "gutterClick", true, signalLater); - } - - // Kludge to work around strange IE behavior where it'll sometimes - // re-fire a series of drag-related events right after the drop (#1551) - var lastDrop = 0; - - function onDrop(e) { - var cm = this; - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) - return; - e_preventDefault(e); - if (ie) lastDrop = +new Date; - var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; - if (!pos || isReadOnly(cm)) return; - // Might be a file drop, in which case we simply extract the text - // and insert it. - if (files && files.length && window.FileReader && window.File) { - var n = files.length, text = Array(n), read = 0; - var loadFile = function(file, i) { - var reader = new FileReader; - reader.onload = operation(cm, function() { - text[i] = reader.result; - if (++read == n) { - pos = clipPos(cm.doc, pos); - var change = {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}; - makeChange(cm.doc, change); - setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))); - } - }); - reader.readAsText(file); - }; - for (var i = 0; i < n; ++i) loadFile(files[i], i); - } else { // Normal drop - // Don't do a replace if the drop happened inside of the selected text. - if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { - cm.state.draggingText(e); - // Ensure the editor is re-focused - setTimeout(bind(focusInput, cm), 20); - return; - } - try { - var text = e.dataTransfer.getData("Text"); - if (text) { - if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey)) - var selected = cm.listSelections(); - setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); - if (selected) for (var i = 0; i < selected.length; ++i) - replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag"); - cm.replaceSelection(text, "around", "paste"); - focusInput(cm); - } - } - catch(e){} - } - } - - function onDragStart(cm, e) { - if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; } - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return; - - e.dataTransfer.setData("Text", cm.getSelection()); - - // Use dummy image instead of default browsers image. - // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. - if (e.dataTransfer.setDragImage && !safari) { - var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); - img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; - if (presto) { - img.width = img.height = 1; - cm.display.wrapper.appendChild(img); - // Force a relayout, or Opera won't use our image for some obscure reason - img._top = img.offsetTop; - } - e.dataTransfer.setDragImage(img, 0, 0); - if (presto) img.parentNode.removeChild(img); - } - } - - // SCROLL EVENTS - - // Sync the scrollable area and scrollbars, ensure the viewport - // covers the visible area. - function setScrollTop(cm, val) { - if (Math.abs(cm.doc.scrollTop - val) < 2) return; - cm.doc.scrollTop = val; - if (!gecko) updateDisplaySimple(cm, {top: val}); - if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val; - cm.display.scrollbars.setScrollTop(val); - if (gecko) updateDisplaySimple(cm); - startWorker(cm, 100); - } - // Sync scroller and scrollbar, ensure the gutter elements are - // aligned. - function setScrollLeft(cm, val, isScroller) { - if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return; - val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); - cm.doc.scrollLeft = val; - alignHorizontally(cm); - if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val; - cm.display.scrollbars.setScrollLeft(val); - } - - // Since the delta values reported on mouse wheel events are - // unstandardized between browsers and even browser versions, and - // generally horribly unpredictable, this code starts by measuring - // the scroll effect that the first few mouse wheel events have, - // and, from that, detects the way it can convert deltas to pixel - // offsets afterwards. - // - // The reason we want to know the amount a wheel event will scroll - // is that it gives us a chance to update the display before the - // actual scrolling happens, reducing flickering. - - var wheelSamples = 0, wheelPixelsPerUnit = null; - // Fill in a browser-detected starting value on browsers where we - // know one. These don't have to be accurate -- the result of them - // being wrong would just be a slight flicker on the first wheel - // scroll (if it is large enough). - if (ie) wheelPixelsPerUnit = -.53; - else if (gecko) wheelPixelsPerUnit = 15; - else if (chrome) wheelPixelsPerUnit = -.7; - else if (safari) wheelPixelsPerUnit = -1/3; - - var wheelEventDelta = function(e) { - var dx = e.wheelDeltaX, dy = e.wheelDeltaY; - if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail; - if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail; - else if (dy == null) dy = e.wheelDelta; - return {x: dx, y: dy}; - }; - CodeMirror.wheelEventPixels = function(e) { - var delta = wheelEventDelta(e); - delta.x *= wheelPixelsPerUnit; - delta.y *= wheelPixelsPerUnit; - return delta; - }; - - function onScrollWheel(cm, e) { - var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; - - var display = cm.display, scroll = display.scroller; - // Quit if there's nothing to scroll here - if (!(dx && scroll.scrollWidth > scroll.clientWidth || - dy && scroll.scrollHeight > scroll.clientHeight)) return; - - // Webkit browsers on OS X abort momentum scrolls when the target - // of the scroll event is removed from the scrollable element. - // This hack (see related code in patchDisplay) makes sure the - // element is kept around. - if (dy && mac && webkit) { - outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { - for (var i = 0; i < view.length; i++) { - if (view[i].node == cur) { - cm.display.currentWheelTarget = cur; - break outer; - } - } - } - } - - // On some browsers, horizontal scrolling will cause redraws to - // happen before the gutter has been realigned, causing it to - // wriggle around in a most unseemly way. When we have an - // estimated pixels/delta value, we just handle horizontal - // scrolling entirely here. It'll be slightly off from native, but - // better than glitching out. - if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { - if (dy) - setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))); - setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))); - e_preventDefault(e); - display.wheelStartX = null; // Abort measurement, if in progress - return; - } - - // 'Project' the visible viewport to cover the area that is being - // scrolled into view (if we know enough to estimate it). - if (dy && wheelPixelsPerUnit != null) { - var pixels = dy * wheelPixelsPerUnit; - var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; - if (pixels < 0) top = Math.max(0, top + pixels - 50); - else bot = Math.min(cm.doc.height, bot + pixels + 50); - updateDisplaySimple(cm, {top: top, bottom: bot}); - } - - if (wheelSamples < 20) { - if (display.wheelStartX == null) { - display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; - display.wheelDX = dx; display.wheelDY = dy; - setTimeout(function() { - if (display.wheelStartX == null) return; - var movedX = scroll.scrollLeft - display.wheelStartX; - var movedY = scroll.scrollTop - display.wheelStartY; - var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || - (movedX && display.wheelDX && movedX / display.wheelDX); - display.wheelStartX = display.wheelStartY = null; - if (!sample) return; - wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); - ++wheelSamples; - }, 200); - } else { - display.wheelDX += dx; display.wheelDY += dy; - } - } - } - - // KEY EVENTS - - // Run a handler that was bound to a key. - function doHandleBinding(cm, bound, dropShift) { - if (typeof bound == "string") { - bound = commands[bound]; - if (!bound) return false; - } - // Ensure previous input has been read, so that the handler sees a - // consistent view of the document - if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false; - var prevShift = cm.display.shift, done = false; - try { - if (isReadOnly(cm)) cm.state.suppressEdits = true; - if (dropShift) cm.display.shift = false; - done = bound(cm) != Pass; - } finally { - cm.display.shift = prevShift; - cm.state.suppressEdits = false; - } - return done; - } - - function lookupKeyForEditor(cm, name, handle) { - for (var i = 0; i < cm.state.keyMaps.length; i++) { - var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); - if (result) return result; - } - return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) - || lookupKey(name, cm.options.keyMap, handle, cm); - } - - var stopSeq = new Delayed; - function dispatchKey(cm, name, e, handle) { - var seq = cm.state.keySeq; - if (seq) { - if (isModifierKey(name)) return "handled"; - stopSeq.set(50, function() { - if (cm.state.keySeq == seq) { - cm.state.keySeq = null; - resetInput(cm); - } - }); - name = seq + " " + name; - } - var result = lookupKeyForEditor(cm, name, handle); - - if (result == "multi") - cm.state.keySeq = name; - if (result == "handled") - signalLater(cm, "keyHandled", cm, name, e); - - if (result == "handled" || result == "multi") { - e_preventDefault(e); - restartBlink(cm); - } - - if (seq && !result && /\'$/.test(name)) { - e_preventDefault(e); - return true; - } - return !!result; - } - - // Handle a key from the keydown event. - function handleKeyBinding(cm, e) { - var name = keyName(e, true); - if (!name) return false; - - if (e.shiftKey && !cm.state.keySeq) { - // First try to resolve full name (including 'Shift-'). Failing - // that, see if there is a cursor-motion command (starting with - // 'go') bound to the keyname without 'Shift-'. - return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);}) - || dispatchKey(cm, name, e, function(b) { - if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) - return doHandleBinding(cm, b); - }); - } else { - return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); }); - } - } - - // Handle a key from the keypress event - function handleCharBinding(cm, e, ch) { - return dispatchKey(cm, "'" + ch + "'", e, - function(b) { return doHandleBinding(cm, b, true); }); - } - - var lastStoppedKey = null; - function onKeyDown(e) { - var cm = this; - ensureFocus(cm); - if (signalDOMEvent(cm, e)) return; - // IE does strange things with escape. - if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false; - var code = e.keyCode; - cm.display.shift = code == 16 || e.shiftKey; - var handled = handleKeyBinding(cm, e); - if (presto) { - lastStoppedKey = handled ? code : null; - // Opera has no cut event... we try to at least catch the key combo - if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) - cm.replaceSelection("", null, "cut"); - } - - // Turn mouse into crosshair when Alt is held on Mac. - if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) - showCrossHair(cm); - } - - function showCrossHair(cm) { - var lineDiv = cm.display.lineDiv; - addClass(lineDiv, "CodeMirror-crosshair"); - - function up(e) { - if (e.keyCode == 18 || !e.altKey) { - rmClass(lineDiv, "CodeMirror-crosshair"); - off(document, "keyup", up); - off(document, "mouseover", up); - } - } - on(document, "keyup", up); - on(document, "mouseover", up); - } - - function onKeyUp(e) { - if (e.keyCode == 16) this.doc.sel.shift = false; - signalDOMEvent(this, e); - } - - function onKeyPress(e) { - var cm = this; - if (signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return; - var keyCode = e.keyCode, charCode = e.charCode; - if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} - if (((presto && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return; - var ch = String.fromCharCode(charCode == null ? keyCode : charCode); - if (handleCharBinding(cm, e, ch)) return; - if (ie && ie_version >= 9) cm.display.inputHasSelection = null; - fastPoll(cm); - } - - // FOCUS/BLUR EVENTS - - function onFocus(cm) { - if (cm.options.readOnly == "nocursor") return; - if (!cm.state.focused) { - signal(cm, "focus", cm); - cm.state.focused = true; - addClass(cm.display.wrapper, "CodeMirror-focused"); - // The prevInput test prevents this from firing when a context - // menu is closed (since the resetInput would kill the - // select-all detection hack) - if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { - resetInput(cm); - if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730 - } - } - slowPoll(cm); - restartBlink(cm); - } - function onBlur(cm) { - if (cm.state.focused) { - signal(cm, "blur", cm); - cm.state.focused = false; - rmClass(cm.display.wrapper, "CodeMirror-focused"); - } - clearInterval(cm.display.blinker); - setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150); - } - - // CONTEXT MENU HANDLING - - // To make the context menu work, we need to briefly unhide the - // textarea (making it as unobtrusive as possible) to let the - // right-click take effect on it. - function onContextMenu(cm, e) { - if (signalDOMEvent(cm, e, "contextmenu")) return; - var display = cm.display; - if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return; - - var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; - if (!pos || presto) return; // Opera is difficult. - - // Reset the current text selection only if the click is done outside of the selection - // and 'resetSelectionOnContextMenu' option is true. - var reset = cm.options.resetSelectionOnContextMenu; - if (reset && cm.doc.sel.contains(pos) == -1) - operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); - - var oldCSS = display.input.style.cssText; - display.inputDiv.style.position = "absolute"; - display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + - "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " + - (ie ? "rgba(255, 255, 255, .05)" : "transparent") + - "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; - if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712) - focusInput(cm); - if (webkit) window.scrollTo(null, oldScrollY); - resetInput(cm); - // Adds "Select all" to context menu in FF - if (!cm.somethingSelected()) display.input.value = display.prevInput = " "; - display.contextMenuPending = true; - display.selForContextMenu = cm.doc.sel; - clearTimeout(display.detectingSelectAll); - - // Select-all will be greyed out if there's nothing to select, so - // this adds a zero-width space so that we can later check whether - // it got selected. - function prepareSelectAllHack() { - if (display.input.selectionStart != null) { - var selected = cm.somethingSelected(); - var extval = display.input.value = "\u200b" + (selected ? display.input.value : ""); - display.prevInput = selected ? "" : "\u200b"; - display.input.selectionStart = 1; display.input.selectionEnd = extval.length; - // Re-set this, in case some other handler touched the - // selection in the meantime. - display.selForContextMenu = cm.doc.sel; - } - } - function rehide() { - display.contextMenuPending = false; - display.inputDiv.style.position = "relative"; - display.input.style.cssText = oldCSS; - if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); - slowPoll(cm); - - // Try to detect the user choosing select-all - if (display.input.selectionStart != null) { - if (!ie || (ie && ie_version < 9)) prepareSelectAllHack(); - var i = 0, poll = function() { - if (display.selForContextMenu == cm.doc.sel && display.input.selectionStart == 0) - operation(cm, commands.selectAll)(cm); - else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500); - else resetInput(cm); - }; - display.detectingSelectAll = setTimeout(poll, 200); - } - } - - if (ie && ie_version >= 9) prepareSelectAllHack(); - if (captureRightClick) { - e_stop(e); - var mouseup = function() { - off(window, "mouseup", mouseup); - setTimeout(rehide, 20); - }; - on(window, "mouseup", mouseup); - } else { - setTimeout(rehide, 50); - } - } - - function contextMenuInGutter(cm, e) { - if (!hasHandler(cm, "gutterContextMenu")) return false; - return gutterEvent(cm, e, "gutterContextMenu", false, signal); - } - - // UPDATING - - // Compute the position of the end of a change (its 'to' property - // refers to the pre-change end). - var changeEnd = CodeMirror.changeEnd = function(change) { - if (!change.text) return change.to; - return Pos(change.from.line + change.text.length - 1, - lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)); - }; - - // Adjust a position to refer to the post-change position of the - // same text, or the end of the change if the change covers it. - function adjustForChange(pos, change) { - if (cmp(pos, change.from) < 0) return pos; - if (cmp(pos, change.to) <= 0) return changeEnd(change); - - var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; - if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch; - return Pos(line, ch); - } - - function computeSelAfterChange(doc, change) { - var out = []; - for (var i = 0; i < doc.sel.ranges.length; i++) { - var range = doc.sel.ranges[i]; - out.push(new Range(adjustForChange(range.anchor, change), - adjustForChange(range.head, change))); - } - return normalizeSelection(out, doc.sel.primIndex); - } - - function offsetPos(pos, old, nw) { - if (pos.line == old.line) - return Pos(nw.line, pos.ch - old.ch + nw.ch); - else - return Pos(nw.line + (pos.line - old.line), pos.ch); - } - - // Used by replaceSelections to allow moving the selection to the - // start or around the replaced test. Hint may be "start" or "around". - function computeReplacedSel(doc, changes, hint) { - var out = []; - var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; - for (var i = 0; i < changes.length; i++) { - var change = changes[i]; - var from = offsetPos(change.from, oldPrev, newPrev); - var to = offsetPos(changeEnd(change), oldPrev, newPrev); - oldPrev = change.to; - newPrev = to; - if (hint == "around") { - var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; - out[i] = new Range(inv ? to : from, inv ? from : to); - } else { - out[i] = new Range(from, from); - } - } - return new Selection(out, doc.sel.primIndex); - } - - // Allow "beforeChange" event handlers to influence a change - function filterChange(doc, change, update) { - var obj = { - canceled: false, - from: change.from, - to: change.to, - text: change.text, - origin: change.origin, - cancel: function() { this.canceled = true; } - }; - if (update) obj.update = function(from, to, text, origin) { - if (from) this.from = clipPos(doc, from); - if (to) this.to = clipPos(doc, to); - if (text) this.text = text; - if (origin !== undefined) this.origin = origin; - }; - signal(doc, "beforeChange", doc, obj); - if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj); - - if (obj.canceled) return null; - return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}; - } - - // Apply a change to a document, and add it to the document's - // history, and propagating it to all linked documents. - function makeChange(doc, change, ignoreReadOnly) { - if (doc.cm) { - if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly); - if (doc.cm.state.suppressEdits) return; - } - - if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { - change = filterChange(doc, change, true); - if (!change) return; - } - - // Possibly split or suppress the update based on the presence - // of read-only spans in its range. - var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); - if (split) { - for (var i = split.length - 1; i >= 0; --i) - makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text}); - } else { - makeChangeInner(doc, change); - } - } - - function makeChangeInner(doc, change) { - if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return; - var selAfter = computeSelAfterChange(doc, change); - addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); - - makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); - var rebased = []; - - linkedDocs(doc, function(doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change); - rebased.push(doc.history); - } - makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); - }); - } - - // Revert a change stored in a document's history. - function makeChangeFromHistory(doc, type, allowSelectionOnly) { - if (doc.cm && doc.cm.state.suppressEdits) return; - - var hist = doc.history, event, selAfter = doc.sel; - var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; - - // Verify that there is a useable event (so that ctrl-z won't - // needlessly clear selection events) - for (var i = 0; i < source.length; i++) { - event = source[i]; - if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) - break; - } - if (i == source.length) return; - hist.lastOrigin = hist.lastSelOrigin = null; - - for (;;) { - event = source.pop(); - if (event.ranges) { - pushSelectionToHistory(event, dest); - if (allowSelectionOnly && !event.equals(doc.sel)) { - setSelection(doc, event, {clearRedo: false}); - return; - } - selAfter = event; - } - else break; - } - - // Build up a reverse change object to add to the opposite history - // stack (redo when undoing, and vice versa). - var antiChanges = []; - pushSelectionToHistory(selAfter, dest); - dest.push({changes: antiChanges, generation: hist.generation}); - hist.generation = event.generation || ++hist.maxGeneration; - - var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); - - for (var i = event.changes.length - 1; i >= 0; --i) { - var change = event.changes[i]; - change.origin = type; - if (filter && !filterChange(doc, change, false)) { - source.length = 0; - return; - } - - antiChanges.push(historyChangeFromChange(doc, change)); - - var after = i ? computeSelAfterChange(doc, change) : lst(source); - makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); - if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); - var rebased = []; - - // Propagate to the linked documents - linkedDocs(doc, function(doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change); - rebased.push(doc.history); - } - makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); - }); - } - } - - // Sub-views need their line numbers shifted when text is added - // above or below them in the parent document. - function shiftDoc(doc, distance) { - if (distance == 0) return; - doc.first += distance; - doc.sel = new Selection(map(doc.sel.ranges, function(range) { - return new Range(Pos(range.anchor.line + distance, range.anchor.ch), - Pos(range.head.line + distance, range.head.ch)); - }), doc.sel.primIndex); - if (doc.cm) { - regChange(doc.cm, doc.first, doc.first - distance, distance); - for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) - regLineChange(doc.cm, l, "gutter"); - } - } - - // More lower-level change function, handling only a single document - // (not linked ones). - function makeChangeSingleDoc(doc, change, selAfter, spans) { - if (doc.cm && !doc.cm.curOp) - return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans); - - if (change.to.line < doc.first) { - shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); - return; - } - if (change.from.line > doc.lastLine()) return; - - // Clip the change to the size of this doc - if (change.from.line < doc.first) { - var shift = change.text.length - 1 - (doc.first - change.from.line); - shiftDoc(doc, shift); - change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), - text: [lst(change.text)], origin: change.origin}; - } - var last = doc.lastLine(); - if (change.to.line > last) { - change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), - text: [change.text[0]], origin: change.origin}; - } - - change.removed = getBetween(doc, change.from, change.to); - - if (!selAfter) selAfter = computeSelAfterChange(doc, change); - if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans); - else updateDoc(doc, change, spans); - setSelectionNoUndo(doc, selAfter, sel_dontScroll); - } - - // Handle the interaction of a change to a document with the editor - // that this document is part of. - function makeChangeSingleDocInEditor(cm, change, spans) { - var doc = cm.doc, display = cm.display, from = change.from, to = change.to; - - var recomputeMaxLength = false, checkWidthStart = from.line; - if (!cm.options.lineWrapping) { - checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); - doc.iter(checkWidthStart, to.line + 1, function(line) { - if (line == display.maxLine) { - recomputeMaxLength = true; - return true; - } - }); - } - - if (doc.sel.contains(change.from, change.to) > -1) - signalCursorActivity(cm); - - updateDoc(doc, change, spans, estimateHeight(cm)); - - if (!cm.options.lineWrapping) { - doc.iter(checkWidthStart, from.line + change.text.length, function(line) { - var len = lineLength(line); - if (len > display.maxLineLength) { - display.maxLine = line; - display.maxLineLength = len; - display.maxLineChanged = true; - recomputeMaxLength = false; - } - }); - if (recomputeMaxLength) cm.curOp.updateMaxLine = true; - } - - // Adjust frontier, schedule worker - doc.frontier = Math.min(doc.frontier, from.line); - startWorker(cm, 400); - - var lendiff = change.text.length - (to.line - from.line) - 1; - // Remember that these lines changed, for updating the display - if (change.full) - regChange(cm); - else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) - regLineChange(cm, from.line, "text"); - else - regChange(cm, from.line, to.line + 1, lendiff); - - var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); - if (changeHandler || changesHandler) { - var obj = { - from: from, to: to, - text: change.text, - removed: change.removed, - origin: change.origin - }; - if (changeHandler) signalLater(cm, "change", cm, obj); - if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); - } - cm.display.selForContextMenu = null; - } - - function replaceRange(doc, code, from, to, origin) { - if (!to) to = from; - if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; } - if (typeof code == "string") code = splitLines(code); - makeChange(doc, {from: from, to: to, text: code, origin: origin}); - } - - // SCROLLING THINGS INTO VIEW - - // If an editor sits on the top or bottom of the window, partially - // scrolled out of view, this ensures that the cursor is visible. - function maybeScrollWindow(cm, coords) { - if (signalDOMEvent(cm, "scrollCursorIntoView")) return; - - var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; - if (coords.top + box.top < 0) doScroll = true; - else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; - if (doScroll != null && !phantom) { - var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " + - (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " + - (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " + - coords.left + "px; width: 2px;"); - cm.display.lineSpace.appendChild(scrollNode); - scrollNode.scrollIntoView(doScroll); - cm.display.lineSpace.removeChild(scrollNode); - } - } - - // Scroll a given position into view (immediately), verifying that - // it actually became visible (as line heights are accurately - // measured, the position of something may 'drift' during drawing). - function scrollPosIntoView(cm, pos, end, margin) { - if (margin == null) margin = 0; - for (var limit = 0; limit < 5; limit++) { - var changed = false, coords = cursorCoords(cm, pos); - var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); - var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left), - Math.min(coords.top, endCoords.top) - margin, - Math.max(coords.left, endCoords.left), - Math.max(coords.bottom, endCoords.bottom) + margin); - var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; - if (scrollPos.scrollTop != null) { - setScrollTop(cm, scrollPos.scrollTop); - if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true; - } - if (scrollPos.scrollLeft != null) { - setScrollLeft(cm, scrollPos.scrollLeft); - if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true; - } - if (!changed) break; - } - return coords; - } - - // Scroll a given set of coordinates into view (immediately). - function scrollIntoView(cm, x1, y1, x2, y2) { - var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2); - if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop); - if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft); - } - - // Calculate a new scroll position needed to scroll the given - // rectangle into view. Returns an object with scrollTop and - // scrollLeft properties. When these are undefined, the - // vertical/horizontal position does not need to be adjusted. - function calculateScrollPos(cm, x1, y1, x2, y2) { - var display = cm.display, snapMargin = textHeight(cm.display); - if (y1 < 0) y1 = 0; - var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; - var screen = displayHeight(cm), result = {}; - if (y2 - y1 > screen) y2 = y1 + screen; - var docBottom = cm.doc.height + paddingVert(display); - var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin; - if (y1 < screentop) { - result.scrollTop = atTop ? 0 : y1; - } else if (y2 > screentop + screen) { - var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen); - if (newTop != screentop) result.scrollTop = newTop; - } - - var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft; - var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0); - var tooWide = x2 - x1 > screenw; - if (tooWide) x2 = x1 + screenw; - if (x1 < 10) - result.scrollLeft = 0; - else if (x1 < screenleft) - result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10)); - else if (x2 > screenw + screenleft - 3) - result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw; - return result; - } - - // Store a relative adjustment to the scroll position in the current - // operation (to be applied when the operation finishes). - function addToScrollPos(cm, left, top) { - if (left != null || top != null) resolveScrollToPos(cm); - if (left != null) - cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left; - if (top != null) - cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; - } - - // Make sure that at the end of the operation the current cursor is - // shown. - function ensureCursorVisible(cm) { - resolveScrollToPos(cm); - var cur = cm.getCursor(), from = cur, to = cur; - if (!cm.options.lineWrapping) { - from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur; - to = Pos(cur.line, cur.ch + 1); - } - cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true}; - } - - // When an operation has its scrollToPos property set, and another - // scroll action is applied before the end of the operation, this - // 'simulates' scrolling that position into view in a cheap way, so - // that the effect of intermediate scroll commands is not ignored. - function resolveScrollToPos(cm) { - var range = cm.curOp.scrollToPos; - if (range) { - cm.curOp.scrollToPos = null; - var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to); - var sPos = calculateScrollPos(cm, Math.min(from.left, to.left), - Math.min(from.top, to.top) - range.margin, - Math.max(from.right, to.right), - Math.max(from.bottom, to.bottom) + range.margin); - cm.scrollTo(sPos.scrollLeft, sPos.scrollTop); - } - } - - // API UTILITIES - - // Indent the given line. The how parameter can be "smart", - // "add"/null, "subtract", or "prev". When aggressive is false - // (typically set to true for forced single-line indents), empty - // lines are not indented, and places where the mode returns Pass - // are left alone. - function indentLine(cm, n, how, aggressive) { - var doc = cm.doc, state; - if (how == null) how = "add"; - if (how == "smart") { - // Fall back to "prev" when the mode doesn't have an indentation - // method. - if (!doc.mode.indent) how = "prev"; - else state = getStateBefore(cm, n); - } - - var tabSize = cm.options.tabSize; - var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); - if (line.stateAfter) line.stateAfter = null; - var curSpaceString = line.text.match(/^\s*/)[0], indentation; - if (!aggressive && !/\S/.test(line.text)) { - indentation = 0; - how = "not"; - } else if (how == "smart") { - indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); - if (indentation == Pass || indentation > 150) { - if (!aggressive) return; - how = "prev"; - } - } - if (how == "prev") { - if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize); - else indentation = 0; - } else if (how == "add") { - indentation = curSpace + cm.options.indentUnit; - } else if (how == "subtract") { - indentation = curSpace - cm.options.indentUnit; - } else if (typeof how == "number") { - indentation = curSpace + how; - } - indentation = Math.max(0, indentation); - - var indentString = "", pos = 0; - if (cm.options.indentWithTabs) - for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} - if (pos < indentation) indentString += spaceStr(indentation - pos); - - if (indentString != curSpaceString) { - replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); - } else { - // Ensure that, if the cursor was in the whitespace at the start - // of the line, it is moved to the end of that space. - for (var i = 0; i < doc.sel.ranges.length; i++) { - var range = doc.sel.ranges[i]; - if (range.head.line == n && range.head.ch < curSpaceString.length) { - var pos = Pos(n, curSpaceString.length); - replaceOneSelection(doc, i, new Range(pos, pos)); - break; - } - } - } - line.stateAfter = null; - } - - // Utility for applying a change to a line by handle or number, - // returning the number and optionally registering the line as - // changed. - function changeLine(doc, handle, changeType, op) { - var no = handle, line = handle; - if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle)); - else no = lineNo(handle); - if (no == null) return null; - if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType); - return line; - } - - // Helper for deleting text near the selection(s), used to implement - // backspace, delete, and similar functionality. - function deleteNearSelection(cm, compute) { - var ranges = cm.doc.sel.ranges, kill = []; - // Build up a set of ranges to kill first, merging overlapping - // ranges. - for (var i = 0; i < ranges.length; i++) { - var toKill = compute(ranges[i]); - while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { - var replaced = kill.pop(); - if (cmp(replaced.from, toKill.from) < 0) { - toKill.from = replaced.from; - break; - } - } - kill.push(toKill); - } - // Next, remove those actual ranges. - runInOp(cm, function() { - for (var i = kill.length - 1; i >= 0; i--) - replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); - ensureCursorVisible(cm); - }); - } - - // Used for horizontal relative motion. Dir is -1 or 1 (left or - // right), unit can be "char", "column" (like char, but doesn't - // cross line boundaries), "word" (across next word), or "group" (to - // the start of next group of word or non-word-non-whitespace - // chars). The visually param controls whether, in right-to-left - // text, direction 1 means to move towards the next index in the - // string, or towards the character to the right of the current - // position. The resulting position will have a hitSide=true - // property if it reached the end of the document. - function findPosH(doc, pos, dir, unit, visually) { - var line = pos.line, ch = pos.ch, origDir = dir; - var lineObj = getLine(doc, line); - var possible = true; - function findNextLine() { - var l = line + dir; - if (l < doc.first || l >= doc.first + doc.size) return (possible = false); - line = l; - return lineObj = getLine(doc, l); - } - function moveOnce(boundToLine) { - var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true); - if (next == null) { - if (!boundToLine && findNextLine()) { - if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj); - else ch = dir < 0 ? lineObj.text.length : 0; - } else return (possible = false); - } else ch = next; - return true; - } - - if (unit == "char") moveOnce(); - else if (unit == "column") moveOnce(true); - else if (unit == "word" || unit == "group") { - var sawType = null, group = unit == "group"; - var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); - for (var first = true;; first = false) { - if (dir < 0 && !moveOnce(!first)) break; - var cur = lineObj.text.charAt(ch) || "\n"; - var type = isWordChar(cur, helper) ? "w" - : group && cur == "\n" ? "n" - : !group || /\s/.test(cur) ? null - : "p"; - if (group && !first && !type) type = "s"; - if (sawType && sawType != type) { - if (dir < 0) {dir = 1; moveOnce();} - break; - } - - if (type) sawType = type; - if (dir > 0 && !moveOnce(!first)) break; - } - } - var result = skipAtomic(doc, Pos(line, ch), origDir, true); - if (!possible) result.hitSide = true; - return result; - } - - // For relative vertical movement. Dir may be -1 or 1. Unit can be - // "page" or "line". The resulting position will have a hitSide=true - // property if it reached the end of the document. - function findPosV(cm, pos, dir, unit) { - var doc = cm.doc, x = pos.left, y; - if (unit == "page") { - var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); - y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display)); - } else if (unit == "line") { - y = dir > 0 ? pos.bottom + 3 : pos.top - 3; - } - for (;;) { - var target = coordsChar(cm, x, y); - if (!target.outside) break; - if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; } - y += dir * 5; - } - return target; - } - - // EDITOR METHODS - - // The publicly visible API. Note that methodOp(f) means - // 'wrap f in an operation, performed on its `this` parameter'. - - // This is not the complete set of editor methods. Most of the - // methods defined on the Doc type are also injected into - // CodeMirror.prototype, for backwards compatibility and - // convenience. - - CodeMirror.prototype = { - constructor: CodeMirror, - focus: function(){window.focus(); focusInput(this); fastPoll(this);}, - - setOption: function(option, value) { - var options = this.options, old = options[option]; - if (options[option] == value && option != "mode") return; - options[option] = value; - if (optionHandlers.hasOwnProperty(option)) - operation(this, optionHandlers[option])(this, value, old); - }, - - getOption: function(option) {return this.options[option];}, - getDoc: function() {return this.doc;}, - - addKeyMap: function(map, bottom) { - this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)); - }, - removeKeyMap: function(map) { - var maps = this.state.keyMaps; - for (var i = 0; i < maps.length; ++i) - if (maps[i] == map || maps[i].name == map) { - maps.splice(i, 1); - return true; - } - }, - - addOverlay: methodOp(function(spec, options) { - var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); - if (mode.startState) throw new Error("Overlays may not be stateful."); - this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque}); - this.state.modeGen++; - regChange(this); - }), - removeOverlay: methodOp(function(spec) { - var overlays = this.state.overlays; - for (var i = 0; i < overlays.length; ++i) { - var cur = overlays[i].modeSpec; - if (cur == spec || typeof spec == "string" && cur.name == spec) { - overlays.splice(i, 1); - this.state.modeGen++; - regChange(this); - return; - } - } - }), - - indentLine: methodOp(function(n, dir, aggressive) { - if (typeof dir != "string" && typeof dir != "number") { - if (dir == null) dir = this.options.smartIndent ? "smart" : "prev"; - else dir = dir ? "add" : "subtract"; - } - if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive); - }), - indentSelection: methodOp(function(how) { - var ranges = this.doc.sel.ranges, end = -1; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (!range.empty()) { - var from = range.from(), to = range.to(); - var start = Math.max(end, from.line); - end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; - for (var j = start; j < end; ++j) - indentLine(this, j, how); - var newRanges = this.doc.sel.ranges; - if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) - replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); - } else if (range.head.line > end) { - indentLine(this, range.head.line, how, true); - end = range.head.line; - if (i == this.doc.sel.primIndex) ensureCursorVisible(this); - } - } - }), - - // Fetch the parser token for a given character. Useful for hacks - // that want to inspect the mode state (say, for completion). - getTokenAt: function(pos, precise) { - return takeToken(this, pos, precise); - }, - - getLineTokens: function(line, precise) { - return takeToken(this, Pos(line), precise, true); - }, - - getTokenTypeAt: function(pos) { - pos = clipPos(this.doc, pos); - var styles = getLineStyles(this, getLine(this.doc, pos.line)); - var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; - var type; - if (ch == 0) type = styles[2]; - else for (;;) { - var mid = (before + after) >> 1; - if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid; - else if (styles[mid * 2 + 1] < ch) before = mid + 1; - else { type = styles[mid * 2 + 2]; break; } - } - var cut = type ? type.indexOf("cm-overlay ") : -1; - return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1); - }, - - getModeAt: function(pos) { - var mode = this.doc.mode; - if (!mode.innerMode) return mode; - return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode; - }, - - getHelper: function(pos, type) { - return this.getHelpers(pos, type)[0]; - }, - - getHelpers: function(pos, type) { - var found = []; - if (!helpers.hasOwnProperty(type)) return helpers; - var help = helpers[type], mode = this.getModeAt(pos); - if (typeof mode[type] == "string") { - if (help[mode[type]]) found.push(help[mode[type]]); - } else if (mode[type]) { - for (var i = 0; i < mode[type].length; i++) { - var val = help[mode[type][i]]; - if (val) found.push(val); - } - } else if (mode.helperType && help[mode.helperType]) { - found.push(help[mode.helperType]); - } else if (help[mode.name]) { - found.push(help[mode.name]); - } - for (var i = 0; i < help._global.length; i++) { - var cur = help._global[i]; - if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) - found.push(cur.val); - } - return found; - }, - - getStateAfter: function(line, precise) { - var doc = this.doc; - line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); - return getStateBefore(this, line + 1, precise); - }, - - cursorCoords: function(start, mode) { - var pos, range = this.doc.sel.primary(); - if (start == null) pos = range.head; - else if (typeof start == "object") pos = clipPos(this.doc, start); - else pos = start ? range.from() : range.to(); - return cursorCoords(this, pos, mode || "page"); - }, - - charCoords: function(pos, mode) { - return charCoords(this, clipPos(this.doc, pos), mode || "page"); - }, - - coordsChar: function(coords, mode) { - coords = fromCoordSystem(this, coords, mode || "page"); - return coordsChar(this, coords.left, coords.top); - }, - - lineAtHeight: function(height, mode) { - height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; - return lineAtHeight(this.doc, height + this.display.viewOffset); - }, - heightAtLine: function(line, mode) { - var end = false, last = this.doc.first + this.doc.size - 1; - if (line < this.doc.first) line = this.doc.first; - else if (line > last) { line = last; end = true; } - var lineObj = getLine(this.doc, line); - return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top + - (end ? this.doc.height - heightAtLine(lineObj) : 0); - }, - - defaultTextHeight: function() { return textHeight(this.display); }, - defaultCharWidth: function() { return charWidth(this.display); }, - - setGutterMarker: methodOp(function(line, gutterID, value) { - return changeLine(this.doc, line, "gutter", function(line) { - var markers = line.gutterMarkers || (line.gutterMarkers = {}); - markers[gutterID] = value; - if (!value && isEmpty(markers)) line.gutterMarkers = null; - return true; - }); - }), - - clearGutter: methodOp(function(gutterID) { - var cm = this, doc = cm.doc, i = doc.first; - doc.iter(function(line) { - if (line.gutterMarkers && line.gutterMarkers[gutterID]) { - line.gutterMarkers[gutterID] = null; - regLineChange(cm, i, "gutter"); - if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null; - } - ++i; - }); - }), - - addLineWidget: methodOp(function(handle, node, options) { - return addLineWidget(this, handle, node, options); - }), - - removeLineWidget: function(widget) { widget.clear(); }, - - lineInfo: function(line) { - if (typeof line == "number") { - if (!isLine(this.doc, line)) return null; - var n = line; - line = getLine(this.doc, line); - if (!line) return null; - } else { - var n = lineNo(line); - if (n == null) return null; - } - return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, - textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, - widgets: line.widgets}; - }, - - getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};}, - - addWidget: function(pos, node, scroll, vert, horiz) { - var display = this.display; - pos = cursorCoords(this, clipPos(this.doc, pos)); - var top = pos.bottom, left = pos.left; - node.style.position = "absolute"; - node.setAttribute("cm-ignore-events", "true"); - display.sizer.appendChild(node); - if (vert == "over") { - top = pos.top; - } else if (vert == "above" || vert == "near") { - var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), - hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); - // Default to positioning above (if specified and possible); otherwise default to positioning below - if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) - top = pos.top - node.offsetHeight; - else if (pos.bottom + node.offsetHeight <= vspace) - top = pos.bottom; - if (left + node.offsetWidth > hspace) - left = hspace - node.offsetWidth; - } - node.style.top = top + "px"; - node.style.left = node.style.right = ""; - if (horiz == "right") { - left = display.sizer.clientWidth - node.offsetWidth; - node.style.right = "0px"; - } else { - if (horiz == "left") left = 0; - else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2; - node.style.left = left + "px"; - } - if (scroll) - scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight); - }, - - triggerOnKeyDown: methodOp(onKeyDown), - triggerOnKeyPress: methodOp(onKeyPress), - triggerOnKeyUp: onKeyUp, - - execCommand: function(cmd) { - if (commands.hasOwnProperty(cmd)) - return commands[cmd](this); - }, - - findPosH: function(from, amount, unit, visually) { - var dir = 1; - if (amount < 0) { dir = -1; amount = -amount; } - for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { - cur = findPosH(this.doc, cur, dir, unit, visually); - if (cur.hitSide) break; - } - return cur; - }, - - moveH: methodOp(function(dir, unit) { - var cm = this; - cm.extendSelectionsBy(function(range) { - if (cm.display.shift || cm.doc.extend || range.empty()) - return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually); - else - return dir < 0 ? range.from() : range.to(); - }, sel_move); - }), - - deleteH: methodOp(function(dir, unit) { - var sel = this.doc.sel, doc = this.doc; - if (sel.somethingSelected()) - doc.replaceSelection("", null, "+delete"); - else - deleteNearSelection(this, function(range) { - var other = findPosH(doc, range.head, dir, unit, false); - return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}; - }); - }), - - findPosV: function(from, amount, unit, goalColumn) { - var dir = 1, x = goalColumn; - if (amount < 0) { dir = -1; amount = -amount; } - for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { - var coords = cursorCoords(this, cur, "div"); - if (x == null) x = coords.left; - else coords.left = x; - cur = findPosV(this, coords, dir, unit); - if (cur.hitSide) break; - } - return cur; - }, - - moveV: methodOp(function(dir, unit) { - var cm = this, doc = this.doc, goals = []; - var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected(); - doc.extendSelectionsBy(function(range) { - if (collapse) - return dir < 0 ? range.from() : range.to(); - var headPos = cursorCoords(cm, range.head, "div"); - if (range.goalColumn != null) headPos.left = range.goalColumn; - goals.push(headPos.left); - var pos = findPosV(cm, headPos, dir, unit); - if (unit == "page" && range == doc.sel.primary()) - addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top); - return pos; - }, sel_move); - if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++) - doc.sel.ranges[i].goalColumn = goals[i]; - }), - - // Find the word at the given position (as returned by coordsChar). - findWordAt: function(pos) { - var doc = this.doc, line = getLine(doc, pos.line).text; - var start = pos.ch, end = pos.ch; - if (line) { - var helper = this.getHelper(pos, "wordChars"); - if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end; - var startChar = line.charAt(start); - var check = isWordChar(startChar, helper) - ? function(ch) { return isWordChar(ch, helper); } - : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} - : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);}; - while (start > 0 && check(line.charAt(start - 1))) --start; - while (end < line.length && check(line.charAt(end))) ++end; - } - return new Range(Pos(pos.line, start), Pos(pos.line, end)); - }, - - toggleOverwrite: function(value) { - if (value != null && value == this.state.overwrite) return; - if (this.state.overwrite = !this.state.overwrite) - addClass(this.display.cursorDiv, "CodeMirror-overwrite"); - else - rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); - - signal(this, "overwriteToggle", this, this.state.overwrite); - }, - hasFocus: function() { return activeElt() == this.display.input; }, - - scrollTo: methodOp(function(x, y) { - if (x != null || y != null) resolveScrollToPos(this); - if (x != null) this.curOp.scrollLeft = x; - if (y != null) this.curOp.scrollTop = y; - }), - getScrollInfo: function() { - var scroller = this.display.scroller; - return {left: scroller.scrollLeft, top: scroller.scrollTop, - height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, - width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, - clientHeight: displayHeight(this), clientWidth: displayWidth(this)}; - }, - - scrollIntoView: methodOp(function(range, margin) { - if (range == null) { - range = {from: this.doc.sel.primary().head, to: null}; - if (margin == null) margin = this.options.cursorScrollMargin; - } else if (typeof range == "number") { - range = {from: Pos(range, 0), to: null}; - } else if (range.from == null) { - range = {from: range, to: null}; - } - if (!range.to) range.to = range.from; - range.margin = margin || 0; - - if (range.from.line != null) { - resolveScrollToPos(this); - this.curOp.scrollToPos = range; - } else { - var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left), - Math.min(range.from.top, range.to.top) - range.margin, - Math.max(range.from.right, range.to.right), - Math.max(range.from.bottom, range.to.bottom) + range.margin); - this.scrollTo(sPos.scrollLeft, sPos.scrollTop); - } - }), - - setSize: methodOp(function(width, height) { - var cm = this; - function interpret(val) { - return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; - } - if (width != null) cm.display.wrapper.style.width = interpret(width); - if (height != null) cm.display.wrapper.style.height = interpret(height); - if (cm.options.lineWrapping) clearLineMeasurementCache(this); - var lineNo = cm.display.viewFrom; - cm.doc.iter(lineNo, cm.display.viewTo, function(line) { - if (line.widgets) for (var i = 0; i < line.widgets.length; i++) - if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; } - ++lineNo; - }); - cm.curOp.forceUpdate = true; - signal(cm, "refresh", this); - }), - - operation: function(f){return runInOp(this, f);}, - - refresh: methodOp(function() { - var oldHeight = this.display.cachedTextHeight; - regChange(this); - this.curOp.forceUpdate = true; - clearCaches(this); - this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop); - updateGutterSpace(this); - if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) - estimateLineHeights(this); - signal(this, "refresh", this); - }), - - swapDoc: methodOp(function(doc) { - var old = this.doc; - old.cm = null; - attachDoc(this, doc); - clearCaches(this); - resetInput(this); - this.scrollTo(doc.scrollLeft, doc.scrollTop); - this.curOp.forceScroll = true; - signalLater(this, "swapDoc", this, old); - return old; - }), - - getInputField: function(){return this.display.input;}, - getWrapperElement: function(){return this.display.wrapper;}, - getScrollerElement: function(){return this.display.scroller;}, - getGutterElement: function(){return this.display.gutters;} - }; - eventMixin(CodeMirror); - - // OPTION DEFAULTS - - // The default configuration options. - var defaults = CodeMirror.defaults = {}; - // Functions to run when options are changed. - var optionHandlers = CodeMirror.optionHandlers = {}; - - function option(name, deflt, handle, notOnInit) { - CodeMirror.defaults[name] = deflt; - if (handle) optionHandlers[name] = - notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle; - } - - // Passed to option handlers when there is no old value. - var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}}; - - // These two are, on init, called from the constructor because they - // have to be initialized before the editor can start at all. - option("value", "", function(cm, val) { - cm.setValue(val); - }, true); - option("mode", null, function(cm, val) { - cm.doc.modeOption = val; - loadMode(cm); - }, true); - - option("indentUnit", 2, loadMode, true); - option("indentWithTabs", false); - option("smartIndent", true); - option("tabSize", 4, function(cm) { - resetModeState(cm); - clearCaches(cm); - regChange(cm); - }, true); - option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val) { - cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); - cm.refresh(); - }, true); - option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true); - option("electricChars", true); - option("rtlMoveVisually", !windows); - option("wholeLineUpdateBefore", true); - - option("theme", "default", function(cm) { - themeChanged(cm); - guttersChanged(cm); - }, true); - option("keyMap", "default", function(cm, val, old) { - var next = getKeyMap(val); - var prev = old != CodeMirror.Init && getKeyMap(old); - if (prev && prev.detach) prev.detach(cm, next); - if (next.attach) next.attach(cm, prev || null); - }); - option("extraKeys", null); - - option("lineWrapping", false, wrappingChanged, true); - option("gutters", [], function(cm) { - setGuttersForLineNumbers(cm.options); - guttersChanged(cm); - }, true); - option("fixedGutter", true, function(cm, val) { - cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; - cm.refresh(); - }, true); - option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true); - option("scrollbarStyle", "native", function(cm) { - initScrollbars(cm); - updateScrollbars(cm); - cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); - cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); - }, true); - option("lineNumbers", false, function(cm) { - setGuttersForLineNumbers(cm.options); - guttersChanged(cm); - }, true); - option("firstLineNumber", 1, guttersChanged, true); - option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true); - option("showCursorWhenSelecting", false, updateSelection, true); - - option("resetSelectionOnContextMenu", true); - - option("readOnly", false, function(cm, val) { - if (val == "nocursor") { - onBlur(cm); - cm.display.input.blur(); - cm.display.disabled = true; - } else { - cm.display.disabled = false; - if (!val) resetInput(cm); - } - }); - option("disableInput", false, function(cm, val) {if (!val) resetInput(cm);}, true); - option("dragDrop", true); - - option("cursorBlinkRate", 530); - option("cursorScrollMargin", 0); - option("cursorHeight", 1, updateSelection, true); - option("singleCursorHeightPerLine", true, updateSelection, true); - option("workTime", 100); - option("workDelay", 100); - option("flattenSpans", true, resetModeState, true); - option("addModeClass", false, resetModeState, true); - option("pollInterval", 100); - option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;}); - option("historyEventDelay", 1250); - option("viewportMargin", 10, function(cm){cm.refresh();}, true); - option("maxHighlightLength", 10000, resetModeState, true); - option("moveInputWithCursor", true, function(cm, val) { - if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0; - }); - - option("tabindex", null, function(cm, val) { - cm.display.input.tabIndex = val || ""; - }); - option("autofocus", null); - - // MODE DEFINITION AND QUERYING - - // Known modes, by name and by MIME - var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; - - // Extra arguments are stored as the mode's dependencies, which is - // used by (legacy) mechanisms like loadmode.js to automatically - // load a mode. (Preferred mechanism is the require/define calls.) - CodeMirror.defineMode = function(name, mode) { - if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; - if (arguments.length > 2) - mode.dependencies = Array.prototype.slice.call(arguments, 2); - modes[name] = mode; - }; - - CodeMirror.defineMIME = function(mime, spec) { - mimeModes[mime] = spec; - }; - - // Given a MIME type, a {name, ...options} config object, or a name - // string, return a mode config object. - CodeMirror.resolveMode = function(spec) { - if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { - spec = mimeModes[spec]; - } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { - var found = mimeModes[spec.name]; - if (typeof found == "string") found = {name: found}; - spec = createObj(found, spec); - spec.name = found.name; - } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { - return CodeMirror.resolveMode("application/xml"); - } - if (typeof spec == "string") return {name: spec}; - else return spec || {name: "null"}; - }; - - // Given a mode spec (anything that resolveMode accepts), find and - // initialize an actual mode object. - CodeMirror.getMode = function(options, spec) { - var spec = CodeMirror.resolveMode(spec); - var mfactory = modes[spec.name]; - if (!mfactory) return CodeMirror.getMode(options, "text/plain"); - var modeObj = mfactory(options, spec); - if (modeExtensions.hasOwnProperty(spec.name)) { - var exts = modeExtensions[spec.name]; - for (var prop in exts) { - if (!exts.hasOwnProperty(prop)) continue; - if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop]; - modeObj[prop] = exts[prop]; - } - } - modeObj.name = spec.name; - if (spec.helperType) modeObj.helperType = spec.helperType; - if (spec.modeProps) for (var prop in spec.modeProps) - modeObj[prop] = spec.modeProps[prop]; - - return modeObj; - }; - - // Minimal default mode. - CodeMirror.defineMode("null", function() { - return {token: function(stream) {stream.skipToEnd();}}; - }); - CodeMirror.defineMIME("text/plain", "null"); - - // This can be used to attach properties to mode objects from - // outside the actual mode definition. - var modeExtensions = CodeMirror.modeExtensions = {}; - CodeMirror.extendMode = function(mode, properties) { - var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); - copyObj(properties, exts); - }; - - // EXTENSIONS - - CodeMirror.defineExtension = function(name, func) { - CodeMirror.prototype[name] = func; - }; - CodeMirror.defineDocExtension = function(name, func) { - Doc.prototype[name] = func; - }; - CodeMirror.defineOption = option; - - var initHooks = []; - CodeMirror.defineInitHook = function(f) {initHooks.push(f);}; - - var helpers = CodeMirror.helpers = {}; - CodeMirror.registerHelper = function(type, name, value) { - if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []}; - helpers[type][name] = value; - }; - CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { - CodeMirror.registerHelper(type, name, value); - helpers[type]._global.push({pred: predicate, val: value}); - }; - - // MODE STATE HANDLING - - // Utility functions for working with state. Exported because nested - // modes need to do this for their inner modes. - - var copyState = CodeMirror.copyState = function(mode, state) { - if (state === true) return state; - if (mode.copyState) return mode.copyState(state); - var nstate = {}; - for (var n in state) { - var val = state[n]; - if (val instanceof Array) val = val.concat([]); - nstate[n] = val; - } - return nstate; - }; - - var startState = CodeMirror.startState = function(mode, a1, a2) { - return mode.startState ? mode.startState(a1, a2) : true; - }; - - // Given a mode and a state (for that mode), find the inner mode and - // state at the position that the state refers to. - CodeMirror.innerMode = function(mode, state) { - while (mode.innerMode) { - var info = mode.innerMode(state); - if (!info || info.mode == mode) break; - state = info.state; - mode = info.mode; - } - return info || {mode: mode, state: state}; - }; - - // STANDARD COMMANDS - - // Commands are parameter-less actions that can be performed on an - // editor, mostly used for keybindings. - var commands = CodeMirror.commands = { - selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);}, - singleSelection: function(cm) { - cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); - }, - killLine: function(cm) { - deleteNearSelection(cm, function(range) { - if (range.empty()) { - var len = getLine(cm.doc, range.head.line).text.length; - if (range.head.ch == len && range.head.line < cm.lastLine()) - return {from: range.head, to: Pos(range.head.line + 1, 0)}; - else - return {from: range.head, to: Pos(range.head.line, len)}; - } else { - return {from: range.from(), to: range.to()}; - } - }); - }, - deleteLine: function(cm) { - deleteNearSelection(cm, function(range) { - return {from: Pos(range.from().line, 0), - to: clipPos(cm.doc, Pos(range.to().line + 1, 0))}; - }); - }, - delLineLeft: function(cm) { - deleteNearSelection(cm, function(range) { - return {from: Pos(range.from().line, 0), to: range.from()}; - }); - }, - delWrappedLineLeft: function(cm) { - deleteNearSelection(cm, function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - var leftPos = cm.coordsChar({left: 0, top: top}, "div"); - return {from: leftPos, to: range.from()}; - }); - }, - delWrappedLineRight: function(cm) { - deleteNearSelection(cm, function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); - return {from: range.from(), to: rightPos }; - }); - }, - undo: function(cm) {cm.undo();}, - redo: function(cm) {cm.redo();}, - undoSelection: function(cm) {cm.undoSelection();}, - redoSelection: function(cm) {cm.redoSelection();}, - goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));}, - goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));}, - goLineStart: function(cm) { - cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); }, - {origin: "+move", bias: 1}); - }, - goLineStartSmart: function(cm) { - cm.extendSelectionsBy(function(range) { - return lineStartSmart(cm, range.head); - }, {origin: "+move", bias: 1}); - }, - goLineEnd: function(cm) { - cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); }, - {origin: "+move", bias: -1}); - }, - goLineRight: function(cm) { - cm.extendSelectionsBy(function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); - }, sel_move); - }, - goLineLeft: function(cm) { - cm.extendSelectionsBy(function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - return cm.coordsChar({left: 0, top: top}, "div"); - }, sel_move); - }, - goLineLeftSmart: function(cm) { - cm.extendSelectionsBy(function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - var pos = cm.coordsChar({left: 0, top: top}, "div"); - if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head); - return pos; - }, sel_move); - }, - goLineUp: function(cm) {cm.moveV(-1, "line");}, - goLineDown: function(cm) {cm.moveV(1, "line");}, - goPageUp: function(cm) {cm.moveV(-1, "page");}, - goPageDown: function(cm) {cm.moveV(1, "page");}, - goCharLeft: function(cm) {cm.moveH(-1, "char");}, - goCharRight: function(cm) {cm.moveH(1, "char");}, - goColumnLeft: function(cm) {cm.moveH(-1, "column");}, - goColumnRight: function(cm) {cm.moveH(1, "column");}, - goWordLeft: function(cm) {cm.moveH(-1, "word");}, - goGroupRight: function(cm) {cm.moveH(1, "group");}, - goGroupLeft: function(cm) {cm.moveH(-1, "group");}, - goWordRight: function(cm) {cm.moveH(1, "word");}, - delCharBefore: function(cm) {cm.deleteH(-1, "char");}, - delCharAfter: function(cm) {cm.deleteH(1, "char");}, - delWordBefore: function(cm) {cm.deleteH(-1, "word");}, - delWordAfter: function(cm) {cm.deleteH(1, "word");}, - delGroupBefore: function(cm) {cm.deleteH(-1, "group");}, - delGroupAfter: function(cm) {cm.deleteH(1, "group");}, - indentAuto: function(cm) {cm.indentSelection("smart");}, - indentMore: function(cm) {cm.indentSelection("add");}, - indentLess: function(cm) {cm.indentSelection("subtract");}, - insertTab: function(cm) {cm.replaceSelection("\t");}, - insertSoftTab: function(cm) { - var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; - for (var i = 0; i < ranges.length; i++) { - var pos = ranges[i].from(); - var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); - spaces.push(new Array(tabSize - col % tabSize + 1).join(" ")); - } - cm.replaceSelections(spaces); - }, - defaultTab: function(cm) { - if (cm.somethingSelected()) cm.indentSelection("add"); - else cm.execCommand("insertTab"); - }, - transposeChars: function(cm) { - runInOp(cm, function() { - var ranges = cm.listSelections(), newSel = []; - for (var i = 0; i < ranges.length; i++) { - var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; - if (line) { - if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1); - if (cur.ch > 0) { - cur = new Pos(cur.line, cur.ch + 1); - cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), - Pos(cur.line, cur.ch - 2), cur, "+transpose"); - } else if (cur.line > cm.doc.first) { - var prev = getLine(cm.doc, cur.line - 1).text; - if (prev) - cm.replaceRange(line.charAt(0) + "\n" + prev.charAt(prev.length - 1), - Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose"); - } - } - newSel.push(new Range(cur, cur)); - } - cm.setSelections(newSel); - }); - }, - newlineAndIndent: function(cm) { - runInOp(cm, function() { - var len = cm.listSelections().length; - for (var i = 0; i < len; i++) { - var range = cm.listSelections()[i]; - cm.replaceRange("\n", range.anchor, range.head, "+input"); - cm.indentLine(range.from().line + 1, null, true); - ensureCursorVisible(cm); - } - }); - }, - toggleOverwrite: function(cm) {cm.toggleOverwrite();} - }; - - - // STANDARD KEYMAPS - - var keyMap = CodeMirror.keyMap = {}; - - keyMap.basic = { - "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", - "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", - "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", - "Tab": "defaultTab", "Shift-Tab": "indentAuto", - "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", - "Esc": "singleSelection" - }; - // Note that the save and find-related commands aren't defined by - // default. User code or addons can define them. Unknown commands - // are simply ignored. - keyMap.pcDefault = { - "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", - "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", - "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", - "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", - "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", - "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", - "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", - fallthrough: "basic" - }; - // Very basic readline/emacs-style bindings, which are standard on Mac. - keyMap.emacsy = { - "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", - "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", - "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", - "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" - }; - keyMap.macDefault = { - "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", - "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", - "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", - "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", - "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", - "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", - "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", - fallthrough: ["basic", "emacsy"] - }; - keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; - - // KEYMAP DISPATCH - - function normalizeKeyName(name) { - var parts = name.split(/-(?!$)/), name = parts[parts.length - 1]; - var alt, ctrl, shift, cmd; - for (var i = 0; i < parts.length - 1; i++) { - var mod = parts[i]; - if (/^(cmd|meta|m)$/i.test(mod)) cmd = true; - else if (/^a(lt)?$/i.test(mod)) alt = true; - else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true; - else if (/^s(hift)$/i.test(mod)) shift = true; - else throw new Error("Unrecognized modifier name: " + mod); - } - if (alt) name = "Alt-" + name; - if (ctrl) name = "Ctrl-" + name; - if (cmd) name = "Cmd-" + name; - if (shift) name = "Shift-" + name; - return name; - } - - // This is a kludge to keep keymaps mostly working as raw objects - // (backwards compatibility) while at the same time support features - // like normalization and multi-stroke key bindings. It compiles a - // new normalized keymap, and then updates the old object to reflect - // this. - CodeMirror.normalizeKeyMap = function(keymap) { - var copy = {}; - for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) { - var value = keymap[keyname]; - if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue; - if (value == "...") { delete keymap[keyname]; continue; } - - var keys = map(keyname.split(" "), normalizeKeyName); - for (var i = 0; i < keys.length; i++) { - var val, name; - if (i == keys.length - 1) { - name = keyname; - val = value; - } else { - name = keys.slice(0, i + 1).join(" "); - val = "..."; - } - var prev = copy[name]; - if (!prev) copy[name] = val; - else if (prev != val) throw new Error("Inconsistent bindings for " + name); - } - delete keymap[keyname]; - } - for (var prop in copy) keymap[prop] = copy[prop]; - return keymap; - }; - - var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) { - map = getKeyMap(map); - var found = map.call ? map.call(key, context) : map[key]; - if (found === false) return "nothing"; - if (found === "...") return "multi"; - if (found != null && handle(found)) return "handled"; - - if (map.fallthrough) { - if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") - return lookupKey(key, map.fallthrough, handle, context); - for (var i = 0; i < map.fallthrough.length; i++) { - var result = lookupKey(key, map.fallthrough[i], handle, context); - if (result) return result; - } - } - }; - - // Modifier key presses don't count as 'real' key presses for the - // purpose of keymap fallthrough. - var isModifierKey = CodeMirror.isModifierKey = function(value) { - var name = typeof value == "string" ? value : keyNames[value.keyCode]; - return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; - }; - - // Look up the name of a key as indicated by an event object. - var keyName = CodeMirror.keyName = function(event, noShift) { - if (presto && event.keyCode == 34 && event["char"]) return false; - var base = keyNames[event.keyCode], name = base; - if (name == null || event.altGraphKey) return false; - if (event.altKey && base != "Alt") name = "Alt-" + name; - if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name; - if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name; - if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name; - return name; - }; - - function getKeyMap(val) { - return typeof val == "string" ? keyMap[val] : val; - } - - // FROMTEXTAREA - - CodeMirror.fromTextArea = function(textarea, options) { - if (!options) options = {}; - options.value = textarea.value; - if (!options.tabindex && textarea.tabindex) - options.tabindex = textarea.tabindex; - if (!options.placeholder && textarea.placeholder) - options.placeholder = textarea.placeholder; - // Set autofocus to true if this textarea is focused, or if it has - // autofocus and no other element is focused. - if (options.autofocus == null) { - var hasFocus = activeElt(); - options.autofocus = hasFocus == textarea || - textarea.getAttribute("autofocus") != null && hasFocus == document.body; - } - - function save() {textarea.value = cm.getValue();} - if (textarea.form) { - on(textarea.form, "submit", save); - // Deplorable hack to make the submit method do the right thing. - if (!options.leaveSubmitMethodAlone) { - var form = textarea.form, realSubmit = form.submit; - try { - var wrappedSubmit = form.submit = function() { - save(); - form.submit = realSubmit; - form.submit(); - form.submit = wrappedSubmit; - }; - } catch(e) {} - } - } - - textarea.style.display = "none"; - var cm = CodeMirror(function(node) { - textarea.parentNode.insertBefore(node, textarea.nextSibling); - }, options); - cm.save = save; - cm.getTextArea = function() { return textarea; }; - cm.toTextArea = function() { - cm.toTextArea = isNaN; // Prevent this from being ran twice - save(); - textarea.parentNode.removeChild(cm.getWrapperElement()); - textarea.style.display = ""; - if (textarea.form) { - off(textarea.form, "submit", save); - if (typeof textarea.form.submit == "function") - textarea.form.submit = realSubmit; - } - }; - return cm; - }; - - // STRING STREAM - - // Fed to the mode parsers, provides helper functions to make - // parsers more succinct. - - var StringStream = CodeMirror.StringStream = function(string, tabSize) { - this.pos = this.start = 0; - this.string = string; - this.tabSize = tabSize || 8; - this.lastColumnPos = this.lastColumnValue = 0; - this.lineStart = 0; - }; - - StringStream.prototype = { - eol: function() {return this.pos >= this.string.length;}, - sol: function() {return this.pos == this.lineStart;}, - peek: function() {return this.string.charAt(this.pos) || undefined;}, - next: function() { - if (this.pos < this.string.length) - return this.string.charAt(this.pos++); - }, - eat: function(match) { - var ch = this.string.charAt(this.pos); - if (typeof match == "string") var ok = ch == match; - else var ok = ch && (match.test ? match.test(ch) : match(ch)); - if (ok) {++this.pos; return ch;} - }, - eatWhile: function(match) { - var start = this.pos; - while (this.eat(match)){} - return this.pos > start; - }, - eatSpace: function() { - var start = this.pos; - while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; - return this.pos > start; - }, - skipToEnd: function() {this.pos = this.string.length;}, - skipTo: function(ch) { - var found = this.string.indexOf(ch, this.pos); - if (found > -1) {this.pos = found; return true;} - }, - backUp: function(n) {this.pos -= n;}, - column: function() { - if (this.lastColumnPos < this.start) { - this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); - this.lastColumnPos = this.start; - } - return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); - }, - indentation: function() { - return countColumn(this.string, null, this.tabSize) - - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); - }, - match: function(pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; - var substr = this.string.substr(this.pos, pattern.length); - if (cased(substr) == cased(pattern)) { - if (consume !== false) this.pos += pattern.length; - return true; - } - } else { - var match = this.string.slice(this.pos).match(pattern); - if (match && match.index > 0) return null; - if (match && consume !== false) this.pos += match[0].length; - return match; - } - }, - current: function(){return this.string.slice(this.start, this.pos);}, - hideFirstChars: function(n, inner) { - this.lineStart += n; - try { return inner(); } - finally { this.lineStart -= n; } - } - }; - - // TEXTMARKERS - - // Created with markText and setBookmark methods. A TextMarker is a - // handle that can be used to clear or find a marked position in the - // document. Line objects hold arrays (markedSpans) containing - // {from, to, marker} object pointing to such marker objects, and - // indicating that such a marker is present on that line. Multiple - // lines may point to the same marker when it spans across lines. - // The spans will have null for their from/to properties when the - // marker continues beyond the start/end of the line. Markers have - // links back to the lines they currently touch. - - var TextMarker = CodeMirror.TextMarker = function(doc, type) { - this.lines = []; - this.type = type; - this.doc = doc; - }; - eventMixin(TextMarker); - - // Clear the marker. - TextMarker.prototype.clear = function() { - if (this.explicitlyCleared) return; - var cm = this.doc.cm, withOp = cm && !cm.curOp; - if (withOp) startOperation(cm); - if (hasHandler(this, "clear")) { - var found = this.find(); - if (found) signalLater(this, "clear", found.from, found.to); - } - var min = null, max = null; - for (var i = 0; i < this.lines.length; ++i) { - var line = this.lines[i]; - var span = getMarkedSpanFor(line.markedSpans, this); - if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text"); - else if (cm) { - if (span.to != null) max = lineNo(line); - if (span.from != null) min = lineNo(line); - } - line.markedSpans = removeMarkedSpan(line.markedSpans, span); - if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm) - updateLineHeight(line, textHeight(cm.display)); - } - if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) { - var visual = visualLine(this.lines[i]), len = lineLength(visual); - if (len > cm.display.maxLineLength) { - cm.display.maxLine = visual; - cm.display.maxLineLength = len; - cm.display.maxLineChanged = true; - } - } - - if (min != null && cm && this.collapsed) regChange(cm, min, max + 1); - this.lines.length = 0; - this.explicitlyCleared = true; - if (this.atomic && this.doc.cantEdit) { - this.doc.cantEdit = false; - if (cm) reCheckSelection(cm.doc); - } - if (cm) signalLater(cm, "markerCleared", cm, this); - if (withOp) endOperation(cm); - if (this.parent) this.parent.clear(); - }; - - // Find the position of the marker in the document. Returns a {from, - // to} object by default. Side can be passed to get a specific side - // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the - // Pos objects returned contain a line object, rather than a line - // number (used to prevent looking up the same line twice). - TextMarker.prototype.find = function(side, lineObj) { - if (side == null && this.type == "bookmark") side = 1; - var from, to; - for (var i = 0; i < this.lines.length; ++i) { - var line = this.lines[i]; - var span = getMarkedSpanFor(line.markedSpans, this); - if (span.from != null) { - from = Pos(lineObj ? line : lineNo(line), span.from); - if (side == -1) return from; - } - if (span.to != null) { - to = Pos(lineObj ? line : lineNo(line), span.to); - if (side == 1) return to; - } - } - return from && {from: from, to: to}; - }; - - // Signals that the marker's widget changed, and surrounding layout - // should be recomputed. - TextMarker.prototype.changed = function() { - var pos = this.find(-1, true), widget = this, cm = this.doc.cm; - if (!pos || !cm) return; - runInOp(cm, function() { - var line = pos.line, lineN = lineNo(pos.line); - var view = findViewForLine(cm, lineN); - if (view) { - clearLineMeasurementCacheFor(view); - cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; - } - cm.curOp.updateMaxLine = true; - if (!lineIsHidden(widget.doc, line) && widget.height != null) { - var oldHeight = widget.height; - widget.height = null; - var dHeight = widgetHeight(widget) - oldHeight; - if (dHeight) - updateLineHeight(line, line.height + dHeight); - } - }); - }; - - TextMarker.prototype.attachLine = function(line) { - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp; - if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) - (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); - } - this.lines.push(line); - }; - TextMarker.prototype.detachLine = function(line) { - this.lines.splice(indexOf(this.lines, line), 1); - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp; - (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); - } - }; - - // Collapsed markers have unique ids, in order to be able to order - // them, which is needed for uniquely determining an outer marker - // when they overlap (they may nest, but not partially overlap). - var nextMarkerId = 0; - - // Create a marker, wire it up to the right lines, and - function markText(doc, from, to, options, type) { - // Shared markers (across linked documents) are handled separately - // (markTextShared will call out to this again, once per - // document). - if (options && options.shared) return markTextShared(doc, from, to, options, type); - // Ensure we are in an operation. - if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type); - - var marker = new TextMarker(doc, type), diff = cmp(from, to); - if (options) copyObj(options, marker, false); - // Don't connect empty markers unless clearWhenEmpty is false - if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) - return marker; - if (marker.replacedWith) { - // Showing up as a widget implies collapsed (widget replaces text) - marker.collapsed = true; - marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget"); - if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true"); - if (options.insertLeft) marker.widgetNode.insertLeft = true; - } - if (marker.collapsed) { - if (conflictingCollapsedRange(doc, from.line, from, to, marker) || - from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) - throw new Error("Inserting collapsed marker partially overlapping an existing one"); - sawCollapsedSpans = true; - } - - if (marker.addToHistory) - addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); - - var curLine = from.line, cm = doc.cm, updateMaxLine; - doc.iter(curLine, to.line + 1, function(line) { - if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) - updateMaxLine = true; - if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0); - addMarkedSpan(line, new MarkedSpan(marker, - curLine == from.line ? from.ch : null, - curLine == to.line ? to.ch : null)); - ++curLine; - }); - // lineIsHidden depends on the presence of the spans, so needs a second pass - if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) { - if (lineIsHidden(doc, line)) updateLineHeight(line, 0); - }); - - if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); }); - - if (marker.readOnly) { - sawReadOnlySpans = true; - if (doc.history.done.length || doc.history.undone.length) - doc.clearHistory(); - } - if (marker.collapsed) { - marker.id = ++nextMarkerId; - marker.atomic = true; - } - if (cm) { - // Sync editor state - if (updateMaxLine) cm.curOp.updateMaxLine = true; - if (marker.collapsed) - regChange(cm, from.line, to.line + 1); - else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css) - for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text"); - if (marker.atomic) reCheckSelection(cm.doc); - signalLater(cm, "markerAdded", cm, marker); - } - return marker; - } - - // SHARED TEXTMARKERS - - // A shared marker spans multiple linked documents. It is - // implemented as a meta-marker-object controlling multiple normal - // markers. - var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) { - this.markers = markers; - this.primary = primary; - for (var i = 0; i < markers.length; ++i) - markers[i].parent = this; - }; - eventMixin(SharedTextMarker); - - SharedTextMarker.prototype.clear = function() { - if (this.explicitlyCleared) return; - this.explicitlyCleared = true; - for (var i = 0; i < this.markers.length; ++i) - this.markers[i].clear(); - signalLater(this, "clear"); - }; - SharedTextMarker.prototype.find = function(side, lineObj) { - return this.primary.find(side, lineObj); - }; - - function markTextShared(doc, from, to, options, type) { - options = copyObj(options); - options.shared = false; - var markers = [markText(doc, from, to, options, type)], primary = markers[0]; - var widget = options.widgetNode; - linkedDocs(doc, function(doc) { - if (widget) options.widgetNode = widget.cloneNode(true); - markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); - for (var i = 0; i < doc.linked.length; ++i) - if (doc.linked[i].isParent) return; - primary = lst(markers); - }); - return new SharedTextMarker(markers, primary); - } - - function findSharedMarkers(doc) { - return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), - function(m) { return m.parent; }); - } - - function copySharedMarkers(doc, markers) { - for (var i = 0; i < markers.length; i++) { - var marker = markers[i], pos = marker.find(); - var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); - if (cmp(mFrom, mTo)) { - var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); - marker.markers.push(subMark); - subMark.parent = marker; - } - } - } - - function detachSharedMarkers(markers) { - for (var i = 0; i < markers.length; i++) { - var marker = markers[i], linked = [marker.primary.doc];; - linkedDocs(marker.primary.doc, function(d) { linked.push(d); }); - for (var j = 0; j < marker.markers.length; j++) { - var subMarker = marker.markers[j]; - if (indexOf(linked, subMarker.doc) == -1) { - subMarker.parent = null; - marker.markers.splice(j--, 1); - } - } - } - } - - // TEXTMARKER SPANS - - function MarkedSpan(marker, from, to) { - this.marker = marker; - this.from = from; this.to = to; - } - - // Search an array of spans for a span matching the given marker. - function getMarkedSpanFor(spans, marker) { - if (spans) for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if (span.marker == marker) return span; - } - } - // Remove a span from an array, returning undefined if no spans are - // left (we don't store arrays for lines without spans). - function removeMarkedSpan(spans, span) { - for (var r, i = 0; i < spans.length; ++i) - if (spans[i] != span) (r || (r = [])).push(spans[i]); - return r; - } - // Add a span to a line. - function addMarkedSpan(line, span) { - line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; - span.marker.attachLine(line); - } - - // Used for the algorithm that adjusts markers for a change in the - // document. These functions cut an array of spans at a given - // character position, returning an array of remaining chunks (or - // undefined if nothing remains). - function markedSpansBefore(old, startCh, isInsert) { - if (old) for (var i = 0, nw; i < old.length; ++i) { - var span = old[i], marker = span.marker; - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); - if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); - (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); - } - } - return nw; - } - function markedSpansAfter(old, endCh, isInsert) { - if (old) for (var i = 0, nw; i < old.length; ++i) { - var span = old[i], marker = span.marker; - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); - if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); - (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, - span.to == null ? null : span.to - endCh)); - } - } - return nw; - } - - // Given a change object, compute the new set of marker spans that - // cover the line in which the change took place. Removes spans - // entirely within the change, reconnects spans belonging to the - // same marker that appear on both sides of the change, and cuts off - // spans partially within the change. Returns an array of span - // arrays with one element for each line in (after) the change. - function stretchSpansOverChange(doc, change) { - if (change.full) return null; - var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; - var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; - if (!oldFirst && !oldLast) return null; - - var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; - // Get the spans that 'stick out' on both sides - var first = markedSpansBefore(oldFirst, startCh, isInsert); - var last = markedSpansAfter(oldLast, endCh, isInsert); - - // Next, merge those two ends - var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); - if (first) { - // Fix up .to properties of first - for (var i = 0; i < first.length; ++i) { - var span = first[i]; - if (span.to == null) { - var found = getMarkedSpanFor(last, span.marker); - if (!found) span.to = startCh; - else if (sameLine) span.to = found.to == null ? null : found.to + offset; - } - } - } - if (last) { - // Fix up .from in last (or move them into first in case of sameLine) - for (var i = 0; i < last.length; ++i) { - var span = last[i]; - if (span.to != null) span.to += offset; - if (span.from == null) { - var found = getMarkedSpanFor(first, span.marker); - if (!found) { - span.from = offset; - if (sameLine) (first || (first = [])).push(span); - } - } else { - span.from += offset; - if (sameLine) (first || (first = [])).push(span); - } - } - } - // Make sure we didn't create any zero-length spans - if (first) first = clearEmptySpans(first); - if (last && last != first) last = clearEmptySpans(last); - - var newMarkers = [first]; - if (!sameLine) { - // Fill gap with whole-line-spans - var gap = change.text.length - 2, gapMarkers; - if (gap > 0 && first) - for (var i = 0; i < first.length; ++i) - if (first[i].to == null) - (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null)); - for (var i = 0; i < gap; ++i) - newMarkers.push(gapMarkers); - newMarkers.push(last); - } - return newMarkers; - } - - // Remove spans that are empty and don't have a clearWhenEmpty - // option of false. - function clearEmptySpans(spans) { - for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) - spans.splice(i--, 1); - } - if (!spans.length) return null; - return spans; - } - - // Used for un/re-doing changes from the history. Combines the - // result of computing the existing spans with the set of spans that - // existed in the history (so that deleting around a span and then - // undoing brings back the span). - function mergeOldSpans(doc, change) { - var old = getOldSpans(doc, change); - var stretched = stretchSpansOverChange(doc, change); - if (!old) return stretched; - if (!stretched) return old; - - for (var i = 0; i < old.length; ++i) { - var oldCur = old[i], stretchCur = stretched[i]; - if (oldCur && stretchCur) { - spans: for (var j = 0; j < stretchCur.length; ++j) { - var span = stretchCur[j]; - for (var k = 0; k < oldCur.length; ++k) - if (oldCur[k].marker == span.marker) continue spans; - oldCur.push(span); - } - } else if (stretchCur) { - old[i] = stretchCur; - } - } - return old; - } - - // Used to 'clip' out readOnly ranges when making a change. - function removeReadOnlyRanges(doc, from, to) { - var markers = null; - doc.iter(from.line, to.line + 1, function(line) { - if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) { - var mark = line.markedSpans[i].marker; - if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) - (markers || (markers = [])).push(mark); - } - }); - if (!markers) return null; - var parts = [{from: from, to: to}]; - for (var i = 0; i < markers.length; ++i) { - var mk = markers[i], m = mk.find(0); - for (var j = 0; j < parts.length; ++j) { - var p = parts[j]; - if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue; - var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); - if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) - newParts.push({from: p.from, to: m.from}); - if (dto > 0 || !mk.inclusiveRight && !dto) - newParts.push({from: m.to, to: p.to}); - parts.splice.apply(parts, newParts); - j += newParts.length - 1; - } - } - return parts; - } - - // Connect or disconnect spans from a line. - function detachMarkedSpans(line) { - var spans = line.markedSpans; - if (!spans) return; - for (var i = 0; i < spans.length; ++i) - spans[i].marker.detachLine(line); - line.markedSpans = null; - } - function attachMarkedSpans(line, spans) { - if (!spans) return; - for (var i = 0; i < spans.length; ++i) - spans[i].marker.attachLine(line); - line.markedSpans = spans; - } - - // Helpers used when computing which overlapping collapsed span - // counts as the larger one. - function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; } - function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; } - - // Returns a number indicating which of two overlapping collapsed - // spans is larger (and thus includes the other). Falls back to - // comparing ids when the spans cover exactly the same range. - function compareCollapsedMarkers(a, b) { - var lenDiff = a.lines.length - b.lines.length; - if (lenDiff != 0) return lenDiff; - var aPos = a.find(), bPos = b.find(); - var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); - if (fromCmp) return -fromCmp; - var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); - if (toCmp) return toCmp; - return b.id - a.id; - } - - // Find out whether a line ends or starts in a collapsed span. If - // so, return the marker for that span. - function collapsedSpanAtSide(line, start) { - var sps = sawCollapsedSpans && line.markedSpans, found; - if (sps) for (var sp, i = 0; i < sps.length; ++i) { - sp = sps[i]; - if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && - (!found || compareCollapsedMarkers(found, sp.marker) < 0)) - found = sp.marker; - } - return found; - } - function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); } - function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); } - - // Test whether there exists a collapsed span that partially - // overlaps (covers the start or end, but not both) of a new span. - // Such overlap is not allowed. - function conflictingCollapsedRange(doc, lineNo, from, to, marker) { - var line = getLine(doc, lineNo); - var sps = sawCollapsedSpans && line.markedSpans; - if (sps) for (var i = 0; i < sps.length; ++i) { - var sp = sps[i]; - if (!sp.marker.collapsed) continue; - var found = sp.marker.find(0); - var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); - var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); - if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue; - if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) || - fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight))) - return true; - } - } - - // A visual line is a line as drawn on the screen. Folding, for - // example, can cause multiple logical lines to appear on the same - // visual line. This finds the start of the visual line that the - // given line is part of (usually that is the line itself). - function visualLine(line) { - var merged; - while (merged = collapsedSpanAtStart(line)) - line = merged.find(-1, true).line; - return line; - } - - // Returns an array of logical lines that continue the visual line - // started by the argument, or undefined if there are no such lines. - function visualLineContinued(line) { - var merged, lines; - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line; - (lines || (lines = [])).push(line); - } - return lines; - } - - // Get the line number of the start of the visual line that the - // given line number is part of. - function visualLineNo(doc, lineN) { - var line = getLine(doc, lineN), vis = visualLine(line); - if (line == vis) return lineN; - return lineNo(vis); - } - // Get the line number of the start of the next visual line after - // the given line. - function visualLineEndNo(doc, lineN) { - if (lineN > doc.lastLine()) return lineN; - var line = getLine(doc, lineN), merged; - if (!lineIsHidden(doc, line)) return lineN; - while (merged = collapsedSpanAtEnd(line)) - line = merged.find(1, true).line; - return lineNo(line) + 1; - } - - // Compute whether a line is hidden. Lines count as hidden when they - // are part of a visual line that starts with another line, or when - // they are entirely covered by collapsed, non-widget span. - function lineIsHidden(doc, line) { - var sps = sawCollapsedSpans && line.markedSpans; - if (sps) for (var sp, i = 0; i < sps.length; ++i) { - sp = sps[i]; - if (!sp.marker.collapsed) continue; - if (sp.from == null) return true; - if (sp.marker.widgetNode) continue; - if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) - return true; - } - } - function lineIsHiddenInner(doc, line, span) { - if (span.to == null) { - var end = span.marker.find(1, true); - return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)); - } - if (span.marker.inclusiveRight && span.to == line.text.length) - return true; - for (var sp, i = 0; i < line.markedSpans.length; ++i) { - sp = line.markedSpans[i]; - if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && - (sp.to == null || sp.to != span.from) && - (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && - lineIsHiddenInner(doc, line, sp)) return true; - } - } - - // LINE WIDGETS - - // Line widgets are block elements displayed above or below a line. - - var LineWidget = CodeMirror.LineWidget = function(cm, node, options) { - if (options) for (var opt in options) if (options.hasOwnProperty(opt)) - this[opt] = options[opt]; - this.cm = cm; - this.node = node; - }; - eventMixin(LineWidget); - - function adjustScrollWhenAboveVisible(cm, line, diff) { - if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) - addToScrollPos(cm, null, diff); - } - - LineWidget.prototype.clear = function() { - var cm = this.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); - if (no == null || !ws) return; - for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1); - if (!ws.length) line.widgets = null; - var height = widgetHeight(this); - runInOp(cm, function() { - adjustScrollWhenAboveVisible(cm, line, -height); - regLineChange(cm, no, "widget"); - updateLineHeight(line, Math.max(0, line.height - height)); - }); - }; - LineWidget.prototype.changed = function() { - var oldH = this.height, cm = this.cm, line = this.line; - this.height = null; - var diff = widgetHeight(this) - oldH; - if (!diff) return; - runInOp(cm, function() { - cm.curOp.forceUpdate = true; - adjustScrollWhenAboveVisible(cm, line, diff); - updateLineHeight(line, line.height + diff); - }); - }; - - function widgetHeight(widget) { - if (widget.height != null) return widget.height; - if (!contains(document.body, widget.node)) { - var parentStyle = "position: relative;"; - if (widget.coverGutter) - parentStyle += "margin-left: -" + widget.cm.display.gutters.offsetWidth + "px;"; - if (widget.noHScroll) - parentStyle += "width: " + widget.cm.display.wrapper.clientWidth + "px;"; - removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, parentStyle)); - } - return widget.height = widget.node.offsetHeight; - } - - function addLineWidget(cm, handle, node, options) { - var widget = new LineWidget(cm, node, options); - if (widget.noHScroll) cm.display.alignWidgets = true; - changeLine(cm.doc, handle, "widget", function(line) { - var widgets = line.widgets || (line.widgets = []); - if (widget.insertAt == null) widgets.push(widget); - else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); - widget.line = line; - if (!lineIsHidden(cm.doc, line)) { - var aboveVisible = heightAtLine(line) < cm.doc.scrollTop; - updateLineHeight(line, line.height + widgetHeight(widget)); - if (aboveVisible) addToScrollPos(cm, null, widget.height); - cm.curOp.forceUpdate = true; - } - return true; - }); - return widget; - } - - // LINE DATA STRUCTURE - - // Line objects. These hold state related to a line, including - // highlighting info (the styles array). - var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) { - this.text = text; - attachMarkedSpans(this, markedSpans); - this.height = estimateHeight ? estimateHeight(this) : 1; - }; - eventMixin(Line); - Line.prototype.lineNo = function() { return lineNo(this); }; - - // Change the content (text, markers) of a line. Automatically - // invalidates cached information and tries to re-estimate the - // line's height. - function updateLine(line, text, markedSpans, estimateHeight) { - line.text = text; - if (line.stateAfter) line.stateAfter = null; - if (line.styles) line.styles = null; - if (line.order != null) line.order = null; - detachMarkedSpans(line); - attachMarkedSpans(line, markedSpans); - var estHeight = estimateHeight ? estimateHeight(line) : 1; - if (estHeight != line.height) updateLineHeight(line, estHeight); - } - - // Detach a line from the document tree and its markers. - function cleanUpLine(line) { - line.parent = null; - detachMarkedSpans(line); - } - - function extractLineClasses(type, output) { - if (type) for (;;) { - var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); - if (!lineClass) break; - type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); - var prop = lineClass[1] ? "bgClass" : "textClass"; - if (output[prop] == null) - output[prop] = lineClass[2]; - else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop])) - output[prop] += " " + lineClass[2]; - } - return type; - } - - function callBlankLine(mode, state) { - if (mode.blankLine) return mode.blankLine(state); - if (!mode.innerMode) return; - var inner = CodeMirror.innerMode(mode, state); - if (inner.mode.blankLine) return inner.mode.blankLine(inner.state); - } - - function readToken(mode, stream, state, inner) { - for (var i = 0; i < 10; i++) { - if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode; - var style = mode.token(stream, state); - if (stream.pos > stream.start) return style; - } - throw new Error("Mode " + mode.name + " failed to advance stream."); - } - - // Utility for getTokenAt and getLineTokens - function takeToken(cm, pos, precise, asArray) { - function getObj(copy) { - return {start: stream.start, end: stream.pos, - string: stream.current(), - type: style || null, - state: copy ? copyState(doc.mode, state) : state}; - } - - var doc = cm.doc, mode = doc.mode, style; - pos = clipPos(doc, pos); - var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise); - var stream = new StringStream(line.text, cm.options.tabSize), tokens; - if (asArray) tokens = []; - while ((asArray || stream.pos < pos.ch) && !stream.eol()) { - stream.start = stream.pos; - style = readToken(mode, stream, state); - if (asArray) tokens.push(getObj(true)); - } - return asArray ? tokens : getObj(); - } - - // Run the given mode's parser over a line, calling f for each token. - function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) { - var flattenSpans = mode.flattenSpans; - if (flattenSpans == null) flattenSpans = cm.options.flattenSpans; - var curStart = 0, curStyle = null; - var stream = new StringStream(text, cm.options.tabSize), style; - var inner = cm.options.addModeClass && [null]; - if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses); - while (!stream.eol()) { - if (stream.pos > cm.options.maxHighlightLength) { - flattenSpans = false; - if (forceToEnd) processLine(cm, text, state, stream.pos); - stream.pos = text.length; - style = null; - } else { - style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses); - } - if (inner) { - var mName = inner[0].name; - if (mName) style = "m-" + (style ? mName + " " + style : mName); - } - if (!flattenSpans || curStyle != style) { - while (curStart < stream.start) { - curStart = Math.min(stream.start, curStart + 50000); - f(curStart, curStyle); - } - curStyle = style; - } - stream.start = stream.pos; - } - while (curStart < stream.pos) { - // Webkit seems to refuse to render text nodes longer than 57444 characters - var pos = Math.min(stream.pos, curStart + 50000); - f(pos, curStyle); - curStart = pos; - } - } - - // Compute a style array (an array starting with a mode generation - // -- for invalidation -- followed by pairs of end positions and - // style strings), which is used to highlight the tokens on the - // line. - function highlightLine(cm, line, state, forceToEnd) { - // A styles array always starts with a number identifying the - // mode/overlays that it is based on (for easy invalidation). - var st = [cm.state.modeGen], lineClasses = {}; - // Compute the base array of styles - runMode(cm, line.text, cm.doc.mode, state, function(end, style) { - st.push(end, style); - }, lineClasses, forceToEnd); - - // Run overlays, adjust style array. - for (var o = 0; o < cm.state.overlays.length; ++o) { - var overlay = cm.state.overlays[o], i = 1, at = 0; - runMode(cm, line.text, overlay.mode, true, function(end, style) { - var start = i; - // Ensure there's a token end at the current position, and that i points at it - while (at < end) { - var i_end = st[i]; - if (i_end > end) - st.splice(i, 1, end, st[i+1], i_end); - i += 2; - at = Math.min(end, i_end); - } - if (!style) return; - if (overlay.opaque) { - st.splice(start, i - start, end, "cm-overlay " + style); - i = start + 2; - } else { - for (; start < i; start += 2) { - var cur = st[start+1]; - st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style; - } - } - }, lineClasses); - } - - return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}; - } - - function getLineStyles(cm, line, updateFrontier) { - if (!line.styles || line.styles[0] != cm.state.modeGen) { - var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line))); - line.styles = result.styles; - if (result.classes) line.styleClasses = result.classes; - else if (line.styleClasses) line.styleClasses = null; - if (updateFrontier === cm.doc.frontier) cm.doc.frontier++; - } - return line.styles; - } - - // Lightweight form of highlight -- proceed over this line and - // update state, but don't save a style array. Used for lines that - // aren't currently visible. - function processLine(cm, text, state, startAt) { - var mode = cm.doc.mode; - var stream = new StringStream(text, cm.options.tabSize); - stream.start = stream.pos = startAt || 0; - if (text == "") callBlankLine(mode, state); - while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) { - readToken(mode, stream, state); - stream.start = stream.pos; - } - } - - // Convert a style as returned by a mode (either null, or a string - // containing one or more styles) to a CSS style. This is cached, - // and also looks for line-wide styles. - var styleToClassCache = {}, styleToClassCacheWithMode = {}; - function interpretTokenStyle(style, options) { - if (!style || /^\s*$/.test(style)) return null; - var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; - return cache[style] || - (cache[style] = style.replace(/\S+/g, "cm-$&")); - } - - // Render the DOM representation of the text of a line. Also builds - // up a 'line map', which points at the DOM nodes that represent - // specific stretches of text, and is used by the measuring code. - // The returned object contains the DOM node, this map, and - // information about line-wide styles that were set by the mode. - function buildLineContent(cm, lineView) { - // The padding-right forces the element to have a 'border', which - // is needed on Webkit to be able to get line-level bounding - // rectangles for it (in measureChar). - var content = elt("span", null, null, webkit ? "padding-right: .1px" : null); - var builder = {pre: elt("pre", [content]), content: content, col: 0, pos: 0, cm: cm}; - lineView.measure = {}; - - // Iterate over the logical lines that make up this visual line. - for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { - var line = i ? lineView.rest[i - 1] : lineView.line, order; - builder.pos = 0; - builder.addToken = buildToken; - // Optionally wire in some hacks into the token-rendering - // algorithm, to deal with browser quirks. - if ((ie || webkit) && cm.getOption("lineWrapping")) - builder.addToken = buildTokenSplitSpaces(builder.addToken); - if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line))) - builder.addToken = buildTokenBadBidi(builder.addToken, order); - builder.map = []; - var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); - insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); - if (line.styleClasses) { - if (line.styleClasses.bgClass) - builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); - if (line.styleClasses.textClass) - builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); - } - - // Ensure at least a single node is present, for measuring. - if (builder.map.length == 0) - builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); - - // Store the map and a cache object for the current logical line - if (i == 0) { - lineView.measure.map = builder.map; - lineView.measure.cache = {}; - } else { - (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map); - (lineView.measure.caches || (lineView.measure.caches = [])).push({}); - } - } - - // See issue #2901 - if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className)) - builder.content.className = "cm-tab-wrap-hack"; - - signal(cm, "renderLine", cm, lineView.line, builder.pre); - if (builder.pre.className) - builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); - - return builder; - } - - function defaultSpecialCharPlaceholder(ch) { - var token = elt("span", "\u2022", "cm-invalidchar"); - token.title = "\\u" + ch.charCodeAt(0).toString(16); - return token; - } - - // Build up the DOM representation for a single token, and add it to - // the line map. Takes care to render special characters separately. - function buildToken(builder, text, style, startStyle, endStyle, title, css) { - if (!text) return; - var special = builder.cm.options.specialChars, mustWrap = false; - if (!special.test(text)) { - builder.col += text.length; - var content = document.createTextNode(text); - builder.map.push(builder.pos, builder.pos + text.length, content); - if (ie && ie_version < 9) mustWrap = true; - builder.pos += text.length; - } else { - var content = document.createDocumentFragment(), pos = 0; - while (true) { - special.lastIndex = pos; - var m = special.exec(text); - var skipped = m ? m.index - pos : text.length - pos; - if (skipped) { - var txt = document.createTextNode(text.slice(pos, pos + skipped)); - if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); - else content.appendChild(txt); - builder.map.push(builder.pos, builder.pos + skipped, txt); - builder.col += skipped; - builder.pos += skipped; - } - if (!m) break; - pos += skipped + 1; - if (m[0] == "\t") { - var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; - var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); - builder.col += tabWidth; - } else { - var txt = builder.cm.options.specialCharPlaceholder(m[0]); - if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); - else content.appendChild(txt); - builder.col += 1; - } - builder.map.push(builder.pos, builder.pos + 1, txt); - builder.pos++; - } - } - if (style || startStyle || endStyle || mustWrap || css) { - var fullStyle = style || ""; - if (startStyle) fullStyle += startStyle; - if (endStyle) fullStyle += endStyle; - var token = elt("span", [content], fullStyle, css); - if (title) token.title = title; - return builder.content.appendChild(token); - } - builder.content.appendChild(content); - } - - function buildTokenSplitSpaces(inner) { - function split(old) { - var out = " "; - for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0"; - out += " "; - return out; - } - return function(builder, text, style, startStyle, endStyle, title) { - inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title); - }; - } - - // Work around nonsense dimensions being reported for stretches of - // right-to-left text. - function buildTokenBadBidi(inner, order) { - return function(builder, text, style, startStyle, endStyle, title) { - style = style ? style + " cm-force-border" : "cm-force-border"; - var start = builder.pos, end = start + text.length; - for (;;) { - // Find the part that overlaps with the start of this text - for (var i = 0; i < order.length; i++) { - var part = order[i]; - if (part.to > start && part.from <= start) break; - } - if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title); - inner(builder, text.slice(0, part.to - start), style, startStyle, null, title); - startStyle = null; - text = text.slice(part.to - start); - start = part.to; - } - }; - } - - function buildCollapsedSpan(builder, size, marker, ignoreWidget) { - var widget = !ignoreWidget && marker.widgetNode; - if (widget) { - builder.map.push(builder.pos, builder.pos + size, widget); - builder.content.appendChild(widget); - } - builder.pos += size; - } - - // Outputs a number of spans to make up a line, taking highlighting - // and marked text into account. - function insertLineContent(line, builder, styles) { - var spans = line.markedSpans, allText = line.text, at = 0; - if (!spans) { - for (var i = 1; i < styles.length; i+=2) - builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options)); - return; - } - - var len = allText.length, pos = 0, i = 1, text = "", style, css; - var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed; - for (;;) { - if (nextChange == pos) { // Update current marker set - spanStyle = spanEndStyle = spanStartStyle = title = css = ""; - collapsed = null; nextChange = Infinity; - var foundBookmarks = []; - for (var j = 0; j < spans.length; ++j) { - var sp = spans[j], m = sp.marker; - if (sp.from <= pos && (sp.to == null || sp.to > pos)) { - if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; } - if (m.className) spanStyle += " " + m.className; - if (m.css) css = m.css; - if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; - if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle; - if (m.title && !title) title = m.title; - if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) - collapsed = sp; - } else if (sp.from > pos && nextChange > sp.from) { - nextChange = sp.from; - } - if (m.type == "bookmark" && sp.from == pos && m.widgetNode) foundBookmarks.push(m); - } - if (collapsed && (collapsed.from || 0) == pos) { - buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, - collapsed.marker, collapsed.from == null); - if (collapsed.to == null) return; - } - if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j) - buildCollapsedSpan(builder, 0, foundBookmarks[j]); - } - if (pos >= len) break; - - var upto = Math.min(len, nextChange); - while (true) { - if (text) { - var end = pos + text.length; - if (!collapsed) { - var tokenText = end > upto ? text.slice(0, upto - pos) : text; - builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, - spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css); - } - if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} - pos = end; - spanStartStyle = ""; - } - text = allText.slice(at, at = styles[i++]); - style = interpretTokenStyle(styles[i++], builder.cm.options); - } - } - } - - // DOCUMENT DATA STRUCTURE - - // By default, updates that start and end at the beginning of a line - // are treated specially, in order to make the association of line - // widgets and marker elements with the text behave more intuitive. - function isWholeLineUpdate(doc, change) { - return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && - (!doc.cm || doc.cm.options.wholeLineUpdateBefore); - } - - // Perform a change on the document data structure. - function updateDoc(doc, change, markedSpans, estimateHeight) { - function spansFor(n) {return markedSpans ? markedSpans[n] : null;} - function update(line, text, spans) { - updateLine(line, text, spans, estimateHeight); - signalLater(line, "change", line, change); - } - function linesFor(start, end) { - for (var i = start, result = []; i < end; ++i) - result.push(new Line(text[i], spansFor(i), estimateHeight)); - return result; - } - - var from = change.from, to = change.to, text = change.text; - var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); - var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; - - // Adjust the line structure - if (change.full) { - doc.insert(0, linesFor(0, text.length)); - doc.remove(text.length, doc.size - text.length); - } else if (isWholeLineUpdate(doc, change)) { - // This is a whole-line replace. Treated specially to make - // sure line objects move the way they are supposed to. - var added = linesFor(0, text.length - 1); - update(lastLine, lastLine.text, lastSpans); - if (nlines) doc.remove(from.line, nlines); - if (added.length) doc.insert(from.line, added); - } else if (firstLine == lastLine) { - if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); - } else { - var added = linesFor(1, text.length - 1); - added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); - doc.insert(from.line + 1, added); - } - } else if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); - doc.remove(from.line + 1, nlines); - } else { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); - update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); - var added = linesFor(1, text.length - 1); - if (nlines > 1) doc.remove(from.line + 1, nlines - 1); - doc.insert(from.line + 1, added); - } - - signalLater(doc, "change", doc, change); - } - - // The document is represented as a BTree consisting of leaves, with - // chunk of lines in them, and branches, with up to ten leaves or - // other branch nodes below them. The top node is always a branch - // node, and is the document object itself (meaning it has - // additional methods and properties). - // - // All nodes have parent links. The tree is used both to go from - // line numbers to line objects, and to go from objects to numbers. - // It also indexes by height, and is used to convert between height - // and line object, and to find the total height of the document. - // - // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html - - function LeafChunk(lines) { - this.lines = lines; - this.parent = null; - for (var i = 0, height = 0; i < lines.length; ++i) { - lines[i].parent = this; - height += lines[i].height; - } - this.height = height; - } - - LeafChunk.prototype = { - chunkSize: function() { return this.lines.length; }, - // Remove the n lines at offset 'at'. - removeInner: function(at, n) { - for (var i = at, e = at + n; i < e; ++i) { - var line = this.lines[i]; - this.height -= line.height; - cleanUpLine(line); - signalLater(line, "delete"); - } - this.lines.splice(at, n); - }, - // Helper used to collapse a small branch into a single leaf. - collapse: function(lines) { - lines.push.apply(lines, this.lines); - }, - // Insert the given array of lines at offset 'at', count them as - // having the given height. - insertInner: function(at, lines, height) { - this.height += height; - this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); - for (var i = 0; i < lines.length; ++i) lines[i].parent = this; - }, - // Used to iterate over a part of the tree. - iterN: function(at, n, op) { - for (var e = at + n; at < e; ++at) - if (op(this.lines[at])) return true; - } - }; - - function BranchChunk(children) { - this.children = children; - var size = 0, height = 0; - for (var i = 0; i < children.length; ++i) { - var ch = children[i]; - size += ch.chunkSize(); height += ch.height; - ch.parent = this; - } - this.size = size; - this.height = height; - this.parent = null; - } - - BranchChunk.prototype = { - chunkSize: function() { return this.size; }, - removeInner: function(at, n) { - this.size -= n; - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at < sz) { - var rm = Math.min(n, sz - at), oldHeight = child.height; - child.removeInner(at, rm); - this.height -= oldHeight - child.height; - if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } - if ((n -= rm) == 0) break; - at = 0; - } else at -= sz; - } - // If the result is smaller than 25 lines, ensure that it is a - // single leaf node. - if (this.size - n < 25 && - (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { - var lines = []; - this.collapse(lines); - this.children = [new LeafChunk(lines)]; - this.children[0].parent = this; - } - }, - collapse: function(lines) { - for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines); - }, - insertInner: function(at, lines, height) { - this.size += lines.length; - this.height += height; - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at <= sz) { - child.insertInner(at, lines, height); - if (child.lines && child.lines.length > 50) { - while (child.lines.length > 50) { - var spilled = child.lines.splice(child.lines.length - 25, 25); - var newleaf = new LeafChunk(spilled); - child.height -= newleaf.height; - this.children.splice(i + 1, 0, newleaf); - newleaf.parent = this; - } - this.maybeSpill(); - } - break; - } - at -= sz; - } - }, - // When a node has grown, check whether it should be split. - maybeSpill: function() { - if (this.children.length <= 10) return; - var me = this; - do { - var spilled = me.children.splice(me.children.length - 5, 5); - var sibling = new BranchChunk(spilled); - if (!me.parent) { // Become the parent node - var copy = new BranchChunk(me.children); - copy.parent = me; - me.children = [copy, sibling]; - me = copy; - } else { - me.size -= sibling.size; - me.height -= sibling.height; - var myIndex = indexOf(me.parent.children, me); - me.parent.children.splice(myIndex + 1, 0, sibling); - } - sibling.parent = me.parent; - } while (me.children.length > 10); - me.parent.maybeSpill(); - }, - iterN: function(at, n, op) { - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at < sz) { - var used = Math.min(n, sz - at); - if (child.iterN(at, used, op)) return true; - if ((n -= used) == 0) break; - at = 0; - } else at -= sz; - } - } - }; - - var nextDocId = 0; - var Doc = CodeMirror.Doc = function(text, mode, firstLine) { - if (!(this instanceof Doc)) return new Doc(text, mode, firstLine); - if (firstLine == null) firstLine = 0; - - BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); - this.first = firstLine; - this.scrollTop = this.scrollLeft = 0; - this.cantEdit = false; - this.cleanGeneration = 1; - this.frontier = firstLine; - var start = Pos(firstLine, 0); - this.sel = simpleSelection(start); - this.history = new History(null); - this.id = ++nextDocId; - this.modeOption = mode; - - if (typeof text == "string") text = splitLines(text); - updateDoc(this, {from: start, to: start, text: text}); - setSelection(this, simpleSelection(start), sel_dontScroll); - }; - - Doc.prototype = createObj(BranchChunk.prototype, { - constructor: Doc, - // Iterate over the document. Supports two forms -- with only one - // argument, it calls that for each line in the document. With - // three, it iterates over the range given by the first two (with - // the second being non-inclusive). - iter: function(from, to, op) { - if (op) this.iterN(from - this.first, to - from, op); - else this.iterN(this.first, this.first + this.size, from); - }, - - // Non-public interface for adding and removing lines. - insert: function(at, lines) { - var height = 0; - for (var i = 0; i < lines.length; ++i) height += lines[i].height; - this.insertInner(at - this.first, lines, height); - }, - remove: function(at, n) { this.removeInner(at - this.first, n); }, - - // From here, the methods are part of the public interface. Most - // are also available from CodeMirror (editor) instances. - - getValue: function(lineSep) { - var lines = getLines(this, this.first, this.first + this.size); - if (lineSep === false) return lines; - return lines.join(lineSep || "\n"); - }, - setValue: docMethodOp(function(code) { - var top = Pos(this.first, 0), last = this.first + this.size - 1; - makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), - text: splitLines(code), origin: "setValue", full: true}, true); - setSelection(this, simpleSelection(top)); - }), - replaceRange: function(code, from, to, origin) { - from = clipPos(this, from); - to = to ? clipPos(this, to) : from; - replaceRange(this, code, from, to, origin); - }, - getRange: function(from, to, lineSep) { - var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); - if (lineSep === false) return lines; - return lines.join(lineSep || "\n"); - }, - - getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;}, - - getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);}, - getLineNumber: function(line) {return lineNo(line);}, - - getLineHandleVisualStart: function(line) { - if (typeof line == "number") line = getLine(this, line); - return visualLine(line); - }, - - lineCount: function() {return this.size;}, - firstLine: function() {return this.first;}, - lastLine: function() {return this.first + this.size - 1;}, - - clipPos: function(pos) {return clipPos(this, pos);}, - - getCursor: function(start) { - var range = this.sel.primary(), pos; - if (start == null || start == "head") pos = range.head; - else if (start == "anchor") pos = range.anchor; - else if (start == "end" || start == "to" || start === false) pos = range.to(); - else pos = range.from(); - return pos; - }, - listSelections: function() { return this.sel.ranges; }, - somethingSelected: function() {return this.sel.somethingSelected();}, - - setCursor: docMethodOp(function(line, ch, options) { - setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); - }), - setSelection: docMethodOp(function(anchor, head, options) { - setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); - }), - extendSelection: docMethodOp(function(head, other, options) { - extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); - }), - extendSelections: docMethodOp(function(heads, options) { - extendSelections(this, clipPosArray(this, heads, options)); - }), - extendSelectionsBy: docMethodOp(function(f, options) { - extendSelections(this, map(this.sel.ranges, f), options); - }), - setSelections: docMethodOp(function(ranges, primary, options) { - if (!ranges.length) return; - for (var i = 0, out = []; i < ranges.length; i++) - out[i] = new Range(clipPos(this, ranges[i].anchor), - clipPos(this, ranges[i].head)); - if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex); - setSelection(this, normalizeSelection(out, primary), options); - }), - addSelection: docMethodOp(function(anchor, head, options) { - var ranges = this.sel.ranges.slice(0); - ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); - setSelection(this, normalizeSelection(ranges, ranges.length - 1), options); - }), - - getSelection: function(lineSep) { - var ranges = this.sel.ranges, lines; - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this, ranges[i].from(), ranges[i].to()); - lines = lines ? lines.concat(sel) : sel; - } - if (lineSep === false) return lines; - else return lines.join(lineSep || "\n"); - }, - getSelections: function(lineSep) { - var parts = [], ranges = this.sel.ranges; - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this, ranges[i].from(), ranges[i].to()); - if (lineSep !== false) sel = sel.join(lineSep || "\n"); - parts[i] = sel; - } - return parts; - }, - replaceSelection: function(code, collapse, origin) { - var dup = []; - for (var i = 0; i < this.sel.ranges.length; i++) - dup[i] = code; - this.replaceSelections(dup, collapse, origin || "+input"); - }, - replaceSelections: docMethodOp(function(code, collapse, origin) { - var changes = [], sel = this.sel; - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i]; - changes[i] = {from: range.from(), to: range.to(), text: splitLines(code[i]), origin: origin}; - } - var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); - for (var i = changes.length - 1; i >= 0; i--) - makeChange(this, changes[i]); - if (newSel) setSelectionReplaceHistory(this, newSel); - else if (this.cm) ensureCursorVisible(this.cm); - }), - undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), - redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), - undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), - redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), - - setExtending: function(val) {this.extend = val;}, - getExtending: function() {return this.extend;}, - - historySize: function() { - var hist = this.history, done = 0, undone = 0; - for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done; - for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone; - return {undo: done, redo: undone}; - }, - clearHistory: function() {this.history = new History(this.history.maxGeneration);}, - - markClean: function() { - this.cleanGeneration = this.changeGeneration(true); - }, - changeGeneration: function(forceSplit) { - if (forceSplit) - this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; - return this.history.generation; - }, - isClean: function (gen) { - return this.history.generation == (gen || this.cleanGeneration); - }, - - getHistory: function() { - return {done: copyHistoryArray(this.history.done), - undone: copyHistoryArray(this.history.undone)}; - }, - setHistory: function(histData) { - var hist = this.history = new History(this.history.maxGeneration); - hist.done = copyHistoryArray(histData.done.slice(0), null, true); - hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); - }, - - addLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass"; - if (!line[prop]) line[prop] = cls; - else if (classTest(cls).test(line[prop])) return false; - else line[prop] += " " + cls; - return true; - }); - }), - removeLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass"; - var cur = line[prop]; - if (!cur) return false; - else if (cls == null) line[prop] = null; - else { - var found = cur.match(classTest(cls)); - if (!found) return false; - var end = found.index + found[0].length; - line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; - } - return true; - }); - }), - - markText: function(from, to, options) { - return markText(this, clipPos(this, from), clipPos(this, to), options, "range"); - }, - setBookmark: function(pos, options) { - var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), - insertLeft: options && options.insertLeft, - clearWhenEmpty: false, shared: options && options.shared}; - pos = clipPos(this, pos); - return markText(this, pos, pos, realOpts, "bookmark"); - }, - findMarksAt: function(pos) { - pos = clipPos(this, pos); - var markers = [], spans = getLine(this, pos.line).markedSpans; - if (spans) for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if ((span.from == null || span.from <= pos.ch) && - (span.to == null || span.to >= pos.ch)) - markers.push(span.marker.parent || span.marker); - } - return markers; - }, - findMarks: function(from, to, filter) { - from = clipPos(this, from); to = clipPos(this, to); - var found = [], lineNo = from.line; - this.iter(from.line, to.line + 1, function(line) { - var spans = line.markedSpans; - if (spans) for (var i = 0; i < spans.length; i++) { - var span = spans[i]; - if (!(lineNo == from.line && from.ch > span.to || - span.from == null && lineNo != from.line|| - lineNo == to.line && span.from > to.ch) && - (!filter || filter(span.marker))) - found.push(span.marker.parent || span.marker); - } - ++lineNo; - }); - return found; - }, - getAllMarks: function() { - var markers = []; - this.iter(function(line) { - var sps = line.markedSpans; - if (sps) for (var i = 0; i < sps.length; ++i) - if (sps[i].from != null) markers.push(sps[i].marker); - }); - return markers; - }, - - posFromIndex: function(off) { - var ch, lineNo = this.first; - this.iter(function(line) { - var sz = line.text.length + 1; - if (sz > off) { ch = off; return true; } - off -= sz; - ++lineNo; - }); - return clipPos(this, Pos(lineNo, ch)); - }, - indexFromPos: function (coords) { - coords = clipPos(this, coords); - var index = coords.ch; - if (coords.line < this.first || coords.ch < 0) return 0; - this.iter(this.first, coords.line, function (line) { - index += line.text.length + 1; - }); - return index; - }, - - copy: function(copyHistory) { - var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first); - doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; - doc.sel = this.sel; - doc.extend = false; - if (copyHistory) { - doc.history.undoDepth = this.history.undoDepth; - doc.setHistory(this.getHistory()); - } - return doc; - }, - - linkedDoc: function(options) { - if (!options) options = {}; - var from = this.first, to = this.first + this.size; - if (options.from != null && options.from > from) from = options.from; - if (options.to != null && options.to < to) to = options.to; - var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from); - if (options.sharedHist) copy.history = this.history; - (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); - copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; - copySharedMarkers(copy, findSharedMarkers(this)); - return copy; - }, - unlinkDoc: function(other) { - if (other instanceof CodeMirror) other = other.doc; - if (this.linked) for (var i = 0; i < this.linked.length; ++i) { - var link = this.linked[i]; - if (link.doc != other) continue; - this.linked.splice(i, 1); - other.unlinkDoc(this); - detachSharedMarkers(findSharedMarkers(this)); - break; - } - // If the histories were shared, split them again - if (other.history == this.history) { - var splitIds = [other.id]; - linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true); - other.history = new History(null); - other.history.done = copyHistoryArray(this.history.done, splitIds); - other.history.undone = copyHistoryArray(this.history.undone, splitIds); - } - }, - iterLinkedDocs: function(f) {linkedDocs(this, f);}, - - getMode: function() {return this.mode;}, - getEditor: function() {return this.cm;} - }); - - // Public alias. - Doc.prototype.eachLine = Doc.prototype.iter; - - // Set up methods on CodeMirror's prototype to redirect to the editor's document. - var dontDelegate = "iter insert remove copy getEditor".split(" "); - for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) - CodeMirror.prototype[prop] = (function(method) { - return function() {return method.apply(this.doc, arguments);}; - })(Doc.prototype[prop]); - - eventMixin(Doc); - - // Call f for all linked documents. - function linkedDocs(doc, f, sharedHistOnly) { - function propagate(doc, skip, sharedHist) { - if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) { - var rel = doc.linked[i]; - if (rel.doc == skip) continue; - var shared = sharedHist && rel.sharedHist; - if (sharedHistOnly && !shared) continue; - f(rel.doc, shared); - propagate(rel.doc, doc, shared); - } - } - propagate(doc, null, true); - } - - // Attach a document to an editor. - function attachDoc(cm, doc) { - if (doc.cm) throw new Error("This document is already in use."); - cm.doc = doc; - doc.cm = cm; - estimateLineHeights(cm); - loadMode(cm); - if (!cm.options.lineWrapping) findMaxLine(cm); - cm.options.mode = doc.modeOption; - regChange(cm); - } - - // LINE UTILITIES - - // Find the line object corresponding to the given line number. - function getLine(doc, n) { - n -= doc.first; - if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document."); - for (var chunk = doc; !chunk.lines;) { - for (var i = 0;; ++i) { - var child = chunk.children[i], sz = child.chunkSize(); - if (n < sz) { chunk = child; break; } - n -= sz; - } - } - return chunk.lines[n]; - } - - // Get the part of a document between two positions, as an array of - // strings. - function getBetween(doc, start, end) { - var out = [], n = start.line; - doc.iter(start.line, end.line + 1, function(line) { - var text = line.text; - if (n == end.line) text = text.slice(0, end.ch); - if (n == start.line) text = text.slice(start.ch); - out.push(text); - ++n; - }); - return out; - } - // Get the lines between from and to, as array of strings. - function getLines(doc, from, to) { - var out = []; - doc.iter(from, to, function(line) { out.push(line.text); }); - return out; - } - - // Update the height of a line, propagating the height change - // upwards to parent nodes. - function updateLineHeight(line, height) { - var diff = height - line.height; - if (diff) for (var n = line; n; n = n.parent) n.height += diff; - } - - // Given a line object, find its line number by walking up through - // its parent links. - function lineNo(line) { - if (line.parent == null) return null; - var cur = line.parent, no = indexOf(cur.lines, line); - for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { - for (var i = 0;; ++i) { - if (chunk.children[i] == cur) break; - no += chunk.children[i].chunkSize(); - } - } - return no + cur.first; - } - - // Find the line at the given vertical position, using the height - // information in the document tree. - function lineAtHeight(chunk, h) { - var n = chunk.first; - outer: do { - for (var i = 0; i < chunk.children.length; ++i) { - var child = chunk.children[i], ch = child.height; - if (h < ch) { chunk = child; continue outer; } - h -= ch; - n += child.chunkSize(); - } - return n; - } while (!chunk.lines); - for (var i = 0; i < chunk.lines.length; ++i) { - var line = chunk.lines[i], lh = line.height; - if (h < lh) break; - h -= lh; - } - return n + i; - } - - - // Find the height above the given line. - function heightAtLine(lineObj) { - lineObj = visualLine(lineObj); - - var h = 0, chunk = lineObj.parent; - for (var i = 0; i < chunk.lines.length; ++i) { - var line = chunk.lines[i]; - if (line == lineObj) break; - else h += line.height; - } - for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { - for (var i = 0; i < p.children.length; ++i) { - var cur = p.children[i]; - if (cur == chunk) break; - else h += cur.height; - } - } - return h; - } - - // Get the bidi ordering for the given line (and cache it). Returns - // false for lines that are fully left-to-right, and an array of - // BidiSpan objects otherwise. - function getOrder(line) { - var order = line.order; - if (order == null) order = line.order = bidiOrdering(line.text); - return order; - } - - // HISTORY - - function History(startGen) { - // Arrays of change events and selections. Doing something adds an - // event to done and clears undo. Undoing moves events from done - // to undone, redoing moves them in the other direction. - this.done = []; this.undone = []; - this.undoDepth = Infinity; - // Used to track when changes can be merged into a single undo - // event - this.lastModTime = this.lastSelTime = 0; - this.lastOp = this.lastSelOp = null; - this.lastOrigin = this.lastSelOrigin = null; - // Used by the isClean() method - this.generation = this.maxGeneration = startGen || 1; - } - - // Create a history change event from an updateDoc-style change - // object. - function historyChangeFromChange(doc, change) { - var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; - attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); - linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true); - return histChange; - } - - // Pop all selection events off the end of a history array. Stop at - // a change event. - function clearSelectionEvents(array) { - while (array.length) { - var last = lst(array); - if (last.ranges) array.pop(); - else break; - } - } - - // Find the top change event in the history. Pop off selection - // events that are in the way. - function lastChangeEvent(hist, force) { - if (force) { - clearSelectionEvents(hist.done); - return lst(hist.done); - } else if (hist.done.length && !lst(hist.done).ranges) { - return lst(hist.done); - } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { - hist.done.pop(); - return lst(hist.done); - } - } - - // Register a change in the history. Merges changes that are within - // a single operation, ore are close together with an origin that - // allows merging (starting with "+") into a single event. - function addChangeToHistory(doc, change, selAfter, opId) { - var hist = doc.history; - hist.undone.length = 0; - var time = +new Date, cur; - - if ((hist.lastOp == opId || - hist.lastOrigin == change.origin && change.origin && - ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) || - change.origin.charAt(0) == "*")) && - (cur = lastChangeEvent(hist, hist.lastOp == opId))) { - // Merge this change into the last event - var last = lst(cur.changes); - if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { - // Optimized case for simple insertion -- don't want to add - // new changesets for every character typed - last.to = changeEnd(change); - } else { - // Add new sub-event - cur.changes.push(historyChangeFromChange(doc, change)); - } - } else { - // Can not be merged, start a new event. - var before = lst(hist.done); - if (!before || !before.ranges) - pushSelectionToHistory(doc.sel, hist.done); - cur = {changes: [historyChangeFromChange(doc, change)], - generation: hist.generation}; - hist.done.push(cur); - while (hist.done.length > hist.undoDepth) { - hist.done.shift(); - if (!hist.done[0].ranges) hist.done.shift(); - } - } - hist.done.push(selAfter); - hist.generation = ++hist.maxGeneration; - hist.lastModTime = hist.lastSelTime = time; - hist.lastOp = hist.lastSelOp = opId; - hist.lastOrigin = hist.lastSelOrigin = change.origin; - - if (!last) signal(doc, "historyAdded"); - } - - function selectionEventCanBeMerged(doc, origin, prev, sel) { - var ch = origin.charAt(0); - return ch == "*" || - ch == "+" && - prev.ranges.length == sel.ranges.length && - prev.somethingSelected() == sel.somethingSelected() && - new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500); - } - - // Called whenever the selection changes, sets the new selection as - // the pending selection in the history, and pushes the old pending - // selection into the 'done' array when it was significantly - // different (in number of selected ranges, emptiness, or time). - function addSelectionToHistory(doc, sel, opId, options) { - var hist = doc.history, origin = options && options.origin; - - // A new event is started when the previous origin does not match - // the current, or the origins don't allow matching. Origins - // starting with * are always merged, those starting with + are - // merged when similar and close together in time. - if (opId == hist.lastSelOp || - (origin && hist.lastSelOrigin == origin && - (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || - selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) - hist.done[hist.done.length - 1] = sel; - else - pushSelectionToHistory(sel, hist.done); - - hist.lastSelTime = +new Date; - hist.lastSelOrigin = origin; - hist.lastSelOp = opId; - if (options && options.clearRedo !== false) - clearSelectionEvents(hist.undone); - } - - function pushSelectionToHistory(sel, dest) { - var top = lst(dest); - if (!(top && top.ranges && top.equals(sel))) - dest.push(sel); - } - - // Used to store marked span information in the history. - function attachLocalSpans(doc, change, from, to) { - var existing = change["spans_" + doc.id], n = 0; - doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) { - if (line.markedSpans) - (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; - ++n; - }); - } - - // When un/re-doing restores text containing marked spans, those - // that have been explicitly cleared should not be restored. - function removeClearedSpans(spans) { - if (!spans) return null; - for (var i = 0, out; i < spans.length; ++i) { - if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); } - else if (out) out.push(spans[i]); - } - return !out ? spans : out.length ? out : null; - } - - // Retrieve and filter the old marked spans stored in a change event. - function getOldSpans(doc, change) { - var found = change["spans_" + doc.id]; - if (!found) return null; - for (var i = 0, nw = []; i < change.text.length; ++i) - nw.push(removeClearedSpans(found[i])); - return nw; - } - - // Used both to provide a JSON-safe object in .getHistory, and, when - // detaching a document, to split the history in two - function copyHistoryArray(events, newGroup, instantiateSel) { - for (var i = 0, copy = []; i < events.length; ++i) { - var event = events[i]; - if (event.ranges) { - copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); - continue; - } - var changes = event.changes, newChanges = []; - copy.push({changes: newChanges}); - for (var j = 0; j < changes.length; ++j) { - var change = changes[j], m; - newChanges.push({from: change.from, to: change.to, text: change.text}); - if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) { - if (indexOf(newGroup, Number(m[1])) > -1) { - lst(newChanges)[prop] = change[prop]; - delete change[prop]; - } - } - } - } - return copy; - } - - // Rebasing/resetting history to deal with externally-sourced changes - - function rebaseHistSelSingle(pos, from, to, diff) { - if (to < pos.line) { - pos.line += diff; - } else if (from < pos.line) { - pos.line = from; - pos.ch = 0; - } - } - - // Tries to rebase an array of history events given a change in the - // document. If the change touches the same lines as the event, the - // event, and everything 'behind' it, is discarded. If the change is - // before the event, the event's positions are updated. Uses a - // copy-on-write scheme for the positions, to avoid having to - // reallocate them all on every rebase, but also avoid problems with - // shared position objects being unsafely updated. - function rebaseHistArray(array, from, to, diff) { - for (var i = 0; i < array.length; ++i) { - var sub = array[i], ok = true; - if (sub.ranges) { - if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } - for (var j = 0; j < sub.ranges.length; j++) { - rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); - rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); - } - continue; - } - for (var j = 0; j < sub.changes.length; ++j) { - var cur = sub.changes[j]; - if (to < cur.from.line) { - cur.from = Pos(cur.from.line + diff, cur.from.ch); - cur.to = Pos(cur.to.line + diff, cur.to.ch); - } else if (from <= cur.to.line) { - ok = false; - break; - } - } - if (!ok) { - array.splice(0, i + 1); - i = 0; - } - } - } - - function rebaseHist(hist, change) { - var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; - rebaseHistArray(hist.done, from, to, diff); - rebaseHistArray(hist.undone, from, to, diff); - } - - // EVENT UTILITIES - - // Due to the fact that we still support jurassic IE versions, some - // compatibility wrappers are needed. - - var e_preventDefault = CodeMirror.e_preventDefault = function(e) { - if (e.preventDefault) e.preventDefault(); - else e.returnValue = false; - }; - var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) { - if (e.stopPropagation) e.stopPropagation(); - else e.cancelBubble = true; - }; - function e_defaultPrevented(e) { - return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false; - } - var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);}; - - function e_target(e) {return e.target || e.srcElement;} - function e_button(e) { - var b = e.which; - if (b == null) { - if (e.button & 1) b = 1; - else if (e.button & 2) b = 3; - else if (e.button & 4) b = 2; - } - if (mac && e.ctrlKey && b == 1) b = 3; - return b; - } - - // EVENT HANDLING - - // Lightweight event framework. on/off also work on DOM nodes, - // registering native DOM handlers. - - var on = CodeMirror.on = function(emitter, type, f) { - if (emitter.addEventListener) - emitter.addEventListener(type, f, false); - else if (emitter.attachEvent) - emitter.attachEvent("on" + type, f); - else { - var map = emitter._handlers || (emitter._handlers = {}); - var arr = map[type] || (map[type] = []); - arr.push(f); - } - }; - - var off = CodeMirror.off = function(emitter, type, f) { - if (emitter.removeEventListener) - emitter.removeEventListener(type, f, false); - else if (emitter.detachEvent) - emitter.detachEvent("on" + type, f); - else { - var arr = emitter._handlers && emitter._handlers[type]; - if (!arr) return; - for (var i = 0; i < arr.length; ++i) - if (arr[i] == f) { arr.splice(i, 1); break; } - } - }; - - var signal = CodeMirror.signal = function(emitter, type /*, values...*/) { - var arr = emitter._handlers && emitter._handlers[type]; - if (!arr) return; - var args = Array.prototype.slice.call(arguments, 2); - for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args); - }; - - var orphanDelayedCallbacks = null; - - // Often, we want to signal events at a point where we are in the - // middle of some work, but don't want the handler to start calling - // other methods on the editor, which might be in an inconsistent - // state or simply not expect any other events to happen. - // signalLater looks whether there are any handlers, and schedules - // them to be executed when the last operation ends, or, if no - // operation is active, when a timeout fires. - function signalLater(emitter, type /*, values...*/) { - var arr = emitter._handlers && emitter._handlers[type]; - if (!arr) return; - var args = Array.prototype.slice.call(arguments, 2), list; - if (operationGroup) { - list = operationGroup.delayedCallbacks; - } else if (orphanDelayedCallbacks) { - list = orphanDelayedCallbacks; - } else { - list = orphanDelayedCallbacks = []; - setTimeout(fireOrphanDelayed, 0); - } - function bnd(f) {return function(){f.apply(null, args);};}; - for (var i = 0; i < arr.length; ++i) - list.push(bnd(arr[i])); - } - - function fireOrphanDelayed() { - var delayed = orphanDelayedCallbacks; - orphanDelayedCallbacks = null; - for (var i = 0; i < delayed.length; ++i) delayed[i](); - } - - // The DOM events that CodeMirror handles can be overridden by - // registering a (non-DOM) handler on the editor for the event name, - // and preventDefault-ing the event in that handler. - function signalDOMEvent(cm, e, override) { - if (typeof e == "string") - e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; - signal(cm, override || e.type, cm, e); - return e_defaultPrevented(e) || e.codemirrorIgnore; - } - - function signalCursorActivity(cm) { - var arr = cm._handlers && cm._handlers.cursorActivity; - if (!arr) return; - var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); - for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1) - set.push(arr[i]); - } - - function hasHandler(emitter, type) { - var arr = emitter._handlers && emitter._handlers[type]; - return arr && arr.length > 0; - } - - // Add on and off methods to a constructor's prototype, to make - // registering events on such objects more convenient. - function eventMixin(ctor) { - ctor.prototype.on = function(type, f) {on(this, type, f);}; - ctor.prototype.off = function(type, f) {off(this, type, f);}; - } - - // MISC UTILITIES - - // Number of pixels added to scroller and sizer to hide scrollbar - var scrollerGap = 30; - - // Returned or thrown by various protocols to signal 'I'm not - // handling this'. - var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}}; - - // Reused option objects for setSelection & friends - var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; - - function Delayed() {this.id = null;} - Delayed.prototype.set = function(ms, f) { - clearTimeout(this.id); - this.id = setTimeout(f, ms); - }; - - // Counts the column offset in a string, taking tabs into account. - // Used mostly to find indentation. - var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) { - if (end == null) { - end = string.search(/[^\s\u00a0]/); - if (end == -1) end = string.length; - } - for (var i = startIndex || 0, n = startValue || 0;;) { - var nextTab = string.indexOf("\t", i); - if (nextTab < 0 || nextTab >= end) - return n + (end - i); - n += nextTab - i; - n += tabSize - (n % tabSize); - i = nextTab + 1; - } - }; - - // The inverse of countColumn -- find the offset that corresponds to - // a particular column. - function findColumn(string, goal, tabSize) { - for (var pos = 0, col = 0;;) { - var nextTab = string.indexOf("\t", pos); - if (nextTab == -1) nextTab = string.length; - var skipped = nextTab - pos; - if (nextTab == string.length || col + skipped >= goal) - return pos + Math.min(skipped, goal - col); - col += nextTab - pos; - col += tabSize - (col % tabSize); - pos = nextTab + 1; - if (col >= goal) return pos; - } - } - - var spaceStrs = [""]; - function spaceStr(n) { - while (spaceStrs.length <= n) - spaceStrs.push(lst(spaceStrs) + " "); - return spaceStrs[n]; - } - - function lst(arr) { return arr[arr.length-1]; } - - var selectInput = function(node) { node.select(); }; - if (ios) // Mobile Safari apparently has a bug where select() is broken. - selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; - else if (ie) // Suppress mysterious IE10 errors - selectInput = function(node) { try { node.select(); } catch(_e) {} }; - - function indexOf(array, elt) { - for (var i = 0; i < array.length; ++i) - if (array[i] == elt) return i; - return -1; - } - function map(array, f) { - var out = []; - for (var i = 0; i < array.length; i++) out[i] = f(array[i], i); - return out; - } - - function createObj(base, props) { - var inst; - if (Object.create) { - inst = Object.create(base); - } else { - var ctor = function() {}; - ctor.prototype = base; - inst = new ctor(); - } - if (props) copyObj(props, inst); - return inst; - }; - - function copyObj(obj, target, overwrite) { - if (!target) target = {}; - for (var prop in obj) - if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) - target[prop] = obj[prop]; - return target; - } - - function bind(f) { - var args = Array.prototype.slice.call(arguments, 1); - return function(){return f.apply(null, args);}; - } - - var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; - var isWordCharBasic = CodeMirror.isWordChar = function(ch) { - return /\w/.test(ch) || ch > "\x80" && - (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); - }; - function isWordChar(ch, helper) { - if (!helper) return isWordCharBasic(ch); - if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true; - return helper.test(ch); - } - - function isEmpty(obj) { - for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false; - return true; - } - - // Extending unicode characters. A series of a non-extending char + - // any number of extending chars is treated as a single unit as far - // as editing and measuring is concerned. This is not fully correct, - // since some scripts/fonts/browsers also treat other configurations - // of code points as a group. - var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; - function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); } - - // DOM UTILITIES - - function elt(tag, content, className, style) { - var e = document.createElement(tag); - if (className) e.className = className; - if (style) e.style.cssText = style; - if (typeof content == "string") e.appendChild(document.createTextNode(content)); - else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]); - return e; - } - - var range; - if (document.createRange) range = function(node, start, end) { - var r = document.createRange(); - r.setEnd(node, end); - r.setStart(node, start); - return r; - }; - else range = function(node, start, end) { - var r = document.body.createTextRange(); - try { r.moveToElementText(node.parentNode); } - catch(e) { return r; } - r.collapse(true); - r.moveEnd("character", end); - r.moveStart("character", start); - return r; - }; - - function removeChildren(e) { - for (var count = e.childNodes.length; count > 0; --count) - e.removeChild(e.firstChild); - return e; - } - - function removeChildrenAndAdd(parent, e) { - return removeChildren(parent).appendChild(e); - } - - function contains(parent, child) { - if (parent.contains) - return parent.contains(child); - while (child = child.parentNode) - if (child == parent) return true; - } - - function activeElt() { return document.activeElement; } - // Older versions of IE throws unspecified error when touching - // document.activeElement in some cases (during loading, in iframe) - if (ie && ie_version < 11) activeElt = function() { - try { return document.activeElement; } - catch(e) { return document.body; } - }; - - function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); } - var rmClass = CodeMirror.rmClass = function(node, cls) { - var current = node.className; - var match = classTest(cls).exec(current); - if (match) { - var after = current.slice(match.index + match[0].length); - node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); - } - }; - var addClass = CodeMirror.addClass = function(node, cls) { - var current = node.className; - if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls; - }; - function joinClasses(a, b) { - var as = a.split(" "); - for (var i = 0; i < as.length; i++) - if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i]; - return b; - } - - // WINDOW-WIDE EVENTS - - // These must be handled carefully, because naively registering a - // handler for each editor will cause the editors to never be - // garbage collected. - - function forEachCodeMirror(f) { - if (!document.body.getElementsByClassName) return; - var byClass = document.body.getElementsByClassName("CodeMirror"); - for (var i = 0; i < byClass.length; i++) { - var cm = byClass[i].CodeMirror; - if (cm) f(cm); - } - } - - var globalsRegistered = false; - function ensureGlobalHandlers() { - if (globalsRegistered) return; - registerGlobalHandlers(); - globalsRegistered = true; - } - function registerGlobalHandlers() { - // When the window resizes, we need to refresh active editors. - var resizeTimer; - on(window, "resize", function() { - if (resizeTimer == null) resizeTimer = setTimeout(function() { - resizeTimer = null; - forEachCodeMirror(onResize); - }, 100); - }); - // When the window loses focus, we want to show the editor as blurred - on(window, "blur", function() { - forEachCodeMirror(onBlur); - }); - } - - // FEATURE DETECTION - - // Detect drag-and-drop - var dragAndDrop = function() { - // There is *some* kind of drag-and-drop support in IE6-8, but I - // couldn't get it to work yet. - if (ie && ie_version < 9) return false; - var div = elt('div'); - return "draggable" in div || "dragDrop" in div; - }(); - - var zwspSupported; - function zeroWidthElement(measure) { - if (zwspSupported == null) { - var test = elt("span", "\u200b"); - removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); - if (measure.firstChild.offsetHeight != 0) - zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); - } - if (zwspSupported) return elt("span", "\u200b"); - else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); - } - - // Feature-detect IE's crummy client rect reporting for bidi text - var badBidiRects; - function hasBadBidiRects(measure) { - if (badBidiRects != null) return badBidiRects; - var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); - var r0 = range(txt, 0, 1).getBoundingClientRect(); - if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780) - var r1 = range(txt, 1, 2).getBoundingClientRect(); - return badBidiRects = (r1.right - r0.right < 3); - } - - // See if "".split is the broken IE version, if so, provide an - // alternative way to split lines. - var splitLines = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { - var pos = 0, result = [], l = string.length; - while (pos <= l) { - var nl = string.indexOf("\n", pos); - if (nl == -1) nl = string.length; - var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); - var rt = line.indexOf("\r"); - if (rt != -1) { - result.push(line.slice(0, rt)); - pos += rt + 1; - } else { - result.push(line); - pos = nl + 1; - } - } - return result; - } : function(string){return string.split(/\r\n?|\n/);}; - - var hasSelection = window.getSelection ? function(te) { - try { return te.selectionStart != te.selectionEnd; } - catch(e) { return false; } - } : function(te) { - try {var range = te.ownerDocument.selection.createRange();} - catch(e) {} - if (!range || range.parentElement() != te) return false; - return range.compareEndPoints("StartToEnd", range) != 0; - }; - - var hasCopyEvent = (function() { - var e = elt("div"); - if ("oncopy" in e) return true; - e.setAttribute("oncopy", "return;"); - return typeof e.oncopy == "function"; - })(); - - var badZoomedRects = null; - function hasBadZoomedRects(measure) { - if (badZoomedRects != null) return badZoomedRects; - var node = removeChildrenAndAdd(measure, elt("span", "x")); - var normal = node.getBoundingClientRect(); - var fromRange = range(node, 0, 1).getBoundingClientRect(); - return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1; - } - - // KEY NAMES - - var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", - 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", - 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", - 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 107: "=", 109: "-", 127: "Delete", - 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", - 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", - 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"}; - CodeMirror.keyNames = keyNames; - (function() { - // Number keys - for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i); - // Alphabetic keys - for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); - // Function keys - for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; - })(); - - // BIDI HELPERS - - function iterateBidiSections(order, from, to, f) { - if (!order) return f(from, to, "ltr"); - var found = false; - for (var i = 0; i < order.length; ++i) { - var part = order[i]; - if (part.from < to && part.to > from || from == to && part.to == from) { - f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr"); - found = true; - } - } - if (!found) f(from, to, "ltr"); - } - - function bidiLeft(part) { return part.level % 2 ? part.to : part.from; } - function bidiRight(part) { return part.level % 2 ? part.from : part.to; } - - function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; } - function lineRight(line) { - var order = getOrder(line); - if (!order) return line.text.length; - return bidiRight(lst(order)); - } - - function lineStart(cm, lineN) { - var line = getLine(cm.doc, lineN); - var visual = visualLine(line); - if (visual != line) lineN = lineNo(visual); - var order = getOrder(visual); - var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual); - return Pos(lineN, ch); - } - function lineEnd(cm, lineN) { - var merged, line = getLine(cm.doc, lineN); - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line; - lineN = null; - } - var order = getOrder(line); - var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line); - return Pos(lineN == null ? lineNo(line) : lineN, ch); - } - function lineStartSmart(cm, pos) { - var start = lineStart(cm, pos.line); - var line = getLine(cm.doc, start.line); - var order = getOrder(line); - if (!order || order[0].level == 0) { - var firstNonWS = Math.max(0, line.text.search(/\S/)); - var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; - return Pos(start.line, inWS ? 0 : firstNonWS); - } - return start; - } - - function compareBidiLevel(order, a, b) { - var linedir = order[0].level; - if (a == linedir) return true; - if (b == linedir) return false; - return a < b; - } - var bidiOther; - function getBidiPartAt(order, pos) { - bidiOther = null; - for (var i = 0, found; i < order.length; ++i) { - var cur = order[i]; - if (cur.from < pos && cur.to > pos) return i; - if ((cur.from == pos || cur.to == pos)) { - if (found == null) { - found = i; - } else if (compareBidiLevel(order, cur.level, order[found].level)) { - if (cur.from != cur.to) bidiOther = found; - return i; - } else { - if (cur.from != cur.to) bidiOther = i; - return found; - } - } - } - return found; - } - - function moveInLine(line, pos, dir, byUnit) { - if (!byUnit) return pos + dir; - do pos += dir; - while (pos > 0 && isExtendingChar(line.text.charAt(pos))); - return pos; - } - - // This is needed in order to move 'visually' through bi-directional - // text -- i.e., pressing left should make the cursor go left, even - // when in RTL text. The tricky part is the 'jumps', where RTL and - // LTR text touch each other. This often requires the cursor offset - // to move more than one unit, in order to visually move one unit. - function moveVisually(line, start, dir, byUnit) { - var bidi = getOrder(line); - if (!bidi) return moveLogically(line, start, dir, byUnit); - var pos = getBidiPartAt(bidi, start), part = bidi[pos]; - var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit); - - for (;;) { - if (target > part.from && target < part.to) return target; - if (target == part.from || target == part.to) { - if (getBidiPartAt(bidi, target) == pos) return target; - part = bidi[pos += dir]; - return (dir > 0) == part.level % 2 ? part.to : part.from; - } else { - part = bidi[pos += dir]; - if (!part) return null; - if ((dir > 0) == part.level % 2) - target = moveInLine(line, part.to, -1, byUnit); - else - target = moveInLine(line, part.from, 1, byUnit); - } - } - } - - function moveLogically(line, start, dir, byUnit) { - var target = start + dir; - if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir; - return target < 0 || target > line.text.length ? null : target; - } - - // Bidirectional ordering algorithm - // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm - // that this (partially) implements. - - // One-char codes used for character types: - // L (L): Left-to-Right - // R (R): Right-to-Left - // r (AL): Right-to-Left Arabic - // 1 (EN): European Number - // + (ES): European Number Separator - // % (ET): European Number Terminator - // n (AN): Arabic Number - // , (CS): Common Number Separator - // m (NSM): Non-Spacing Mark - // b (BN): Boundary Neutral - // s (B): Paragraph Separator - // t (S): Segment Separator - // w (WS): Whitespace - // N (ON): Other Neutrals - - // Returns null if characters are ordered as they appear - // (left-to-right), or an array of sections ({from, to, level} - // objects) in the order in which they occur visually. - var bidiOrdering = (function() { - // Character types for codepoints 0 to 0xff - var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; - // Character types for codepoints 0x600 to 0x6ff - var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm"; - function charType(code) { - if (code <= 0xf7) return lowTypes.charAt(code); - else if (0x590 <= code && code <= 0x5f4) return "R"; - else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600); - else if (0x6ee <= code && code <= 0x8ac) return "r"; - else if (0x2000 <= code && code <= 0x200b) return "w"; - else if (code == 0x200c) return "b"; - else return "L"; - } - - var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; - var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; - // Browsers seem to always treat the boundaries of block elements as being L. - var outerType = "L"; - - function BidiSpan(level, from, to) { - this.level = level; - this.from = from; this.to = to; - } - - return function(str) { - if (!bidiRE.test(str)) return false; - var len = str.length, types = []; - for (var i = 0, type; i < len; ++i) - types.push(type = charType(str.charCodeAt(i))); - - // W1. Examine each non-spacing mark (NSM) in the level run, and - // change the type of the NSM to the type of the previous - // character. If the NSM is at the start of the level run, it will - // get the type of sor. - for (var i = 0, prev = outerType; i < len; ++i) { - var type = types[i]; - if (type == "m") types[i] = prev; - else prev = type; - } - - // W2. Search backwards from each instance of a European number - // until the first strong type (R, L, AL, or sor) is found. If an - // AL is found, change the type of the European number to Arabic - // number. - // W3. Change all ALs to R. - for (var i = 0, cur = outerType; i < len; ++i) { - var type = types[i]; - if (type == "1" && cur == "r") types[i] = "n"; - else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; } - } - - // W4. A single European separator between two European numbers - // changes to a European number. A single common separator between - // two numbers of the same type changes to that type. - for (var i = 1, prev = types[0]; i < len - 1; ++i) { - var type = types[i]; - if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1"; - else if (type == "," && prev == types[i+1] && - (prev == "1" || prev == "n")) types[i] = prev; - prev = type; - } - - // W5. A sequence of European terminators adjacent to European - // numbers changes to all European numbers. - // W6. Otherwise, separators and terminators change to Other - // Neutral. - for (var i = 0; i < len; ++i) { - var type = types[i]; - if (type == ",") types[i] = "N"; - else if (type == "%") { - for (var end = i + 1; end < len && types[end] == "%"; ++end) {} - var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; - for (var j = i; j < end; ++j) types[j] = replace; - i = end - 1; - } - } - - // W7. Search backwards from each instance of a European number - // until the first strong type (R, L, or sor) is found. If an L is - // found, then change the type of the European number to L. - for (var i = 0, cur = outerType; i < len; ++i) { - var type = types[i]; - if (cur == "L" && type == "1") types[i] = "L"; - else if (isStrong.test(type)) cur = type; - } - - // N1. A sequence of neutrals takes the direction of the - // surrounding strong text if the text on both sides has the same - // direction. European and Arabic numbers act as if they were R in - // terms of their influence on neutrals. Start-of-level-run (sor) - // and end-of-level-run (eor) are used at level run boundaries. - // N2. Any remaining neutrals take the embedding direction. - for (var i = 0; i < len; ++i) { - if (isNeutral.test(types[i])) { - for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} - var before = (i ? types[i-1] : outerType) == "L"; - var after = (end < len ? types[end] : outerType) == "L"; - var replace = before || after ? "L" : "R"; - for (var j = i; j < end; ++j) types[j] = replace; - i = end - 1; - } - } - - // Here we depart from the documented algorithm, in order to avoid - // building up an actual levels array. Since there are only three - // levels (0, 1, 2) in an implementation that doesn't take - // explicit embedding into account, we can build up the order on - // the fly, without following the level-based algorithm. - var order = [], m; - for (var i = 0; i < len;) { - if (countsAsLeft.test(types[i])) { - var start = i; - for (++i; i < len && countsAsLeft.test(types[i]); ++i) {} - order.push(new BidiSpan(0, start, i)); - } else { - var pos = i, at = order.length; - for (++i; i < len && types[i] != "L"; ++i) {} - for (var j = pos; j < i;) { - if (countsAsNum.test(types[j])) { - if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j)); - var nstart = j; - for (++j; j < i && countsAsNum.test(types[j]); ++j) {} - order.splice(at, 0, new BidiSpan(2, nstart, j)); - pos = j; - } else ++j; - } - if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i)); - } - } - if (order[0].level == 1 && (m = str.match(/^\s+/))) { - order[0].from = m[0].length; - order.unshift(new BidiSpan(0, 0, m[0].length)); - } - if (lst(order).level == 1 && (m = str.match(/\s+$/))) { - lst(order).to -= m[0].length; - order.push(new BidiSpan(0, len - m[0].length, len)); - } - if (order[0].level != lst(order).level) - order.push(new BidiSpan(order[0].level, len, len)); - - return order; - }; - })(); - - // THE END - - CodeMirror.version = "4.12.0"; - - return CodeMirror; -}); diff --git a/html/forums/admin/jscripts/codemirror/lib/index.html b/html/forums/admin/jscripts/codemirror/lib/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/lib/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/mode/css/css.js b/html/forums/admin/jscripts/codemirror/mode/css/css.js deleted file mode 100644 index 3f02907..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/css/css.js +++ /dev/null @@ -1,717 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("css", function(config, parserConfig) { - if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css"); - - var indentUnit = config.indentUnit, - tokenHooks = parserConfig.tokenHooks, - mediaTypes = parserConfig.mediaTypes || {}, - mediaFeatures = parserConfig.mediaFeatures || {}, - propertyKeywords = parserConfig.propertyKeywords || {}, - nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {}, - colorKeywords = parserConfig.colorKeywords || {}, - valueKeywords = parserConfig.valueKeywords || {}, - fontProperties = parserConfig.fontProperties || {}, - allowNested = parserConfig.allowNested; - - var type, override; - function ret(style, tp) { type = tp; return style; } - - // Tokenizers - - function tokenBase(stream, state) { - var ch = stream.next(); - if (tokenHooks[ch]) { - var result = tokenHooks[ch](stream, state); - if (result !== false) return result; - } - if (ch == "@") { - stream.eatWhile(/[\w\\\-]/); - return ret("def", stream.current()); - } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) { - return ret(null, "compare"); - } else if (ch == "\"" || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } else if (ch == "#") { - stream.eatWhile(/[\w\\\-]/); - return ret("atom", "hash"); - } else if (ch == "!") { - stream.match(/^\s*\w*/); - return ret("keyword", "important"); - } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) { - stream.eatWhile(/[\w.%]/); - return ret("number", "unit"); - } else if (ch === "-") { - if (/[\d.]/.test(stream.peek())) { - stream.eatWhile(/[\w.%]/); - return ret("number", "unit"); - } else if (stream.match(/^\w+-/)) { - return ret("meta", "meta"); - } - } else if (/[,+>*\/]/.test(ch)) { - return ret(null, "select-op"); - } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { - return ret("qualifier", "qualifier"); - } else if (/[:;{}\[\]\(\)]/.test(ch)) { - return ret(null, ch); - } else if (ch == "u" && stream.match("rl(")) { - stream.backUp(1); - state.tokenize = tokenParenthesized; - return ret("property", "word"); - } else if (/[\w\\\-]/.test(ch)) { - stream.eatWhile(/[\w\\\-]/); - return ret("property", "word"); - } else { - return ret(null, null); - } - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - if (quote == ")") stream.backUp(1); - break; - } - escaped = !escaped && ch == "\\"; - } - if (ch == quote || !escaped && quote != ")") state.tokenize = null; - return ret("string", "string"); - }; - } - - function tokenParenthesized(stream, state) { - stream.next(); // Must be '(' - if (!stream.match(/\s*[\"\')]/, false)) - state.tokenize = tokenString(")"); - else - state.tokenize = null; - return ret(null, "("); - } - - // Context management - - function Context(type, indent, prev) { - this.type = type; - this.indent = indent; - this.prev = prev; - } - - function pushContext(state, stream, type) { - state.context = new Context(type, stream.indentation() + indentUnit, state.context); - return type; - } - - function popContext(state) { - state.context = state.context.prev; - return state.context.type; - } - - function pass(type, stream, state) { - return states[state.context.type](type, stream, state); - } - function popAndPass(type, stream, state, n) { - for (var i = n || 1; i > 0; i--) - state.context = state.context.prev; - return pass(type, stream, state); - } - - // Parser - - function wordAsValue(stream) { - var word = stream.current().toLowerCase(); - if (valueKeywords.hasOwnProperty(word)) - override = "atom"; - else if (colorKeywords.hasOwnProperty(word)) - override = "keyword"; - else - override = "variable"; - } - - var states = {}; - - states.top = function(type, stream, state) { - if (type == "{") { - return pushContext(state, stream, "block"); - } else if (type == "}" && state.context.prev) { - return popContext(state); - } else if (type == "@media") { - return pushContext(state, stream, "media"); - } else if (type == "@font-face") { - return "font_face_before"; - } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) { - return "keyframes"; - } else if (type && type.charAt(0) == "@") { - return pushContext(state, stream, "at"); - } else if (type == "hash") { - override = "builtin"; - } else if (type == "word") { - override = "tag"; - } else if (type == "variable-definition") { - return "maybeprop"; - } else if (type == "interpolation") { - return pushContext(state, stream, "interpolation"); - } else if (type == ":") { - return "pseudo"; - } else if (allowNested && type == "(") { - return pushContext(state, stream, "parens"); - } - return state.context.type; - }; - - states.block = function(type, stream, state) { - if (type == "word") { - var word = stream.current().toLowerCase(); - if (propertyKeywords.hasOwnProperty(word)) { - override = "property"; - return "maybeprop"; - } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) { - override = "string-2"; - return "maybeprop"; - } else if (allowNested) { - override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag"; - return "block"; - } else { - override += " error"; - return "maybeprop"; - } - } else if (type == "meta") { - return "block"; - } else if (!allowNested && (type == "hash" || type == "qualifier")) { - override = "error"; - return "block"; - } else { - return states.top(type, stream, state); - } - }; - - states.maybeprop = function(type, stream, state) { - if (type == ":") return pushContext(state, stream, "prop"); - return pass(type, stream, state); - }; - - states.prop = function(type, stream, state) { - if (type == ";") return popContext(state); - if (type == "{" && allowNested) return pushContext(state, stream, "propBlock"); - if (type == "}" || type == "{") return popAndPass(type, stream, state); - if (type == "(") return pushContext(state, stream, "parens"); - - if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { - override += " error"; - } else if (type == "word") { - wordAsValue(stream); - } else if (type == "interpolation") { - return pushContext(state, stream, "interpolation"); - } - return "prop"; - }; - - states.propBlock = function(type, _stream, state) { - if (type == "}") return popContext(state); - if (type == "word") { override = "property"; return "maybeprop"; } - return state.context.type; - }; - - states.parens = function(type, stream, state) { - if (type == "{" || type == "}") return popAndPass(type, stream, state); - if (type == ")") return popContext(state); - if (type == "(") return pushContext(state, stream, "parens"); - if (type == "word") wordAsValue(stream); - return "parens"; - }; - - states.pseudo = function(type, stream, state) { - if (type == "word") { - override = "variable-3"; - return state.context.type; - } - return pass(type, stream, state); - }; - - states.media = function(type, stream, state) { - if (type == "(") return pushContext(state, stream, "media_parens"); - if (type == "}") return popAndPass(type, stream, state); - if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top"); - - if (type == "word") { - var word = stream.current().toLowerCase(); - if (word == "only" || word == "not" || word == "and") - override = "keyword"; - else if (mediaTypes.hasOwnProperty(word)) - override = "attribute"; - else if (mediaFeatures.hasOwnProperty(word)) - override = "property"; - else - override = "error"; - } - return state.context.type; - }; - - states.media_parens = function(type, stream, state) { - if (type == ")") return popContext(state); - if (type == "{" || type == "}") return popAndPass(type, stream, state, 2); - return states.media(type, stream, state); - }; - - states.font_face_before = function(type, stream, state) { - if (type == "{") - return pushContext(state, stream, "font_face"); - return pass(type, stream, state); - }; - - states.font_face = function(type, stream, state) { - if (type == "}") return popContext(state); - if (type == "word") { - if (!fontProperties.hasOwnProperty(stream.current().toLowerCase())) - override = "error"; - else - override = "property"; - return "maybeprop"; - } - return "font_face"; - }; - - states.keyframes = function(type, stream, state) { - if (type == "word") { override = "variable"; return "keyframes"; } - if (type == "{") return pushContext(state, stream, "top"); - return pass(type, stream, state); - }; - - states.at = function(type, stream, state) { - if (type == ";") return popContext(state); - if (type == "{" || type == "}") return popAndPass(type, stream, state); - if (type == "word") override = "tag"; - else if (type == "hash") override = "builtin"; - return "at"; - }; - - states.interpolation = function(type, stream, state) { - if (type == "}") return popContext(state); - if (type == "{" || type == ";") return popAndPass(type, stream, state); - if (type != "variable") override = "error"; - return "interpolation"; - }; - - return { - startState: function(base) { - return {tokenize: null, - state: "top", - context: new Context("top", base || 0, null)}; - }, - - token: function(stream, state) { - if (!state.tokenize && stream.eatSpace()) return null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style && typeof style == "object") { - type = style[1]; - style = style[0]; - } - override = style; - state.state = states[state.state](type, stream, state); - return override; - }, - - indent: function(state, textAfter) { - var cx = state.context, ch = textAfter && textAfter.charAt(0); - var indent = cx.indent; - if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev; - if (cx.prev && - (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") || - ch == ")" && (cx.type == "parens" || cx.type == "media_parens") || - ch == "{" && (cx.type == "at" || cx.type == "media"))) { - indent = cx.indent - indentUnit; - cx = cx.prev; - } - return indent; - }, - - electricChars: "}", - blockCommentStart: "/*", - blockCommentEnd: "*/", - fold: "brace" - }; -}); - - function keySet(array) { - var keys = {}; - for (var i = 0; i < array.length; ++i) { - keys[array[i]] = true; - } - return keys; - } - - var mediaTypes_ = [ - "all", "aural", "braille", "handheld", "print", "projection", "screen", - "tty", "tv", "embossed" - ], mediaTypes = keySet(mediaTypes_); - - var mediaFeatures_ = [ - "width", "min-width", "max-width", "height", "min-height", "max-height", - "device-width", "min-device-width", "max-device-width", "device-height", - "min-device-height", "max-device-height", "aspect-ratio", - "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio", - "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color", - "max-color", "color-index", "min-color-index", "max-color-index", - "monochrome", "min-monochrome", "max-monochrome", "resolution", - "min-resolution", "max-resolution", "scan", "grid" - ], mediaFeatures = keySet(mediaFeatures_); - - var propertyKeywords_ = [ - "align-content", "align-items", "align-self", "alignment-adjust", - "alignment-baseline", "anchor-point", "animation", "animation-delay", - "animation-direction", "animation-duration", "animation-fill-mode", - "animation-iteration-count", "animation-name", "animation-play-state", - "animation-timing-function", "appearance", "azimuth", "backface-visibility", - "background", "background-attachment", "background-clip", "background-color", - "background-image", "background-origin", "background-position", - "background-repeat", "background-size", "baseline-shift", "binding", - "bleed", "bookmark-label", "bookmark-level", "bookmark-state", - "bookmark-target", "border", "border-bottom", "border-bottom-color", - "border-bottom-left-radius", "border-bottom-right-radius", - "border-bottom-style", "border-bottom-width", "border-collapse", - "border-color", "border-image", "border-image-outset", - "border-image-repeat", "border-image-slice", "border-image-source", - "border-image-width", "border-left", "border-left-color", - "border-left-style", "border-left-width", "border-radius", "border-right", - "border-right-color", "border-right-style", "border-right-width", - "border-spacing", "border-style", "border-top", "border-top-color", - "border-top-left-radius", "border-top-right-radius", "border-top-style", - "border-top-width", "border-width", "bottom", "box-decoration-break", - "box-shadow", "box-sizing", "break-after", "break-before", "break-inside", - "caption-side", "clear", "clip", "color", "color-profile", "column-count", - "column-fill", "column-gap", "column-rule", "column-rule-color", - "column-rule-style", "column-rule-width", "column-span", "column-width", - "columns", "content", "counter-increment", "counter-reset", "crop", "cue", - "cue-after", "cue-before", "cursor", "direction", "display", - "dominant-baseline", "drop-initial-after-adjust", - "drop-initial-after-align", "drop-initial-before-adjust", - "drop-initial-before-align", "drop-initial-size", "drop-initial-value", - "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis", - "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap", - "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings", - "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust", - "font-stretch", "font-style", "font-synthesis", "font-variant", - "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", - "font-variant-ligatures", "font-variant-numeric", "font-variant-position", - "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", - "grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end", - "grid-column-start", "grid-row", "grid-row-end", "grid-row-start", - "grid-template", "grid-template-areas", "grid-template-columns", - "grid-template-rows", "hanging-punctuation", "height", "hyphens", - "icon", "image-orientation", "image-rendering", "image-resolution", - "inline-box-align", "justify-content", "left", "letter-spacing", - "line-break", "line-height", "line-stacking", "line-stacking-ruby", - "line-stacking-shift", "line-stacking-strategy", "list-style", - "list-style-image", "list-style-position", "list-style-type", "margin", - "margin-bottom", "margin-left", "margin-right", "margin-top", - "marker-offset", "marks", "marquee-direction", "marquee-loop", - "marquee-play-count", "marquee-speed", "marquee-style", "max-height", - "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index", - "nav-left", "nav-right", "nav-up", "object-fit", "object-position", - "opacity", "order", "orphans", "outline", - "outline-color", "outline-offset", "outline-style", "outline-width", - "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y", - "padding", "padding-bottom", "padding-left", "padding-right", "padding-top", - "page", "page-break-after", "page-break-before", "page-break-inside", - "page-policy", "pause", "pause-after", "pause-before", "perspective", - "perspective-origin", "pitch", "pitch-range", "play-during", "position", - "presentation-level", "punctuation-trim", "quotes", "region-break-after", - "region-break-before", "region-break-inside", "region-fragment", - "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness", - "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang", - "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin", - "shape-outside", "size", "speak", "speak-as", "speak-header", - "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", - "tab-size", "table-layout", "target", "target-name", "target-new", - "target-position", "text-align", "text-align-last", "text-decoration", - "text-decoration-color", "text-decoration-line", "text-decoration-skip", - "text-decoration-style", "text-emphasis", "text-emphasis-color", - "text-emphasis-position", "text-emphasis-style", "text-height", - "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow", - "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position", - "text-wrap", "top", "transform", "transform-origin", "transform-style", - "transition", "transition-delay", "transition-duration", - "transition-property", "transition-timing-function", "unicode-bidi", - "vertical-align", "visibility", "voice-balance", "voice-duration", - "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress", - "voice-volume", "volume", "white-space", "widows", "width", "word-break", - "word-spacing", "word-wrap", "z-index", - // SVG-specific - "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color", - "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events", - "color-interpolation", "color-interpolation-filters", - "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering", - "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke", - "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", - "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering", - "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal", - "glyph-orientation-vertical", "text-anchor", "writing-mode" - ], propertyKeywords = keySet(propertyKeywords_); - - var nonStandardPropertyKeywords_ = [ - "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color", - "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color", - "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside", - "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button", - "searchfield-results-decoration", "zoom" - ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_); - - var colorKeywords_ = [ - "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", - "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", - "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", - "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", - "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", - "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", - "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", - "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", - "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", - "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew", - "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender", - "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", - "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink", - "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", - "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", - "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", - "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", - "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", - "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered", - "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", - "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", - "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown", - "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", - "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", - "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", - "whitesmoke", "yellow", "yellowgreen" - ], colorKeywords = keySet(colorKeywords_); - - var valueKeywords_ = [ - "above", "absolute", "activeborder", "activecaption", "afar", - "after-white-space", "ahead", "alias", "all", "all-scroll", "alternate", - "always", "amharic", "amharic-abegede", "antialiased", "appworkspace", - "arabic-indic", "armenian", "asterisks", "auto", "avoid", "avoid-column", "avoid-page", - "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary", - "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box", - "both", "bottom", "break", "break-all", "break-word", "button", "button-bevel", - "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian", - "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret", - "cell", "center", "checkbox", "circle", "cjk-earthly-branch", - "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote", - "col-resize", "collapse", "column", "compact", "condensed", "contain", "content", - "content-box", "context-menu", "continuous", "copy", "cover", "crop", - "cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal", - "decimal-leading-zero", "default", "default-button", "destination-atop", - "destination-in", "destination-out", "destination-over", "devanagari", - "disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted", - "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", - "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", - "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er", - "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", - "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et", - "ethiopic-halehame-gez", "ethiopic-halehame-om-et", - "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et", - "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", - "ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed", - "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "footnotes", - "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove", - "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", - "help", "hidden", "hide", "higher", "highlight", "highlighttext", - "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore", - "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", - "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis", - "inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert", - "italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer", - "landscape", "lao", "large", "larger", "left", "level", "lighter", - "line-through", "linear", "lines", "list-item", "listbox", "listitem", - "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", - "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian", - "lower-roman", "lowercase", "ltr", "malayalam", "match", - "media-controls-background", "media-current-time-display", - "media-fullscreen-button", "media-mute-button", "media-play-button", - "media-return-to-realtime-button", "media-rewind-button", - "media-seek-back-button", "media-seek-forward-button", "media-slider", - "media-sliderthumb", "media-time-remaining-display", "media-volume-slider", - "media-volume-slider-container", "media-volume-sliderthumb", "medium", - "menu", "menulist", "menulist-button", "menulist-text", - "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", - "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize", - "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", - "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap", - "ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote", - "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset", - "outside", "outside-shape", "overlay", "overline", "padding", "padding-box", - "painted", "page", "paused", "persian", "plus-darker", "plus-lighter", "pointer", - "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button", - "radio", "read-only", "read-write", "read-write-plaintext-only", "rectangle", "region", - "relative", "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba", - "ridge", "right", "round", "row-resize", "rtl", "run-in", "running", - "s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield", - "searchfield-cancel-button", "searchfield-decoration", - "searchfield-results-button", "searchfield-results-decoration", - "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", - "single", "skip-white-space", "slide", "slider-horizontal", - "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", - "small", "small-caps", "small-caption", "smaller", "solid", "somali", - "source-atop", "source-in", "source-out", "source-over", "space", "square", - "square-button", "start", "static", "status-bar", "stretch", "stroke", - "sub", "subpixel-antialiased", "super", "sw-resize", "table", - "table-caption", "table-cell", "table-column", "table-column-group", - "table-footer-group", "table-header-group", "table-row", "table-row-group", - "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", - "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight", - "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", - "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top", - "transparent", "ultra-condensed", "ultra-expanded", "underline", "up", - "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal", - "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", - "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted", - "visibleStroke", "visual", "w-resize", "wait", "wave", "wider", - "window", "windowframe", "windowtext", "x-large", "x-small", "xor", - "xx-large", "xx-small" - ], valueKeywords = keySet(valueKeywords_); - - var fontProperties_ = [ - "font-family", "src", "unicode-range", "font-variant", "font-feature-settings", - "font-stretch", "font-weight", "font-style" - ], fontProperties = keySet(fontProperties_); - - var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_) - .concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_); - CodeMirror.registerHelper("hintWords", "css", allWords); - - function tokenCComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == "/") { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return ["comment", "comment"]; - } - - function tokenSGMLComment(stream, state) { - if (stream.skipTo("-->")) { - stream.match("-->"); - state.tokenize = null; - } else { - stream.skipToEnd(); - } - return ["comment", "comment"]; - } - - CodeMirror.defineMIME("text/css", { - mediaTypes: mediaTypes, - mediaFeatures: mediaFeatures, - propertyKeywords: propertyKeywords, - nonStandardPropertyKeywords: nonStandardPropertyKeywords, - colorKeywords: colorKeywords, - valueKeywords: valueKeywords, - fontProperties: fontProperties, - tokenHooks: { - "<": function(stream, state) { - if (!stream.match("!--")) return false; - state.tokenize = tokenSGMLComment; - return tokenSGMLComment(stream, state); - }, - "/": function(stream, state) { - if (!stream.eat("*")) return false; - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - }, - name: "css" - }); - - CodeMirror.defineMIME("text/x-scss", { - mediaTypes: mediaTypes, - mediaFeatures: mediaFeatures, - propertyKeywords: propertyKeywords, - nonStandardPropertyKeywords: nonStandardPropertyKeywords, - colorKeywords: colorKeywords, - valueKeywords: valueKeywords, - fontProperties: fontProperties, - allowNested: true, - tokenHooks: { - "/": function(stream, state) { - if (stream.eat("/")) { - stream.skipToEnd(); - return ["comment", "comment"]; - } else if (stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } else { - return ["operator", "operator"]; - } - }, - ":": function(stream) { - if (stream.match(/\s*\{/)) - return [null, "{"]; - return false; - }, - "$": function(stream) { - stream.match(/^[\w-]+/); - if (stream.match(/^\s*:/, false)) - return ["variable-2", "variable-definition"]; - return ["variable-2", "variable"]; - }, - "#": function(stream) { - if (!stream.eat("{")) return false; - return [null, "interpolation"]; - } - }, - name: "css", - helperType: "scss" - }); - - CodeMirror.defineMIME("text/x-less", { - mediaTypes: mediaTypes, - mediaFeatures: mediaFeatures, - propertyKeywords: propertyKeywords, - nonStandardPropertyKeywords: nonStandardPropertyKeywords, - colorKeywords: colorKeywords, - valueKeywords: valueKeywords, - fontProperties: fontProperties, - allowNested: true, - tokenHooks: { - "/": function(stream, state) { - if (stream.eat("/")) { - stream.skipToEnd(); - return ["comment", "comment"]; - } else if (stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } else { - return ["operator", "operator"]; - } - }, - "@": function(stream) { - if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false; - stream.eatWhile(/[\w\\\-]/); - if (stream.match(/^\s*:/, false)) - return ["variable-2", "variable-definition"]; - return ["variable-2", "variable"]; - }, - "&": function() { - return ["atom", "atom"]; - } - }, - name: "css", - helperType: "less" - }); - -}); diff --git a/html/forums/admin/jscripts/codemirror/mode/css/index.html b/html/forums/admin/jscripts/codemirror/mode/css/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/css/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/mode/css/less.html b/html/forums/admin/jscripts/codemirror/mode/css/less.html deleted file mode 100644 index 6ccb721..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/css/less.html +++ /dev/null @@ -1,152 +0,0 @@ - - -CodeMirror: LESS mode - - - - - - - - - - -
-

LESS mode

- - - -

The LESS mode is a sub-mode of the CSS mode (defined in css.js.

- -

Parsing/Highlighting Tests: normal, verbose.

-
diff --git a/html/forums/admin/jscripts/codemirror/mode/css/less_test.js b/html/forums/admin/jscripts/codemirror/mode/css/less_test.js deleted file mode 100644 index 2ba6998..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/css/less_test.js +++ /dev/null @@ -1,51 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - "use strict"; - - var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); } - - MT("variable", - "[variable-2 @base]: [atom #f04615];", - "[qualifier .class] {", - " [property width]: [variable percentage]([number 0.5]); [comment // returns `50%`]", - " [property color]: [variable saturate]([variable-2 @base], [number 5%]);", - "}"); - - MT("amp", - "[qualifier .child], [qualifier .sibling] {", - " [qualifier .parent] [atom &] {", - " [property color]: [keyword black];", - " }", - " [atom &] + [atom &] {", - " [property color]: [keyword red];", - " }", - "}"); - - MT("mixin", - "[qualifier .mixin] ([variable dark]; [variable-2 @color]) {", - " [property color]: [variable darken]([variable-2 @color], [number 10%]);", - "}", - "[qualifier .mixin] ([variable light]; [variable-2 @color]) {", - " [property color]: [variable lighten]([variable-2 @color], [number 10%]);", - "}", - "[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {", - " [property display]: [atom block];", - "}", - "[variable-2 @switch]: [variable light];", - "[qualifier .class] {", - " [qualifier .mixin]([variable-2 @switch]; [atom #888]);", - "}"); - - MT("nest", - "[qualifier .one] {", - " [def @media] ([property width]: [number 400px]) {", - " [property font-size]: [number 1.2em];", - " [def @media] [attribute print] [keyword and] [property color] {", - " [property color]: [keyword blue];", - " }", - " }", - "}"); -})(); diff --git a/html/forums/admin/jscripts/codemirror/mode/css/scss.html b/html/forums/admin/jscripts/codemirror/mode/css/scss.html deleted file mode 100644 index 21f20e0..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/css/scss.html +++ /dev/null @@ -1,157 +0,0 @@ - - -CodeMirror: SCSS mode - - - - - - - - - -
-

SCSS mode

-
- - -

The SCSS mode is a sub-mode of the CSS mode (defined in css.js.

- -

Parsing/Highlighting Tests: normal, verbose.

- -
diff --git a/html/forums/admin/jscripts/codemirror/mode/css/scss_test.js b/html/forums/admin/jscripts/codemirror/mode/css/scss_test.js deleted file mode 100644 index 8dcea9e..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/css/scss_test.js +++ /dev/null @@ -1,110 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } - - MT('url_with_quotation', - "[tag foo] { [property background]:[atom url]([string test.jpg]) }"); - - MT('url_with_double_quotes', - "[tag foo] { [property background]:[atom url]([string \"test.jpg\"]) }"); - - MT('url_with_single_quotes', - "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) }"); - - MT('string', - "[def @import] [string \"compass/css3\"]"); - - MT('important_keyword', - "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) [keyword !important] }"); - - MT('variable', - "[variable-2 $blue]:[atom #333]"); - - MT('variable_as_attribute', - "[tag foo] { [property color]:[variable-2 $blue] }"); - - MT('numbers', - "[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }"); - - MT('number_percentage', - "[tag foo] { [property width]:[number 80%] }"); - - MT('selector', - "[builtin #hello][qualifier .world]{}"); - - MT('singleline_comment', - "[comment // this is a comment]"); - - MT('multiline_comment', - "[comment /*foobar*/]"); - - MT('attribute_with_hyphen', - "[tag foo] { [property font-size]:[number 10px] }"); - - MT('string_after_attribute', - "[tag foo] { [property content]:[string \"::\"] }"); - - MT('directives', - "[def @include] [qualifier .mixin]"); - - MT('basic_structure', - "[tag p] { [property background]:[keyword red]; }"); - - MT('nested_structure', - "[tag p] { [tag a] { [property color]:[keyword red]; } }"); - - MT('mixin', - "[def @mixin] [tag table-base] {}"); - - MT('number_without_semicolon', - "[tag p] {[property width]:[number 12]}", - "[tag a] {[property color]:[keyword red];}"); - - MT('atom_in_nested_block', - "[tag p] { [tag a] { [property color]:[atom #000]; } }"); - - MT('interpolation_in_property', - "[tag foo] { #{[variable-2 $hello]}:[number 2]; }"); - - MT('interpolation_in_selector', - "[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }"); - - MT('interpolation_error', - "[tag foo]#{[error foo]} { [property color]:[atom #000]; }"); - - MT("divide_operator", - "[tag foo] { [property width]:[number 4] [operator /] [number 2] }"); - - MT('nested_structure_with_id_selector', - "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }"); - - MT('indent_mixin', - "[def @mixin] [tag container] (", - " [variable-2 $a]: [number 10],", - " [variable-2 $b]: [number 10])", - "{}"); - - MT('indent_nested', - "[tag foo] {", - " [tag bar] {", - " }", - "}"); - - MT('indent_parentheses', - "[tag foo] {", - " [property color]: [variable darken]([variable-2 $blue],", - " [number 9%]);", - "}"); - - MT('indent_vardef', - "[variable-2 $name]:", - " [string 'val'];", - "[tag tag] {", - " [tag inner] {", - " [property margin]: [number 3px];", - " }", - "}"); -})(); diff --git a/html/forums/admin/jscripts/codemirror/mode/css/test.js b/html/forums/admin/jscripts/codemirror/mode/css/test.js deleted file mode 100644 index d236e2a..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/css/test.js +++ /dev/null @@ -1,135 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "css"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - // Error, because "foobarhello" is neither a known type or property, but - // property was expected (after "and"), and it should be in parenthese. - MT("atMediaUnknownType", - "[def @media] [attribute screen] [keyword and] [error foobarhello] { }"); - - // Soft error, because "foobarhello" is not a known property or type. - MT("atMediaUnknownProperty", - "[def @media] [attribute screen] [keyword and] ([error foobarhello]) { }"); - - // Make sure nesting works with media queries - MT("atMediaMaxWidthNested", - "[def @media] [attribute screen] [keyword and] ([property max-width]: [number 25px]) { [tag foo] { } }"); - - MT("tagSelector", - "[tag foo] { }"); - - MT("classSelector", - "[qualifier .foo-bar_hello] { }"); - - MT("idSelector", - "[builtin #foo] { [error #foo] }"); - - MT("tagSelectorUnclosed", - "[tag foo] { [property margin]: [number 0] } [tag bar] { }"); - - MT("tagStringNoQuotes", - "[tag foo] { [property font-family]: [variable hello] [variable world]; }"); - - MT("tagStringDouble", - "[tag foo] { [property font-family]: [string \"hello world\"]; }"); - - MT("tagStringSingle", - "[tag foo] { [property font-family]: [string 'hello world']; }"); - - MT("tagColorKeyword", - "[tag foo] {", - " [property color]: [keyword black];", - " [property color]: [keyword navy];", - " [property color]: [keyword yellow];", - "}"); - - MT("tagColorHex3", - "[tag foo] { [property background]: [atom #fff]; }"); - - MT("tagColorHex6", - "[tag foo] { [property background]: [atom #ffffff]; }"); - - MT("tagColorHex4", - "[tag foo] { [property background]: [atom&error #ffff]; }"); - - MT("tagColorHexInvalid", - "[tag foo] { [property background]: [atom&error #ffg]; }"); - - MT("tagNegativeNumber", - "[tag foo] { [property margin]: [number -5px]; }"); - - MT("tagPositiveNumber", - "[tag foo] { [property padding]: [number 5px]; }"); - - MT("tagVendor", - "[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][atom border-box]; }"); - - MT("tagBogusProperty", - "[tag foo] { [property&error barhelloworld]: [number 0]; }"); - - MT("tagTwoProperties", - "[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }"); - - MT("tagTwoPropertiesURL", - "[tag foo] { [property background]: [atom url]([string //example.com/foo.png]); [property padding]: [number 0]; }"); - - MT("commentSGML", - "[comment ]"); - - MT("commentSGML2", - "[comment ] [tag div] {}"); - - MT("indent_tagSelector", - "[tag strong], [tag em] {", - " [property background]: [atom rgba](", - " [number 255], [number 255], [number 0], [number .2]", - " );", - "}"); - - MT("indent_atMedia", - "[def @media] {", - " [tag foo] {", - " [property color]:", - " [keyword yellow];", - " }", - "}"); - - MT("indent_comma", - "[tag foo] {", - " [property font-family]: [variable verdana],", - " [atom sans-serif];", - "}"); - - MT("indent_parentheses", - "[tag foo]:[variable-3 before] {", - " [property background]: [atom url](", - "[string blahblah]", - "[string etc]", - "[string ]) [keyword !important];", - "}"); - - MT("font_face", - "[def @font-face] {", - " [property font-family]: [string 'myfont'];", - " [error nonsense]: [string 'abc'];", - " [property src]: [atom url]([string http://blah]),", - " [atom url]([string http://foo]);", - "}"); - - MT("empty_url", - "[def @import] [tag url]() [tag screen];"); - - MT("parens", - "[qualifier .foo] {", - " [property background-image]: [variable fade]([atom #000], [number 20%]);", - " [property border-image]: [variable linear-gradient](", - " [atom to] [atom bottom],", - " [variable fade]([atom #000], [number 20%]) [number 0%],", - " [variable fade]([atom #000], [number 20%]) [number 100%]", - " );", - "}"); -})(); diff --git a/html/forums/admin/jscripts/codemirror/mode/htmlmixed/htmlmixed.js b/html/forums/admin/jscripts/codemirror/mode/htmlmixed/htmlmixed.js deleted file mode 100644 index 1cc438f..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/htmlmixed/htmlmixed.js +++ /dev/null @@ -1,121 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("htmlmixed", function(config, parserConfig) { - var htmlMode = CodeMirror.getMode(config, {name: "xml", - htmlMode: true, - multilineTagIndentFactor: parserConfig.multilineTagIndentFactor, - multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag}); - var cssMode = CodeMirror.getMode(config, "css"); - - var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes; - scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, - mode: CodeMirror.getMode(config, "javascript")}); - if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) { - var conf = scriptTypesConf[i]; - scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)}); - } - scriptTypes.push({matches: /./, - mode: CodeMirror.getMode(config, "text/plain")}); - - function html(stream, state) { - var tagName = state.htmlState.tagName; - if (tagName) tagName = tagName.toLowerCase(); - var style = htmlMode.token(stream, state.htmlState); - if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") { - // Script block: mode to change to depends on type attribute - var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i); - scriptType = scriptType ? scriptType[1] : ""; - if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1); - for (var i = 0; i < scriptTypes.length; ++i) { - var tp = scriptTypes[i]; - if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) { - if (tp.mode) { - state.token = script; - state.localMode = tp.mode; - state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, "")); - } - break; - } - } - } else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") { - state.token = css; - state.localMode = cssMode; - state.localState = cssMode.startState(htmlMode.indent(state.htmlState, "")); - } - return style; - } - function maybeBackup(stream, pat, style) { - var cur = stream.current(); - var close = cur.search(pat), m; - if (close > -1) stream.backUp(cur.length - close); - else if (m = cur.match(/<\/?$/)) { - stream.backUp(cur.length); - if (!stream.match(pat, false)) stream.match(cur); - } - return style; - } - function script(stream, state) { - if (stream.match(/^<\/\s*script\s*>/i, false)) { - state.token = html; - state.localState = state.localMode = null; - return null; - } - return maybeBackup(stream, /<\/\s*script\s*>/, - state.localMode.token(stream, state.localState)); - } - function css(stream, state) { - if (stream.match(/^<\/\s*style\s*>/i, false)) { - state.token = html; - state.localState = state.localMode = null; - return null; - } - return maybeBackup(stream, /<\/\s*style\s*>/, - cssMode.token(stream, state.localState)); - } - - return { - startState: function() { - var state = htmlMode.startState(); - return {token: html, localMode: null, localState: null, htmlState: state}; - }, - - copyState: function(state) { - if (state.localState) - var local = CodeMirror.copyState(state.localMode, state.localState); - return {token: state.token, localMode: state.localMode, localState: local, - htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; - }, - - token: function(stream, state) { - return state.token(stream, state); - }, - - indent: function(state, textAfter) { - if (!state.localMode || /^\s*<\//.test(textAfter)) - return htmlMode.indent(state.htmlState, textAfter); - else if (state.localMode.indent) - return state.localMode.indent(state.localState, textAfter); - else - return CodeMirror.Pass; - }, - - innerMode: function(state) { - return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode}; - } - }; -}, "xml", "javascript", "css"); - -CodeMirror.defineMIME("text/html", "htmlmixed"); - -}); diff --git a/html/forums/admin/jscripts/codemirror/mode/htmlmixed/index.html b/html/forums/admin/jscripts/codemirror/mode/htmlmixed/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/htmlmixed/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/mode/javascript/index.html b/html/forums/admin/jscripts/codemirror/mode/javascript/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/javascript/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/mode/javascript/javascript.js b/html/forums/admin/jscripts/codemirror/mode/javascript/javascript.js deleted file mode 100644 index 93df06d..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/javascript/javascript.js +++ /dev/null @@ -1,692 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// TODO actually recognize syntax of TypeScript constructs - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("javascript", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var statementIndent = parserConfig.statementIndent; - var jsonldMode = parserConfig.jsonld; - var jsonMode = parserConfig.json || jsonldMode; - var isTS = parserConfig.typescript; - var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; - - // Tokenizer - - var keywords = function(){ - function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); - var operator = kw("operator"), atom = {type: "atom", style: "atom"}; - - var jsKeywords = { - "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C, - "var": kw("var"), "const": kw("var"), "let": kw("var"), - "function": kw("function"), "catch": kw("catch"), - "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), - "in": operator, "typeof": operator, "instanceof": operator, - "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, - "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"), - "yield": C, "export": kw("export"), "import": kw("import"), "extends": C - }; - - // Extend the 'normal' keywords with the TypeScript language extensions - if (isTS) { - var type = {type: "variable", style: "variable-3"}; - var tsKeywords = { - // object-like things - "interface": kw("interface"), - "extends": kw("extends"), - "constructor": kw("constructor"), - - // scope modifiers - "public": kw("public"), - "private": kw("private"), - "protected": kw("protected"), - "static": kw("static"), - - // types - "string": type, "number": type, "bool": type, "any": type - }; - - for (var attr in tsKeywords) { - jsKeywords[attr] = tsKeywords[attr]; - } - } - - return jsKeywords; - }(); - - var isOperatorChar = /[+\-*&%=<>!?|~^]/; - var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/; - - function readRegexp(stream) { - var escaped = false, next, inSet = false; - while ((next = stream.next()) != null) { - if (!escaped) { - if (next == "/" && !inSet) return; - if (next == "[") inSet = true; - else if (inSet && next == "]") inSet = false; - } - escaped = !escaped && next == "\\"; - } - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - function ret(tp, style, cont) { - type = tp; content = cont; - return style; - } - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { - return ret("number", "number"); - } else if (ch == "." && stream.match("..")) { - return ret("spread", "meta"); - } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - return ret(ch); - } else if (ch == "=" && stream.eat(">")) { - return ret("=>", "operator"); - } else if (ch == "0" && stream.eat(/x/i)) { - stream.eatWhile(/[\da-f]/i); - return ret("number", "number"); - } else if (/\d/.test(ch)) { - stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); - return ret("number", "number"); - } else if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } else if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } else if (state.lastType == "operator" || state.lastType == "keyword c" || - state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) { - readRegexp(stream); - stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla - return ret("regexp", "string-2"); - } else { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator", stream.current()); - } - } else if (ch == "`") { - state.tokenize = tokenQuasi; - return tokenQuasi(stream, state); - } else if (ch == "#") { - stream.skipToEnd(); - return ret("error", "error"); - } else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator", stream.current()); - } else if (wordRE.test(ch)) { - stream.eatWhile(wordRE); - var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; - return (known && state.lastType != ".") ? ret(known.type, known.style, word) : - ret("variable", "variable", word); - } - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next; - if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ - state.tokenize = tokenBase; - return ret("jsonld-keyword", "meta"); - } - while ((next = stream.next()) != null) { - if (next == quote && !escaped) break; - escaped = !escaped && next == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return ret("string", "string"); - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenQuasi(stream, state) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && next == "\\"; - } - return ret("quasi", "string-2", stream.current()); - } - - var brackets = "([{}])"; - // This is a crude lookahead trick to try and notice that we're - // parsing the argument patterns for a fat-arrow function before we - // actually hit the arrow token. It only works if the arrow is on - // the same line as the arguments and there's no strange noise - // (comments) in between. Fallback is to only notice when we hit the - // arrow, and not declare the arguments as locals for the arrow - // body. - function findFatArrow(stream, state) { - if (state.fatArrowAt) state.fatArrowAt = null; - var arrow = stream.string.indexOf("=>", stream.start); - if (arrow < 0) return; - - var depth = 0, sawSomething = false; - for (var pos = arrow - 1; pos >= 0; --pos) { - var ch = stream.string.charAt(pos); - var bracket = brackets.indexOf(ch); - if (bracket >= 0 && bracket < 3) { - if (!depth) { ++pos; break; } - if (--depth == 0) break; - } else if (bracket >= 3 && bracket < 6) { - ++depth; - } else if (wordRE.test(ch)) { - sawSomething = true; - } else if (/["'\/]/.test(ch)) { - return; - } else if (sawSomething && !depth) { - ++pos; - break; - } - } - if (sawSomething && !depth) state.fatArrowAt = pos; - } - - // Parser - - var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true}; - - function JSLexical(indented, column, type, align, prev, info) { - this.indented = indented; - this.column = column; - this.type = type; - this.prev = prev; - this.info = info; - if (align != null) this.align = align; - } - - function inScope(state, varname) { - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return true; - for (var cx = state.context; cx; cx = cx.prev) { - for (var v = cx.vars; v; v = v.next) - if (v.name == varname) return true; - } - } - - function parseJS(state, style, type, content, stream) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style; - - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - - while(true) { - var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; - if (combinator(type, content)) { - while(cc.length && cc[cc.length - 1].lex) - cc.pop()(); - if (cx.marked) return cx.marked; - if (type == "variable" && inScope(state, content)) return "variable-2"; - return style; - } - } - } - - // Combinator utils - - var cx = {state: null, column: null, marked: null, cc: null}; - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - function register(varname) { - function inList(list) { - for (var v = list; v; v = v.next) - if (v.name == varname) return true; - return false; - } - var state = cx.state; - if (state.context) { - cx.marked = "def"; - if (inList(state.localVars)) return; - state.localVars = {name: varname, next: state.localVars}; - } else { - if (inList(state.globalVars)) return; - if (parserConfig.globalVars) - state.globalVars = {name: varname, next: state.globalVars}; - } - } - - // Combinators - - var defaultVars = {name: "this", next: {name: "arguments"}}; - function pushcontext() { - cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; - cx.state.localVars = defaultVars; - } - function popcontext() { - cx.state.localVars = cx.state.context.vars; - cx.state.context = cx.state.context.prev; - } - function pushlex(type, info) { - var result = function() { - var state = cx.state, indent = state.indented; - if (state.lexical.type == "stat") indent = state.lexical.indented; - else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev) - indent = outer.indented; - state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info); - }; - result.lex = true; - return result; - } - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - poplex.lex = true; - - function expect(wanted) { - function exp(type) { - if (type == wanted) return cont(); - else if (wanted == ";") return pass(); - else return cont(exp); - }; - return exp; - } - - function statement(type, value) { - if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); - if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); - if (type == "keyword b") return cont(pushlex("form"), statement, poplex); - if (type == "{") return cont(pushlex("}"), block, poplex); - if (type == ";") return cont(); - if (type == "if") { - if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) - cx.state.cc.pop()(); - return cont(pushlex("form"), expression, statement, poplex, maybeelse); - } - if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); - if (type == "variable") return cont(pushlex("stat"), maybelabel); - if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), - block, poplex, poplex); - if (type == "case") return cont(expression, expect(":")); - if (type == "default") return cont(expect(":")); - if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), - statement, poplex, popcontext); - if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex); - if (type == "class") return cont(pushlex("form"), className, poplex); - if (type == "export") return cont(pushlex("form"), afterExport, poplex); - if (type == "import") return cont(pushlex("form"), afterImport, poplex); - return pass(pushlex("stat"), expression, expect(";"), poplex); - } - function expression(type) { - return expressionInner(type, false); - } - function expressionNoComma(type) { - return expressionInner(type, true); - } - function expressionInner(type, noComma) { - if (cx.state.fatArrowAt == cx.stream.start) { - var body = noComma ? arrowBodyNoComma : arrowBody; - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); - else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); - } - - var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; - if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); - if (type == "function") return cont(functiondef, maybeop); - if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); - if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); - if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); - if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); - if (type == "{") return contCommasep(objprop, "}", null, maybeop); - if (type == "quasi") { return pass(quasi, maybeop); } - return cont(); - } - function maybeexpression(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expression); - } - function maybeexpressionNoComma(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expressionNoComma); - } - - function maybeoperatorComma(type, value) { - if (type == ",") return cont(expression); - return maybeoperatorNoComma(type, value, false); - } - function maybeoperatorNoComma(type, value, noComma) { - var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; - var expr = noComma == false ? expression : expressionNoComma; - if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); - if (type == "operator") { - if (/\+\+|--/.test(value)) return cont(me); - if (value == "?") return cont(expression, expect(":"), expr); - return cont(expr); - } - if (type == "quasi") { return pass(quasi, me); } - if (type == ";") return; - if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); - if (type == ".") return cont(property, me); - if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); - } - function quasi(type, value) { - if (type != "quasi") return pass(); - if (value.slice(value.length - 2) != "${") return cont(quasi); - return cont(expression, continueQuasi); - } - function continueQuasi(type) { - if (type == "}") { - cx.marked = "string-2"; - cx.state.tokenize = tokenQuasi; - return cont(quasi); - } - } - function arrowBody(type) { - findFatArrow(cx.stream, cx.state); - return pass(type == "{" ? statement : expression); - } - function arrowBodyNoComma(type) { - findFatArrow(cx.stream, cx.state); - return pass(type == "{" ? statement : expressionNoComma); - } - function maybelabel(type) { - if (type == ":") return cont(poplex, statement); - return pass(maybeoperatorComma, expect(";"), poplex); - } - function property(type) { - if (type == "variable") {cx.marked = "property"; return cont();} - } - function objprop(type, value) { - if (type == "variable" || cx.style == "keyword") { - cx.marked = "property"; - if (value == "get" || value == "set") return cont(getterSetter); - return cont(afterprop); - } else if (type == "number" || type == "string") { - cx.marked = jsonldMode ? "property" : (cx.style + " property"); - return cont(afterprop); - } else if (type == "jsonld-keyword") { - return cont(afterprop); - } else if (type == "[") { - return cont(expression, expect("]"), afterprop); - } - } - function getterSetter(type) { - if (type != "variable") return pass(afterprop); - cx.marked = "property"; - return cont(functiondef); - } - function afterprop(type) { - if (type == ":") return cont(expressionNoComma); - if (type == "(") return pass(functiondef); - } - function commasep(what, end) { - function proceed(type) { - if (type == ",") { - var lex = cx.state.lexical; - if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; - return cont(what, proceed); - } - if (type == end) return cont(); - return cont(expect(end)); - } - return function(type) { - if (type == end) return cont(); - return pass(what, proceed); - }; - } - function contCommasep(what, end, info) { - for (var i = 3; i < arguments.length; i++) - cx.cc.push(arguments[i]); - return cont(pushlex(end, info), commasep(what, end), poplex); - } - function block(type) { - if (type == "}") return cont(); - return pass(statement, block); - } - function maybetype(type) { - if (isTS && type == ":") return cont(typedef); - } - function typedef(type) { - if (type == "variable"){cx.marked = "variable-3"; return cont();} - } - function vardef() { - return pass(pattern, maybetype, maybeAssign, vardefCont); - } - function pattern(type, value) { - if (type == "variable") { register(value); return cont(); } - if (type == "[") return contCommasep(pattern, "]"); - if (type == "{") return contCommasep(proppattern, "}"); - } - function proppattern(type, value) { - if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { - register(value); - return cont(maybeAssign); - } - if (type == "variable") cx.marked = "property"; - return cont(expect(":"), pattern, maybeAssign); - } - function maybeAssign(_type, value) { - if (value == "=") return cont(expressionNoComma); - } - function vardefCont(type) { - if (type == ",") return cont(vardef); - } - function maybeelse(type, value) { - if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex); - } - function forspec(type) { - if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); - } - function forspec1(type) { - if (type == "var") return cont(vardef, expect(";"), forspec2); - if (type == ";") return cont(forspec2); - if (type == "variable") return cont(formaybeinof); - return pass(expression, expect(";"), forspec2); - } - function formaybeinof(_type, value) { - if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } - return cont(maybeoperatorComma, forspec2); - } - function forspec2(type, value) { - if (type == ";") return cont(forspec3); - if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } - return pass(expression, expect(";"), forspec3); - } - function forspec3(type) { - if (type != ")") cont(expression); - } - function functiondef(type, value) { - if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} - if (type == "variable") {register(value); return cont(functiondef);} - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext); - } - function funarg(type) { - if (type == "spread") return cont(funarg); - return pass(pattern, maybetype); - } - function className(type, value) { - if (type == "variable") {register(value); return cont(classNameAfter);} - } - function classNameAfter(type, value) { - if (value == "extends") return cont(expression, classNameAfter); - if (type == "{") return cont(pushlex("}"), classBody, poplex); - } - function classBody(type, value) { - if (type == "variable" || cx.style == "keyword") { - cx.marked = "property"; - if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody); - return cont(functiondef, classBody); - } - if (value == "*") { - cx.marked = "keyword"; - return cont(classBody); - } - if (type == ";") return cont(classBody); - if (type == "}") return cont(); - } - function classGetterSetter(type) { - if (type != "variable") return pass(); - cx.marked = "property"; - return cont(); - } - function afterModule(type, value) { - if (type == "string") return cont(statement); - if (type == "variable") { register(value); return cont(maybeFrom); } - } - function afterExport(_type, value) { - if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } - if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); } - return pass(statement); - } - function afterImport(type) { - if (type == "string") return cont(); - return pass(importSpec, maybeFrom); - } - function importSpec(type, value) { - if (type == "{") return contCommasep(importSpec, "}"); - if (type == "variable") register(value); - return cont(); - } - function maybeFrom(_type, value) { - if (value == "from") { cx.marked = "keyword"; return cont(expression); } - } - function arrayLiteral(type) { - if (type == "]") return cont(); - return pass(expressionNoComma, maybeArrayComprehension); - } - function maybeArrayComprehension(type) { - if (type == "for") return pass(comprehension, expect("]")); - if (type == ",") return cont(commasep(maybeexpressionNoComma, "]")); - return pass(commasep(expressionNoComma, "]")); - } - function comprehension(type) { - if (type == "for") return cont(forspec, comprehension); - if (type == "if") return cont(expression, comprehension); - } - - function isContinuedStatement(state, textAfter) { - return state.lastType == "operator" || state.lastType == "," || - isOperatorChar.test(textAfter.charAt(0)) || - /[,.]/.test(textAfter.charAt(0)); - } - - // Interface - - return { - startState: function(basecolumn) { - var state = { - tokenize: tokenBase, - lastType: "sof", - cc: [], - lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), - localVars: parserConfig.localVars, - context: parserConfig.localVars && {vars: parserConfig.localVars}, - indented: 0 - }; - if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") - state.globalVars = parserConfig.globalVars; - return state; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - findFatArrow(stream, state); - } - if (state.tokenize != tokenComment && stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (type == "comment") return style; - state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; - return parseJS(state, style, type, content, stream); - }, - - indent: function(state, textAfter) { - if (state.tokenize == tokenComment) return CodeMirror.Pass; - if (state.tokenize != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; - // Kludge to prevent 'maybelse' from blocking lexical scope pops - if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { - var c = state.cc[i]; - if (c == poplex) lexical = lexical.prev; - else if (c != maybeelse) break; - } - if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; - if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") - lexical = lexical.prev; - var type = lexical.type, closing = firstChar == type; - - if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); - else if (type == "form" && firstChar == "{") return lexical.indented; - else if (type == "form") return lexical.indented + indentUnit; - else if (type == "stat") - return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0); - else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false) - return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); - else if (lexical.align) return lexical.column + (closing ? 0 : 1); - else return lexical.indented + (closing ? 0 : indentUnit); - }, - - electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, - blockCommentStart: jsonMode ? null : "/*", - blockCommentEnd: jsonMode ? null : "*/", - lineComment: jsonMode ? null : "//", - fold: "brace", - - helperType: jsonMode ? "json" : "javascript", - jsonldMode: jsonldMode, - jsonMode: jsonMode - }; -}); - -CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/); - -CodeMirror.defineMIME("text/javascript", "javascript"); -CodeMirror.defineMIME("text/ecmascript", "javascript"); -CodeMirror.defineMIME("application/javascript", "javascript"); -CodeMirror.defineMIME("application/x-javascript", "javascript"); -CodeMirror.defineMIME("application/ecmascript", "javascript"); -CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); -CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); -CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true}); -CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); -CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); - -}); diff --git a/html/forums/admin/jscripts/codemirror/mode/javascript/json-ld.html b/html/forums/admin/jscripts/codemirror/mode/javascript/json-ld.html deleted file mode 100644 index 3a37f0b..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/javascript/json-ld.html +++ /dev/null @@ -1,72 +0,0 @@ - - -CodeMirror: JSON-LD mode - - - - - - - - - - - - -
-

JSON-LD mode

- - -
- - - -

This is a specialization of the JavaScript mode.

-
diff --git a/html/forums/admin/jscripts/codemirror/mode/javascript/test.js b/html/forums/admin/jscripts/codemirror/mode/javascript/test.js deleted file mode 100644 index 91b0e89..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/javascript/test.js +++ /dev/null @@ -1,200 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "javascript"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("locals", - "[keyword function] [variable foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }"); - - MT("comma-and-binop", - "[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }"); - - MT("destructuring", - "([keyword function]([def a], [[[def b], [def c] ]]) {", - " [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);", - " [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];", - "})();"); - - MT("class_body", - "[keyword class] [variable Foo] {", - " [property constructor]() {}", - " [property sayName]() {", - " [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];", - " }", - "}"); - - MT("class", - "[keyword class] [variable Point] [keyword extends] [variable SuperThing] {", - " [property get] [property prop]() { [keyword return] [number 24]; }", - " [property constructor]([def x], [def y]) {", - " [keyword super]([string 'something']);", - " [keyword this].[property x] [operator =] [variable-2 x];", - " }", - "}"); - - MT("module", - "[keyword module] [string 'foo'] {", - " [keyword export] [keyword let] [def x] [operator =] [number 42];", - " [keyword export] [keyword *] [keyword from] [string 'somewhere'];", - "}"); - - MT("import", - "[keyword function] [variable foo]() {", - " [keyword import] [def $] [keyword from] [string 'jquery'];", - " [keyword module] [def crypto] [keyword from] [string 'crypto'];", - " [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];", - "}"); - - MT("const", - "[keyword function] [variable f]() {", - " [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];", - "}"); - - MT("for/of", - "[keyword for]([keyword let] [variable of] [keyword of] [variable something]) {}"); - - MT("generator", - "[keyword function*] [variable repeat]([def n]) {", - " [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])", - " [keyword yield] [variable-2 i];", - "}"); - - MT("quotedStringAddition", - "[keyword let] [variable f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];"); - - MT("quotedFatArrow", - "[keyword let] [variable f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];"); - - MT("fatArrow", - "[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);", - "[variable a];", // No longer in scope - "[keyword let] [variable f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];", - "[variable c];"); - - MT("spread", - "[keyword function] [variable f]([def a], [meta ...][def b]) {", - " [variable something]([variable-2 a], [meta ...][variable-2 b]);", - "}"); - - MT("comprehension", - "[keyword function] [variable f]() {", - " [[([variable x] [operator +] [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];", - " ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] [operator ===] [string 'blue']));", - "}"); - - MT("quasi", - "[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]"); - - MT("quasi_no_function", - "[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]"); - - MT("indent_statement", - "[keyword var] [variable x] [operator =] [number 10]", - "[variable x] [operator +=] [variable y] [operator +]", - " [atom Infinity]", - "[keyword debugger];"); - - MT("indent_if", - "[keyword if] ([number 1])", - " [keyword break];", - "[keyword else] [keyword if] ([number 2])", - " [keyword continue];", - "[keyword else]", - " [number 10];", - "[keyword if] ([number 1]) {", - " [keyword break];", - "} [keyword else] [keyword if] ([number 2]) {", - " [keyword continue];", - "} [keyword else] {", - " [number 10];", - "}"); - - MT("indent_for", - "[keyword for] ([keyword var] [variable i] [operator =] [number 0];", - " [variable i] [operator <] [number 100];", - " [variable i][operator ++])", - " [variable doSomething]([variable i]);", - "[keyword debugger];"); - - MT("indent_c_style", - "[keyword function] [variable foo]()", - "{", - " [keyword debugger];", - "}"); - - MT("indent_else", - "[keyword for] (;;)", - " [keyword if] ([variable foo])", - " [keyword if] ([variable bar])", - " [number 1];", - " [keyword else]", - " [number 2];", - " [keyword else]", - " [number 3];"); - - MT("indent_funarg", - "[variable foo]([number 10000],", - " [keyword function]([def a]) {", - " [keyword debugger];", - "};"); - - MT("indent_below_if", - "[keyword for] (;;)", - " [keyword if] ([variable foo])", - " [number 1];", - "[number 2];"); - - MT("multilinestring", - "[keyword var] [variable x] [operator =] [string 'foo\\]", - "[string bar'];"); - - MT("scary_regexp", - "[string-2 /foo[[/]]bar/];"); - - MT("indent_strange_array", - "[keyword var] [variable x] [operator =] [[", - " [number 1],,", - " [number 2],", - "]];", - "[number 10];"); - - var jsonld_mode = CodeMirror.getMode( - {indentUnit: 2}, - {name: "javascript", jsonld: true} - ); - function LD(name) { - test.mode(name, jsonld_mode, Array.prototype.slice.call(arguments, 1)); - } - - LD("json_ld_keywords", - '{', - ' [meta "@context"]: {', - ' [meta "@base"]: [string "http://example.com"],', - ' [meta "@vocab"]: [string "http://xmlns.com/foaf/0.1/"],', - ' [property "likesFlavor"]: {', - ' [meta "@container"]: [meta "@list"]', - ' [meta "@reverse"]: [string "@beFavoriteOf"]', - ' },', - ' [property "nick"]: { [meta "@container"]: [meta "@set"] },', - ' [property "nick"]: { [meta "@container"]: [meta "@index"] }', - ' },', - ' [meta "@graph"]: [[ {', - ' [meta "@id"]: [string "http://dbpedia.org/resource/John_Lennon"],', - ' [property "name"]: [string "John Lennon"],', - ' [property "modified"]: {', - ' [meta "@value"]: [string "2010-05-29T14:17:39+02:00"],', - ' [meta "@type"]: [string "http://www.w3.org/2001/XMLSchema#dateTime"]', - ' }', - ' } ]]', - '}'); - - LD("json_ld_fake", - '{', - ' [property "@fake"]: [string "@fake"],', - ' [property "@contextual"]: [string "@identifier"],', - ' [property "user@domain.com"]: [string "@graphical"],', - ' [property "@ID"]: [string "@@ID"]', - '}'); -})(); diff --git a/html/forums/admin/jscripts/codemirror/mode/javascript/typescript.html b/html/forums/admin/jscripts/codemirror/mode/javascript/typescript.html deleted file mode 100644 index 2cfc538..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/javascript/typescript.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: TypeScript mode - - - - - - - - - -
-

TypeScript mode

- - -
- - - -

This is a specialization of the JavaScript mode.

-
diff --git a/html/forums/admin/jscripts/codemirror/mode/xml/index.html b/html/forums/admin/jscripts/codemirror/mode/xml/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/xml/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/mode/xml/test.js b/html/forums/admin/jscripts/codemirror/mode/xml/test.js deleted file mode 100644 index f48156b..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/xml/test.js +++ /dev/null @@ -1,51 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml"; - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); } - - MT("matching", - "[tag&bracket <][tag top][tag&bracket >]", - " text", - " [tag&bracket <][tag inner][tag&bracket />]", - "[tag&bracket ]"); - - MT("nonmatching", - "[tag&bracket <][tag top][tag&bracket >]", - " [tag&bracket <][tag inner][tag&bracket />]", - " [tag&bracket ]"); - - MT("doctype", - "[meta ]", - "[tag&bracket <][tag top][tag&bracket />]"); - - MT("cdata", - "[tag&bracket <][tag top][tag&bracket >]", - " [atom ]", - "[tag&bracket ]"); - - // HTML tests - mode = CodeMirror.getMode({indentUnit: 2}, "text/html"); - - MT("selfclose", - "[tag&bracket <][tag html][tag&bracket >]", - " [tag&bracket <][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \"/foobar\"][tag&bracket >]", - "[tag&bracket ]"); - - MT("list", - "[tag&bracket <][tag ol][tag&bracket >]", - " [tag&bracket <][tag li][tag&bracket >]one", - " [tag&bracket <][tag li][tag&bracket >]two", - "[tag&bracket ]"); - - MT("valueless", - "[tag&bracket <][tag input] [attribute type]=[string checkbox] [attribute checked][tag&bracket />]"); - - MT("pThenArticle", - "[tag&bracket <][tag p][tag&bracket >]", - " foo", - "[tag&bracket <][tag article][tag&bracket >]bar"); - -})(); diff --git a/html/forums/admin/jscripts/codemirror/mode/xml/xml.js b/html/forums/admin/jscripts/codemirror/mode/xml/xml.js deleted file mode 100644 index 2f3b8f8..0000000 --- a/html/forums/admin/jscripts/codemirror/mode/xml/xml.js +++ /dev/null @@ -1,384 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("xml", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1; - var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag; - if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true; - - var Kludges = parserConfig.htmlMode ? { - autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, - 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, - 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, - 'track': true, 'wbr': true, 'menuitem': true}, - implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, - 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, - 'th': true, 'tr': true}, - contextGrabbers: { - 'dd': {'dd': true, 'dt': true}, - 'dt': {'dd': true, 'dt': true}, - 'li': {'li': true}, - 'option': {'option': true, 'optgroup': true}, - 'optgroup': {'optgroup': true}, - 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, - 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, - 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, - 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, - 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, - 'rp': {'rp': true, 'rt': true}, - 'rt': {'rp': true, 'rt': true}, - 'tbody': {'tbody': true, 'tfoot': true}, - 'td': {'td': true, 'th': true}, - 'tfoot': {'tbody': true}, - 'th': {'td': true, 'th': true}, - 'thead': {'tbody': true, 'tfoot': true}, - 'tr': {'tr': true} - }, - doNotIndent: {"pre": true}, - allowUnquoted: true, - allowMissing: true, - caseFold: true - } : { - autoSelfClosers: {}, - implicitlyClosed: {}, - contextGrabbers: {}, - doNotIndent: {}, - allowUnquoted: false, - allowMissing: false, - caseFold: false - }; - var alignCDATA = parserConfig.alignCDATA; - - // Return variables for tokenizers - var type, setStyle; - - function inText(stream, state) { - function chain(parser) { - state.tokenize = parser; - return parser(stream, state); - } - - var ch = stream.next(); - if (ch == "<") { - if (stream.eat("!")) { - if (stream.eat("[")) { - if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); - else return null; - } else if (stream.match("--")) { - return chain(inBlock("comment", "-->")); - } else if (stream.match("DOCTYPE", true, true)) { - stream.eatWhile(/[\w\._\-]/); - return chain(doctype(1)); - } else { - return null; - } - } else if (stream.eat("?")) { - stream.eatWhile(/[\w\._\-]/); - state.tokenize = inBlock("meta", "?>"); - return "meta"; - } else { - type = stream.eat("/") ? "closeTag" : "openTag"; - state.tokenize = inTag; - return "tag bracket"; - } - } else if (ch == "&") { - var ok; - if (stream.eat("#")) { - if (stream.eat("x")) { - ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); - } else { - ok = stream.eatWhile(/[\d]/) && stream.eat(";"); - } - } else { - ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";"); - } - return ok ? "atom" : "error"; - } else { - stream.eatWhile(/[^&<]/); - return null; - } - } - - function inTag(stream, state) { - var ch = stream.next(); - if (ch == ">" || (ch == "/" && stream.eat(">"))) { - state.tokenize = inText; - type = ch == ">" ? "endTag" : "selfcloseTag"; - return "tag bracket"; - } else if (ch == "=") { - type = "equals"; - return null; - } else if (ch == "<") { - state.tokenize = inText; - state.state = baseState; - state.tagName = state.tagStart = null; - var next = state.tokenize(stream, state); - return next ? next + " tag error" : "tag error"; - } else if (/[\'\"]/.test(ch)) { - state.tokenize = inAttribute(ch); - state.stringStartCol = stream.column(); - return state.tokenize(stream, state); - } else { - stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/); - return "word"; - } - } - - function inAttribute(quote) { - var closure = function(stream, state) { - while (!stream.eol()) { - if (stream.next() == quote) { - state.tokenize = inTag; - break; - } - } - return "string"; - }; - closure.isInAttribute = true; - return closure; - } - - function inBlock(style, terminator) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - state.tokenize = inText; - break; - } - stream.next(); - } - return style; - }; - } - function doctype(depth) { - return function(stream, state) { - var ch; - while ((ch = stream.next()) != null) { - if (ch == "<") { - state.tokenize = doctype(depth + 1); - return state.tokenize(stream, state); - } else if (ch == ">") { - if (depth == 1) { - state.tokenize = inText; - break; - } else { - state.tokenize = doctype(depth - 1); - return state.tokenize(stream, state); - } - } - } - return "meta"; - }; - } - - function Context(state, tagName, startOfLine) { - this.prev = state.context; - this.tagName = tagName; - this.indent = state.indented; - this.startOfLine = startOfLine; - if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) - this.noIndent = true; - } - function popContext(state) { - if (state.context) state.context = state.context.prev; - } - function maybePopContext(state, nextTagName) { - var parentTagName; - while (true) { - if (!state.context) { - return; - } - parentTagName = state.context.tagName; - if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || - !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { - return; - } - popContext(state); - } - } - - function baseState(type, stream, state) { - if (type == "openTag") { - state.tagStart = stream.column(); - return tagNameState; - } else if (type == "closeTag") { - return closeTagNameState; - } else { - return baseState; - } - } - function tagNameState(type, stream, state) { - if (type == "word") { - state.tagName = stream.current(); - setStyle = "tag"; - return attrState; - } else { - setStyle = "error"; - return tagNameState; - } - } - function closeTagNameState(type, stream, state) { - if (type == "word") { - var tagName = stream.current(); - if (state.context && state.context.tagName != tagName && - Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName)) - popContext(state); - if (state.context && state.context.tagName == tagName) { - setStyle = "tag"; - return closeState; - } else { - setStyle = "tag error"; - return closeStateErr; - } - } else { - setStyle = "error"; - return closeStateErr; - } - } - - function closeState(type, _stream, state) { - if (type != "endTag") { - setStyle = "error"; - return closeState; - } - popContext(state); - return baseState; - } - function closeStateErr(type, stream, state) { - setStyle = "error"; - return closeState(type, stream, state); - } - - function attrState(type, _stream, state) { - if (type == "word") { - setStyle = "attribute"; - return attrEqState; - } else if (type == "endTag" || type == "selfcloseTag") { - var tagName = state.tagName, tagStart = state.tagStart; - state.tagName = state.tagStart = null; - if (type == "selfcloseTag" || - Kludges.autoSelfClosers.hasOwnProperty(tagName)) { - maybePopContext(state, tagName); - } else { - maybePopContext(state, tagName); - state.context = new Context(state, tagName, tagStart == state.indented); - } - return baseState; - } - setStyle = "error"; - return attrState; - } - function attrEqState(type, stream, state) { - if (type == "equals") return attrValueState; - if (!Kludges.allowMissing) setStyle = "error"; - return attrState(type, stream, state); - } - function attrValueState(type, stream, state) { - if (type == "string") return attrContinuedState; - if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;} - setStyle = "error"; - return attrState(type, stream, state); - } - function attrContinuedState(type, stream, state) { - if (type == "string") return attrContinuedState; - return attrState(type, stream, state); - } - - return { - startState: function() { - return {tokenize: inText, - state: baseState, - indented: 0, - tagName: null, tagStart: null, - context: null}; - }, - - token: function(stream, state) { - if (!state.tagName && stream.sol()) - state.indented = stream.indentation(); - - if (stream.eatSpace()) return null; - type = null; - var style = state.tokenize(stream, state); - if ((style || type) && style != "comment") { - setStyle = null; - state.state = state.state(type || style, stream, state); - if (setStyle) - style = setStyle == "error" ? style + " error" : setStyle; - } - return style; - }, - - indent: function(state, textAfter, fullLine) { - var context = state.context; - // Indent multi-line strings (e.g. css). - if (state.tokenize.isInAttribute) { - if (state.tagStart == state.indented) - return state.stringStartCol + 1; - else - return state.indented + indentUnit; - } - if (context && context.noIndent) return CodeMirror.Pass; - if (state.tokenize != inTag && state.tokenize != inText) - return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; - // Indent the starts of attribute names. - if (state.tagName) { - if (multilineTagIndentPastTag) - return state.tagStart + state.tagName.length + 2; - else - return state.tagStart + indentUnit * multilineTagIndentFactor; - } - if (alignCDATA && /$/, - blockCommentStart: "", - - configuration: parserConfig.htmlMode ? "html" : "xml", - helperType: parserConfig.htmlMode ? "html" : "xml" - }; -}); - -CodeMirror.defineMIME("text/xml", "xml"); -CodeMirror.defineMIME("application/xml", "xml"); -if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) - CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); - -}); diff --git a/html/forums/admin/jscripts/codemirror/theme/index.html b/html/forums/admin/jscripts/codemirror/theme/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/codemirror/theme/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/codemirror/theme/mybb.css b/html/forums/admin/jscripts/codemirror/theme/mybb.css deleted file mode 100644 index d3bf390..0000000 --- a/html/forums/admin/jscripts/codemirror/theme/mybb.css +++ /dev/null @@ -1,41 +0,0 @@ -.cm-s-mybb { font:13px/1.4em Trebuchet, Verdana, sans-serif; } /* - customized editor font - */ - -.cm-s-mybb.CodeMirror { background: #fafafa; color: black; height: 500px; width: 100%; max-width: 100%; } -.cm-s-mybb div.CodeMirror-selected { background: #b3c6d3 !important; } -.cm-s-mybb .CodeMirror-gutters { background: #1F4661; border-right: 7px solid #3E7087; } -.cm-s-mybb .CodeMirror-linenumber { color: white; } -.cm-s-mybb .CodeMirror-cursor { border-left: 1px solid black !important; } -.cm-s-mybb .CodeMirror-scroll { overflow-x: auto; } - -.cm-s-mybb .cm-keyword {color: #708;} -.cm-s-mybb .cm-atom {color: #219;} -.cm-s-mybb .cm-number {color: #164;} -.cm-s-mybb .cm-def {color: #00f;} -.cm-s-mybb .cm-variable {color: black;} -.cm-s-mybb .cm-variable-2 {color: #05a;} -.cm-s-mybb .cm-variable-3 {color: #085;} -.cm-s-mybb .cm-property {color: black;} -.cm-s-mybb .cm-operator {color: black;} -.cm-s-mybb .cm-comment {color: #a50;} -.cm-s-mybb .cm-string {color: #a11;} -.cm-s-mybb .cm-string-2 {color: #f50;} -.cm-s-mybb .cm-meta {color: #555;} -.cm-s-mybb .cm-error {color: #f00;} -.cm-s-mybb .cm-qualifier {color: #555;} -.cm-s-mybb .cm-builtin {color: #30a;} -.cm-s-mybb .cm-bracket {color: #997;} -.cm-s-mybb .cm-tag {color: #170;} -.cm-s-mybb .cm-attribute {color: #00c;} -.cm-s-mybb .cm-header {color: blue;} -.cm-s-mybb .cm-quote {color: #090;} -.cm-s-mybb .cm-hr {color: #999;} -.cm-s-mybb .cm-link {color: #00c;} - -.cm-negative {color: #d44;} -.cm-positive {color: #292;} -.cm-header, .cm-strong {font-weight: bold;} -.cm-em {font-style: italic;} -.cm-emstrong {font-style: italic; font-weight: bold;} -.cm-link {text-decoration: underline;} - -.cm-invalidchar {color: #f00;} \ No newline at end of file diff --git a/html/forums/admin/jscripts/index.html b/html/forums/admin/jscripts/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/jscripts/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/animated-overlay.gif b/html/forums/admin/jscripts/jqueryui/css/redmond/images/animated-overlay.gif deleted file mode 100644 index d441f75..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/animated-overlay.gif and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png deleted file mode 100644 index a2e6bfc..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png deleted file mode 100644 index f732551..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png deleted file mode 100644 index 423d44a..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png deleted file mode 100644 index b7879f5..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png deleted file mode 100644 index 7fb8918..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png deleted file mode 100644 index 66f0b82..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png deleted file mode 100644 index fd8794d..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png deleted file mode 100644 index a9ad56b..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_217bc0_256x240.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_217bc0_256x240.png deleted file mode 100644 index 9276f55..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_217bc0_256x240.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_2e83ff_256x240.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_2e83ff_256x240.png deleted file mode 100644 index 08957e9..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_2e83ff_256x240.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_469bdd_256x240.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_469bdd_256x240.png deleted file mode 100644 index 5a36105..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_469bdd_256x240.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_6da8d5_256x240.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_6da8d5_256x240.png deleted file mode 100644 index 36494ad..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_6da8d5_256x240.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_cd0a0a_256x240.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_cd0a0a_256x240.png deleted file mode 100644 index ee9dfec..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_cd0a0a_256x240.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_d8e7f3_256x240.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_d8e7f3_256x240.png deleted file mode 100644 index 31c55fb..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_d8e7f3_256x240.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_f9bd01_256x240.png b/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_f9bd01_256x240.png deleted file mode 100644 index a71ec49..0000000 Binary files a/html/forums/admin/jscripts/jqueryui/css/redmond/images/ui-icons_f9bd01_256x240.png and /dev/null differ diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/jquery-ui.min.css b/html/forums/admin/jscripts/jqueryui/css/redmond/jquery-ui.min.css deleted file mode 100644 index 77d558c..0000000 --- a/html/forums/admin/jscripts/jqueryui/css/redmond/jquery-ui.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! jQuery UI - v1.11.2 - 2015-01-29 -* http://jqueryui.com -* Includes: core.css, draggable.css, sortable.css, theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=gloss_wave&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=inset_hard&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=glass&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=inset_hard&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=flat&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ - -.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-widget{font-family:Lucida Grande,Lucida Sans,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Lucida Grande,Lucida Sans,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #a6c9e2;background:#fcfdfd url("images/ui-bg_inset-hard_100_fcfdfd_1x100.png") 50% bottom repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #4297d7;background:#5c9ccc url("images/ui-bg_gloss-wave_55_5c9ccc_500x100.png") 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #c5dbec;background:#dfeffc url("images/ui-bg_glass_85_dfeffc_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#2e6e9e}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#2e6e9e;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #79b7e7;background:#d0e5f5 url("images/ui-bg_glass_75_d0e5f5_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#1d5987}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#1d5987;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #79b7e7;background:#f5f8f9 url("images/ui-bg_inset-hard_100_f5f8f9_1x100.png") 50% 50% repeat-x;font-weight:bold;color:#e17009}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#e17009;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fad42e;background:#fbec88 url("images/ui-bg_flat_55_fbec88_40x100.png") 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_469bdd_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_d8e7f3_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_6da8d5_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_217bc0_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_f9bd01_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:5px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:5px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:5px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:5px}.ui-widget-overlay{background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px} \ No newline at end of file diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/jquery-ui.structure.min.css b/html/forums/admin/jscripts/jqueryui/css/redmond/jquery-ui.structure.min.css deleted file mode 100644 index 3916325..0000000 --- a/html/forums/admin/jscripts/jqueryui/css/redmond/jquery-ui.structure.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery UI - v1.11.2 - 2015-01-29 -* http://jqueryui.com -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ - -.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-sortable-handle{-ms-touch-action:none;touch-action:none} \ No newline at end of file diff --git a/html/forums/admin/jscripts/jqueryui/css/redmond/jquery-ui.theme.min.css b/html/forums/admin/jscripts/jqueryui/css/redmond/jquery-ui.theme.min.css deleted file mode 100644 index 22d3906..0000000 --- a/html/forums/admin/jscripts/jqueryui/css/redmond/jquery-ui.theme.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery UI - v1.11.2 - 2015-01-29 -* http://jqueryui.com -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ - -.ui-widget{font-family:Lucida Grande,Lucida Sans,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Lucida Grande,Lucida Sans,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #a6c9e2;background:#fcfdfd url("images/ui-bg_inset-hard_100_fcfdfd_1x100.png") 50% bottom repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #4297d7;background:#5c9ccc url("images/ui-bg_gloss-wave_55_5c9ccc_500x100.png") 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #c5dbec;background:#dfeffc url("images/ui-bg_glass_85_dfeffc_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#2e6e9e}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#2e6e9e;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #79b7e7;background:#d0e5f5 url("images/ui-bg_glass_75_d0e5f5_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#1d5987}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#1d5987;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #79b7e7;background:#f5f8f9 url("images/ui-bg_inset-hard_100_f5f8f9_1x100.png") 50% 50% repeat-x;font-weight:bold;color:#e17009}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#e17009;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fad42e;background:#fbec88 url("images/ui-bg_flat_55_fbec88_40x100.png") 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_469bdd_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_d8e7f3_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_6da8d5_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_217bc0_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_f9bd01_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:5px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:5px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:5px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:5px}.ui-widget-overlay{background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px} \ No newline at end of file diff --git a/html/forums/admin/jscripts/jqueryui/js/jquery-ui.min.js b/html/forums/admin/jscripts/jqueryui/js/jquery-ui.min.js deleted file mode 100644 index 3b86294..0000000 --- a/html/forums/admin/jscripts/jqueryui/js/jquery-ui.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! jQuery UI - v1.11.2 - 2015-01-29 -* http://jqueryui.com -* Includes: core.js, widget.js, mouse.js, draggable.js, droppable.js, sortable.js -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ - -(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,s){var a,n,o,r=t.nodeName.toLowerCase();return"area"===r?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(o=e("img[usemap='#"+n+"']")[0],!!o&&i(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||s:s)&&i(t)}function i(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}e.ui=e.ui||{},e.extend(e.ui,{version:"1.11.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(t){var i=this.css("position"),s="absolute"===i,a=t?/(auto|scroll|hidden)/:/(auto|scroll)/,n=this.parents().filter(function(){var t=e(this);return s&&"static"===t.css("position")?!1:a.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==i&&n.length?n:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(i){return t(i,!isNaN(e.attr(i,"tabindex")))},tabbable:function(i){var s=e.attr(i,"tabindex"),a=isNaN(s);return(a||s>=0)&&t(i,!a)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(t,i){function s(t,i,s,n){return e.each(a,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),n&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var a="Width"===i?["Left","Right"]:["Top","Bottom"],n=i.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+i]=function(t){return void 0===t?o["inner"+i].call(this):this.each(function(){e(this).css(n,s(this,t)+"px")})},e.fn["outer"+i]=function(t,a){return"number"!=typeof t?o["outer"+i].call(this,t):this.each(function(){e(this).css(n,s(this,t,!0,a)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(void 0!==t)return this.css("zIndex",t);if(this.length)for(var i,s,a=e(this[0]);a.length&&a[0]!==document;){if(i=a.css("position"),("absolute"===i||"relative"===i||"fixed"===i)&&(s=parseInt(a.css("zIndex"),10),!isNaN(s)&&0!==s))return s;a=a.parent()}return 0}}),e.ui.plugin={add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i,s){var a,n=e.plugins[t];if(n&&(s||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(a=0;n.length>a;a++)e.options[n[a][0]]&&n[a][1].apply(e.element,i)}};var s=0,a=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,a,n;for(n=0;null!=(a=i[n]);n++)try{s=e._data(a,"events"),s&&s.remove&&e(a).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var a,n,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],a=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[l]=e[l]||{},n=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,n,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},a=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,n=this._superApply;return this._super=e,this._superApply=a,t=s.apply(this,arguments),this._super=i,this._superApply=n,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:n?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:a}),n?(e.each(n._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var i,s,n=a.call(arguments,1),o=0,r=n.length;r>o;o++)for(i in n[o])s=n[o][i],n[o].hasOwnProperty(i)&&void 0!==s&&(t[i]=e.isPlainObject(s)?e.isPlainObject(t[i])?e.widget.extend({},t[i],s):e.widget.extend({},s):s);return t},e.widget.bridge=function(t,i){var s=i.prototype.widgetFullName||t;e.fn[t]=function(n){var o="string"==typeof n,r=a.call(arguments,1),h=this;return n=!o&&r.length?e.widget.extend.apply(null,[n].concat(r)):n,o?this.each(function(){var i,a=e.data(this,s);return"instance"===n?(h=a,!1):a?e.isFunction(a[n])&&"_"!==n.charAt(0)?(i=a[n].apply(a,r),i!==a&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+n+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+n+"'")}):this.each(function(){var t=e.data(this,s);t?(t.option(n||{}),t._init&&t._init()):e.data(this,s,new i(n,this))}),h}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(t,i){i=e(i||this.defaultElement||this)[0],this.element=e(i),this.uuid=s++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),i!==this&&(e.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===i&&this.destroy()}}),this.document=e(i.style?i.ownerDocument:i.document||i),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,a,n,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(a=o[t]=e.widget.extend({},this.options[t]),n=0;s.length-1>n;n++)a[s[n]]=a[s[n]]||{},a=a[s[n]];if(t=s.pop(),1===arguments.length)return void 0===a[t]?null:a[t];a[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var a,n=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=a=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,a=this.widget()),e.each(s,function(s,o){function r(){return t||n.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?n[o]:o).apply(n,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+n.eventNamespace,u=h[2];u?a.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var a,n,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],n=i.originalEvent)for(a in n)a in i||(i[a]=n[a]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,a,n){"string"==typeof a&&(a={effect:a});var o,r=a?a===!0||"number"==typeof a?i:a.effect||i:t;a=a||{},"number"==typeof a&&(a={duration:a}),o=!e.isEmptyObject(a),a.complete=n,a.delay&&s.delay(a.delay),o&&e.effects&&e.effects.effect[r]?s[t](a):r!==t&&s[r]?s[r](a.duration,a.easing,n):s.queue(function(i){e(this)[t](),n&&n.call(s[0]),i()})}}),e.widget;var n=!1;e(document).mouseup(function(){n=!1}),e.widget("ui.mouse",{version:"1.11.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!n){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var i=this,s=1===t.which,a="string"==typeof this.options.cancel&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;return s&&!a&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(t)!==!1,!this._mouseStarted)?(t.preventDefault(),!0):(!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return i._mouseMove(e)},this._mouseUpDelegate=function(e){return i._mouseUp(e)},this.document.bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),n=!0,!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button)return this._mouseUp(t);if(!t.which)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),n=!1,!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),e.widget("ui.draggable",e.ui.mouse,{version:"1.11.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._setHandleClassName(),this._mouseInit()},_setOption:function(e,t){this._super(e,t),"handle"===e&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(t){var i=this.options;return this._blurActiveElement(t),this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(t){this.iframeBlocks=this.document.find(t).map(function(){var t=e(this);return e("
").css("position","absolute").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var i=this.document[0];if(this.handleElement.is(t.target))try{i.activeElement&&"body"!==i.activeElement.nodeName.toLowerCase()&&e(i.activeElement).blur()}catch(s){}},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===e(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(t),this.originalPosition=this.position=this._generatePosition(t,!1),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._normalizeRightBottom(),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_refreshOffsets:function(e){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:e.pageX-this.offset.left,top:e.pageY-this.offset.top}},_mouseDrag:function(t,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1},_mouseUp:function(t){return this._unblockFrames(),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),this.handleElement.is(t.target)&&this.element.focus(),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this.handleElement.addClass("ui-draggable-handle")},_removeHandleClassName:function(){this.handleElement.removeClass("ui-draggable-handle")},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper),a=s?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return a.parents("body").length||a.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&a[0]===this.element[0]&&this._setPositionRelative(),a[0]===this.element[0]||/(fixed|absolute)/.test(a.css("position"))||a.css("position","absolute"),a},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_isRootNode:function(e){return/(html|body)/i.test(e.tagName)||e===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var e=this.element.position(),t=this._isRootNode(this.scrollParent[0]);return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+(t?0:this.scrollParent.scrollTop()),left:e.left-(parseInt(this.helper.css("left"),10)||0)+(t?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,a=this.options,n=this.document[0];return this.relativeContainer=null,a.containment?"window"===a.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||n.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===a.containment?(this.containment=[0,0,e(n).width()-this.helperProportions.width-this.margins.left,(e(n).height()||n.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):a.containment.constructor===Array?(this.containment=a.containment,void 0):("parent"===a.containment&&(a.containment=this.helper[0].parentNode),i=e(a.containment),s=i[0],s&&(t=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)},_convertPositionTo:function(e,t){t||(t=this.position);var i="absolute"===e?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:t.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:t.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(e,t){var i,s,a,n,o=this.options,r=this._isRootNode(this.scrollParent[0]),h=e.pageX,l=e.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),t&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.lefti[2]&&(h=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(a=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?a-this.offset.click.top>=i[1]||a-this.offset.click.top>i[3]?a:a-this.offset.click.top>=i[1]?a-o.grid[1]:a+o.grid[1]:a,n=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?n-this.offset.click.left>=i[0]||n-this.offset.click.left>i[2]?n:n-this.offset.click.left>=i[0]?n-o.grid[0]:n+o.grid[0]:n),"y"===o.axis&&(h=this.originalPageX),"x"===o.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_normalizeRightBottom:function(){"y"!==this.options.axis&&"auto"!==this.helper.css("right")&&(this.helper.width(this.helper.width()),this.helper.css("right","auto")),"x"!==this.options.axis&&"auto"!==this.helper.css("bottom")&&(this.helper.height(this.helper.height()),this.helper.css("bottom","auto"))},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i,s){var a=e.extend({},i,{item:s.element});s.sortables=[],e(s.options.connectToSortable).each(function(){var i=e(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",t,a))})},stop:function(t,i,s){var a=e.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,e.each(s.sortables,function(){var e=this;e.isOver?(e.isOver=0,s.cancelHelperRemoval=!0,e.cancelHelperRemoval=!1,e._storedCSS={position:e.placeholder.css("position"),top:e.placeholder.css("top"),left:e.placeholder.css("left")},e._mouseStop(t),e.options.helper=e.options._helper):(e.cancelHelperRemoval=!0,e._trigger("deactivate",t,a))})},drag:function(t,i,s){e.each(s.sortables,function(){var a=!1,n=this;n.positionAbs=s.positionAbs,n.helperProportions=s.helperProportions,n.offset.click=s.offset.click,n._intersectsWith(n.containerCache)&&(a=!0,e.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==n&&this._intersectsWith(this.containerCache)&&e.contains(n.element[0],this.element[0])&&(a=!1),a})),a?(n.isOver||(n.isOver=1,n.currentItem=i.helper.appendTo(n.element).data("ui-sortable-item",!0),n.options._helper=n.options.helper,n.options.helper=function(){return i.helper[0]},t.target=n.currentItem[0],n._mouseCapture(t,!0),n._mouseStart(t,!0,!0),n.offset.click.top=s.offset.click.top,n.offset.click.left=s.offset.click.left,n.offset.parent.left-=s.offset.parent.left-n.offset.parent.left,n.offset.parent.top-=s.offset.parent.top-n.offset.parent.top,s._trigger("toSortable",t),s.dropped=n.element,e.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,n.fromOutside=s),n.currentItem&&(n._mouseDrag(t),i.position=n.position)):n.isOver&&(n.isOver=0,n.cancelHelperRemoval=!0,n.options._revert=n.options.revert,n.options.revert=!1,n._trigger("out",t,n._uiHash(n)),n._mouseStop(t,!0),n.options.revert=n.options._revert,n.options.helper=n.options._helper,n.placeholder&&n.placeholder.remove(),s._refreshOffsets(t),i.position=s._generatePosition(t,!0),s._trigger("fromSortable",t),s.dropped=!1,e.each(s.sortables,function(){this.refreshPositions()}))})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,i,s){var a=e("body"),n=s.options;a.css("cursor")&&(n._cursor=a.css("cursor")),a.css("cursor",n.cursor)},stop:function(t,i,s){var a=s.options;a._cursor&&e("body").css("cursor",a._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i,s){var a=e(i.helper),n=s.options;a.css("opacity")&&(n._opacity=a.css("opacity")),a.css("opacity",n.opacity)},stop:function(t,i,s){var a=s.options;a._opacity&&e(i.helper).css("opacity",a._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(e,t,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,i,s){var a=s.options,n=!1,o=s.scrollParentNotHidden[0],r=s.document[0];o!==r&&"HTML"!==o.tagName?(a.axis&&"x"===a.axis||(s.overflowOffset.top+o.offsetHeight-t.pageY=0;c--)h=s.snapElements[c].left-s.margins.left,l=h+s.snapElements[c].width,u=s.snapElements[c].top-s.margins.top,d=u+s.snapElements[c].height,h-m>v||g>l+m||u-m>b||y>d+m||!e.contains(s.snapElements[c].item.ownerDocument,s.snapElements[c].item)?(s.snapElements[c].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(a=m>=Math.abs(u-b),n=m>=Math.abs(d-y),o=m>=Math.abs(h-v),r=m>=Math.abs(l-g),a&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),n&&(i.position.top=s._convertPositionTo("relative",{top:d,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left)),p=a||n||o||r,"outer"!==f.snapMode&&(a=m>=Math.abs(u-y),n=m>=Math.abs(d-b),o=m>=Math.abs(h-g),r=m>=Math.abs(l-v),a&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),n&&(i.position.top=s._convertPositionTo("relative",{top:d-s.helperProportions.height,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[c].snapping&&(a||n||o||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=a||n||o||r||p)}}),e.ui.plugin.add("draggable","stack",{start:function(t,i,s){var a,n=s.options,o=e.makeArray(e(n.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});o.length&&(a=parseInt(e(o[0]).css("zIndex"),10)||0,e(o).each(function(t){e(this).css("zIndex",a+t)}),this.css("zIndex",a+o.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i,s){var a=e(i.helper),n=s.options;a.css("zIndex")&&(n._zIndex=a.css("zIndex")),a.css("zIndex",n.zIndex)},stop:function(t,i,s){var a=s.options;a._zIndex&&e(i.helper).css("zIndex",a._zIndex)}}),e.ui.draggable,e.widget("ui.droppable",{version:"1.11.2",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(s)?s:function(e){return e.is(s) -},this.proportions=function(){return arguments.length?(t=arguments[0],void 0):t?t:t={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(i.scope),i.addClasses&&this.element.addClass("ui-droppable")},_addToManager:function(t){e.ui.ddmanager.droppables[t]=e.ui.ddmanager.droppables[t]||[],e.ui.ddmanager.droppables[t].push(this)},_splice:function(e){for(var t=0;e.length>t;t++)e[t]===this&&e.splice(t,1)},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];this._splice(t),this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,i){if("accept"===t)this.accept=e.isFunction(i)?i:function(e){return e.is(i)};else if("scope"===t){var s=e.ui.ddmanager.droppables[this.options.scope];this._splice(s),this._addToManager(i)}this._super(t,i)},_activate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",t,this.ui(i))},_deactivate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",t,this.ui(i))},_over:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(i)))},_out:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(i)))},_drop:function(t,i){var s=i||e.ui.ddmanager.current,a=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var i=e(this).droppable("instance");return i.options.greedy&&!i.options.disabled&&i.options.scope===s.options.scope&&i.accept.call(i.element[0],s.currentItem||s.element)&&e.ui.intersect(s,e.extend(i,{offset:i.element.offset()}),i.options.tolerance,t)?(a=!0,!1):void 0}),a?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(s)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(){function e(e,t,i){return e>=t&&t+i>e}return function(t,i,s,a){if(!i.offset)return!1;var n=(t.positionAbs||t.position.absolute).left+t.margins.left,o=(t.positionAbs||t.position.absolute).top+t.margins.top,r=n+t.helperProportions.width,h=o+t.helperProportions.height,l=i.offset.left,u=i.offset.top,d=l+i.proportions().width,c=u+i.proportions().height;switch(s){case"fit":return n>=l&&d>=r&&o>=u&&c>=h;case"intersect":return n+t.helperProportions.width/2>l&&d>r-t.helperProportions.width/2&&o+t.helperProportions.height/2>u&&c>h-t.helperProportions.height/2;case"pointer":return e(a.pageY,u,i.proportions().height)&&e(a.pageX,l,i.proportions().width);case"touch":return(o>=u&&c>=o||h>=u&&c>=h||u>o&&h>c)&&(n>=l&&d>=n||r>=l&&d>=r||l>n&&r>d);default:return!1}}}(),e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,i){var s,a,n=e.ui.ddmanager.droppables[t.options.scope]||[],o=i?i.type:null,r=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(s=0;n.length>s;s++)if(!(n[s].options.disabled||t&&!n[s].accept.call(n[s].element[0],t.currentItem||t.element))){for(a=0;r.length>a;a++)if(r[a]===n[s].element[0]){n[s].proportions().height=0;continue e}n[s].visible="none"!==n[s].element.css("display"),n[s].visible&&("mousedown"===o&&n[s]._activate.call(n[s],i),n[s].offset=n[s].element.offset(),n[s].proportions({width:n[s].element[0].offsetWidth,height:n[s].element[0].offsetHeight}))}},drop:function(t,i){var s=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance,i)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(t,i){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)})},drag:function(t,i){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,i),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,a,n,o=e.ui.intersect(t,this,this.options.tolerance,i),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(a=this.options.scope,n=this.element.parents(":data(ui-droppable)").filter(function(){return e(this).droppable("instance").options.scope===a}),n.length&&(s=e(n[0]).droppable("instance"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(t,i){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)}},e.ui.droppable,e.widget("ui.sortable",e.ui.mouse,{version:"1.11.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(e,t,i){return e>=t&&t+i>e},_isFloating:function(e){return/left|right/.test(e.css("float"))||/inline|table-cell/.test(e.css("display"))},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===e.axis||this._isFloating(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(e,t){this._super(e,t),"handle"===e&&this._setHandleClassName()},_setHandleClassName:function(){this.element.find(".ui-sortable-handle").removeClass("ui-sortable-handle"),e.each(this.items,function(){(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item).addClass("ui-sortable-handle")})},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").find(".ui-sortable-handle").removeClass("ui-sortable-handle"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_mouseCapture:function(t,i){var s=null,a=!1,n=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(t),e(t.target).parents().each(function(){return e.data(this,n.widgetName+"-item")===n?(s=e(this),!1):void 0}),e.data(t.target,n.widgetName+"-item")===n&&(s=e(t.target)),s?!this.options.handle||i||(e(this.options.handle,s).find("*").addBack().each(function(){this===t.target&&(a=!0)}),a)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(t,i,s){var a,n,o=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,o.cursorAt&&this._adjustOffsetFromHelper(o.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),o.containment&&this._setContainment(),o.cursor&&"auto"!==o.cursor&&(n=this.document.find("body"),this.storedCursor=n.css("cursor"),n.css("cursor",o.cursor),this.storedStylesheet=e("").appendTo(n)),o.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",o.opacity)),o.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",o.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(a=this.containers.length-1;a>=0;a--)this.containers[a]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!o.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){var i,s,a,n,o=this.options,r=!1;for(this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY=0;i--)if(s=this.items[i],a=s.item[0],n=this._intersectsWithPointer(s),n&&s.instance===this.currentContainer&&a!==this.currentItem[0]&&this.placeholder[1===n?"next":"prev"]()[0]!==a&&!e.contains(this.placeholder[0],a)&&("semi-dynamic"===this.options.type?!e.contains(this.element[0],a):!0)){if(this.direction=1===n?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,i){if(t){if(e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t),this.options.revert){var s=this,a=this.placeholder.offset(),n=this.options.axis,o={};n&&"x"!==n||(o.left=a.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),n&&"y"!==n||(o.top=a.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,e(this.helper).animate(o,parseInt(this.options.revert,10)||500,function(){s._clear(t)})}else this._clear(t,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},e(i).each(function(){var i=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[\-=_](.+)/);i&&s.push((t.key||i[1]+"[]")+"="+(t.key&&t.expression?i[1]:i[2]))}),!s.length&&t.key&&s.push(t.key+"="),s.join("&")},toArray:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},i.each(function(){s.push(e(t.item||this).attr(t.attribute||"id")||"")}),s},_intersectsWith:function(e){var t=this.positionAbs.left,i=t+this.helperProportions.width,s=this.positionAbs.top,a=s+this.helperProportions.height,n=e.left,o=n+e.width,r=e.top,h=r+e.height,l=this.offset.click.top,u=this.offset.click.left,d="x"===this.options.axis||s+l>r&&h>s+l,c="y"===this.options.axis||t+u>n&&o>t+u,p=d&&c;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?p:t+this.helperProportions.width/2>n&&o>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>a-this.helperProportions.height/2},_intersectsWithPointer:function(e){var t="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,e.top,e.height),i="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,e.left,e.width),s=t&&i,a=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return s?this.floating?n&&"right"===n||"down"===a?2:1:a&&("down"===a?2:1):!1},_intersectsWithSides:function(e){var t=this._isOverAxis(this.positionAbs.top+this.offset.click.top,e.top+e.height/2,e.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,e.left+e.width/2,e.width),s=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return this.floating&&a?"right"===a&&i||"left"===a&&!i:s&&("down"===s&&t||"up"===s&&!t)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return 0!==e&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return 0!==e&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor===String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){function i(){r.push(this)}var s,a,n,o,r=[],h=[],l=this._connectWith();if(l&&t)for(s=l.length-1;s>=0;s--)for(n=e(l[s]),a=n.length-1;a>=0;a--)o=e.data(n[a],this.widgetFullName),o&&o!==this&&!o.options.disabled&&h.push([e.isFunction(o.options.items)?o.options.items.call(o.element):e(o.options.items,o.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),o]);for(h.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=h.length-1;s>=0;s--)h[s][0].each(i);return e(r)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var i=0;t.length>i;i++)if(t[i]===e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var i,s,a,n,o,r,h,l,u=this.items,d=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],c=this._connectWith();if(c&&this.ready)for(i=c.length-1;i>=0;i--)for(a=e(c[i]),s=a.length-1;s>=0;s--)n=e.data(a[s],this.widgetFullName),n&&n!==this&&!n.options.disabled&&(d.push([e.isFunction(n.options.items)?n.options.items.call(n.element[0],t,{item:this.currentItem}):e(n.options.items,n.element),n]),this.containers.push(n));for(i=d.length-1;i>=0;i--)for(o=d[i][1],r=d[i][0],s=0,l=r.length;l>s;s++)h=e(r[s]),h.data(this.widgetName+"-item",o),u.push({item:h,instance:o,width:0,height:0,left:0,top:0})},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,a,n;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(a=this.options.toleranceElement?e(this.options.toleranceElement,s.item):s.item,t||(s.width=a.outerWidth(),s.height=a.outerHeight()),n=a.offset(),s.left=n.left,s.top=n.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)n=this.containers[i].element.offset(),this.containers[i].containerCache.left=n.left,this.containers[i].containerCache.top=n.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(t){t=t||this;var i,s=t.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=t.currentItem[0].nodeName.toLowerCase(),a=e("<"+s+">",t.document[0]).addClass(i||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?t.currentItem.children().each(function(){e(" ",t.document[0]).attr("colspan",e(this).attr("colspan")||1).appendTo(a)}):"img"===s&&a.attr("src",t.currentItem.attr("src")),i||a.css("visibility","hidden"),a},update:function(e,a){(!i||s.forcePlaceholderSize)&&(a.height()||a.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),a.width()||a.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10)))}}),t.placeholder=e(s.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),s.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var i,s,a,n,o,r,h,l,u,d,c=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!e.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(c&&e.contains(this.containers[i].element[0],c.element[0]))continue;c=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0);if(c)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",t,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(a=1e4,n=null,u=c.floating||this._isFloating(this.currentItem),o=u?"left":"top",r=u?"width":"height",d=u?"clientX":"clientY",s=this.items.length-1;s>=0;s--)e.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(h=this.items[s].item.offset()[o],l=!1,t[d]-h>this.items[s][r]/2&&(l=!0),a>Math.abs(t[d]-h)&&(a=Math.abs(t[d]-h),n=this.items[s],this.direction=l?"up":"down"));if(!n&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",t,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;n?this._rearrange(t,n,null,!0):this._rearrange(t,null,this.containers[p].element,!0),this._trigger("change",t,this._uiHash()),this.containers[p]._trigger("change",t,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",t,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||e("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,a=this.options;"parent"===a.containment&&(a.containment=this.helper[0].parentNode),("document"===a.containment||"window"===a.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e("document"===a.containment?document:window).width()-this.helperProportions.width-this.margins.left,(e("document"===a.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(a.containment)||(t=e(a.containment)[0],i=e(a.containment).offset(),s="hidden"!==e(t).css("overflow"),this.containment=[i.left+(parseInt(e(t).css("borderLeftWidth"),10)||0)+(parseInt(e(t).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(e(t).css("borderTopWidth"),10)||0)+(parseInt(e(t).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(t.scrollWidth,t.offsetWidth):t.offsetWidth)-(parseInt(e(t).css("borderLeftWidth"),10)||0)-(parseInt(e(t).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(t.scrollHeight,t.offsetHeight):t.offsetHeight)-(parseInt(e(t).css("borderTopWidth"),10)||0)-(parseInt(e(t).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(t,i){i||(i=this.position);var s="absolute"===t?1:-1,a="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,n=/(html|body)/i.test(a[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():n?0:a.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():n?0:a.scrollLeft())*s}},_generatePosition:function(t){var i,s,a=this.options,n=t.pageX,o=t.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(t.pageX-this.offset.click.leftthis.containment[2]&&(n=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),a.grid&&(i=this.originalPageY+Math.round((o-this.originalPageY)/a.grid[1])*a.grid[1],o=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-a.grid[1]:i+a.grid[1]:i,s=this.originalPageX+Math.round((n-this.originalPageX)/a.grid[0])*a.grid[0],n=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-a.grid[0]:s+a.grid[0]:s)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:n-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(e,t,i,s){i?i[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var a=this.counter;this._delay(function(){a===this.counter&&this.refreshPositions(!s)})},_clear:function(e,t){function i(e,t,i){return function(s){i._trigger(e,s,t._uiHash(t))}}this.reverting=!1;var s,a=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!t&&a.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||t||a.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(t||(a.push(function(e){this._trigger("remove",e,this._uiHash())}),a.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),a.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)t||a.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(a.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,t||this._trigger("beforeStop",e,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!t){for(s=0;a.length>s;s++)a[s].call(this,e);this._trigger("stop",e,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var i=t||this;return{helper:i.helper,placeholder:i.placeholder||e([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:t?t.element:null}}})}); \ No newline at end of file diff --git a/html/forums/admin/jscripts/mycode_sandbox.js b/html/forums/admin/jscripts/mycode_sandbox.js deleted file mode 100644 index 775a949..0000000 --- a/html/forums/admin/jscripts/mycode_sandbox.js +++ /dev/null @@ -1,57 +0,0 @@ -function MyCodeSandbox(url, button, regex_textbox, replacement_textbox, test_textbox, html_textbox, actual_div) -{ - if(button && regex_textbox && replacement_textbox && test_textbox && html_textbox && actual_div) - { - this.url = url; - this.button = button; - this.regex_textbox = regex_textbox; - this.replacement_textbox = replacement_textbox; - this.test_textbox = test_textbox; - this.html_textbox = html_textbox; - this.actual_div = actual_div; - - $(button).on('click', function(e) { - e.preventDefault(); - this.update(); - }.bind(this)); - } -} - -MyCodeSandbox.prototype.update = function(e) -{ - postData = "regex="+encodeURIComponent($(this.regex_textbox).val())+"&replacement="+encodeURIComponent($(this.replacement_textbox).val())+"&test_value="+encodeURIComponent($(this.test_textbox).val())+"&my_post_key="+encodeURIComponent(my_post_key); - - $.ajax( - { - url: this.url, - async: true, - method: 'post', - data: postData, - complete: function (request) - { - this.onComplete(request); - }.bind(this) - }); -}; - -MyCodeSandbox.prototype.onComplete = function(request) -{ - if(request.responseText.match(/(.*)<\/error>/)) - { - message = request.responseText.match(/(.*)<\/error>/); - - if(!message[1]) - { - message[1] = lang.unknown_error; - } - - alert(lang.mycode_sandbox_test_error + '\n\n' + message[1]); - } - else if(request.responseText) - { - $(this.actual_div).html(request.responseText); - $(this.html_textbox).val(request.responseText); - } - - return true; -}; \ No newline at end of file diff --git a/html/forums/admin/jscripts/peeker.js b/html/forums/admin/jscripts/peeker.js deleted file mode 100644 index 6992d77..0000000 --- a/html/forums/admin/jscripts/peeker.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Peeker controls the visibility of an element based on the value of an input - * - * Examples: - * new Peeker($('#myController'), $('#myDomain'), 1, false); - * new Peeker($('.myControllerNode'), $('#myDomain, #myDomain2'), 1, true); - * new Peeker($('#myController'), $('#nestedPeeker'), /works/, false); - * new Peeker($('#nestedPeeker'), $('#nestedPeekerChild'), /\d+/, false); - */ - -var Peeker = (function() { - /** - * Constructor - * - * @param string ID of the controlling select menu - * @param string ID of the thing to show/hide - * @param regexp If this regexp matches value of the select menu, then the 'thing' will be shown - * @param boolean Should be set to true for radio/checkboxes - */ - function Peeker(controller, domain, match, isNodelist) { - var fn; - - // verify input - if (!controller || - (isNodelist && controller.length <= 0) || - !domain) { - return; - } - this.controller = controller; - this.domain = domain; - this.match = match; - this.isNodelist = isNodelist; - - // create a context-bound copy of the function - fn = $.proxy(this.check, this); - - if (isNodelist) { - // attach event handlers to the inputs in the node list - this.controller.each(function(i, el) { - el = $(el); - el.on('change', fn); - el.click(fn); - }); - } else { - this.controller.on('change', fn); - } - this.check(); - } - - /** - * Checks the controller and shows/hide - * - * @return void - */ - function check() { - var type = '', show = false, regex = this.match; - - if (this.isNodelist) { - this.controller.each(function(i, el) { - if ($(el).is(':visible') && el.checked && - el.value.match(regex)) { - show = true; - return false; - } - }); - this.domain[show ? 'show' : 'hide'](); - } else { - type = this.controller.val() || ''; - this.domain[(type.match(regex) && this.controller.is(':visible')) ? 'show' : 'hide'](); - } - - $(this.domain).each(function() { - $(this).find('input, textarea, select').each(function() { - $(this).trigger('change'); - }); - }); - } - - Peeker.prototype = { - controller: null, - domain: null, - match: null, - isNodelist: null, - check: check, - }; - - return Peeker; -})(); - -/** - * Add a "required" asterisk to a FormContainer row - * @param string ID of the row - */ -function add_star(id) { - if (!$('#' + id).length) { - return; - } - - cell = $('#' + id).children('td')[0]; - label = $(cell).children('label')[0]; - star = $(document.createElement('em')); - starText = $(document.createTextNode(' *')); - star.append(starText); - $(label).append(star); -} \ No newline at end of file diff --git a/html/forums/admin/jscripts/quick_perm_editor.js b/html/forums/admin/jscripts/quick_perm_editor.js deleted file mode 100644 index 8a700e3..0000000 --- a/html/forums/admin/jscripts/quick_perm_editor.js +++ /dev/null @@ -1,63 +0,0 @@ -var QuickPermEditor = { - - init: function(id) - { - if(!$('#fields_enabled_'+id) || !$('#fields_disabled_'+id)) - { - return; - } - if(!$('#fields_'+id)) - { - return; - } - - $("#fields_enabled_"+id).sortable({ - connectWith: "#fields_disabled_"+id, - dropOnEmpty: true, - update: function(event, ui) { - QuickPermEditor.buildFieldsList(id); - } - }).disableSelection(); - - $("#fields_disabled_"+id).sortable({ - connectWith: "#fields_enabled_"+id, - dropOnEmpty: true, - update: function(event, ui) { - QuickPermEditor.buildFieldsList(id); - } - }).disableSelection(); - }, - - buildFieldsList: function(id) - { - new_input = ''; - - $('#fields_enabled_'+id).children().each(function() { - var textid = $(this).attr('id').split("-"); - - if(textid[1]) - { - if(new_input) - { - new_input += ","; - } - new_input += textid[1]; - } - }); - - if($('#fields_'+id).val() != new_input) - { - if($('#default_permissions_'+id)) - { - $('#default_permissions_'+id).attr('checked', false); - } - } - - $('#fields_'+id).val(new_input); - - if($('#fields_inherit_'+id)) - { - $('#fields_inherit_'+id).val(0); - } - }, -}; \ No newline at end of file diff --git a/html/forums/admin/jscripts/search.js b/html/forums/admin/jscripts/search.js deleted file mode 100644 index 16298c0..0000000 --- a/html/forums/admin/jscripts/search.js +++ /dev/null @@ -1,74 +0,0 @@ -var SettingSearch = { - - error_unknown : "", - - init: function(settings_search, error_unknown) - { - this.error_unknown = error_unknown; - - $('#settings_search').bind("submit", this.onSubmit); - $('#search_results').css('display', 'none'); - - $('#search').focusin(function() { - if($('#search').val() == settings_search) - { - $('#search').removeClass('search_default'); - $('#search').val(''); - } - }); - - $('#search').focusout(function() { - if($('#search').val() == "") - { - $('#search').addClass('search_default'); - $('#search').val(settings_search); - $("#search_results").css('display', "none"); - $("#group_list").css('display', ""); - } - }); - }, - - onSubmit: function(e) - { - e.preventDefault(); - if($('#search').val() != "") - { - $.jGrowl(lang.searching, {theme:'jgrowl_process'}); - pars = "module=config-settings&action=change&ajax_search=1&search="+encodeURIComponent($('#search').val()); - $.ajax({ - type: 'get', - url: "index.php", - data: pars, - complete: function (request, status) - { - try - { - var json = $.parseJSON(request.responseText); - if(typeof json == 'object') - { - if(json.hasOwnProperty("errors")) - { - $("div.jGrowl").jGrowl("close"); - - $.each(json.errors, function(i, message) - { - $.jGrowl(lang.search_error + ' ' + message, {theme:'jgrowl_error'}); - }); - return false; - } - } - } - catch(error) - { - $('#search_results').css('display', ''); - $('#group_list').css('display', 'none'); - $('#search_results').html(request.responseText); - loadPeekers(); - $.jGrowl(lang.search_done, {theme:'jgrowl_success'}); - return false; - } - } - }); - } - }, -}; \ No newline at end of file diff --git a/html/forums/admin/jscripts/tabs.js b/html/forums/admin/jscripts/tabs.js deleted file mode 100644 index af4562d..0000000 --- a/html/forums/admin/jscripts/tabs.js +++ /dev/null @@ -1,43 +0,0 @@ -$(function() -{ - $('ul.tabs').each(function() - { - if($(this).data('rendered')) - { - return; - } - - $(this).data('rendered', 'yes'); - - var activeTab, activeContent, links = $(this).find('a'); - - activeTab = $(links.filter('[href="'+location.hash+'"]')[0] || links[0]); - activeTab.addClass('active'); - activeContent = $(activeTab.attr('href')); - - // Hide the remaining content - links.not(activeTab).each(function() - { - $($(this).attr('href')).hide(); - }); - - // Tab functionality - $(this).on('click', 'a', function(e) - { - activeTab.removeClass('active'); - activeContent.hide(); - - activeTab = $(this); - activeContent = $($(this).attr('href')); - - // update address bar - window.location.hash = $(this).attr('href'); - - activeTab.addClass('active'); - activeContent.show(); - - e.preventDefault(); - }); - }); - -}); \ No newline at end of file diff --git a/html/forums/admin/jscripts/theme_properties.js b/html/forums/admin/jscripts/theme_properties.js deleted file mode 100644 index ffc486d..0000000 --- a/html/forums/admin/jscripts/theme_properties.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * functions for stylesheet file/color attachments - */ - -var themeProperties = (function() { - /** - * @var number the total attached files for this stylesheet - */ - var attachedCount = 0; - - /** - * attach event handlers - * - * @return void - */ - function init() { - for (var i = 0; i < attachedCount; ++i) { - $("#delete_img_" + i).click(removeAttachmentBox); - } - $("#new_specific_file").click(addAttachmentBox); - } - - /** - * allow external setup - * - * @param string the count at load time - * @return void - */ - function setup(count) { - attachedCount = count || 0; - } - - /** - * create a new blank attachment box - * - * @param object the event - * @return void - */ - function addAttachmentBox(e) { - e.preventDefault(); - - var next_count = Number(attachedCount) + 1, - contents = "
\n\n\n\n\n\n\n\n\n\n
\""" + file_lang_string + "  
\n
\n
\n
\n
\n" + specific_actions_desc_lang_string + "\n\n\n\n\n
\n
\n
\n
\n
\n"; - - // if this is the first attachment, create the first - if (!$("#attach_box_" + attachedCount).attr('id')) { - $("#attach_1").html(contents).show(); - } else { - $("#attach_box_" + attachedCount).html(contents).show(); - } - - checkAction('action_' + attachedCount); - - if ($("#attached_form_" + attachedCount)) { - $("#delete_img_" + attachedCount).click(removeAttachmentBox); - } - ++attachedCount; - } - - /** - * remove an entire attachment box - * - * @param object the event - * @return void - */ - function removeAttachmentBox(e) { - var idArray, id; - - idArray = e.currentTarget.id.split('_'); - if (!idArray.length) { - return; - } - id = idArray[idArray.length - 1]; - e.preventDefault(); - - if (confirm(delete_confirm_lang_string) == true) { - $("#attached_form_" + id).remove(); - } - } - - $(document).ready(init); - - // the only public method - return { - setup: setup, - }; -})(); diff --git a/html/forums/admin/jscripts/themes.js b/html/forums/admin/jscripts/themes.js deleted file mode 100644 index d2976cd..0000000 --- a/html/forums/admin/jscripts/themes.js +++ /dev/null @@ -1,345 +0,0 @@ -/** - * ThemeSelector loads various selectors' properties when they are select from - * a list - */ - -var ThemeSelector = { - - /** - * Constructor - * - * @param string the address to the load script - * @param string the address to the save script - * @param object the select element - * @param object the stylesheet info div - * @param string the stylesheet file name - * @param object the form element - * @param number the theme id - * @return void - */ - init: function(url, saveUrl, selector, styleSheet, file, selectorForm, tid) { - // verify input - if (!url || !saveUrl || !selector || !styleSheet || !file || !selectorForm || !tid) { - return; - } - - ThemeSelector.url = url; - ThemeSelector.saveUrl = saveUrl; - ThemeSelector.selector = selector; - ThemeSelector.selectorPrevOpt = ThemeSelector.selector.val(); - ThemeSelector.styleSheet = styleSheet; - ThemeSelector.file = file; - ThemeSelector.selectorForm = selectorForm; - ThemeSelector.tid = tid; - - ThemeSelector.background = $("#css_bits\\[background\\]").val(); - ThemeSelector.width = $("#css_bits\\[width\\]").val(); - ThemeSelector.color = $("#css_bits\\[color\\]").val(); - ThemeSelector.extra = $("#css_bits\\[extra\\]").val(); - ThemeSelector.text_decoration = $("#css_bits\\[text_decoration\\]").val(); - ThemeSelector.font_family = $("#css_bits\\[font_family\\]").val(); - ThemeSelector.font_size = $("#css_bits\\[font_size\\]").val(); - ThemeSelector.font_style = $("#css_bits\\[font_style\\]").val(); - ThemeSelector.font_weight = $("#css_bits\\[font_weight\\]").val(); - - $("#save").on('click', function(event) { ThemeSelector.save(event, true); } ); - $("#save_close").on('click', function(event) { ThemeSelector.saveClose(event); } ); - - - $(window).on('beforeunload', function(event){ - if(ThemeSelector.isChanged()) - { - return ' '; - } - }); - - - - ThemeSelector.selector.on("change", ThemeSelector.updateSelector); - ThemeSelector.selectorForm.on("submit", ThemeSelector.updateSelector); - }, - - /** - * prevents no-save warning messaging when saving - * - * @return void - */ - saveClose: function(e) { - ThemeSelector.isClosing = true; - }, - - /** - * updates the stylesheet info to match the current selection, checking - * first that work isn't lost - * - * @param object the event - * @return void - */ - updateSelector: function(e) { - var postData; - - e.preventDefault() - - ThemeSelector.saveCheck(e, true); - - postData = "file=" + encodeURIComponent(ThemeSelector.file) + "&tid=" + encodeURIComponent(ThemeSelector.tid) + "&selector=" + encodeURIComponent(ThemeSelector.selector.val()) + "&my_post_key=" + encodeURIComponent(my_post_key); - - ThemeSelector.selectorGoText = $("#mini_spinner").html(); - $("#mini_spinner").html(" \"\" "); - - $.ajax({ - type: 'post', - url: ThemeSelector.url, - data: postData, - complete: ThemeSelector.onComplete, - }); - }, - - /** - * handles the AJAX return data - * - * @param object the request - * @return true - */ - onComplete: function(request) { - var message, saved; - - if (request.responseText.match(/(.*)<\/error>/)) { - message = request.responseText.match(/(.*)<\/error>/); - - if (!message[1]) { - message[1] = lang.unknown_error; - } - $.jGrowl(lang.theme_info_fetch_error + '\n\n' + message[1], {theme:'jgrowl_error'}); - } else if(request.responseText) { - if ($("#saved").html()) { - saved = $("#saved").html(); - } - ThemeSelector.styleSheet.html(request.responseText); - } - - ThemeSelector.background = $("#css_bits\\[background\\]").val(); - ThemeSelector.width = $("#css_bits\\[width\\]").val(); - ThemeSelector.color = $("#css_bits\\[color\\]").val(); - ThemeSelector.extra = $("#css_bits\\[extra\\]").val(); - ThemeSelector.text_decoration = $("#css_bits\\[text_decoration\\]").val(); - ThemeSelector.font_family = $("#css_bits\\[font_family\\]").val(); - ThemeSelector.font_size = $("#css_bits\\[font_size\\]").val(); - ThemeSelector.font_style = $("#css_bits\\[font_style\\]").val(); - ThemeSelector.font_weight = $("#css_bits\\[font_weight\\]").val(); - - if (saved) { - $("#saved").html(saved); - window.setTimeout(function() { - $("#saved").html(""); - }, 30000); - } - - $("#mini_spinner").html(ThemeSelector.selectorGoText); - ThemeSelector.selectorGoText = ''; - - return true; - }, - - isChanged: function() - { - return (ThemeSelector.background != $("#css_bits\\[background\\]").val() || - ThemeSelector.width != $("#css_bits\\[width\\]").val() || - ThemeSelector.color != $("#css_bits\\[color\\]").val() || - ThemeSelector.extra != $("#css_bits\\[extra\\]").val() || - ThemeSelector.text_decoration != $("#css_bits\\[text_decoration\\]").val() || - ThemeSelector.font_family != $("#css_bits\\[font_family\\]").val() || - ThemeSelector.font_size != $("#css_bits\\[font_size\\]").val() || - ThemeSelector.font_style != $("#css_bits\\[font_style\\]").val() || - ThemeSelector.font_weight != $("#css_bits\\[font_weight\\]").val()); - }, - - /** - * check if anything has changed - * - * @param object the event - * @param bool true if AJAX, false if not - * @return true - */ - saveCheck: function(e, isAjax) { - - - if (ThemeSelector.isClosing == true) { - return true; - } - - if(e != null && isAjax == true) - e.preventDefault(); - - if (ThemeSelector.isChanged()) { - - e.preventDefault(); - - if(isAjax == false) - return save_changes_lang_string; - else - { - confirmReturn = confirm(save_changes_lang_string); - if (confirmReturn == true) { - ThemeSelector.save(false, isAjax); - $.jGrowl(lang.saved, {theme:'jgrowl_success'}); - } - } - } - else if(isAjax == true) - { - ThemeSelector.selectorPrevOpt = ThemeSelector.selector.val(); - return true; - } - }, - - /** - * saves the selector info - * - * @param object the event - * @param bool true if AJAX, false if not - * @return true - */ - save: function(e, isAjax) { - var cssBits, postData, completeMethod = 'onUnloadSaveComplete'; - - if (e) { - e.preventDefault(); - } - - cssBits = { - 'background': $('#css_bits\\[background\\]').val(), - 'width': $('#css_bits\\[width\\]').val(), - 'color': $('#css_bits\\[color\\]').val(), - 'extra': $('#css_bits\\[extra\\]').val(), - 'text_decoration': $('#css_bits\\[text_decoration\\]').val(), - 'font_family': $('#css_bits\\[font_family\\]').val(), - 'font_size': $('#css_bits\\[font_size\\]').val(), - 'font_style': $('#css_bits\\[font_style\\]').val(), - 'font_weight': $('#css_bits\\[font_weight\\]').val() - }; - - postData = "css_bits=" + encodeURIComponent(jsArrayToPhpArray(cssBits)) + "&selector=" + encodeURIComponent(ThemeSelector.selectorPrevOpt) + "&file=" + encodeURIComponent(ThemeSelector.file) + "&tid=" + encodeURIComponent(ThemeSelector.tid) + "&my_post_key=" + encodeURIComponent(my_post_key) + "&serialized=1"; - - if (isAjax == true) { - postData += "&ajax=1"; - } - - ThemeSelector.isAjax = isAjax; - - if (isAjax == true) { - completeMethod = 'onSaveComplete'; - $.jGrowl(lang.saving, {theme:'jgrowl_process'}); - } - - $.ajax({ - type: 'post', - url: ThemeSelector.saveUrl, - data: postData, - complete: ThemeSelector[completeMethod], - }); - return !isAjax; - }, - - /** - * handle errors, reset values and clean up - * - * @param object the request - * @return true - */ - onSaveComplete: function(request) { - var message; - - if (request.responseText.match(/(.*)<\/error>/)) { - message = request.responseText.match(/(.*)<\/error>/); - - if (!message[1]) { - message[1] = lang.unkown_error; - } - $.jGrowl(lang.theme_info_save_error + '\n\n' + message[1], {theme:'jgrowl_error'}); - return false; - } else if(request.responseText) { - $("#saved").html(" (" + lang.saved + " @ "+ Date() + ")"); - if ($("#ajax_alert")) { - $("#ajax_alert").html('').hide(); - } - } - - ThemeSelector.background = $("#css_bits\\[background\\]").val(); - ThemeSelector.width = $("#css_bits\\[width\\]").val(); - ThemeSelector.color = $("#css_bits\\[color\\]").val(); - ThemeSelector.extra = $("#css_bits\\[extra\\]").val(); - ThemeSelector.text_decoration = $("#css_bits\\[text_decoration\\]").val(); - ThemeSelector.font_family = $("#css_bits\\[font_family\\]").val(); - ThemeSelector.font_size = $("#css_bits\\[font_size\\]").val(); - ThemeSelector.font_style = $("#css_bits\\[font_style\\]").val(); - ThemeSelector.font_weight = $("#css_bits\\[font_weight\\]").val(); - - return true; - }, - - /** - * handle leaving page save - * - * @param object the request - * @return true - */ - onUnloadSaveComplete: function(request) { - var message; - - if (request.responseText.match(/(.*)<\/error>/)) { - message = request.responseText.match(/(.*)<\/error>/); - - if (!message[1]) { - message[1] = lang.unkown_error; - } - $.jGrowl(lang.theme_info_save_error + '\n\n' + message[1], {theme:'jgrowl_error'}); - return false; - } - return true; - }, - - url: null, - saveUrl: null, - selector: null, - styleSheet: null, - file: null, - selectorForm: null, - tid: null, - miniSpinnerImage: "../images/spinner.gif", - isAjax: false, - specific_count: 0, - selectorGoText: null, - selectorPrevOpt: null, - isClosing: false, - background: null, - width: null, - color: null, - extra: null, - text_decoration: null, - font_family: null, - font_size: null, - font_style: null, - font_weight: null -}; - -/** - * converts a JS object to a JSON of a PHP associative array - * - * @param array the JS array - * @return string the JSON - */ -function jsArrayToPhpArray(a) { - var a_php = "", total = 0; - - for (var key in a) { - ++total; - a_php += "s:" + - String(key).length + ":\"" + - String(key) + "\";s:" + - String(a[key]).length + - ":\"" + String(a[key]) + "\";"; - } - a_php = "a:" + total + ":{" + a_php + "}"; - return a_php; -} diff --git a/html/forums/admin/jscripts/users.js b/html/forums/admin/jscripts/users.js deleted file mode 100644 index 72a1b26..0000000 --- a/html/forums/admin/jscripts/users.js +++ /dev/null @@ -1,13 +0,0 @@ -var Users = { - last_value: '', - cached_users: '', - - init: function() - { - } -}; - -$(function() -{ - Users.init(); -}); \ No newline at end of file diff --git a/html/forums/admin/jscripts/view_manager.js b/html/forums/admin/jscripts/view_manager.js deleted file mode 100644 index a0da901..0000000 --- a/html/forums/admin/jscripts/view_manager.js +++ /dev/null @@ -1,53 +0,0 @@ -var ViewManager = { - init: function() - { - if(!$('#fields_enabled') || !$('#fields_disabled')) - { - return; - } - - if(!$('#fields_js')) - { - return; - } - - $("#fields_enabled").sortable({ - connectWith: "#fields_disabled", - dropOnEmpty: true, - update: function(event, ui) { - ViewManager.buildFieldsList(); - } - }).disableSelection(); - - $("#fields_disabled").sortable({ - connectWith: "#fields_enabled", - dropOnEmpty: true, - update: function(event, ui) { - ViewManager.buildFieldsList(); - } - }).disableSelection(); - }, - - buildFieldsList: function() - { - new_input = ''; - $('#fields_enabled').children().each(function() { - id = $(this).attr('id').split("-"); - - if(id[1]) - { - if(new_input) - { - new_input += ","; - } - new_input += id[1]; - } - }); - $('#fields_js').val(new_input); - } -}; - -$(function() -{ - ViewManager.init(); -}); \ No newline at end of file diff --git a/html/forums/admin/modules/config/attachment_types.php b/html/forums/admin/modules/config/attachment_types.php deleted file mode 100644 index 91f6459..0000000 --- a/html/forums/admin/modules/config/attachment_types.php +++ /dev/null @@ -1,746 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->attachment_types, "index.php?module=config-attachment_types"); - -$plugins->run_hooks("admin_config_attachment_types_begin"); - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_config_attachment_types_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['mimetype']) && !trim($mybb->input['extension'])) - { - $errors[] = $lang->error_missing_mime_type; - } - - if(!trim($mybb->input['extension']) && !trim($mybb->input['mimetype'])) - { - $errors[] = $lang->error_missing_extension; - } - - if(!$errors) - { - if($mybb->input['mimetype'] == "images/attachtypes/") - { - $mybb->input['mimetype'] = ''; - } - - if(substr($mybb->input['extension'], 0, 1) == '.') - { - $mybb->input['extension'] = substr($mybb->input['extension'], 1); - } - - foreach(array('groups', 'forums') as $key) - { - if($mybb->input[$key] == 'all') - { - $mybb->input[$key] = -1; - } - elseif($mybb->input[$key] == 'custom') - { - if(isset($mybb->input['select'][$key]) && is_array($mybb->input['select'][$key])) - { - foreach($mybb->input['select'][$key] as &$val) - { - $val = (int)$val; - } - unset($val); - - $mybb->input[$key] = implode(',', (array)$mybb->input['select'][$key]); - } - else - { - $mybb->input[$key] = ''; - } - } - else - { - $mybb->input[$key] = ''; - } - } - - $maxsize = $mybb->get_input('maxsize', MyBB::INPUT_INT); - - if($maxsize == 0) - { - $maxsize = ""; - } - - $new_type = array( - "name" => $db->escape_string($mybb->input['name']), - "mimetype" => $db->escape_string($mybb->input['mimetype']), - "extension" => $db->escape_string($mybb->input['extension']), - "maxsize" => $maxsize, - "icon" => $db->escape_string($mybb->input['icon']), - 'enabled' => $mybb->get_input('enabled', MyBB::INPUT_INT), - 'groups' => $db->escape_string($mybb->get_input('groups')), - 'forums' => $db->escape_string($mybb->get_input('forums')), - 'avatarfile' => $mybb->get_input('avatarfile', MyBB::INPUT_INT) - ); - - $atid = $db->insert_query("attachtypes", $new_type); - - $plugins->run_hooks("admin_config_attachment_types_add_commit"); - - // Log admin action - log_admin_action($atid, htmlspecialchars_uni($mybb->input['extension'])); - - $cache->update_attachtypes(); - - flash_message($lang->success_attachment_type_created, 'success'); - admin_redirect("index.php?module=config-attachment_types"); - } - } - - $page->add_breadcrumb_item($lang->add_new_attachment_type); - $page->output_header($lang->attachment_types." - ".$lang->add_new_attachment_type); - - $sub_tabs['attachment_types'] = array( - 'title' => $lang->attachment_types, - 'link' => "index.php?module=config-attachment_types" - ); - - $sub_tabs['add_attachment_type'] = array( - 'title' => $lang->add_new_attachment_type, - 'link' => "index.php?module=config-attachment_types&action=add", - 'description' => $lang->add_attachment_type_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_attachment_type'); - - $form = new Form("index.php?module=config-attachment_types&action=add", "post", "add"); - - if($errors) - { - switch($mybb->input['groups']) - { - case 'all': - $mybb->input['groups'] = -1; - break; - case 'custom': - $mybb->input['groups'] = implode(',', (array)$mybb->input['select']['groups']); - break; - default: - $mybb->input['groups'] = ''; - break; - } - - switch($mybb->input['forums']) - { - case 'all': - $mybb->input['forums'] = -1; - break; - case 'custom': - $mybb->input['forums'] = implode(',', (array)$mybb->input['select']['forums']); - break; - default: - $mybb->input['forums'] = ''; - break; - } - - $page->output_inline_error($errors); - } - else - { - $mybb->input['maxsize'] = '1024'; - $mybb->input['icon'] = "images/attachtypes/"; - } - - if(empty($mybb->input['groups'])) - { - $mybb->input['groups'] = ''; - } - - if(empty($mybb->input['forums'])) - { - $mybb->input['forums'] = ''; - } - - // PHP settings - $upload_max_filesize = @ini_get('upload_max_filesize'); - $post_max_size = @ini_get('post_max_size'); - $limit_string = ''; - if($upload_max_filesize || $post_max_size) - { - $limit_string = '

'.$lang->limit_intro; - if($upload_max_filesize) - { - $limit_string .= '
'.$lang->sprintf($lang->limit_upload_max_filesize, $upload_max_filesize); - } - if($post_max_size) - { - $limit_string .= '
'.$lang->sprintf($lang->limit_post_max_size, $post_max_size); - } - } - - $selected_values = ''; - if($mybb->input['groups'] != '' && $mybb->input['groups'] != -1) - { - $selected_values = explode(',', $mybb->get_input('groups')); - - foreach($selected_values as &$value) - { - $value = (int)$value; - } - unset($value); - } - - $group_checked = array('all' => '', 'custom' => '', 'none' => ''); - if($mybb->input['groups'] == -1) - { - $group_checked['all'] = 'checked="checked"'; - } - elseif($mybb->input['groups'] != '') - { - $group_checked['custom'] = 'checked="checked"'; - } - else - { - $group_checked['none'] = 'checked="checked"'; - } - - print_selection_javascript(); - - $groups_select_code = " -
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('select[groups][]', $selected_values, array('id' => 'groups', 'multiple' => true, 'size' => 5))."
-
-
-
- "; - - $selected_values = ''; - if($mybb->input['forums'] != '' && $mybb->input['forums'] != -1) - { - $selected_values = explode(',', $mybb->get_input('forums')); - - foreach($selected_values as &$value) - { - $value = (int)$value; - } - unset($value); - } - - $forum_checked = array('all' => '', 'custom' => '', 'none' => ''); - if($mybb->input['forums'] == -1) - { - $forum_checked['all'] = 'checked="checked"'; - } - elseif($mybb->input['forums'] != '') - { - $forum_checked['custom'] = 'checked="checked"'; - } - else - { - $forum_checked['none'] = 'checked="checked"'; - } - - $forums_select_code = " -
-
-
-
- - - - - -
{$lang->forums_colon}".$form->generate_forum_select('select[forums][]', $selected_values, array('id' => 'forums', 'multiple' => true, 'size' => 5))."
-
-
-
- "; - - $form_container = new FormContainer($lang->add_new_attachment_type); - $form_container->output_row($lang->name, $lang->name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->file_extension." *", $lang->file_extension_desc, $form->generate_text_box('extension', $mybb->input['extension'], array('id' => 'extension')), 'extension'); - $form_container->output_row($lang->mime_type." *", $lang->mime_type_desc, $form->generate_text_box('mimetype', $mybb->input['mimetype'], array('id' => 'mimetype')), 'mimetype'); - $form_container->output_row($lang->maximum_file_size, $lang->maximum_file_size_desc.$limit_string, $form->generate_numeric_field('maxsize', $mybb->input['maxsize'], array('id' => 'maxsize', 'min' => 0)), 'maxsize'); - $form_container->output_row($lang->attachment_icon, $lang->attachment_icon_desc, $form->generate_text_box('icon', $mybb->input['icon'], array('id' => 'icon')), 'icon'); - $form_container->output_row($lang->enabled, '', $form->generate_yes_no_radio('enabled', $mybb->input['enabled']), 'enabled'); - $form_container->output_row($lang->available_to_groups, '', $groups_select_code, '', array(), array('id' => 'row_groups')); - $form_container->output_row($lang->available_in_forums, '', $forums_select_code, '', array(), array('id' => 'row_forums')); - $form_container->output_row($lang->avatar_file, $lang->avatar_file_desc, $form->generate_yes_no_radio('avatarfile', $mybb->input['avatarfile']), 'avatarfile'); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_attachment_type); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("attachtypes", "*", "atid='".$mybb->get_input('atid', MyBB::INPUT_INT)."'"); - $attachment_type = $db->fetch_array($query); - - if(!$attachment_type['atid']) - { - flash_message($lang->error_invalid_attachment_type, 'error'); - admin_redirect("index.php?module=config-attachment_types"); - } - - $plugins->run_hooks("admin_config_attachment_types_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['mimetype']) && !trim($mybb->input['extension'])) - { - $errors[] = $lang->error_missing_mime_type; - } - - if(!trim($mybb->input['extension']) && !trim($mybb->input['mimetype'])) - { - $errors[] = $lang->error_missing_extension; - } - - if(!$errors) - { - if($mybb->input['mimetype'] == "images/attachtypes/") - { - $mybb->input['mimetype'] = ''; - } - - if(substr($mybb->input['extension'], 0, 1) == '.') - { - $mybb->input['extension'] = substr($mybb->input['extension'], 1); - } - - foreach(array('groups', 'forums') as $key) - { - if($mybb->input[$key] == 'all') - { - $mybb->input[$key] = -1; - } - elseif($mybb->input[$key] == 'custom') - { - if(isset($mybb->input['select'][$key]) && is_array($mybb->input['select'][$key])) - { - foreach($mybb->input['select'][$key] as &$val) - { - $val = (int)$val; - } - unset($val); - - $mybb->input[$key] = implode(',', (array)$mybb->input['select'][$key]); - } - else - { - $mybb->input[$key] = ''; - } - } - else - { - $mybb->input[$key] = ''; - } - } - - $updated_type = array( - "name" => $db->escape_string($mybb->input['name']), - "mimetype" => $db->escape_string($mybb->input['mimetype']), - "extension" => $db->escape_string($mybb->input['extension']), - "maxsize" => $mybb->get_input('maxsize', MyBB::INPUT_INT), - "icon" => $db->escape_string($mybb->input['icon']), - 'enabled' => $mybb->get_input('enabled', MyBB::INPUT_INT), - 'groups' => $db->escape_string($mybb->get_input('groups')), - 'forums' => $db->escape_string($mybb->get_input('forums')), - 'avatarfile' => $mybb->get_input('avatarfile', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_config_attachment_types_edit_commit"); - - $db->update_query("attachtypes", $updated_type, "atid='{$attachment_type['atid']}'"); - - // Log admin action - log_admin_action($attachment_type['atid'], htmlspecialchars_uni($mybb->input['extension'])); - - $cache->update_attachtypes(); - - flash_message($lang->success_attachment_type_updated, 'success'); - admin_redirect("index.php?module=config-attachment_types"); - } - } - - $page->add_breadcrumb_item($lang->edit_attachment_type); - $page->output_header($lang->attachment_types." - ".$lang->edit_attachment_type); - - $sub_tabs['edit_attachment_type'] = array( - 'title' => $lang->edit_attachment_type, - 'link' => "index.php?module=config-attachment_types&action=edit&atid={$attachment_type['atid']}", - 'description' => $lang->edit_attachment_type_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_attachment_type'); - - $form = new Form("index.php?module=config-attachment_types&action=edit&atid={$attachment_type['atid']}", "post", "add"); - - if($errors) - { - switch($mybb->input['groups']) - { - case 'all': - $mybb->input['groups'] = -1; - break; - case 'custom': - $mybb->input['groups'] = implode(',', (array)$mybb->input['select']['groups']); - break; - default: - $mybb->input['groups'] = ''; - break; - } - - switch($mybb->input['forums']) - { - case 'all': - $mybb->input['forums'] = -1; - break; - case 'custom': - $mybb->input['forums'] = implode(',', (array)$mybb->input['select']['forums']); - break; - default: - $mybb->input['forums'] = ''; - break; - } - - $page->output_inline_error($errors); - } - else - { - $mybb->input = array_merge($mybb->input, $attachment_type); - } - - if(empty($mybb->input['groups'])) - { - $mybb->input['groups'] = ''; - } - - if(empty($mybb->input['forums'])) - { - $mybb->input['forums'] = ''; - } - - // PHP settings - $upload_max_filesize = @ini_get('upload_max_filesize'); - $post_max_size = @ini_get('post_max_size'); - $limit_string = ''; - if($upload_max_filesize || $post_max_size) - { - $limit_string = '

'.$lang->limit_intro; - if($upload_max_filesize) - { - $limit_string .= '
'.$lang->sprintf($lang->limit_upload_max_filesize, $upload_max_filesize); - } - if($post_max_size) - { - $limit_string .= '
'.$lang->sprintf($lang->limit_post_max_size, $post_max_size); - } - } - - $selected_values = ''; - if($mybb->input['groups'] != '' && $mybb->input['groups'] != -1) - { - $selected_values = explode(',', $mybb->get_input('groups')); - - foreach($selected_values as &$value) - { - $value = (int)$value; - } - unset($value); - } - - $group_checked = array('all' => '', 'custom' => '', 'none' => ''); - if($mybb->input['groups'] == -1) - { - $group_checked['all'] = 'checked="checked"'; - } - elseif($mybb->input['groups'] != '') - { - $group_checked['custom'] = 'checked="checked"'; - } - else - { - $group_checked['none'] = 'checked="checked"'; - } - - print_selection_javascript(); - - $groups_select_code = " -
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('select[groups][]', $selected_values, array('id' => 'groups', 'multiple' => true, 'size' => 5))."
-
-
-
- "; - - $selected_values = ''; - if($mybb->input['forums'] != '' && $mybb->input['forums'] != -1) - { - $selected_values = explode(',', $mybb->get_input('forums')); - - foreach($selected_values as &$value) - { - $value = (int)$value; - } - unset($value); - } - - $forum_checked = array('all' => '', 'custom' => '', 'none' => ''); - if($mybb->input['forums'] == -1) - { - $forum_checked['all'] = 'checked="checked"'; - } - elseif($mybb->input['forums'] != '') - { - $forum_checked['custom'] = 'checked="checked"'; - } - else - { - $forum_checked['none'] = 'checked="checked"'; - } - - $forums_select_code = " -
-
-
-
- - - - - -
{$lang->forums_colon}".$form->generate_forum_select('select[forums][]', $selected_values, array('id' => 'forums', 'multiple' => true, 'size' => 5))."
-
-
-
- "; - - $form_container = new FormContainer($lang->edit_attachment_type); - $form_container->output_row($lang->name, $lang->name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->file_extension." *", $lang->file_extension_desc, $form->generate_text_box('extension', $mybb->input['extension'], array('id' => 'extension')), 'extension'); - $form_container->output_row($lang->mime_type." *", $lang->mime_type_desc, $form->generate_text_box('mimetype', $mybb->input['mimetype'], array('id' => 'mimetype')), 'mimetype'); - $form_container->output_row($lang->maximum_file_size, $lang->maximum_file_size_desc.$limit_string, $form->generate_numeric_field('maxsize', $mybb->input['maxsize'], array('id' => 'maxsize', 'min' => 0)), 'maxsize'); - $form_container->output_row($lang->attachment_icon, $lang->attachment_icon_desc, $form->generate_text_box('icon', $mybb->input['icon'], array('id' => 'icon')), 'icon'); - $form_container->output_row($lang->enabled, '', $form->generate_yes_no_radio('enabled', $mybb->input['enabled']), 'enabled'); - $form_container->output_row($lang->available_to_groups, '', $groups_select_code, '', array(), array('id' => 'row_groups')); - $form_container->output_row($lang->available_in_forums, '', $forums_select_code, '', array(), array('id' => 'row_forums')); - $form_container->output_row($lang->avatar_file, $lang->avatar_file_desc, $form->generate_yes_no_radio('avatarfile', $mybb->input['avatarfile']), 'avatarfile'); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_attachment_type); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-attachment_types"); - } - - $query = $db->simple_select("attachtypes", "*", "atid='".$mybb->get_input('atid', MyBB::INPUT_INT)."'"); - $attachment_type = $db->fetch_array($query); - - if(!$attachment_type['atid']) - { - flash_message($lang->error_invalid_attachment_type, 'error'); - admin_redirect("index.php?module=config-attachment_types"); - } - - $plugins->run_hooks("admin_config_attachment_types_delete"); - - if($mybb->request_method == "post") - { - $db->delete_query("attachtypes", "atid='{$attachment_type['atid']}'"); - - $plugins->run_hooks("admin_config_attachment_types_delete_commit"); - - $cache->update_attachtypes(); - - // Log admin action - log_admin_action($attachment_type['atid'], htmlspecialchars_uni($attachment_type['extension'])); - - flash_message($lang->success_attachment_type_deleted, 'success'); - admin_redirect("index.php?module=config-attachment_types"); - } - else - { - $page->output_confirm_action("index.php?module=config-attachment_types&action=delete&atid={$attachment_type['atid']}", $lang->confirm_attachment_type_deletion); - } -} - -if($mybb->input['action'] == 'toggle_status') -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect('index.php?module=config-attachment_types'); - } - - $atid = $mybb->get_input('atid', MyBB::INPUT_INT); - - $query = $db->simple_select('attachtypes', '*', "atid='{$atid}'"); - $attachment_type = $db->fetch_array($query); - - if(!$attachment_type['atid']) - { - flash_message($lang->error_invalid_mycode, 'error'); - admin_redirect('index.php?module=config-attachment_types'); - } - - $plugins->run_hooks('admin_config_attachment_types_toggle_status'); - - $update_array = array('enabled' => 1); - $phrase = $lang->success_activated_attachment_type; - if($attachment_type['enabled'] == 1) - { - $update_array['enabled'] = 0; - $phrase = $lang->success_activated_attachment_type; - } - - $plugins->run_hooks('admin_config_attachment_types_toggle_status_commit'); - - $db->update_query('attachtypes', $update_array, "atid='{$atid}'"); - - $cache->update_attachtypes(); - - // Log admin action - log_admin_action($atid, htmlspecialchars_uni($attachment_type['extension']), $update_array['enabled']); - - flash_message($phrase, 'success'); - admin_redirect('index.php?module=config-attachment_types'); -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->attachment_types); - - $sub_tabs['attachment_types'] = array( - 'title' => $lang->attachment_types, - 'link' => "index.php?module=config-attachment_types", - 'description' => $lang->attachment_types_desc - ); - $sub_tabs['add_attachment_type'] = array( - 'title' => $lang->add_new_attachment_type, - 'link' => "index.php?module=config-attachment_types&action=add", - ); - - $plugins->run_hooks("admin_config_attachment_types_start"); - - $page->output_nav_tabs($sub_tabs, 'attachment_types'); - - $table = new Table; - $table->construct_header($lang->extension, array("colspan" => 2)); - $table->construct_header($lang->mime_type); - $table->construct_header($lang->alt_enabled, array('class' => 'align_center')); - $table->construct_header($lang->maximum_size, array("class" => "align_center")); - $table->construct_header($lang->controls, array("class" => "align_center")); - - $query = $db->simple_select("attachtypes", "*", "", array('order_by' => 'extension')); - while($attachment_type = $db->fetch_array($query)) - { - // Just show default icons in ACP - $attachment_type['icon'] = htmlspecialchars_uni(str_replace("{theme}", "images", $attachment_type['icon'])); - if(my_validate_url($attachment_type['icon'], true)) - { - $image = $attachment_type['icon']; - } - else - { - $image = "../".$attachment_type['icon']; - } - - if(!$attachment_type['icon'] || $attachment_type['icon'] == "images/attachtypes/") - { - $attachment_type['icon'] = " "; - } - else - { - $attachment_type['name'] = htmlspecialchars_uni($attachment_type['name']); - $attachment_type['icon'] = "\"\""; - } - - if($attachment_type['enabled']) - { - $phrase = $lang->disable; - $icon = "on.png\" alt=\"({$lang->alt_enabled})\" title=\"{$lang->alt_enabled}"; - } - else - { - $phrase = $lang->enable; - $icon = "off.png\" alt=\"({$lang->alt_disabled})\" title=\"{$lang->alt_disabled}"; - } - - $table->construct_cell($attachment_type['icon'], array("width" => 1)); - $table->construct_cell(".{$attachment_type['extension']}"); - $table->construct_cell(htmlspecialchars_uni($attachment_type['mimetype'])); - $table->construct_cell("style}/images/icons/bullet_{$icon}\" style=\"vertical-align: middle;\" />", array("class" => "align_center")); - $table->construct_cell(get_friendly_size(($attachment_type['maxsize']*1024)), array("class" => "align_center")); - - $popup = new PopupMenu("attachment_type_{$attachment_type['atid']}", $lang->options); - $popup->add_item($lang->edit, "index.php?module=config-attachment_types&action=edit&atid={$attachment_type['atid']}"); - $popup->add_item($phrase, "index.php?module=config-attachment_types&action=toggle_status&atid={$attachment_type['atid']}&my_post_key={$mybb->post_code}"); - $popup->add_item($lang->delete, "index.php?module=config-attachment_types&action=delete&atid={$attachment_type['atid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_attachment_type_deletion}')"); - $table->construct_cell($popup->fetch(), array('class' => 'align_center')); - - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_attachment_types, array('colspan' => 6)); - $table->construct_row(); - } - - $table->output($lang->attachment_types); - - $page->output_footer(); -} - diff --git a/html/forums/admin/modules/config/badwords.php b/html/forums/admin/modules/config/badwords.php deleted file mode 100644 index 20b6805..0000000 --- a/html/forums/admin/modules/config/badwords.php +++ /dev/null @@ -1,269 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->bad_words, "index.php?module=config-badwords"); - -$plugins->run_hooks("admin_config_badwords_begin"); - -if($mybb->input['action'] == "add" && $mybb->request_method == "post") -{ - $plugins->run_hooks("admin_config_badwords_add"); - - if(!trim($mybb->input['badword'])) - { - $errors[] = $lang->error_missing_bad_word; - } - - if(strlen(trim($mybb->input['badword'])) > 100) - { - $errors[] = $lang->bad_word_max; - } - - if(strlen($mybb->input['replacement']) > 100) - { - $errors[] = $lang->replacement_word_max; - } - - if(!$errors) - { - $query = $db->simple_select("badwords", "bid", "badword = '".$db->escape_string($mybb->input['badword'])."'"); - - if($db->num_rows($query)) - { - $errors[] = $lang->error_bad_word_filtered; - } - } - - $badword = str_replace('\*', '([a-zA-Z0-9_]{1})', preg_quote($mybb->input['badword'], "#")); - - // Don't allow certain badword replacements to be added if it would cause an infinite recursive loop. - if(strlen($mybb->input['badword']) == strlen($mybb->input['replacement']) && preg_match("#(^|\W)".$badword."(\W|$)#i", $mybb->input['replacement'])) - { - $errors[] = $lang->error_replacement_word_invalid; - } - - if(!$errors) - { - $new_badword = array( - "badword" => $db->escape_string($mybb->input['badword']), - "replacement" => $db->escape_string($mybb->input['replacement']) - ); - - $bid = $db->insert_query("badwords", $new_badword); - - $plugins->run_hooks("admin_config_badwords_add_commit"); - - // Log admin action - log_admin_action($bid, $mybb->input['badword']); - - $cache->update_badwords(); - flash_message($lang->success_added_bad_word, 'success'); - admin_redirect("index.php?module=config-badwords"); - } - else - { - $mybb->input['action'] = ''; - } -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("badwords", "*", "bid='".$mybb->get_input('bid', MyBB::INPUT_INT)."'"); - $badword = $db->fetch_array($query); - - // Does the bad word not exist? - if(!$badword['bid']) - { - flash_message($lang->error_invalid_bid, 'error'); - admin_redirect("index.php?module=config-badwords"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-badwords"); - } - - $plugins->run_hooks("admin_config_badwords_delete"); - - if($mybb->request_method == "post") - { - // Delete the bad word - $db->delete_query("badwords", "bid='{$badword['bid']}'"); - - $plugins->run_hooks("admin_config_badwords_delete_commit"); - - // Log admin action - log_admin_action($badword['bid'], $badword['badword']); - - $cache->update_badwords(); - - flash_message($lang->success_deleted_bad_word, 'success'); - admin_redirect("index.php?module=config-badwords"); - } - else - { - $page->output_confirm_action("index.php?module=config-badwords&action=delete&bid={$badword['bid']}", $lang->confirm_bad_word_deletion); - } -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("badwords", "*", "bid='".$mybb->get_input('bid', MyBB::INPUT_INT)."'"); - $badword = $db->fetch_array($query); - - // Does the bad word not exist? - if(!$badword['bid']) - { - flash_message($lang->error_invalid_bid, 'error'); - admin_redirect("index.php?module=config-badwords"); - } - - $plugins->run_hooks("admin_config_badwords_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['badword'])) - { - $errors[] = $lang->error_missing_bad_word; - } - - if(strlen(trim($mybb->input['badword'])) > 100) - { - $errors[] = $lang->bad_word_max; - } - - if(strlen($mybb->input['replacement']) > 100) - { - $errors[] = $lang->replacement_word_max; - } - - if(!$errors) - { - $updated_badword = array( - "badword" => $db->escape_string($mybb->input['badword']), - "replacement" => $db->escape_string($mybb->input['replacement']) - ); - - $plugins->run_hooks("admin_config_badwords_edit_commit"); - - $db->update_query("badwords", $updated_badword, "bid='{$badword['bid']}'"); - - // Log admin action - log_admin_action($badword['bid'], $mybb->input['badword']); - - $cache->update_badwords(); - - flash_message($lang->success_updated_bad_word, 'success'); - admin_redirect("index.php?module=config-badwords"); - } - } - - $page->add_breadcrumb_item($lang->edit_bad_word); - $page->output_header($lang->bad_words." - ".$lang->edit_bad_word); - - $sub_tabs['editbadword'] = array( - 'title' => $lang->edit_bad_word, - 'description' => $lang->edit_bad_word_desc, - 'link' => "index.php?module=config-badwords" - ); - - $page->output_nav_tabs($sub_tabs, "editbadword"); - - $form = new Form("index.php?module=config-badwords&action=edit&bid={$badword['bid']}", "post"); - - if($errors) - { - $page->output_inline_error($errors); - $badword_data = $mybb->input; - } - else - { - $badword_data = $badword; - } - - $form_container = new FormContainer($lang->edit_bad_word); - $form_container->output_row($lang->bad_word." *", $lang->bad_word_desc, $form->generate_text_box('badword', $badword_data['badword'], array('id' => 'badword')), 'badword'); - $form_container->output_row($lang->replacement, $lang->replacement_desc, $form->generate_text_box('replacement', $badword_data['replacement'], array('id' => 'replacement')), 'replacement'); - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->save_bad_word); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->bad_words); - - $sub_tabs['badwords'] = array( - 'title' => $lang->bad_word_filters, - 'description' => $lang->bad_word_filters_desc, - 'link' => "index.php?module=config-badwords" - ); - - $plugins->run_hooks("admin_config_badwords_start"); - - $page->output_nav_tabs($sub_tabs, "badwords"); - - if($errors) - { - $page->output_inline_error($errors); - } - - $table = new Table; - $table->construct_header($lang->bad_word); - $table->construct_header($lang->replacement, array("width" => "50%")); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150, "colspan" => 2)); - - $query = $db->simple_select("badwords", "*", "", array("order_by" => "badword", "order_dir" => "asc")); - while($badword = $db->fetch_array($query)) - { - $badword['badword'] = htmlspecialchars_uni($badword['badword']); - $badword['replacement'] = htmlspecialchars_uni($badword['replacement']); - if(!$badword['replacement']) - { - $badword['replacement'] = '*****'; - } - $table->construct_cell($badword['badword']); - $table->construct_cell($badword['replacement']); - $table->construct_cell("
{$lang->edit}", array("class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_bad_word_deletion}');\">{$lang->delete}", array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_bad_words, array("colspan" => 4)); - $table->construct_row(); - } - - $table->output($lang->bad_word_filters); - - $form = new Form("index.php?module=config-badwords&action=add", "post", "add"); - - $form_container = new FormContainer($lang->add_bad_word); - $form_container->output_row($lang->bad_word." *", $lang->bad_word_desc, $form->generate_text_box('badword', $mybb->input['badword'], array('id' => 'badword')), 'badword'); - $form_container->output_row($lang->replacement, $lang->replacement_desc, $form->generate_text_box('replacement', $mybb->input['replacement'], array('id' => 'replacement')), 'replacement'); - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->save_bad_word); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - diff --git a/html/forums/admin/modules/config/banning.php b/html/forums/admin/modules/config/banning.php deleted file mode 100644 index 719adb1..0000000 --- a/html/forums/admin/modules/config/banning.php +++ /dev/null @@ -1,294 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->banning, "index.php?module=config-banning"); - -$plugins->run_hooks("admin_config_banning_begin"); - -if($mybb->input['action'] == "add" && $mybb->request_method == "post") -{ - $plugins->run_hooks("admin_config_banning_add"); - - if(!trim($mybb->input['filter'])) - { - $errors[] = $lang->error_missing_ban_input; - } - - $query = $db->simple_select("banfilters", "fid", "filter = '".$db->escape_string($mybb->input['filter'])."' AND type = '".$mybb->get_input('type', MyBB::INPUT_INT)."'"); - if($db->num_rows($query)) - { - $errors[] = $lang->error_filter_already_banned; - } - - if(!$errors) - { - $new_filter = array( - "filter" => $db->escape_string($mybb->input['filter']), - "type" => $mybb->get_input('type', MyBB::INPUT_INT), - "dateline" => TIME_NOW - ); - $fid = $db->insert_query("banfilters", $new_filter); - - $plugins->run_hooks("admin_config_banning_add_commit"); - - if($mybb->input['type'] == 1) - { - $cache->update_bannedips(); - } - else if($mybb->input['type'] == 3) - { - $cache->update_bannedemails(); - } - - // Log admin action - log_admin_action($fid, htmlspecialchars_uni($mybb->input['filter']), (int)$mybb->input['type']); - - if($mybb->input['type'] == 1) - { - flash_message($lang->success_ip_banned, 'success'); - admin_redirect("index.php?module=config-banning"); - } - else if($mybb->input['type'] == 2) - { - flash_message($lang->success_username_disallowed, 'success'); - admin_redirect("index.php?module=config-banning&type=usernames"); - } - else if($mybb->input['type'] == 3) - { - flash_message($lang->success_email_disallowed, 'success'); - admin_redirect("index.php?module=config-banning&type=emails"); - } - } - else - { - if($mybb->input['type'] == 1) - { - $mybb->input['type'] = "ips"; - } - else if($mybb->input['type'] == 2) - { - $mybb->input['type'] = "usernames"; - } - else if($mybb->input['type'] == 3) - { - $mybb->input['type'] = "emails"; - } - $mybb->input['action'] = ''; - } -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("banfilters", "*", "fid='".$mybb->get_input('fid', MyBB::INPUT_INT)."'"); - $filter = $db->fetch_array($query); - - // Does the filter not exist? - if(!$filter['fid']) - { - flash_message($lang->error_invalid_filter, 'error'); - admin_redirect("index.php?module=config-banning"); - } - - $plugins->run_hooks("admin_config_banning_delete"); - - if($filter['type'] == 3) - { - $type = "emails"; - } - else if($filter['type'] == 2) - { - $type = "usernames"; - } - else - { - $type = "ips"; - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-banning&type={$type}"); - } - - if($mybb->request_method == "post") - { - // Delete the ban filter - $db->delete_query("banfilters", "fid='{$filter['fid']}'"); - - $plugins->run_hooks("admin_config_banning_delete_commit"); - - // Log admin action - log_admin_action($filter['fid'], htmlspecialchars_uni($filter['filter']), (int)$filter['type']); - - // Banned IP? Rebuild banned IP cache - if($filter['type'] == 1) - { - $cache->update_bannedips(); - } - else if($filter['type'] == 3) - { - $cache->update_bannedemails(); - } - - flash_message($lang->success_ban_deleted, 'success'); - admin_redirect("index.php?module=config-banning&type={$type}"); - } - else - { - $page->output_confirm_action("index.php?module=config-banning&action=delete&fid={$filter['fid']}", $lang->confirm_ban_deletion); - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_banning_start"); - - switch($mybb->input['type']) - { - case "emails": - $type = "3"; - $title = $lang->disallowed_email_addresses; - break; - case "usernames": - $type = "2"; - $title = $lang->disallowed_usernames; - break; - default: - $type = "1"; - $title = $lang->banned_ip_addresses; - $mybb->input['type'] = "ips"; - } - - $page->output_header($title); - - $sub_tabs['ips'] = array( - 'title' => $lang->banned_ips, - 'link' => "index.php?module=config-banning", - 'description' => $lang->banned_ips_desc - ); - - $sub_tabs['users'] = array( - 'title' => $lang->banned_accounts, - 'link' => "index.php?module=user-banning" - ); - - $sub_tabs['usernames'] = array( - 'title' => $lang->disallowed_usernames, - 'link' => "index.php?module=config-banning&type=usernames", - 'description' => $lang->disallowed_usernames_desc - ); - - $sub_tabs['emails'] = array( - 'title' => $lang->disallowed_email_addresses, - 'link' => "index.php?module=config-banning&type=emails", - 'description' => $lang->disallowed_email_addresses_desc - ); - - $page->output_nav_tabs($sub_tabs, $mybb->input['type']); - - if($errors) - { - $page->output_inline_error($errors); - } - - $table = new Table; - if($mybb->input['type'] == "usernames") - { - $table->construct_header($lang->username); - $table->construct_header($lang->date_disallowed, array("class" => "align_center", "width" => 200)); - $table->construct_header($lang->last_attempted_use, array("class" => "align_center", "width" => 200)); - } - else if($mybb->input['type'] == "emails") - { - $table->construct_header($lang->email_address); - $table->construct_header($lang->date_disallowed, array("class" => "align_center", "width" => 200)); - $table->construct_header($lang->last_attempted_use, array("class" => "align_center", "width" => 200)); - } - else - { - $table->construct_header($lang->ip_address); - $table->construct_header($lang->ban_date, array("class" => "align_center", "width" => 200)); - $table->construct_header($lang->last_access, array("class" => "align_center", "width" => 200)); - } - $table->construct_header($lang->controls, array("width" => 1)); - - $query = $db->simple_select("banfilters", "*", "type='{$type}'", array("order_by" => "filter", "order_dir" => "asc")); - while($filter = $db->fetch_array($query)) - { - $filter['filter'] = htmlspecialchars_uni($filter['filter']); - - if($filter['lastuse'] > 0) - { - $last_use = my_date('relative', $filter['lastuse']); - } - else - { - $last_use = $lang->never; - } - - if($filter['dateline'] > 0) - { - $date = my_date('relative', $filter['dateline']); - } - else - { - $date = $lang->na; - } - - $table->construct_cell($filter['filter']); - $table->construct_cell($date, array("class" => "align_center")); - $table->construct_cell($last_use, array("class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_ban_deletion}');\">style}/images/icons/delete.png\" title=\"{$lang->delete}\" alt=\"{$lang->delete}\" />", array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_bans, array("colspan" => 4)); - $table->construct_row(); - } - - $table->output($title); - - $form = new Form("index.php?module=config-banning&action=add", "post", "add"); - - if($mybb->input['type'] == "usernames") - { - $form_container = new FormContainer($lang->add_disallowed_username); - $form_container->output_row($lang->username." *", $lang->username_desc, $form->generate_text_box('filter', $mybb->input['filter'], array('id' => 'filter')), 'filter'); - $buttons[] = $form->generate_submit_button($lang->disallow_username); - } - else if($mybb->input['type'] == "emails") - { - $form_container = new FormContainer($lang->add_disallowed_email_address); - $form_container->output_row($lang->email_address." *", $lang->email_address_desc, $form->generate_text_box('filter', $mybb->input['filter'], array('id' => 'filter')), 'filter'); - $buttons[] = $form->generate_submit_button($lang->disallow_email_address); - } - else - { - $form_container = new FormContainer($lang->ban_an_ip_address); - $form_container->output_row($lang->ip_address." *", $lang->ip_address_desc, $form->generate_text_box('filter', $mybb->input['filter'], array('id' => 'filter')), 'filter'); - $buttons[] = $form->generate_submit_button($lang->ban_ip_address); - } - - $form_container->end(); - echo $form->generate_hidden_field("type", $type); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - diff --git a/html/forums/admin/modules/config/calendars.php b/html/forums/admin/modules/config/calendars.php deleted file mode 100644 index e4128b9..0000000 --- a/html/forums/admin/modules/config/calendars.php +++ /dev/null @@ -1,479 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->calendars, "index.php?module=config-calendars"); - -if($mybb->input['action'] == "add" || $mybb->input['action'] == "permissions" || !$mybb->input['action']) -{ - $sub_tabs['manage_calendars'] = array( - 'title' => $lang->manage_calendars, - 'link' => "index.php?module=config-calendars", - 'description' => $lang->manage_calendars_desc - ); - $sub_tabs['add_calendar'] = array( - 'title' => $lang->add_calendar, - 'link' => "index.php?module=config-calendars&action=add", - 'description' => $lang->add_calendar_desc - ); -} - -$plugins->run_hooks("admin_config_calendars_begin"); - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_config_calendars_add"); - - if($mybb->request_method == "post") - { - $plugins->run_hooks("admin_config_calendars_add_commit"); - - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - - if(!isset($mybb->input['disporder'])) - { - $errors[] = $lang->error_missing_order; - } - - if(!$errors) - { - $calendar = array( - "name" => $db->escape_string($mybb->input['name']), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "startofweek" => $mybb->get_input('startofweek', MyBB::INPUT_INT), - "eventlimit" => $mybb->get_input('eventlimit', MyBB::INPUT_INT), - "showbirthdays" => $mybb->get_input('showbirthdays', MyBB::INPUT_INT), - "moderation" => $mybb->get_input('moderation', MyBB::INPUT_INT), - "allowhtml" => $mybb->get_input('allowhtml', MyBB::INPUT_INT), - "allowmycode" => $mybb->get_input('allowmycode', MyBB::INPUT_INT), - "allowimgcode" => $mybb->get_input('allowimgcode', MyBB::INPUT_INT), - "allowvideocode" => $mybb->get_input('allowvideocode', MyBB::INPUT_INT), - "allowsmilies" => $mybb->get_input('allowsmilies', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_config_calendars_add_commit_start"); - - $cid = $db->insert_query("calendars", $calendar); - - $plugins->run_hooks("admin_config_calendars_add_commit_end"); - - // Log admin action - log_admin_action($cid, $mybb->input['name']); - - flash_message($lang->success_calendar_created, 'success'); - admin_redirect("index.php?module=config-calendars"); - } - } - else - { - $mybb->input = array_merge($mybb->input, array( - "allowhtml" => 0, - "eventlimit" => 4, - "disporder" => 1, - "moderation" => 0 - ) - ); - } - - $page->add_breadcrumb_item($lang->add_calendar); - $page->output_header($lang->calendars." - ".$lang->add_calendar); - - $page->output_nav_tabs($sub_tabs, 'add_calendar'); - $form = new Form("index.php?module=config-calendars&action=add", "post"); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer($lang->add_calendar); - $form_container->output_row($lang->name." *", "", $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->display_order, $lang->display_order_desc, $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $select_list = array($lang->sunday, $lang->monday, $lang->tuesday, $lang->wednesday, $lang->thursday, $lang->friday, $lang->saturday); - $form_container->output_row($lang->week_start, $lang->week_start_desc, $form->generate_select_box('startofweek', $select_list, $mybb->input['startofweek'], array('id' => 'startofweek')), 'startofweek'); - $form_container->output_row($lang->event_limit, $lang->event_limit_desc, $form->generate_numeric_field('eventlimit', $mybb->input['eventlimit'], array('id' => 'eventlimit', 'min' => 0)), 'eventlimit'); - $form_container->output_row($lang->show_birthdays, $lang->show_birthdays_desc, $form->generate_yes_no_radio('showbirthdays', $mybb->input['showbirthdays'], true)); - $form_container->output_row($lang->moderate_events, $lang->moderate_events_desc, $form->generate_yes_no_radio('moderation', $mybb->input['moderation'], true)); - $form_container->output_row($lang->allow_html, "", $form->generate_yes_no_radio('allowhtml', $mybb->input['allowhtml'])); - $form_container->output_row($lang->allow_mycode, "", $form->generate_yes_no_radio('allowmycode', $mybb->input['allowmycode'])); - $form_container->output_row($lang->allow_img, "", $form->generate_yes_no_radio('allowimgcode', $mybb->input['allowimgcode'])); - $form_container->output_row($lang->allow_video, "", $form->generate_yes_no_radio('allowvideocode', $mybb->input['allowvideocode'])); - $form_container->output_row($lang->allow_smilies, "", $form->generate_yes_no_radio('allowsmilies', $mybb->input['allowsmilies'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_calendar); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "permissions") -{ - $usergroups = array(); - - $query = $db->simple_select("calendars", "*", "cid='".$mybb->get_input('cid', MyBB::INPUT_INT)."'"); - $calendar = $db->fetch_array($query); - - // Does the calendar not exist? - if(!$calendar['cid']) - { - flash_message($lang->error_invalid_calendar, 'error'); - admin_redirect("index.php?module=config-calendars"); - } - - $plugins->run_hooks("admin_config_calendars_permissions"); - - $query = $db->simple_select("usergroups", "*", "", array("order" => "name")); - while($usergroup = $db->fetch_array($query)) - { - $usergroups[$usergroup['gid']] = $usergroup; - } - - $query = $db->simple_select("calendarpermissions", "*", "cid='{$calendar['cid']}'"); - while($existing = $db->fetch_array($query)) - { - $existing_permissions[$existing['gid']] = $existing; - } - - if($mybb->request_method == "post") - { - foreach(array_keys($usergroups) as $group_id) - { - $permissions = $mybb->input['permissions'][$group_id]; - $db->delete_query("calendarpermissions", "cid='{$calendar['cid']}' AND gid='".(int)$group_id."'"); - - if(!$mybb->input['default_permissions'][$group_id]) - { - foreach(array('canviewcalendar','canaddevents','canbypasseventmod','canmoderateevents') as $calendar_permission) - { - if($permissions[$calendar_permission] == 1) - { - $permissions_array[$calendar_permission] = 1; - } - else - { - $permissions_array[$calendar_permission] = 0; - } - } - $permissions_array['gid'] = (int)$group_id; - $permissions_array['cid'] = $calendar['cid']; - $db->insert_query("calendarpermissions", $permissions_array); - } - } - - $plugins->run_hooks("admin_config_calendars_permissions_commit"); - - // Log admin action - log_admin_action($calendar['cid'], $calendar['name']); - - flash_message($lang->success_calendar_permissions_updated, 'success'); - admin_redirect("index.php?module=config-calendars"); - } - - $calendar['name'] = htmlspecialchars_uni($calendar['name']); - $page->add_breadcrumb_item($calendar['name'], "index.php?module=config-calendars&action=edit&cid={$calendar['cid']}"); - $page->add_breadcrumb_item($lang->permissions); - $page->output_header($lang->calendars." - ".$lang->edit_permissions); - - $form = new Form("index.php?module=config-calendars&action=permissions", "post"); - echo $form->generate_hidden_field("cid", $calendar['cid']); - - $table = new Table; - $table->construct_header($lang->permissions_group); - $table->construct_header($lang->permissions_view, array("class" => "align_center", "width" => "10%")); - $table->construct_header($lang->permissions_post_events, array("class" => "align_center", "width" => "10%")); - $table->construct_header($lang->permissions_bypass_moderation, array("class" => "align_center", "width" => "10%")); - $table->construct_header($lang->permissions_moderator, array("class" => "align_center", "width" => "10%")); - $table->construct_header($lang->permissions_all, array("class" => "align_center", "width" => "10%")); - - foreach($usergroups as $usergroup) - { - if($existing_permissions[$usergroup['gid']]) - { - $perms = $existing_permissions[$usergroup['gid']]; - $default_checked = false; - } - else - { - $perms = $usergroup; - $default_checked = true; - } - $perm_check = $all_check = ""; - $all_checked = true; - foreach(array('canviewcalendar','canaddevents','canbypasseventmod','canmoderateevents') as $calendar_permission) - { - if($usergroup[$calendar_permission] == 1) - { - $value = "this.checked"; - } - else - { - $value = "false"; - } - if($perms[$calendar_permission] != 1) - { - $all_checked = false; - } - if($perms[$calendar_permission] == 1) - { - $perms_checked[$calendar_permission] = 1; - } - else - { - $perms_checked[$calendar_permission] = 0; - } - $all_check .= "\$('#permissions_{$usergroup['gid']}_{$calendar_permission}').prop('checked', this.checked);\n"; - $perm_check .= "\$('#permissions_{$usergroup['gid']}_{$calendar_permission}').prop('checked', $value);\n"; - } - $default_click = "if(\$(this).is(':checked')) { $perm_check }"; - $reset_default = "if(!\$(this).is(':checked')) { \$('#permissions_{$usergroup['gid']}_all').prop('checked', false); }\n"; - $usergroup['title'] = htmlspecialchars_uni($usergroup['title']); - $table->construct_cell("{$usergroup['title']}
".$form->generate_check_box("default_permissions[{$usergroup['gid']}];", 1, "", array("id" => "default_permissions_{$usergroup['gid']}", "checked" => $default_checked, "onclick" => $default_click))." "); - $table->construct_cell($form->generate_check_box("permissions[{$usergroup['gid']}][canviewcalendar]", 1, "", array("id" => "permissions_{$usergroup['gid']}_canviewcalendar", "checked" => $perms_checked['canviewcalendar'], "onclick" => $reset_default)), array('class' => 'align_center')); - $table->construct_cell($form->generate_check_box("permissions[{$usergroup['gid']}][canaddevents]", 1, "", array("id" => "permissions_{$usergroup['gid']}_canaddevents", "checked" => $perms_checked['canaddevents'], "onclick" => $reset_default)), array('class' => 'align_center')); - $table->construct_cell($form->generate_check_box("permissions[{$usergroup['gid']}][canbypasseventmod]", 1, "", array("id" => "permissions_{$usergroup['gid']}_canbypasseventmod", "checked" => $perms_checked['canbypasseventmod'], "onclick" => $reset_default)), array('class' => 'align_center')); - $table->construct_cell($form->generate_check_box("permissions[{$usergroup['gid']}][canmoderateevents]", 1, "", array("id" => "permissions_{$usergroup['gid']}_canmoderateevents", "checked" => $perms_checked['canmoderateevents'], "onclick" => $reset_default)), array('class' => 'align_center')); - $table->construct_cell($form->generate_check_box("permissions[{$usergroup['gid']}][all]", 1, "", array("id" => "permissions_{$usergroup['gid']}_all", "checked" => $all_checked, "onclick" => $all_check)), array('class' => 'align_center')); - $table->construct_row(); - } - $table->output("{$lang->calendar_permissions_for} {$calendar['name']}"); - - if(!$no_results) - { - $buttons[] = $form->generate_submit_button($lang->save_permissions); - $form->output_submit_wrapper($buttons); - } - - $form->end(); - - $page->output_footer(); - -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("calendars", "*", "cid='".$mybb->get_input('cid', MyBB::INPUT_INT)."'"); - $calendar = $db->fetch_array($query); - - // Does the calendar not exist? - if(!$calendar['cid']) - { - flash_message($lang->error_invalid_calendar, 'error'); - admin_redirect("index.php?module=config-calendars"); - } - - $plugins->run_hooks("admin_config_calendars_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - - if(!isset($mybb->input['disporder'])) - { - $errors[] = $lang->error_missing_order; - } - - if(!$errors) - { - $updated_calendar = array( - "name" => $db->escape_string($mybb->input['name']), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "startofweek" => $mybb->get_input('startofweek', MyBB::INPUT_INT), - "eventlimit" => $mybb->get_input('eventlimit', MyBB::INPUT_INT), - "showbirthdays" => $mybb->get_input('showbirthdays', MyBB::INPUT_INT), - "moderation" => $mybb->get_input('moderation', MyBB::INPUT_INT), - "allowhtml" => $mybb->get_input('allowhtml', MyBB::INPUT_INT), - "allowmycode" => $mybb->get_input('allowmycode', MyBB::INPUT_INT), - "allowimgcode" => $mybb->get_input('allowimgcode', MyBB::INPUT_INT), - "allowvideocode" => $mybb->get_input('allowvideocode', MyBB::INPUT_INT), - "allowsmilies" => $mybb->get_input('allowsmilies', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_config_calendars_edit_commit"); - - $db->update_query("calendars", $updated_calendar, "cid='{$calendar['cid']}'"); - - // Log admin action - log_admin_action($calendar['cid'], $mybb->input['name']); - - flash_message($lang->success_calendar_updated, 'success'); - admin_redirect("index.php?module=config-calendars"); - } - } - - $page->add_breadcrumb_item($lang->edit_calendar); - $page->output_header($lang->calendars." - ".$lang->edit_calendar); - - $sub_tabs['edit_calendar'] = array( - 'title' => $lang->edit_calendar, - 'link' => "index.php?module=config-calendars&action=edit", - 'description' => $lang->edit_calendar_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_calendar'); - $form = new Form("index.php?module=config-calendars&action=edit", "post"); - - echo $form->generate_hidden_field("cid", $calendar['cid']); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = $calendar; - } - - $form_container = new FormContainer($lang->edit_calendar); - $form_container->output_row($lang->name." *", "", $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->display_order." *", $lang->display_order_desc, $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $select_list = array($lang->sunday, $lang->monday, $lang->tuesday, $lang->wednesday, $lang->thursday, $lang->friday, $lang->saturday); - $form_container->output_row($lang->week_start, $lang->week_start_desc, $form->generate_select_box('startofweek', $select_list, $mybb->input['startofweek'], array('id' => 'startofweek')), 'startofweek'); - $form_container->output_row($lang->event_limit, $lang->event_limit_desc, $form->generate_numeric_field('eventlimit', $mybb->input['eventlimit'], array('id' => 'eventlimit', 'min' => 0)), 'eventlimit'); - $form_container->output_row($lang->show_birthdays, $lang->show_birthdays_desc, $form->generate_yes_no_radio('showbirthdays', $mybb->input['showbirthdays'], true)); - $form_container->output_row($lang->moderate_events, $lang->moderate_events_desc, $form->generate_yes_no_radio('moderation', $mybb->input['moderation'], true)); - $form_container->output_row($lang->allow_html, "", $form->generate_yes_no_radio('allowhtml', $mybb->input['allowhtml'])); - $form_container->output_row($lang->allow_mycode, "", $form->generate_yes_no_radio('allowmycode', $mybb->input['allowmycode'])); - $form_container->output_row($lang->allow_img, "", $form->generate_yes_no_radio('allowimgcode', $mybb->input['allowimgcode'])); - $form_container->output_row($lang->allow_video, "", $form->generate_yes_no_radio('allowvideocode', $mybb->input['allowvideocode'])); - $form_container->output_row($lang->allow_smilies, "", $form->generate_yes_no_radio('allowsmilies', $mybb->input['allowsmilies'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_calendar); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("calendars", "*", "cid='".$mybb->get_input('cid', MyBB::INPUT_INT)."'"); - $calendar = $db->fetch_array($query); - - // Does the calendar not exist? - if(!$calendar['cid']) - { - flash_message($lang->error_invalid_calendar, 'error'); - admin_redirect("index.php?module=config-calendars"); - } - - $plugins->run_hooks("admin_config_calendars_delete"); - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-calendars"); - } - - if($mybb->request_method == "post") - { - // Delete the calendar - $db->delete_query("calendars", "cid='{$calendar['cid']}'"); - $db->delete_query("calendarpermissions", "cid='{$calendar['cid']}'"); - $db->delete_query("events", "cid='{$calendar['cid']}'"); - - $plugins->run_hooks("admin_config_calendars_delete_commit"); - - // Log admin action - log_admin_action($calendar['cid'], $calendar['name']); - - flash_message($lang->success_calendar_deleted, 'success'); - admin_redirect("index.php?module=config-calendars"); - } - else - { - $page->output_confirm_action("index.php?module=config-calendars&action=delete&cid={$calendar['cid']}", $lang->confirm_calendar_deletion); - } -} - -if($mybb->input['action'] == "update_order" && $mybb->request_method == "post") -{ - if(!is_array($mybb->input['disporder'])) - { - admin_redirect("index.php?module=config-calendars"); - } - - $plugins->run_hooks("admin_config_calendars_update_order"); - - foreach($mybb->input['disporder'] as $cid => $order) - { - $update_query = array( - "disporder" => (int)$order - ); - $db->update_query("calendars", $update_query, "cid='".(int)$cid."'"); - } - - $plugins->run_hooks("admin_config_calendars_update_order_commit"); - - // Log admin action - log_admin_action(); - - flash_message($lang->success_calendar_orders_updated, 'success'); - admin_redirect("index.php?module=config-calendars"); -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->manage_calendars); - - $page->output_nav_tabs($sub_tabs, 'manage_calendars'); - - $form = new Form("index.php?module=config-calendars&action=update_order", "post"); - $table = new Table; - $table->construct_header($lang->calendar); - $table->construct_header($lang->order, array('width' => '5%', 'class' => 'align_center')); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 3, "width" => 300)); - - $query = $db->simple_select("calendars", "*", "", array('order_by' => 'disporder')); - while($calendar = $db->fetch_array($query)) - { - $calendar['name'] = htmlspecialchars_uni($calendar['name']); - $table->construct_cell("{$calendar['name']}"); - $table->construct_cell($form->generate_numeric_field("disporder[{$calendar['cid']}]", $calendar['disporder'], array('id' => 'disporder', 'style' => 'width: 80%', 'class' => 'align_center', 'min' => 0))); - $table->construct_cell("{$lang->edit}", array("width" => 100, "class" => "align_center")); - $table->construct_cell("{$lang->permissions}", array("width" => 100, "class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_calendar_deletion}')\">{$lang->delete}", array("width" => 100, "class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_calendars, array('colspan' => 5)); - $table->construct_row(); - $no_results = true; - } - - $table->output($lang->manage_calendars); - - if(!$no_results) - { - $buttons[] = $form->generate_submit_button($lang->save_calendar_orders); - $form->output_submit_wrapper($buttons); - } - - $form->end(); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/config/help_documents.php b/html/forums/admin/modules/config/help_documents.php deleted file mode 100644 index a303c3a..0000000 --- a/html/forums/admin/modules/config/help_documents.php +++ /dev/null @@ -1,624 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->help_documents, "index.php?module=config-help_documents"); - -$plugins->run_hooks("admin_config_help_documents_begin"); - -// Add something -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_config_help_documents_add"); - - // Add section - if($mybb->input['type'] == "section") - { - $plugins->run_hooks("admin_config_help_documents_add_section"); - - // Do add? - if($mybb->request_method == "post") - { - if(empty($mybb->input['name'])) - { - $errors[] = $lang->error_section_missing_name; - } - - if(empty($mybb->input['description'])) - { - $errors[] = $lang->error_section_missing_description; - } - - if(!isset($mybb->input['enabled'])) - { - $errors[] = $lang->error_section_missing_enabled; - } - - if($mybb->input['enabled'] != 1) - { - $mybb->input['enabled'] = 0; - } - - if(!is_array($errors)) - { - $sql_array = array( - "name" => $db->escape_string($mybb->input['name']), - "description" => $db->escape_string($mybb->input['description']), - "usetranslation" => $mybb->get_input('usetranslation', MyBB::INPUT_INT), - "enabled" => $mybb->get_input('enabled', MyBB::INPUT_INT), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT) - ); - - $sid = $db->insert_query("helpsections", $sql_array); - - $plugins->run_hooks("admin_config_help_documents_add_section_commit"); - - // Log admin action - log_admin_action($sid, $mybb->input['name'], 'section'); - - flash_message($lang->success_help_section_added, 'success'); - admin_redirect('index.php?module=config-help_documents'); - } - } - - $page->add_breadcrumb_item($lang->add_new_section); - $page->output_header($lang->help_documents." - ".$lang->add_new_section); - - $sub_tabs['manage_help_documents'] = array( - 'title' => $lang->manage_help_documents, - 'link' => "index.php?module=config-help_documents" - ); - - $sub_tabs['add_help_document'] = array( - 'title' => $lang->add_new_document, - 'link' => "index.php?module=config-help_documents&action=add&type=document" - ); - - $sub_tabs['add_help_section'] = array( - 'title' => $lang->add_new_section, - 'link' => "index.php?module=config-help_documents&action=add&type=section", - 'description' => $lang->add_new_section_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_help_section'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $query = $db->simple_select("helpsections", "MAX(disporder) as maxdisp"); - $mybb->input['disporder'] = $db->fetch_field($query, "maxdisp")+1; - $mybb->input['enabled'] = 1; - $mybb->input['usetranslation'] = 1; - } - - $form = new Form("index.php?module=config-help_documents&action=add&type=section", "post", "add"); - echo $form->generate_hidden_field("usetranslation", $mybb->input['usetranslation']); - - $form_container = new FormContainer($lang->add_new_section); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->short_description." *", "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->display_order, "", $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->output_row($lang->enabled." *", "", $form->generate_yes_no_radio('enabled', $mybb->input['enabled'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_section); - - $form->output_submit_wrapper($buttons); - $form->end(); - } - - // Add page - else - { - $plugins->run_hooks("admin_config_help_documents_add_page"); - - // Do add? - if($mybb->request_method == "post") - { - if(empty($mybb->input['sid'])) - { - $errors[] = $lang->error_missing_sid; - } - - if(empty($mybb->input['name'])) - { - $errors[] = $lang->error_document_missing_name; - } - - if(empty($mybb->input['description'])) - { - $errors[] = $lang->error_document_missing_description; - } - - if(empty($mybb->input['document'])) - { - $errors[] = $lang->error_document_missing_document; - } - - if(!isset($mybb->input['enabled'])) - { - $errors[] = $lang->error_document_missing_enabled; - } - - if($mybb->input['enabled'] != 1) - { - $mybb->input['enabled'] = 0; - } - - if(!is_array($errors)) - { - $sql_array = array( - "sid" => $mybb->get_input('sid', MyBB::INPUT_INT), - "name" => $db->escape_string($mybb->input['name']), - "description" => $db->escape_string($mybb->input['description']), - "document" => $db->escape_string($mybb->input['document']), - "usetranslation" => $mybb->get_input('usetranslation', MyBB::INPUT_INT), - "enabled" => $mybb->get_input('enabled', MyBB::INPUT_INT), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT) - ); - - $hid = $db->insert_query("helpdocs", $sql_array); - - $plugins->run_hooks("admin_config_help_documents_add_page_commit"); - - // Log admin action - log_admin_action($hid, $mybb->input['name'], 'document'); - - flash_message($lang->success_help_document_added, 'success'); - admin_redirect('index.php?module=config-help_documents'); - } - } - - $page->add_breadcrumb_item($lang->add_new_document); - $page->output_header($lang->help_documents." - ".$lang->add_new_document); - - $sub_tabs['manage_help_documents'] = array( - 'title' => $lang->manage_help_documents, - 'link' => "index.php?module=config-help_documents" - ); - - $sub_tabs['add_help_document'] = array( - 'title' => $lang->add_new_document, - 'link' => "index.php?module=config-help_documents&action=add&type=document", - 'description' => $lang->add_new_document_desc - ); - - $sub_tabs['add_help_section'] = array( - 'title' => $lang->add_new_section, - 'link' => "index.php?module=config-help_documents&action=add&type=section" - ); - - $page->output_nav_tabs($sub_tabs, 'add_help_document'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - // Select the largest existing display order - $query = $db->simple_select("helpdocs", "MAX(disporder) as maxdisp"); - $mybb->input['disporder'] = $db->fetch_field($query, "maxdisp")+1; - $mybb->input['enabled'] = 1; - $mybb->input['usetranslation'] = 1; - } - - $form = new Form("index.php?module=config-help_documents&action=add&type=document", "post", "add"); - echo $form->generate_hidden_field("usetranslation", $mybb->input['usetranslation']); - - $form_container = new FormContainer($lang->add_new_document); - $query = $db->simple_select("helpsections", "sid, name"); - - $sections = array(); - while($section = $db->fetch_array($query)) - { - $sections[$section['sid']] = $section['name']; - } - $form_container->output_row($lang->section." *", "", $form->generate_select_box("sid", $sections, $mybb->input['sid'], array('id' => 'sid')), 'sid'); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->short_description." *", "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->document." *", "", $form->generate_text_area('document', $mybb->input['document'], array('id' => 'document')), 'document'); - $form_container->output_row($lang->display_order, "", $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->output_row($lang->enabled." *", "", $form->generate_yes_no_radio('enabled', $mybb->input['enabled'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_document); - - $form->output_submit_wrapper($buttons); - $form->end(); - } - - $page->output_footer(); -} - -// Edit something -if($mybb->input['action'] == "edit") -{ - $plugins->run_hooks("admin_config_help_documents_edit"); - - // Edit a section - if($mybb->input['sid'] && !$mybb->input['hid']) - { - $query = $db->simple_select("helpsections", "*", "sid = '".$mybb->get_input('sid', MyBB::INPUT_INT)."'"); - $section = $db->fetch_array($query); - - $plugins->run_hooks("admin_config_help_documents_edit_section"); - - // Do edit? - if($mybb->request_method == "post") - { - $sid = $mybb->get_input('sid', MyBB::INPUT_INT); - - if(empty($sid)) - { - $errors[] = $lang->error_invalid_sid; - } - - if(empty($mybb->input['name'])) - { - $errors[] = $lang->error_section_missing_name; - } - - if(empty($mybb->input['description'])) - { - $errors[] = $lang->error_section_missing_description; - } - - if(!isset($mybb->input['enabled'])) - { - $errors[] = $lang->error_section_missing_enabled; - } - - if($mybb->input['enabled'] != 1) - { - $mybb->input['enabled'] = 0; - } - - if(!is_array($errors)) - { - $sql_array = array( - "name" => $db->escape_string($mybb->input['name']), - "description" => $db->escape_string($mybb->input['description']), - "usetranslation" => $mybb->get_input('usetranslation', MyBB::INPUT_INT), - "enabled" => $mybb->get_input('enabled', MyBB::INPUT_INT), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_config_help_documents_edit_section_commit"); - - $db->update_query("helpsections", $sql_array, "sid = '{$sid}'"); - - // Log admin action - log_admin_action($sid, $mybb->input['name'], 'section'); - - flash_message($lang->success_help_section_updated, 'success'); - admin_redirect('index.php?module=config-help_documents'); - } - } - - $page->add_breadcrumb_item($lang->edit_section); - $page->output_header($lang->help_documents." - ".$lang->edit_section); - - - $sub_tabs['edit_help_section'] = array( - 'title' => $lang->edit_section, - 'link' => "index.php?module=config-help_documents&action=edit&sid=".$section['sid'], - 'description' => $lang->edit_section_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_help_section'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['sid'] = $section['sid']; - $mybb->input['name'] = $section['name']; - $mybb->input['description'] = $section['description']; - $mybb->input['disporder'] = $section['disporder']; - $mybb->input['enabled'] = $section['enabled']; - $mybb->input['usetranslation'] = $section['usetranslation']; - } - - $form = new Form("index.php?module=config-help_documents&action=edit", "post", "edit"); - - echo $form->generate_hidden_field("sid", $section['sid']); - echo $form->generate_hidden_field("usetranslation", $mybb->input['usetranslation']); - - $form_container = new FormContainer($lang->edit_section." ({$lang->id} ".$section['sid'].")"); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->short_description." *", "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->display_order, "", $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->output_row($lang->enabled." *", "", $form->generate_yes_no_radio('enabled', $mybb->input['enabled'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->edit_section); - - $form->output_submit_wrapper($buttons); - $form->end(); - } - - // Edit document - else - { - $plugins->run_hooks("admin_config_help_documents_edit_page"); - - // Do edit? - if($mybb->request_method == "post") - { - $hid = $mybb->get_input('hid', MyBB::INPUT_INT); - - if(empty($hid)) - { - $errors[] = $lang->error_invalid_sid; - } - - if(empty($mybb->input['name'])) - { - $errors[] = $lang->error_document_missing_name; - } - - if(empty($mybb->input['description'])) - { - $errors[] = $lang->error_document_missing_description; - } - - if(empty($mybb->input['document'])) - { - $errors[] = $lang->error_document_missing_document; - } - - if(!isset($mybb->input['enabled'])) - { - $errors[] = $lang->error_document_missing_enabled; - } - - if($mybb->input['enabled'] != 1) - { - $mybb->input['enabled'] = 0; - } - - if(!is_array($errors)) - { - $sql_array = array( - "sid" => $mybb->get_input('sid', MyBB::INPUT_INT), - "name" => $db->escape_string($mybb->input['name']), - "description" => $db->escape_string($mybb->input['description']), - "document" => $db->escape_string($mybb->input['document']), - "usetranslation" => $mybb->get_input('usetranslation', MyBB::INPUT_INT), - "enabled" => $mybb->get_input('enabled', MyBB::INPUT_INT), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_config_help_documents_edit_page_commit"); - - $db->update_query("helpdocs", $sql_array, "hid = '{$hid}'"); - - // Log admin action - log_admin_action($hid, $mybb->input['name'], 'document'); - - flash_message($lang->success_help_document_updated, 'success'); - admin_redirect('index.php?module=config-help_documents'); - } - } - - $page->add_breadcrumb_item($lang->edit_document); - $page->output_header($lang->help_documents." - ".$lang->edit_document); - - - $sub_tabs['edit_help_document'] = array( - 'title' => $lang->edit_document, - 'link' => "index.php?module=config-help_documents&action=edit&hid=".$hid, - 'description' => $lang->edit_document_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_help_document'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $query = $db->simple_select("helpdocs", "*", "hid = '".$mybb->get_input('hid', MyBB::INPUT_INT)."'"); - $doc = $db->fetch_array($query); - $mybb->input['hid'] = $doc['hid']; - $mybb->input['sid'] = $doc['sid']; - $mybb->input['name'] = $doc['name']; - $mybb->input['description'] = $doc['description']; - $mybb->input['document'] = $doc['document']; - $mybb->input['disporder'] = $doc['disporder']; - $mybb->input['enabled'] = $doc['enabled']; - $mybb->input['usetranslation'] = $doc['usetranslation']; - } - - $form = new Form("index.php?module=config-help_documents&action=edit", "post", "edit"); - - echo $form->generate_hidden_field("hid", $doc['hid']); - echo $form->generate_hidden_field("usetranslation", $mybb->input['usetranslation']); - - $form_container = new FormContainer($lang->edit_document." ({$lang->id} ".$doc['hid'].")"); - - $sections = array(); - $query = $db->simple_select("helpsections", "sid, name"); - while($section = $db->fetch_array($query)) - { - $sections[$section['sid']] = $section['name']; - } - $form_container->output_row($lang->section." *", "", $form->generate_select_box("sid", $sections, $mybb->input['sid']), 'sid'); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->short_description." *", "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->document." *", "", $form->generate_text_area('document', $mybb->input['document'], array('id' => 'document')), 'document'); - $form_container->output_row($lang->display_order, "", $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->output_row($lang->enabled." *", "", $form->generate_yes_no_radio('enabled', $mybb->input['enabled'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->edit_document); - - $form->output_submit_wrapper($buttons); - $form->end(); - } - - $page->output_footer(); -} - -// Delete something -if($mybb->input['action'] == "delete") -{ - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-help_documents"); - } - - $plugins->run_hooks("admin_config_help_documents_delete"); - - // Do delete something? - if($mybb->request_method == "post") - { - // Delete section - if(isset($mybb->input['sid'])) - { - $sid = $mybb->get_input('sid', MyBB::INPUT_INT); - - $query = $db->simple_select("helpsections", "*", "sid='{$sid}'"); - $section = $db->fetch_array($query); - - // Invalid section? - if(!$section['sid']) - { - flash_message($lang->error_missing_section_id, 'error'); - admin_redirect("index.php?module=config-help_documents"); - } - - // Delete section and its documents - $db->delete_query("helpsections", "sid = '{$section['sid']}'", 1); - $db->delete_query("helpdocs", "sid = '{$section['sid']}'"); - - $plugins->run_hooks("admin_config_help_documents_delete_section_commit"); - - // Log admin action - log_admin_action($section['sid'], $section['name'], 'section'); - - flash_message($lang->success_section_deleted, 'success'); - admin_redirect("index.php?module=config-help_documents"); - } - - // Delete document - else - { - $hid = $mybb->get_input('hid', MyBB::INPUT_INT); - - $query = $db->simple_select("helpdocs", "*", "hid='{$hid}'"); - $doc = $db->fetch_array($query); - - // Invalid document? - if(!$doc['hid']) - { - flash_message($lang->error_missing_hid, 'error'); - admin_redirect("index.php?module=config-help_documents"); - } - - $db->delete_query("helpdocs", "hid = '{$doc['hid']}'", 1); - - $plugins->run_hooks("admin_config_help_documents_delete_page_commit"); - - // Log admin action - log_admin_action($doc['hid'], $doc['name'], 'document'); - - flash_message($lang->success_document_deleted, 'success'); - admin_redirect("index.php?module=config-help_documents"); - } - } - // Show form for deletion - else - { - // Section - if(isset($mybb->input['sid'])) - { - $sid = $mybb->get_input('sid', MyBB::INPUT_INT); - $page->output_confirm_action("index.php?module=config-help_documents&action=delete&sid={$sid}", $lang->confirm_section_deletion); - } - // Document - else - { - $hid = $mybb->get_input('hid', MyBB::INPUT_INT); - $page->output_confirm_action("index.php?module=config-help_documents&action=delete&hid={$hid}", $lang->confirm_document_deletion); - } - } -} - -// List document and sections -if(!$mybb->input['action']) -{ - $page->output_header($lang->help_documents); - - $sub_tabs['manage_help_documents'] = array( - 'title' => $lang->manage_help_documents, - 'link' => "index.php?module=config-help_documents", - 'description'=> $lang->manage_help_documents_desc - ); - - $sub_tabs['add_help_document'] = array( - 'title' => $lang->add_new_document, - 'link' => "index.php?module=config-help_documents&action=add&type=document" - ); - - $sub_tabs['add_help_section'] = array( - 'title' => $lang->add_new_section, - 'link' => "index.php?module=config-help_documents&action=add&type=section" - ); - - $plugins->run_hooks("admin_config_help_documents_start"); - - $page->output_nav_tabs($sub_tabs, 'manage_help_documents'); - - $table = new Table; - $table->construct_header($lang->section_document); - $table->construct_header($lang->controls, array('class' => "align_center", 'colspan' => 2, "width" => "150")); - - $query = $db->simple_select("helpsections", "*", "", array('order_by' => "disporder")); - while($section = $db->fetch_array($query)) - { - $table->construct_cell("
{$section['name']}
{$section['description']}
"); - $table->construct_cell("{$lang->edit}", array("class" => "align_center", "width" => '60')); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_section_deletion}')\">{$lang->delete}", array("class" => "align_center", "width" => '90')); - $table->construct_row(); - - $query2 = $db->simple_select("helpdocs", "*", "sid='{$section['sid']}'", array('order_by' => "disporder")); - while($doc = $db->fetch_array($query2)) - { - $table->construct_cell("
{$doc['name']}
{$doc['description']}
"); - $table->construct_cell("{$lang->edit}", array("class" => "align_center", "width" => '60')); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_document_deletion}')\">{$lang->delete}", array("class" => "align_center", "width" => '90')); - $table->construct_row(); - } - } - - // No documents message - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_help_documents, array('colspan' => 3)); - $table->construct_row(); - } - - $table->output($lang->help_documents); - $page->output_footer(); -} diff --git a/html/forums/admin/modules/config/index.html b/html/forums/admin/modules/config/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/modules/config/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/modules/config/languages.php b/html/forums/admin/modules/config/languages.php deleted file mode 100644 index ef90833..0000000 --- a/html/forums/admin/modules/config/languages.php +++ /dev/null @@ -1,1052 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$languages = $lang->get_languages(); - -$page->add_breadcrumb_item($lang->languages, "index.php?module=config-languages"); - -$plugins->run_hooks("admin_config_languages_begin"); - -if($mybb->input['action'] == "edit_properties") -{ - $editlang = basename($mybb->input['lang']); - $file = MYBB_ROOT."inc/languages/".$editlang.".php"; - if(!file_exists($file)) - { - flash_message($lang->error_invalid_file, 'error'); - admin_redirect("index.php?module=config-languages"); - } - - $plugins->run_hooks("admin_config_languages_edit_properties"); - - if($mybb->request_method == "post") - { - if(!is_writable($file)) - { - flash_message($lang->error_cannot_write_to_file, 'error'); - admin_redirect("index.php?module=config-languages"); - } - - foreach($mybb->input['info'] as $key => $info) - { - $info = str_replace("\\", "\\\\", $info); - $info = str_replace('$', '\$', $info); - - if($key == 'admin' || $key == 'rtl') - { - $info = (int)$info; - } - - $newlanginfo[$key] = str_replace("\"", '\"', $info); - } - - // Get contents of existing file - require $file; - - // Make the contents of the new file - $newfile = " on all pages -\$langinfo['htmllang'] = \"{$newlanginfo['htmllang']}\"; - -// Sets the character set, blank uses the default. -\$langinfo['charset'] = \"{$newlanginfo['charset']}\";\n"; - - // Put it in! - if($file = fopen($file, "w")) - { - fwrite($file, $newfile); - fclose($file); - - $plugins->run_hooks("admin_config_languages_edit_properties_commit"); - - // Log admin action - log_admin_action($editlang); - - flash_message($lang->success_langprops_updated, 'success'); - admin_redirect("index.php?module=config-languages&action=edit&lang={$editlang}&editwith={$editwith}"); - } - else - { - $errors[] = $lang->error_cannot_write_to_file; - } - } - - $page->add_breadcrumb_item(preg_replace("<\?|\?>", "?", $languages[$editlang]), "index.php?module=config-languages&action=edit&lang={$editlang}"); - $page->add_breadcrumb_item($lang->nav_editing_set); - - $page->output_header($lang->languages); - - $sub_tabs['edit_properties'] = array( - "title" => $lang->edit_properties, - "link" => "index.php?module=config-languages", - "description" => $lang->edit_properties_desc - ); - $page->output_nav_tabs($sub_tabs, "edit_properties"); - - // Get language info - require $file; - - $form = new Form("index.php?module=config-languages&action=edit_properties", "post", "editset"); - echo $form->generate_hidden_field("lang", $editlang); - echo $form->generate_hidden_field("info[author]", $langinfo['author']); - echo $form->generate_hidden_field("info[website]", $langinfo['website']); - echo $form->generate_hidden_field("info[version]", $langinfo['version']); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - if($langinfo['admin']) - { - $mybb->input['info']['admin'] = 1; - } - else - { - $mybb->input['info']['admin'] = 0; - } - - if($langinfo['rtl']) - { - $mybb->input['info']['rtl'] = 1; - } - else - { - $mybb->input['info']['rtl'] = 0; - } - - $mybb->input['info']['name'] = $langinfo['name']; - $mybb->input['info']['htmllang'] = $langinfo['htmllang']; - $mybb->input['info']['charset'] = $langinfo['charset']; - } - - $form_container = new FormContainer($lang->edit_properties); - - $form_container->output_row($lang->friendly_name." *", "", $form->generate_text_box('info[name]', $mybb->input['info']['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->language_in_html." *", "", $form->generate_text_box('info[htmllang]', $mybb->input['info']['htmllang'], array('id' => 'htmllang')), 'htmllang'); - $form_container->output_row($lang->charset." *", "", $form->generate_text_box('info[charset]', $mybb->input['info']['charset'], array('id' => 'charset')), 'charset'); - $form_container->output_row($lang->rtl." *", "", $form->generate_yes_no_radio('info[rtl]', $mybb->input['info']['rtl'], array('id' => 'rtl')), 'rtl'); - $form_container->output_row($lang->admin." *", "", $form->generate_yes_no_radio('info[admin]', $mybb->input['info']['admin'], array('id' => 'admin')), 'admin'); - - // Check if file is writable, before allowing submission - if(!is_writable($file)) - { - $no_write = 1; - $page->output_alert($lang->alert_note_cannot_write); - } - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_language_file, array('disabled' => $no_write)); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "quick_phrases") -{ - // Validate input - $editlang = basename($mybb->input['lang']); - $folder = MYBB_ROOT."inc/languages/".$editlang."/"; - - $page->add_breadcrumb_item(preg_replace("<\?|\?>", "?", $languages[$editlang]), "index.php?module=config-languages&action=quick_edit&lang={$editlang}"); - - // Validate that this language pack really exists - if(file_exists(MYBB_ROOT."inc/languages/".$editlang.".php")) - { - // Then validate language pack folders (and try to fix them if missing) - @mkdir($folder); - @mkdir($folder."admin"); - } - - if(!file_exists($folder) || !file_exists($folder."admin")) - { - flash_message($lang->error_folders_fail, 'error'); - admin_redirect("index.php?module=config-languages"); - } - - $plugins->run_hooks("admin_config_languages_quick_phrases"); - - $quick_phrases = array( - 'member.lang.php' => array( - 'agreement' => $lang->quickphrases_agreement, - 'agreement_1' => $lang->quickphrases_agreement_1, - 'agreement_2' => $lang->quickphrases_agreement_2, - 'agreement_3' => $lang->quickphrases_agreement_3, - 'agreement_4' => $lang->quickphrases_agreement_4, - 'agreement_5' => $lang->quickphrases_agreement_5 - ), - 'messages.lang.php' => array( - 'error_nopermission_guest_1' => $lang->quickphrases_error_nopermission_guest_1, - 'error_nopermission_guest_2' => $lang->quickphrases_error_nopermission_guest_2, - 'error_nopermission_guest_3' => $lang->quickphrases_error_nopermission_guest_3, - 'error_nopermission_guest_4' => $lang->quickphrases_error_nopermission_guest_4 - ) - ); - - if($mybb->request_method == 'post') - { - if($mybb->request_method == 'post') - { - // We have more than one file to edit, lets set flag for all of them. - $editsuccess = true; - foreach($quick_phrases as $file => $phrases) - { - @include $folder.$file; - $contents_file = (array)$l; - unset($l); - - foreach($phrases as $key => $value) - { - // validation - we fetch from input only variables that are defined in $quick_phrases array - $contents_file[$key] = $mybb->input['edit'][$key]; - } - // Save edited language file - if($fp = @fopen($folder.$file, "w")) - { - // We need info about edited language files to generate credits for our file - require MYBB_ROOT."inc/languages/".$editlang.".php"; - - // Lets make nice credits header in language file - $lang_file_credits = "#i", " ", $langinfo['name'])."\n"; - $lang_file_credits .= "// Author of the language pack : ".preg_replace("#<\?|\?>#i", " ", $langinfo['author'])."\n"; - $lang_file_credits .= "// Language pack translators website : ".preg_replace("#<\?|\?>#i", " ", $langinfo['website'])."\n"; - $lang_file_credits .= "// Compatible version of MyBB : ".preg_replace("#<\?|\?>#i", " ", $langinfo['version'])."\n"; - $lang_file_credits .= "// Last edited in MyBB Editor by : ".preg_replace("#<\?|\?>#i", " ", $mybb->user['username'])."\n"; - $lang_file_credits .= "// Last edited date : ".gmdate("r")."\n"; - $lang_file_credits .= "// ".str_repeat('-',80)."\n\n"; - - $contents_wfile = $lang_file_credits; - foreach($contents_file as $key => $value) - { - $contents_wfile .= "\$l['".$key."'] = ".var_export($value, true).";\n"; - } - - flock($fp, LOCK_EX); - fwrite($fp, $contents_wfile); - flock($fp, LOCK_UN); - fclose($fp); - } - else - { - // One of files failed - $editsuccess = false; - } - } - - if($editsuccess == true) - { - // Log admin action - log_admin_action($editlang); - - flash_message($lang->success_quickphrases_updated, 'success'); - admin_redirect('index.php?module=config-languages&action=edit&lang='.$editlang); - } - } - } - - $page->output_header($lang->languages); - - $sub_tabs['language_files'] = array( - 'title' => $lang->language_files, - 'link' => "index.php?module=config-languages&action=edit&lang=".$editlang, - 'description' => $lang->language_files_desc - ); - - $sub_tabs['quick_phrases'] = array( - 'title' => $lang->quick_phrases, - 'link' => "index.php?module=config-languages&action=quick_phrases&lang=".$editlang, - 'description' => $lang->quick_phrases_desc - ); - - $page->output_nav_tabs($sub_tabs, 'quick_phrases'); - - $form = new Form('index.php?module=config-languages&action=quick_phrases&lang='.$editlang, 'post', 'quick_phrases'); - - if($errors) - { - $page->output_inline_error($errors); - } - - $table = new Table; - - // Check if files are writable, before allowing submission - $no_write = null; - foreach($quick_phrases as $file => $phrases) - { - if(file_exists($folder.$file) && !is_writable($folder.$file) || !is_writable($folder)) - { - $no_write = 1; - } - } - - if($no_write) - { - $page->output_alert($lang->alert_note_cannot_write); - } - - $form_container = new FormContainer($lang->quick_phrases); - - foreach($quick_phrases as $file => $phrases) - { - unset($langinfo); - @include MYBB_ROOT."inc/languages/".$editlang.".php"; - $quickphrases_dir_class = " langeditor_ltr"; - if((int)$langinfo['rtl'] > 0) - { - $quickphrases_dir_class = " langeditor_rtl"; - } - - @include $folder.$file; - foreach($phrases as $phrase => $description) - { - $value = $l[$phrase]; - if(my_strtolower($langinfo['charset']) == "utf-8") - { - $value = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return dec_to_utf8(hexdec($matches[1]));'), $value); - } - else - { - $value = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return "&#".hexdec($matches[1]).";";'), $value); - } - - $form_container->output_row($description, $phrase, $form->generate_text_area("edit[$phrase]", $value, array('id' => 'lang_'.$phrase, 'rows' => 2, 'class' => "langeditor_textarea_edit {$quickphrases_dir_class}")), 'lang_'.$phrase, array('width' => '50%')); - } - } - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_language_file, array('disabled' => $no_write)); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - // Validate input - $editlang = basename($mybb->input['lang']); - $folder = MYBB_ROOT."inc/languages/".$editlang."/"; - - $page->add_breadcrumb_item(preg_replace("<\?|\?>", "?", $languages[$editlang]), "index.php?module=config-languages&action=edit&lang={$editlang}"); - - $editwith = basename($mybb->input['editwith']); - $editwithfolder = ''; - - if($editwith) - { - $editwithfolder = MYBB_ROOT."inc/languages/".$editwith."/"; - } - - // Validate that edited language pack really exists - if(file_exists(MYBB_ROOT."inc/languages/".$editlang.".php")) - { - // Then validate edited language pack folders (and try to fix them if missing) - @mkdir($folder); - @mkdir($folder."admin"); - } - - if(!file_exists($folder) || !file_exists($folder."admin")) - { - flash_message($lang->error_folders_fail, 'error'); - admin_redirect("index.php?module=config-languages"); - } - - // If we edit in compare mode, verify that at least folders of compared language exists - if($editwithfolder && (!file_exists($editwithfolder) || !file_exists($editwithfolder))) - { - flash_message($lang->error_invalid_set, 'error'); - admin_redirect("index.php?module=config-languages"); - } - - $plugins->run_hooks("admin_config_languages_edit"); - - if(isset($mybb->input['file'])) - { - // Validate input - $file = basename($mybb->input['file']); - if($mybb->input['inadmin'] == 1) - { - $file = 'admin/'.$file; - } - $page->add_breadcrumb_item($file); - - $editfile = $folder.$file; - $withfile = ''; - - $editwithfile = ''; - if($editwithfolder) - { - $editwithfile = $editwithfolder.$file; - } - - if($mybb->request_method == "post") - { - // Save edited phrases to language file - - // To validate input - build array of keys that allready exist in files - @include $editfile; - $valid_keys = (array)$l; - unset($l); - @include $editwithfile; - $valid_keys = array_merge($valid_keys, (array)$l); - unset($l); - - // Then fetch from input only valid keys - foreach($valid_keys as $key => $value) - { - $contents_wfile .= "\$l['".$key."'] = ".var_export($mybb->input['edit'][$key], true).";\n"; - } - - // Save edited language file - if($fp = @fopen($editfile, "w")) - { - // We need info about edited language files to generate credits for our file - require MYBB_ROOT."inc/languages/".$editlang.".php"; - - // Lets make nice credits header in language file - $lang_file_credits = "#i", " ", $langinfo['name'])."\n"; - $lang_file_credits .= "// Author of the language pack : ".preg_replace("#<\?|\?>#i", " ", $langinfo['author'])."\n"; - $lang_file_credits .= "// Language pack translators website : ".preg_replace("#<\?|\?>#i", " ", $langinfo['website'])."\n"; - $lang_file_credits .= "// Compatible version of MyBB : ".preg_replace("#<\?|\?>#i", " ", $langinfo['version'])."\n"; - $lang_file_credits .= "// Last edited in MyBB Editor by : ".preg_replace("#<\?|\?>#i", " ", $mybb->user['username'])."\n"; - $lang_file_credits .= "// Last edited date : ".gmdate("r")."\n"; - $lang_file_credits .= "// ".str_repeat('-',80)."\n\n"; - - $contents_wfile = $lang_file_credits.$contents_wfile; - - flock($fp, LOCK_EX); - fwrite($fp, $contents_wfile); - flock($fp, LOCK_UN); - fclose($fp); - - $plugins->run_hooks("admin_config_languages_edit_commit"); - - // Log admin action - log_admin_action($editlang, $editfile, $mybb->get_input('inadmin', MyBB::INPUT_INT)); - - flash_message($lang->success_langfile_updated, 'success'); - admin_redirect("index.php?module=config-languages&action=edit&lang={$editlang}&editwith={$editwith}"); - } - else - { - $errors[] = $lang->error_cannot_write_to_file; - } - } - - unset($langinfo); - @include MYBB_ROOT."inc/languages/".$editwith.".php"; - $editwith_dir_class = " langeditor_ltr"; - if((int)$langinfo['rtl'] > 0) - { - $editwith_dir_class = " langeditor_rtl"; - } - unset($langinfo); - @include MYBB_ROOT."inc/languages/".$editlang.".php"; - $editlang_dir_class = " langeditor_ltr"; - if((int)$langinfo['rtl'] > 0) - { - $editlang_dir_class = " langeditor_rtl"; - } - - // Build and output form with edited phrases - - // Get file being edited in an array - @include $editfile; - $editvars = (array)$l; - unset($l); - - $withvars = array(); - // Get edit with file in an array if exists - if($editwithfile) - { - // File we will compare to, may not exists, but dont worry we will auto switch to solo mode later if so - @include $editwithfile; - $withvars = (array)$l; - unset($l); - } - - // Start output - $page->output_header($lang->languages); - - $sub_tabs['edit_language_variables'] = array( - "title" => $lang->edit_language_variables, - "link" => "index.php?module=config-languages", - "description" => $lang->edit_language_variables_desc - ); - $page->output_nav_tabs($sub_tabs, "edit_language_variables"); - - $form = new Form("index.php?module=config-languages&action=edit", "post", "edit"); - echo $form->generate_hidden_field("file", htmlspecialchars_uni($file)); - echo $form->generate_hidden_field("lang", $editlang); - echo $form->generate_hidden_field("editwith", $editwith); - echo $form->generate_hidden_field("inadmin", $mybb->get_input('inadmin', MyBB::INPUT_INT)); - if($errors) - { - $page->output_inline_error($errors); - } - - // Check if file is writable, before allowing submission - $no_write = null; - if(file_exists($editfile) && !is_writable($editfile) || !is_writable($folder)) - { - $no_write = 1; - $page->output_alert($lang->alert_note_cannot_write); - } - - $form_container = new FormContainer(htmlspecialchars_uni($file)); - if($editwithfile && $withvars) - { - // Editing with another file - - $form_container->output_row_header(preg_replace("<\?|\?>", "?", $languages[$editwith])); - $form_container->output_row_header(preg_replace("<\?|\?>", "?", $languages[$editlang])); - - foreach($withvars as $key => $value) - { - if(my_strtolower($langinfo['charset']) == "utf-8") - { - $withvars[$key] = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return dec_to_utf8(hexdec($matches[1]));'), $withvars[$key]); - $editvars[$key] = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return dec_to_utf8(hexdec($matches[1]));'), $editvars[$key]); - } - else - { - $withvars[$key] = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return dec_to_utf8(hexdec($matches[1]));'), $withvars[$key]); - $editvars[$key] = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return "&#".hexdec($matches[1]).";";'), $editvars[$key]); - } - - // Find problems and differences in editfile in comparision to editwithfile - - // Count {x} in left and right variable - $withvars_value_cbvCount = preg_match_all("/{[ \t]*\d+[ \t]*}/", $withvars[$key], $matches); - $editvars_value_cbvCount = preg_match_all("/{[ \t]*\d+[ \t]*}/", $editvars[$key], $matches); - - // If left contain something but right is empty or only spaces || count of {x} are different betwin left and right - if($withvars[$key] && !$editvars[$key] || $withvars_value_cbvCount != $editvars_value_cbvCount) - { - $textarea_issue_class = " langeditor_textarea_issue"; - } - else - { - $textarea_issue_class = ""; - } - - $form_container->output_row($key, "", $form->generate_text_area("", $withvars[$key], array('readonly' => true, 'rows' => 2, 'class' => "langeditor_textarea_editwith {$editwith_dir_class}")), "", array('width' => '50%', 'skip_construct' => true)); - $form_container->output_row($key, "", $form->generate_text_area("edit[$key]", $editvars[$key], array('id' => 'lang_'.$key, 'rows' => 2, 'class' => "langeditor_textarea_edit {$textarea_issue_class} {$editlang_dir_class}")), 'lang_'.$key, array('width' => '50%')); - } - - // Create form fields for extra variables that are present only in edited file - $present_in_edit_vars_only = (array)array_diff_key($editvars, $withvars); - if($present_in_edit_vars_only) - { - foreach($present_in_edit_vars_only as $key => $value) - { - if(my_strtolower($langinfo['charset']) == "utf-8") - { - $editvars[$key] = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return dec_to_utf8(hexdec($matches[1]));'), $editvars[$key]); - } - else - { - $editvars[$key] = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return "&#".hexdec($matches[1]).";";'), $editvars[$key]); - } - - $form_container->output_row("", "", "", "", array('width' => '50%', 'skip_construct' => true)); - $form_container->output_row($key, "", $form->generate_text_area("edit[$key]", $editvars[$key], array('id' => 'lang_'.$key, 'rows' => 2, 'class' => "langeditor_textarea_edit {$editlang_dir_class}")), 'lang_'.$key, array('width' => '50%')); - } - } - - } - else - { - // Editing individually - $form_container->output_row_header(preg_replace("<\?|\?>", "?", $languages[$editlang])); - - // Make each editing row from current file that we edit - foreach($editvars as $key => $value) - { - if(my_strtolower($langinfo['charset']) == "utf-8") - { - $value = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return dec_to_utf8(hexdec($matches[1]));'), $value); - } - else - { - $value = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return "&#".hexdec($matches[1]).";";'), $value); - } - $form_container->output_row($key, "", $form->generate_text_area("edit[$key]", $value, array('id' => 'lang_'.$key, 'rows' => 2, 'class' => "langeditor_textarea_edit {$editlang_dir_class}")), 'lang_'.$key, array('width' => '50%')); - } - } - $form_container->end(); - - if(!count($editvars)) - { - $no_write = 1; - } - - $buttons[] = $form->generate_submit_button($lang->save_language_file, array('disabled' => $no_write)); - - $form->output_submit_wrapper($buttons); - $form->end(); - } - else - { - // Build and output list of available language files - - $page->output_header($lang->languages); - - $sub_tabs['language_files'] = array( - 'title' => $lang->language_files, - 'link' => "index.php?module=config-languages&action=edit&lang=".$editlang, - 'description' => $lang->language_files_desc - ); - - $sub_tabs['quick_phrases'] = array( - 'title' => $lang->quick_phrases, - 'link' => "index.php?module=config-languages&action=quick_phrases&lang=".$editlang, - 'description' => $lang->quick_phrases_desc - ); - - $page->output_nav_tabs($sub_tabs, 'language_files'); - - if(!file_exists(MYBB_ROOT."inc/languages/".$editlang.".php")) - { - flash_message($lang->error_invalid_set, 'error'); - admin_redirect("index.php?module=config-languages"); - } - require MYBB_ROOT."inc/languages/".$editlang.".php"; - - $table = new Table; - if($editwithfolder) - { - $table->construct_header(preg_replace("<\?|\?>", "?", $languages[$editwith])); - $table->construct_header($lang->phrases, array("class" => "align_center", "width" => 100)); - $table->construct_header(preg_replace("<\?|\?>", "?", $languages[$editlang])); - $table->construct_header($lang->issues, array("class" => "align_center", "width" => 100)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 100)); - } - else - { - $table->construct_header(preg_replace("<\?|\?>", "?", $languages[$editlang])); - $table->construct_header($lang->phrases, array("class" => "align_center", "width" => 100)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 100)); - } - - // Get files in main folder - $filenames = array(); - if($handle = opendir($folder)) - { - while(false !== ($file = readdir($handle))) - { - if(preg_match("#\.lang\.php$#", $file)) - { - $filenames[] = $file; - } - } - closedir($handle); - sort($filenames); - } - - $edit_colspan = 3; - // Get files from folder we want to peek at (if possible) - if($editwithfolder) - { - $edit_colspan = 5; - $filenameswith = array(); - if($handle = opendir($editwithfolder)) - { - while(false !== ($file = readdir($handle))) - { - if(preg_match("#\.lang\.php$#", $file)) - { - $filenameswith[] = $file; - } - } - closedir($handle); - sort($filenameswith); - } - } - - if($editwithfolder) - { - $files_left = array_diff($filenameswith, $filenames); - $files_right = array_diff($filenames, $filenameswith); - $files_both = array_intersect($filenameswith, $filenames); - - foreach($files_left as $key => $file) - { - @include $editwithfolder.$file; - $editvars_left = (array)$l; - unset($l); - - $icon_issues = ""; - if(count($editvars_left) >0) - { - $icon_issues = ""; - } - - $table->construct_cell($file, array("class" => "langeditor_editwithfile")); - $table->construct_cell(count($editvars_left), array("class" => "langeditor_phrases")); - $table->construct_cell("", array("class" => "langeditor_editfile")); - $table->construct_cell($icon_issues, array("class" => "langeditor_issues")); - $table->construct_cell("{$lang->edit}", array("class" => "langeditor_edit")); - $table->construct_row(); - } - foreach($files_right as $key => $file) - { - @include $folder.$file; - $editvars_right = (array)$l; - unset($l); - - $icon_issues = ""; - if(count($editvars_right >0)) - { - $icon_issues = ""; - } - - $table->construct_cell("", array("class" => "langeditor_editwithfile")); - $table->construct_cell("", array("class" => "langeditor_phrases")); - $table->construct_cell($file, array("class" => "langeditor_editfile")); - $table->construct_cell($icon_issues, array("class" => "langeditor_issues")); - $table->construct_cell("{$lang->edit}", array("class" => "langeditor_edit")); - $table->construct_row(); - } - foreach($files_both as $key => $file) - { - @include $editwithfolder.$file; - $editvars_left = (array)$l; - unset($l); - @include $folder.$file; - $editvars_right = (array)$l; - unset($l); - - $table->construct_cell($file, array("class" => "langeditor_editwithfile")); - $table->construct_cell(count($editvars_left), array("class" => "langeditor_phrases")); - $table->construct_cell($file, array("class" => "langeditor_editfile")); - - $icon_issues = ""; - - // Find problems and differences in editfile in comparision to editwithfile - foreach($editvars_left as $editvars_left_key => $editvars_left_value) - { - // Count {x} in left and right variable - $editvars_left_value_cbvCount = preg_match_all("/{[ \t]*\d+[ \t]*}/", $editvars_left_value, $matches); - $editvars_right_value_cbvCount = preg_match_all("/{[ \t]*\d+[ \t]*}/", $editvars_right[$editvars_left_key], $matches); - // If left contain something but right is empty || count of {x} are different betwin left and right - if($editvars_left_value && !$editvars_right[$editvars_left_key] || $editvars_left_value_cbvCount != $editvars_right_value_cbvCount) - { - $icon_issues = ""; - // One difference is enought, so lets abort checking for more. - break; - } - } - - $table->construct_cell($icon_issues, array("class" => "langeditor_issues")); - $table->construct_cell("{$lang->edit}", array("class" => "langeditor_edit")); - $table->construct_row(); - } - } - else - { - foreach($filenames as $key => $file) - { - @include $folder.$file; - $editvars_count = (array)$l; - unset($l); - - $table->construct_cell($file, array("class" => "langeditor_editfile")); - $table->construct_cell(count($editvars_count), array("class" => "langeditor_phrases")); - $table->construct_cell("{$lang->edit}", array("class" => "langeditor_edit")); - $table->construct_row(); - } - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_language_files_front_end, array('colspan' => $edit_colspan)); - $table->construct_row(); - } - - $table->output($lang->front_end); - - if($langinfo['admin'] != 0) - { - $table = new Table; - if($editwithfolder) - { - $table->construct_header(preg_replace("<\?|\?>", "?", $languages[$editwith])); - $table->construct_header($lang->phrases, array("class" => "align_center", "width" => 100)); - $table->construct_header(preg_replace("<\?|\?>", "?", $languages[$editlang])); - $table->construct_header($lang->issues, array("class" => "align_center", "width" => 100)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 100)); - } - else - { - $table->construct_header(preg_replace("<\?|\?>", "?", $languages[$editlang])); - $table->construct_header($lang->phrases, array("class" => "align_center", "width" => 100)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 100)); - } - - // Get files in admin folder - $adminfilenames = array(); - if($handle = opendir($folder."admin")) - { - while(false !== ($file = readdir($handle))) - { - if(preg_match("#\.lang\.php$#", $file)) - { - $adminfilenames[] = $file; - } - } - closedir($handle); - sort($adminfilenames); - } - - $edit_colspan = 3; - // Get files from admin folder we want to peek at (if possible) - if($editwithfolder) - { - $edit_colspan = 5; - $adminfilenameswith = array(); - if($handle = opendir($editwithfolder."admin")) - { - while(false !== ($file = readdir($handle))) - { - if(preg_match("#\.lang\.php$#", $file)) - { - $adminfilenameswith[] = $file; - } - } - closedir($handle); - sort($adminfilenameswith); - } - } - - if($editwithfolder) - { - $files_left = array_diff($adminfilenameswith, $adminfilenames); - $files_right = array_diff($adminfilenames, $adminfilenameswith); - $files_both = array_intersect($adminfilenameswith, $adminfilenames); - - foreach($files_left as $key => $file) - { - @include $editwithfolder."admin/".$file; - $editvars_left = (array)$l; - unset($l); - - $icon_issues = ""; - if(count($editvars_left) >0) - { - $icon_issues = ""; - } - - $table->construct_cell($file, array("class" => "langeditor_editwithfile")); - $table->construct_cell(count($editvars_left), array("class" => "langeditor_phrases")); - $table->construct_cell("", array("class" => "langeditor_editfile")); - $table->construct_cell($icon_issues, array("class" => "langeditor_issues")); - $table->construct_cell("{$lang->edit}", array("class" => "langeditor_edit")); - $table->construct_row(); - } - foreach($files_right as $key => $file) - { - @include $folder."admin/".$file; - $editvars_right = (array)$l; - unset($l); - - $icon_issues = ""; - if(count($editvars_right >0)) - { - $icon_issues = ""; - } - - $table->construct_cell("", array("class" => "langeditor_editwithfile")); - $table->construct_cell("", array("class" => "langeditor_phrases")); - $table->construct_cell($file, array("class" => "langeditor_editfile")); - $table->construct_cell($icon_issues, array("class" => "langeditor_issues")); - $table->construct_cell("{$lang->edit}", array("class" => "langeditor_edit")); - $table->construct_row(); - } - foreach($files_both as $key => $file) - { - @include $editwithfolder."admin/".$file; - $editvars_left = (array)$l; - unset($l); - @include $folder."admin/".$file; - $editvars_right = (array)$l; - unset($l); - - $table->construct_cell($file, array("class" => "langeditor_editwithfile")); - $table->construct_cell(count($editvars_left), array("class" => "langeditor_phrases")); - $table->construct_cell($file, array("class" => "langeditor_editfile")); - - $icon_issues = ""; - - // Find problems and differences in editfile in comparision to editwithfile - foreach($editvars_left as $editvars_left_key => $editvars_left_value) - { - // Count {x} in left and right variable - $editvars_left_value_cbvCount = preg_match_all("/{[ \t]*\d+[ \t]*}/", $editvars_left_value, $matches); - $editvars_right_value_cbvCount = preg_match_all("/{[ \t]*\d+[ \t]*}/", $editvars_right[$editvars_left_key], $matches); - // If left contain something but right is empty || count of {x} are different betwin left and right - if($editvars_left_value && !$editvars_right[$editvars_left_key] || $editvars_left_value_cbvCount != $editvars_right_value_cbvCount) - { - $icon_issues = ""; - // One difference is enought. - break; - } - } - - $table->construct_cell($icon_issues, array("class" => "langeditor_issues")); - $table->construct_cell("{$lang->edit}", array("class" => "langeditor_edit")); - $table->construct_row(); - } - } - else - { - foreach($adminfilenames as $key => $file) - { - @include $folder."admin/".$file; - $editvars_count = (array)$l; - unset($l); - - $table->construct_cell($file, array("class" => "langeditor_editfile")); - $table->construct_cell(count($editvars_count), array("class" => "langeditor_phrases")); - $table->construct_cell("{$lang->edit}", array("class" => "langeditor_edit")); - $table->construct_row(); - } - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_language_files_admin_cp, array('colspan' => $edit_colspan)); - $table->construct_row(); - } - - $table->output($lang->admin_cp); - } - } - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->languages); - - $sub_tabs['languages'] = array( - 'title' => $lang->languages, - 'link' => "index.php?module=config-languages", - 'description' => $lang->languages_desc - ); - $sub_tabs['find_language'] = array( - 'title' => $lang->find_language_packs, - 'link' => "https://community.mybb.com/mods.php?action=browse&category=19", - 'target' => "_blank" - ); - - $plugins->run_hooks("admin_config_languages_start"); - - $page->output_nav_tabs($sub_tabs, 'languages'); - - $table = new Table; - $table->construct_header($lang->languagevar); - $table->construct_header($lang->version, array("class" => "align_center", "width" => 100)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 155)); - - asort($languages); - - foreach($languages as $key1 => $langname1) - { - $langselectlangs[$key1] = $lang->sprintf($lang->edit_with, preg_replace("<\?|\?>", "?", $langname1)); - } - - foreach($languages as $key => $langname) - { - include MYBB_ROOT."inc/languages/".$key.".php"; - - if(!empty($langinfo['website'])) - { - $author = "{$langinfo['author']}"; - } - else - { - $author = $langinfo['author']; - } - - $table->construct_cell("".preg_replace("<\?|\?>", "?", $langinfo['name'])."
{$author}"); - $table->construct_cell($langinfo['version'], array("class" => "align_center")); - - $popup = new PopupMenu("language_{$key}", $lang->options); - $popup->add_item($lang->edit_language_variables, "index.php?module=config-languages&action=edit&lang={$key}"); - foreach($langselectlangs as $key1 => $langname1) - { - if($key != $key1) - { - $popup->add_item($langname1, "index.php?module=config-languages&action=edit&lang={$key}&editwith={$key1}"); - } - } - $popup->add_item($lang->edit_properties, "index.php?module=config-languages&action=edit_properties&lang={$key}"); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_language, array('colspan' => 3)); - $table->construct_row(); - } - - $table->output($lang->installed_language_packs); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/config/mod_tools.php b/html/forums/admin/modules/config/mod_tools.php deleted file mode 100644 index dbb784f..0000000 --- a/html/forums/admin/modules/config/mod_tools.php +++ /dev/null @@ -1,2362 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->mod_tools, "index.php?module=config-mod_tools"); - -$plugins->run_hooks("admin_config_mod_tools_begin"); - -if($mybb->input['action'] == "delete_post_tool") -{ - $query = $db->simple_select("modtools", "*", "tid='{$mybb->input['tid']}'"); - $tool = $db->fetch_array($query); - - // Does the post tool not exist? - if(!$tool['tid']) - { - flash_message($lang->error_invalid_post_tool, 'error'); - admin_redirect("index.php?module=config-mod_tools&action=post_tools"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-mod_tools&action=post_tools"); - } - - $plugins->run_hooks("admin_config_mod_tools_delete_post_tool"); - - if($mybb->request_method == 'post') - { - // Delete the type - $db->delete_query('modtools', "tid='{$tool['tid']}'"); - - $plugins->run_hooks("admin_config_mod_tools_delete_post_tool_commit"); - - // Log admin action - log_admin_action($tool['tid'], $tool['name']); - $cache->update_forumsdisplay(); - - flash_message($lang->success_post_tool_deleted, 'success'); - admin_redirect("index.php?module=config-mod_tools&action=post_tools"); - } - else - { - $page->output_confirm_action("index.php?module=config-mod_tools&action=post_tools&tid={$type['tid']}", $lang->confirm_post_tool_deletion); - } -} - -if($mybb->input['action'] == "delete_thread_tool") -{ - $query = $db->simple_select("modtools", "*", "tid='{$mybb->input['tid']}'"); - $tool = $db->fetch_array($query); - - // Does the post tool not exist? - if(!$tool['tid']) - { - flash_message($lang->error_invalid_thread_tool, 'error'); - admin_redirect("index.php?module=config-mod_tools"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-mod_tools"); - } - - $plugins->run_hooks("admin_config_mod_tools_delete_thread_tool"); - - if($mybb->request_method == 'post') - { - // Delete the type - $db->delete_query('modtools', "tid='{$tool['tid']}'"); - - $plugins->run_hooks("admin_config_mod_tools_delete_thread_tool_commit"); - - // Log admin action - log_admin_action($tool['tid'], $tool['name']); - $cache->update_forumsdisplay(); - - flash_message($lang->success_thread_tool_deleted, 'success'); - admin_redirect("index.php?module=config-mod_tools"); - } - else - { - $page->output_confirm_action("index.php?module=config-mod_tools&action=delete_thread_tool&tid={$tool['tid']}", $lang->confirm_thread_tool_deletion); - } -} - -if($mybb->input['action'] == "post_tools") -{ - $plugins->run_hooks("admin_config_mod_tools_post_tools"); - - $page->add_breadcrumb_item($lang->post_tools); - $page->output_header($lang->mod_tools." - ".$lang->post_tools); - - $sub_tabs['thread_tools'] = array( - 'title' => $lang->thread_tools, - 'link' => "index.php?module=config-mod_tools" - ); - $sub_tabs['add_thread_tool'] = array( - 'title'=> $lang->add_thread_tool, - 'link' => "index.php?module=config-mod_tools&action=add_thread_tool" - ); - $sub_tabs['post_tools'] = array( - 'title' => $lang->post_tools, - 'link' => "index.php?module=config-mod_tools&action=post_tools", - 'description' => $lang->post_tools_desc - ); - $sub_tabs['add_post_tool'] = array( - 'title'=> $lang->add_post_tool, - 'link' => "index.php?module=config-mod_tools&action=add_post_tool" - ); - - $page->output_nav_tabs($sub_tabs, 'post_tools'); - - $table = new Table; - $table->construct_header($lang->title); - $table->construct_header($lang->controls, array('class' => "align_center", 'colspan' => 2)); - - $query = $db->simple_select('modtools', 'tid, name, description, type', "type='p'", array('order_by' => 'name')); - while($tool = $db->fetch_array($query)) - { - $table->construct_cell("".htmlspecialchars_uni($tool['name'])."
".htmlspecialchars_uni($tool['description']).""); - $table->construct_cell("{$lang->edit}", array('width' => 100, 'class' => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_post_tool_deletion}')\">{$lang->delete}", array('width' => 100, 'class' => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_post_tools, array('colspan' => 3)); - $table->construct_row(); - } - - $table->output($lang->post_tools); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit_thread_tool") -{ - $query = $db->simple_select("modtools", "COUNT(tid) as tools", "tid = '{$mybb->input['tid']}' AND type='t'"); - if($db->fetch_field($query, "tools") < 1) - { - flash_message($lang->error_invalid_thread_tool, 'error'); - admin_redirect("index.php?module=config-mod_tools"); - } - - $plugins->run_hooks("admin_config_mod_tools_edit_thread_tool"); - - if($mybb->request_method == 'post') - { - if(trim($mybb->input['title']) == "") - { - $errors[] = $lang->error_missing_title; - } - - if(trim($mybb->input['description']) == "") - { - $errors[] = $lang->error_missing_description; - } - - if($mybb->input['forum_type'] == 2) - { - $forum_checked[1] = ''; - $forum_checked[2] = "checked=\"checked\""; - - if(count($mybb->input['forum_1_forums']) < 1) - { - $errors[] = $lang->error_no_forums_selected; - } - } - else - { - $forum_checked[1] = "checked=\"checked\""; - $forum_checked[2] = ''; - - $mybb->input['forum_1_forums'] = ''; - } - - if($mybb->input['group_type'] == 2) - { - $group_checked[1] = ''; - $group_checked[2] = "checked=\"checked\""; - - if(count($mybb->input['group_1_groups']) < 1) - { - $errors[] = $lang->error_no_groups_selected; - } - } - else - { - $group_checked[1] = "checked=\"checked\""; - $group_checked[2] = ''; - - $mybb->input['group_1_groups'] = ''; - } - - if($mybb->input['approvethread'] != '' && $mybb->input['approvethread'] != 'approve' && $mybb->input['approvethread'] != 'unapprove' && $mybb->input['approvethread'] != 'toggle') - { - $mybb->input['approvethread'] = ''; - } - - if($mybb->input['softdeletethread'] != '' && $mybb->input['softdeletethread'] != 'softdelete' && $mybb->input['softdeletethread'] != 'restore' && $mybb->input['softdeletethread'] != 'toggle') - { - $mybb->input['softdeletethread'] = ''; - } - - if($mybb->input['openthread'] != '' && $mybb->input['openthread'] != 'open' && $mybb->input['openthread'] != 'close' && $mybb->input['openthread'] != 'toggle') - { - $mybb->input['openthread'] = ''; - } - - if($mybb->input['stickthread'] != '' && $mybb->input['stickthread'] != 'stick' && $mybb->input['stickthread'] != 'unstick' && $mybb->input['stickthread'] != 'toggle') - { - $mybb->input['stickthread'] = ''; - } - - if($mybb->input['move_type'] == 2) - { - $move_checked[1] = ''; - $move_checked[2] = "checked=\"checked\""; - - if(!$mybb->input['move_1_forum']) - { - $errors[] = $lang->error_no_move_forum_selected; - } - else - { - // Check that the destination forum is not a category - $query = $db->simple_select("forums", "type", "fid = '".$mybb->get_input('move_1_forum', MyBB::INPUT_INT)."'"); - if($db->fetch_field($query, "type") == "c") - { - $errors[] = $lang->error_forum_is_category; - } - } - - if($mybb->input['move_2_redirect'] != 1 && $mybb->input['move_2_redirect'] != 0) - { - $mybb->input['move_2_redirect'] = 0; - } - - if(!isset($mybb->input['move_3_redirecttime'])) - { - $mybb->input['move_3_redirecttime'] = ''; - } - } - else - { - $move_checked[1] = "checked=\"checked\""; - $move_checked[2] = ''; - - $mybb->input['move_1_forum'] = ''; - $mybb->input['move_2_redirect'] = 0; - $mybb->input['move_3_redirecttime'] = ''; - } - - if($mybb->input['copy_type'] == 2) - { - $copy_checked[1] = ''; - $copy_checked[2] = "checked=\"checked\""; - - if(!$mybb->input['copy_1_forum']) - { - $errors[] = $lang->error_no_copy_forum_selected; - } - else - { - $query = $db->simple_select("forums", "type", "fid = '".$mybb->get_input('copy_1_forum', MyBB::INPUT_INT)."'"); - if($db->fetch_field($query, "type") == "c") - { - $errors[] = $lang->error_forum_is_category; - } - } - } - else - { - $copy_checked[1] = "checked=\"checked\""; - $copy_checked[2] = ''; - - $mybb->input['copy_1_forum'] = ''; - } - - if(!$errors) - { - $thread_options = array( - 'confirmation' => $mybb->get_input('confirmation', MyBB::INPUT_INT), - 'deletethread' => $mybb->get_input('deletethread', MyBB::INPUT_INT), - 'mergethreads' => $mybb->get_input('mergethreads', MyBB::INPUT_INT), - 'deletepoll' => $mybb->get_input('deletepoll', MyBB::INPUT_INT), - 'removeredirects' => $mybb->get_input('removeredirects', MyBB::INPUT_INT), - 'removesubscriptions' => $mybb->get_input('removesubscriptions', MyBB::INPUT_INT), - 'recountrebuild' => $mybb->get_input('recountrebuild', MyBB::INPUT_INT), - 'approvethread' => $mybb->input['approvethread'], - 'softdeletethread' => $mybb->input['softdeletethread'], - 'openthread' => $mybb->input['openthread'], - 'stickthread' => $mybb->input['stickthread'], - 'movethread' => $mybb->get_input('move_1_forum', MyBB::INPUT_INT), - 'movethreadredirect' => $mybb->get_input('move_2_redirect', MyBB::INPUT_INT), - 'movethreadredirectexpire' => $mybb->get_input('move_3_redirecttime', MyBB::INPUT_INT), - 'copythread' => $mybb->get_input('copy_1_forum', MyBB::INPUT_INT), - 'newsubject' => $mybb->input['newsubject'], - 'addreply' => $mybb->input['newreply'], - 'replysubject' => $mybb->input['newreplysubject'], - 'pm_subject' => $mybb->input['pm_subject'], - 'pm_message' => $mybb->input['pm_message'], - 'threadprefix' => $mybb->get_input('threadprefix', MyBB::INPUT_INT) - ); - - $update_tool['type'] = 't'; - $update_tool['threadoptions'] = $db->escape_string(my_serialize($thread_options)); - $update_tool['name'] = $db->escape_string($mybb->input['title']); - $update_tool['description'] = $db->escape_string($mybb->input['description']); - $update_tool['forums'] = ''; - $update_tool['groups'] = ''; - - if($mybb->input['forum_type'] == 2) - { - if(is_array($mybb->input['forum_1_forums'])) - { - $checked = array(); - - foreach($mybb->input['forum_1_forums'] as $fid) - { - $checked[] = (int)$fid; - } - - $update_tool['forums'] = implode(',', $checked); - } - } - else - { - $update_tool['forums'] = "-1"; - } - - if($mybb->input['group_type'] == 2) - { - if(is_array($mybb->input['group_1_groups'])) - { - $checked = array(); - - foreach($mybb->input['group_1_groups'] as $gid) - { - $checked[] = (int)$gid; - } - - $update_tool['groups'] = implode(',', $checked); - } - } - else - { - $update_tool['groups'] = "-1"; - } - - $plugins->run_hooks("admin_config_mod_tools_edit_thread_tool_commit"); - - $db->update_query("modtools", $update_tool, "tid='{$mybb->input['tid']}'"); - - // Log admin action - log_admin_action($mybb->input['tid'], $mybb->input['title']); - $cache->update_forumsdisplay(); - - flash_message($lang->success_mod_tool_updated, 'success'); - admin_redirect("index.php?module=config-mod_tools"); - } - } - - $page->add_breadcrumb_item($lang->edit_thread_tool); - $page->output_header($lang->mod_tools." - ".$lang->edit_thread_tool); - - $sub_tabs['edit_thread_tool'] = array( - "title" => $lang->edit_thread_tool, - "description" => $lang->edit_thread_tool_desc, - "link" => "index.php?module=config-mod_tools" - ); - - $page->output_nav_tabs($sub_tabs, 'edit_thread_tool'); - - $form = new Form("index.php?module=config-mod_tools&action=edit_thread_tool", 'post'); - echo $form->generate_hidden_field("tid", $mybb->input['tid']); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $query = $db->simple_select("modtools", "*", "tid = '{$mybb->input['tid']}'"); - $modtool = $db->fetch_array($query); - $thread_options = my_unserialize($modtool['threadoptions']); - - $mybb->input['title'] = $modtool['name']; - $mybb->input['description'] = $modtool['description']; - $mybb->input['forum_1_forums'] = explode(",", $modtool['forums']); - $mybb->input['group_1_groups'] = explode(",", $modtool['groups']); - - if(!$modtool['forums'] || $modtool['forums'] == -1) - { - $forum_checked[1] = "checked=\"checked\""; - $forum_checked[2] = ''; - } - else - { - $forum_checked[1] = ''; - $forum_checked[2] = "checked=\"checked\""; - } - - if(!$modtool['groups'] || $modtool['groups'] == -1) - { - $group_checked[1] = "checked=\"checked\""; - $group_checked[2] = ''; - } - else - { - $group_checked[1] = ''; - $group_checked[2] = "checked=\"checked\""; - } - - $mybb->input['confirmation'] = $thread_options['confirmation']; - $mybb->input['approvethread'] = $thread_options['approvethread']; - $mybb->input['softdeletethread'] = $thread_options['softdeletethread']; - $mybb->input['openthread'] = $thread_options['openthread']; - $mybb->input['stickthread'] = $thread_options['stickthread']; - $mybb->input['move_1_forum'] = $thread_options['movethread']; - $mybb->input['move_2_redirect'] = $thread_options['movethreadredirect']; - $mybb->input['move_3_redirecttime'] = $thread_options['movethreadredirectexpire']; - - if(!$thread_options['movethread']) - { - $move_checked[1] = "checked=\"checked\""; - $move_checked[2] = ''; - } - else - { - $move_checked[1] = ''; - $move_checked[2] = "checked=\"checked\""; - } - - if(!$thread_options['copythread']) - { - $copy_checked[1] = "checked=\"checked\""; - $copy_checked[2] = ''; - } - else - { - $copy_checked[1] = ''; - $copy_checked[2] = "checked=\"checked\""; - } - - $mybb->input['copy_1_forum'] = $thread_options['copythread']; - $mybb->input['deletethread'] = $thread_options['deletethread']; - $mybb->input['mergethreads'] = $thread_options['mergethreads']; - $mybb->input['deletepoll'] = $thread_options['deletepoll']; - $mybb->input['removeredirects'] = $thread_options['removeredirects']; - $mybb->input['removesubscriptions'] = $thread_options['removesubscriptions']; - $mybb->input['recountrebuild'] = $thread_options['recountrebuild']; - $mybb->input['threadprefix'] = $thread_options['threadprefix']; - $mybb->input['newsubject'] = $thread_options['newsubject']; - $mybb->input['newreply'] = $thread_options['addreply']; - $mybb->input['newreplysubject'] = $thread_options['replysubject']; - $mybb->input['pm_subject'] = $thread_options['pm_subject']; - $mybb->input['pm_message'] = $thread_options['pm_message']; - } - - $form_container = new FormContainer($lang->general_options); - $form_container->output_row($lang->name." *", '', $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_description." *", '', $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - - $actions = " -
-
-
-
- - - - - -
{$lang->forums_colon}".$form->generate_forum_select('forum_1_forums[]', $mybb->input['forum_1_forums'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_in_forums." *", '', $actions); - - $actions = "
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('group_1_groups[]', $mybb->input['group_1_groups'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_to_groups." *", '', $actions); - $form_container->output_row($lang->show_confirmation." *", '', $form->generate_yes_no_radio('confirmation', $mybb->input['confirmation'], array('style' => 'width: 2em;'))); - $form_container->end(); - - $approve_unapprove = array( - '' => $lang->no_change, - 'approve' => $lang->approve, - 'unapprove' => $lang->unapprove, - 'toggle' => $lang->toggle - ); - - $open_close = array( - '' => $lang->no_change, - 'open' => $lang->open, - 'close' => $lang->close, - 'toggle' => $lang->toggle - ); - - $stick_unstick = array( - '' => $lang->no_change, - 'stick' => $lang->stick, - 'unstick' => $lang->unstick, - 'toggle' => $lang->toggle - ); - - $form_container = new FormContainer($lang->thread_moderation); - $form_container->output_row($lang->approve_unapprove." *", '', $form->generate_select_box('approvethread', $approve_unapprove, $mybb->input['approvethread'], array('id' => 'approvethread')), 'approvethread'); - $form_container->output_row($lang->open_close_thread." *", '', $form->generate_select_box('openthread', $open_close, $mybb->input['openthread'], array('id' => 'openthread')), 'openthread'); - $form_container->output_row($lang->stick_unstick_thread." *", '', $form->generate_select_box('stickthread', $stick_unstick, $mybb->input['stickthread'], array('id' => 'stickthread')), 'stickthread'); - - - $actions = " -
-
-
-
- - - - - - - - - - - - - -
{$lang->forum_to_move_to}".$form->generate_forum_select('move_1_forum', $mybb->input['move_1_forum'])."
{$lang->leave_redirect}".$form->generate_yes_no_radio('move_2_redirect', $mybb->input['move_2_redirect'], array('style' => 'width: 2em;'))."
{$lang->delete_redirect_after}".$form->generate_numeric_field('move_3_redirecttime', $mybb->input['move_3_redirecttime'], array('style' => 'width: 3em;', 'min' => 0))." {$lang->days}
-
-
- "; - $form_container->output_row($lang->move_thread." *", $lang->move_thread_desc, $actions); - - $actions = " -
-
-
-
- - - - - -
{$lang->forum_to_copy_to}".$form->generate_forum_select('copy_1_forum', $mybb->input['copy_1_forum'])."
-
-
- "; - $form_container->output_row($lang->copy_thread." *", '', $actions); - - $softdelete_restore = array( - '' => $lang->no_change, - 'restore' => $lang->restore, - 'softdelete' => $lang->softdelete, - 'toggle' => $lang->toggle - ); - - $form_container->output_row($lang->softdelete_restore_thread." *", '', $form->generate_select_box('softdeletethread', $softdelete_restore, $mybb->input['softdeletethread'], array('id' => 'softdeletethread')), 'softdeletethread'); - $form_container->output_row($lang->delete_thread." *", '', $form->generate_yes_no_radio('deletethread', $mybb->input['deletethread'], array('style' => 'width: 2em;'))); - $form_container->output_row($lang->merge_thread." *", $lang->merge_thread_desc, $form->generate_yes_no_radio('mergethreads', $mybb->input['mergethreads'], array('style' => 'width: 2em;'))); - $form_container->output_row($lang->delete_poll." *", '', $form->generate_yes_no_radio('deletepoll', $mybb->input['deletepoll'], array('style' => 'width: 2em;'))); - $form_container->output_row($lang->delete_redirects." *", '', $form->generate_yes_no_radio('removeredirects', $mybb->input['removeredirects'], array('style' => 'width: 2em;'))); - $form_container->output_row($lang->remove_subscriptions." *", '', $form->generate_yes_no_radio('removesubscriptions', $mybb->input['removesubscriptions'], array('style' => 'width: 2em;'))); - $form_container->output_row($lang->recount_rebuild." *", '', $form->generate_yes_no_radio('recountrebuild', $mybb->input['recountrebuild'], array('style' => 'width: 2em;'))); - - $threadprefixes = build_prefixes(); - if(!empty($threadprefixes)) - { - $thread_prefixes = array( - '-1' => $lang->no_change, - '0' => $lang->no_prefix - ); - - foreach($threadprefixes as $prefix) - { - $thread_prefixes[$prefix['pid']] = $prefix['prefix']; - } - - $form_container->output_row($lang->apply_thread_prefix." *", '', $form->generate_select_box('threadprefix', $thread_prefixes, array($mybb->get_input('threadprefix', MyBB::INPUT_INT)), array('id' => 'threadprefix')), 'threadprefix'); - } - - $form_container->output_row($lang->new_subject." *", $lang->new_subject_desc, $form->generate_text_box('newsubject', $mybb->input['newsubject'], array('id' => 'newsubject'))); - $form_container->end(); - - $form_container = new FormContainer($lang->add_new_reply); - $form_container->output_row($lang->add_new_reply, $lang->add_new_reply_desc, $form->generate_text_area('newreply', $mybb->input['newreply'], array('id' => 'newreply')), 'newreply'); - $form_container->output_row($lang->reply_subject, $lang->reply_subject_desc, $form->generate_text_box('newreplysubject', $mybb->input['newreplysubject'], array('id' => 'newreplysubject')), 'newreplysubject'); - $form_container->end(); - - $form_container = new FormContainer($lang->send_private_message); - $form_container->output_row($lang->private_message_message, $lang->private_message_message_desc, $form->generate_text_area('pm_message', $mybb->input['pm_message'], array('id' => 'pm_message')), 'pm_message'); - $form_container->output_row($lang->private_message_subject, $lang->private_message_subject_desc, $form->generate_text_box('pm_subject', $mybb->input['pm_subject'], array('id' => 'pm_subject')), 'pm_subject'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_thread_tool); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "add_thread_tool") -{ - $plugins->run_hooks("admin_config_mod_tools_add_thread_tool"); - - if($mybb->request_method == 'post') - { - if(trim($mybb->input['title']) == "") - { - $errors[] = $lang->error_missing_title; - } - - if(trim($mybb->input['description']) == "") - { - $errors[] = $lang->error_missing_description; - } - - if($mybb->input['forum_type'] == 2) - { - $forum_checked[1] = ''; - $forum_checked[2] = "checked=\"checked\""; - - if(count($mybb->input['forum_1_forums']) < 1) - { - $errors[] = $lang->error_no_forums_selected; - } - } - else - { - $forum_checked[1] = "checked=\"checked\""; - $forum_checked[2] = ''; - - $mybb->input['forum_1_forums'] = ''; - } - - if($mybb->input['group_type'] == 2) - { - $group_checked[1] = ''; - $group_checked[2] = "checked=\"checked\""; - - if(count($mybb->input['group_1_groups']) < 1) - { - $errors[] = $lang->error_no_groups_selected; - } - } - else - { - $group_checked[1] = "checked=\"checked\""; - $group_checked[2] = ''; - - $mybb->input['group_1_groups'] = ''; - } - - if($mybb->input['approvethread'] != '' && $mybb->input['approvethread'] != 'approve' && $mybb->input['approvethread'] != 'unapprove' && $mybb->input['approvethread'] != 'toggle') - { - $mybb->input['approvethread'] = ''; - } - - if($mybb->input['softdeletethread'] != '' && $mybb->input['softdeletethread'] != 'restore' && $mybb->input['softdeletethread'] != 'softdelete' && $mybb->input['softdeletethread'] != 'toggle') - { - $mybb->input['softdeletethread'] = ''; - } - - if($mybb->input['openthread'] != '' && $mybb->input['openthread'] != 'open' && $mybb->input['openthread'] != 'close' && $mybb->input['openthread'] != 'toggle') - { - $mybb->input['openthread'] = ''; - } - - if($mybb->input['stickthread'] != '' && $mybb->input['stickthread'] != 'stick' && $mybb->input['stickthread'] != 'unstick' && $mybb->input['stickthread'] != 'toggle') - { - $mybb->input['stickthread'] = ''; - } - - if(!isset($mybb->input['threadprefix'])) - { - $mybb->input['threadprefix'] = ''; - } - - if($mybb->input['move_type'] == 2) - { - $move_checked[1] = ''; - $move_checked[2] = "checked=\"checked\""; - - if(!$mybb->input['move_1_forum']) - { - $errors[] = $lang->error_no_move_forum_selected; - } - else - { - // Check that the destination forum is not a category - $query = $db->simple_select("forums", "type", "fid = '".$mybb->get_input('move_1_forum', MyBB::INPUT_INT)."'"); - if($db->fetch_field($query, "type") == "c") - { - $errors[] = $lang->error_forum_is_category; - } - } - } - else - { - $move_checked[1] = "checked=\"checked\""; - $move_checked[2] = ''; - - $mybb->input['move_1_forum'] = ''; - $mybb->input['move_2_redirect'] = 0; - $mybb->input['move_3_redirecttime'] = ''; - } - - if($mybb->input['copy_type'] == 2) - { - $copy_checked[1] = ''; - $copy_checked[2] = "checked=\"checked\""; - - if(!$mybb->input['copy_1_forum']) - { - $errors[] = $lang->error_no_copy_forum_selected; - } - else - { - $query = $db->simple_select("forums", "type", "fid = '".$mybb->get_input('copy_1_forum', MyBB::INPUT_INT)."'"); - if($db->fetch_field($query, "type") == "c") - { - $errors[] = $lang->error_forum_is_category; - } - } - } - else - { - $copy_checked[1] = "checked=\"checked\""; - $copy_checked[2] = ''; - - $mybb->input['copy_1_forum'] = ''; - } - - if(!$errors) - { - $thread_options = array( - 'confirmation' => $mybb->get_input('confirmation', MyBB::INPUT_INT), - 'deletethread' => $mybb->get_input('deletethread', MyBB::INPUT_INT), - 'mergethreads' => $mybb->get_input('mergethreads', MyBB::INPUT_INT), - 'deletepoll' => $mybb->get_input('deletepoll', MyBB::INPUT_INT), - 'removeredirects' => $mybb->get_input('removeredirects', MyBB::INPUT_INT), - 'removesubscriptions' => $mybb->get_input('removesubscriptions', MyBB::INPUT_INT), - 'recountrebuild' => $mybb->get_input('recountrebuild', MyBB::INPUT_INT), - 'approvethread' => $mybb->input['approvethread'], - 'softdeletethread' => $mybb->input['softdeletethread'], - 'openthread' => $mybb->input['openthread'], - 'stickthread' => $mybb->input['stickthread'], - 'movethread' => $mybb->get_input('move_1_forum', MyBB::INPUT_INT), - 'movethreadredirect' => $mybb->get_input('move_2_redirect', MyBB::INPUT_INT), - 'movethreadredirectexpire' => $mybb->get_input('move_3_redirecttime', MyBB::INPUT_INT), - 'copythread' => $mybb->get_input('copy_1_forum', MyBB::INPUT_INT), - 'newsubject' => $mybb->input['newsubject'], - 'addreply' => $mybb->input['newreply'], - 'replysubject' => $mybb->input['newreplysubject'], - 'pm_subject' => $mybb->input['pm_subject'], - 'pm_message' => $mybb->input['pm_message'], - 'threadprefix' => $mybb->input['threadprefix'], - ); - - $new_tool['type'] = 't'; - $new_tool['threadoptions'] = $db->escape_string(my_serialize($thread_options)); - $new_tool['name'] = $db->escape_string($mybb->input['title']); - $new_tool['description'] = $db->escape_string($mybb->input['description']); - $new_tool['forums'] = ''; - $new_tool['groups'] = ''; - $new_tool['postoptions'] = ''; - - if($mybb->input['forum_type'] == 2) - { - if(is_array($mybb->input['forum_1_forums'])) - { - $checked = array(); - - foreach($mybb->input['forum_1_forums'] as $fid) - { - $checked[] = (int)$fid; - } - - $new_tool['forums'] = implode(',', $checked); - } - } - else - { - $new_tool['forums'] = "-1"; - } - - if($mybb->input['group_type'] == 2) - { - if(is_array($mybb->input['group_1_groups'])) - { - $checked = array(); - - foreach($mybb->input['group_1_groups'] as $gid) - { - $checked[] = (int)$gid; - } - - $new_tool['groups'] = implode(',', $checked); - } - } - else - { - $new_tool['groups'] = "-1"; - } - - if($mybb->get_input('threadprefix', MyBB::INPUT_INT) >= 0) - { - $thread_options['threadprefix'] = $mybb->get_input('threadprefix', MyBB::INPUT_INT); - } - - $tid = $db->insert_query("modtools", $new_tool); - - $plugins->run_hooks("admin_config_mod_tools_add_thread_tool_commit"); - - // Log admin action - log_admin_action($tid, $mybb->input['title']); - $cache->update_forumsdisplay(); - - flash_message($lang->success_mod_tool_created, 'success'); - admin_redirect("index.php?module=config-mod_tools"); - } - } - - $page->add_breadcrumb_item($lang->add_new_thread_tool); - $page->output_header($lang->mod_tools." - ".$lang->add_new_thread_tool); - - $sub_tabs['thread_tools'] = array( - 'title' => $lang->thread_tools, - 'link' => "index.php?module=config-mod_tools" - ); - $sub_tabs['add_thread_tool'] = array( - 'title'=> $lang->add_new_thread_tool, - 'link' => "index.php?module=config-mod_tools&action=add_thread_tool", - 'description' => $lang->add_thread_tool_desc - ); - $sub_tabs['post_tools'] = array( - 'title' => $lang->post_tools, - 'link' => "index.php?module=config-mod_tools&action=post_tools", - ); - $sub_tabs['add_post_tool'] = array( - 'title'=> $lang->add_new_post_tool, - 'link' => "index.php?module=config-mod_tools&action=add_post_tool" - ); - - $page->output_nav_tabs($sub_tabs, 'add_thread_tool'); - - $form = new Form("index.php?module=config-mod_tools&action=add_thread_tool", 'post'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['title'] = ''; - $mybb->input['description'] = ''; - $mybb->input['forum_1_forums'] = ''; - $forum_checked[1] = "checked=\"checked\""; - $forum_checked[2] = ''; - $mybb->input['group_1_groups'] = ''; - $group_checked[1] = "checked=\"checked\""; - $group_checked[2] = ''; - $mybb->input['confirmation'] = '0'; - $mybb->input['approvethread'] = ''; - $mybb->input['softdeletethread'] = ''; - $mybb->input['openthread'] = ''; - $mybb->input['stickthread'] = ''; - $mybb->input['move_1_forum'] = ''; - $mybb->input['move_2_redirect'] = '0'; - $mybb->input['move_3_redirecttime'] = ''; - $move_checked[1] = "checked=\"checked\""; - $move_checked[2] = ''; - $copy_checked[1] = "checked=\"checked\""; - $copy_checked[2] = ''; - $mybb->input['copy_1_forum'] = ''; - $mybb->input['deletethread'] = '0'; - $mybb->input['mergethreads'] = '0'; - $mybb->input['deletepoll'] = '0'; - $mybb->input['removeredirects'] = '0'; - $mybb->input['removesubscriptions'] = '0'; - $mybb->input['recountrebuild'] = '0'; - $mybb->input['threadprefix'] = '-1'; - $mybb->input['newsubject'] = '{subject}'; - $mybb->input['newreply'] = ''; - $mybb->input['newreplysubject'] = '{subject}'; - $mybb->input['pm_subject'] = ''; - $mybb->input['pm_message'] = ''; - } - - $form_container = new FormContainer($lang->general_options); - $form_container->output_row($lang->name." *", '', $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_description." *", '', $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - - $actions = " -
-
-
-
- - - - - -
{$lang->forums_colon}".$form->generate_forum_select('forum_1_forums[]', $mybb->input['forum_1_forums'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_in_forums." *", '', $actions); - - $actions = "
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('group_1_groups[]', $mybb->input['group_1_groups'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_to_groups." *", '', $actions); - $form_container->output_row($lang->show_confirmation." *", '', $form->generate_yes_no_radio('confirmation', $mybb->input['confirmation'], array('style' => 'width: 2em;'))); - $form_container->end(); - - $approve_unapprove = array( - '' => $lang->no_change, - 'approve' => $lang->approve, - 'unapprove' => $lang->unapprove, - 'toggle' => $lang->toggle - ); - - $open_close = array( - '' => $lang->no_change, - 'open' => $lang->open, - 'close' => $lang->close, - 'toggle' => $lang->toggle - ); - - $stick_unstick = array( - '' => $lang->no_change, - 'stick' => $lang->stick, - 'unstick' => $lang->unstick, - 'toggle' => $lang->toggle - ); - - $form_container = new FormContainer($lang->thread_moderation); - $form_container->output_row($lang->approve_unapprove." *", '', $form->generate_select_box('approvethread', $approve_unapprove, $mybb->input['approvethread'], array('id' => 'approvethread')), 'approvethread'); - $form_container->output_row($lang->open_close_thread." *", '', $form->generate_select_box('openthread', $open_close, $mybb->input['openthread'], array('id' => 'openthread')), 'openthread'); - $form_container->output_row($lang->stick_unstick_thread." *", '', $form->generate_select_box('stickthread', $stick_unstick, $mybb->input['stickthread'], array('id' => 'stickthread')), 'stickthread'); - - - $actions = " -
-
-
-
- - - - - - - - - - - - - -
{$lang->forum_to_move_to}".$form->generate_forum_select('move_1_forum', $mybb->input['move_1_forum'])."
{$lang->leave_redirect}".$form->generate_yes_no_radio('move_2_redirect', $mybb->input['move_2_redirect'], array('style' => 'width: 2em;'))."
{$lang->delete_redirect_after}".$form->generate_numeric_field('move_3_redirecttime', $mybb->input['move_3_redirecttime'], array('style' => 'width: 3em;', 'min' => 0))." {$lang->days}
-
-
- "; - $form_container->output_row($lang->move_thread." *", $lang->move_thread_desc, $actions); - - $actions = " -
-
-
-
- - - - - -
{$lang->forum_to_copy_to}".$form->generate_forum_select('copy_1_forum', $mybb->input['copy_1_forum'])."
-
-
- "; - $form_container->output_row($lang->copy_thread." *", '', $actions); - - $softdelete_restore = array( - '' => $lang->no_change, - 'restore' => $lang->restore, - 'softdelete' => $lang->softdelete, - 'toggle' => $lang->toggle - ); - - $form_container->output_row($lang->softdelete_restore_thread." *", '', $form->generate_select_box('softdeletethread', $softdelete_restore, $mybb->input['softdeletethread'], array('id' => 'softdeletethread')), 'softdeletethread'); - $form_container->output_row($lang->delete_thread." *", '', $form->generate_yes_no_radio('deletethread', $mybb->input['deletethread'], array('style' => 'width: 2em;'))); - $form_container->output_row($lang->merge_thread." *", $lang->merge_thread_desc, $form->generate_yes_no_radio('mergethreads', $mybb->input['mergethreads'], array('style' => 'width: 2em;'))); - $form_container->output_row($lang->delete_poll." *", '', $form->generate_yes_no_radio('deletepoll', $mybb->input['deletepoll'], array('style' => 'width: 2em;'))); - $form_container->output_row($lang->delete_redirects." *", '', $form->generate_yes_no_radio('removeredirects', $mybb->input['removeredirects'], array('style' => 'width: 2em;'))); - $form_container->output_row($lang->remove_subscriptions." *", '', $form->generate_yes_no_radio('removesubscriptions', $mybb->input['removesubscriptions'], array('style' => 'width: 2em;'))); - $form_container->output_row($lang->recount_rebuild." *", '', $form->generate_yes_no_radio('recountrebuild', $mybb->input['recountrebuild'], array('style' => 'width: 2em;'))); - - $threadprefixes = build_prefixes(); - if(!empty($threadprefixes)) - { - $thread_prefixes = array( - '-1' => $lang->no_change, - '0' => $lang->no_prefix - ); - - foreach($threadprefixes as $prefix) - { - $thread_prefixes[$prefix['pid']] = $prefix['prefix']; - } - - $form_container->output_row($lang->apply_thread_prefix." *", '', $form->generate_select_box('threadprefix', $thread_prefixes, $mybb->input['threadprefix'], array('id' => 'threadprefix')), 'threadprefix'); - } - - $form_container->output_row($lang->new_subject." *", $lang->new_subject_desc, $form->generate_text_box('newsubject', $mybb->input['newsubject'], array('id' => 'newsubject'))); - $form_container->end(); - - $form_container = new FormContainer($lang->add_new_reply); - $form_container->output_row($lang->add_new_reply, $lang->add_new_reply_desc, $form->generate_text_area('newreply', $mybb->input['newreply'], array('id' => 'newreply')), 'newreply'); - $form_container->output_row($lang->reply_subject, $lang->reply_subject_desc, $form->generate_text_box('newreplysubject', $mybb->input['newreplysubject'], array('id' => 'newreplysubject')), 'newreplysubject'); - $form_container->end(); - - $form_container = new FormContainer($lang->send_private_message); - $form_container->output_row($lang->private_message_message, $lang->private_message_message_desc, $form->generate_text_area('pm_message', $mybb->input['pm_message'], array('id' => 'pm_message')), 'pm_message'); - $form_container->output_row($lang->private_message_subject, $lang->private_message_subject_desc, $form->generate_text_box('pm_subject', $mybb->input['pm_subject'], array('id' => 'pm_subject')), 'pm_subject'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_thread_tool); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit_post_tool") -{ - $query = $db->simple_select("modtools", "COUNT(tid) as tools", "tid = '{$mybb->input['tid']}' AND type='p'"); - if($db->fetch_field($query, "tools") < 1) - { - flash_message($lang->error_invalid_post_tool, 'error'); - admin_redirect("index.php?module=config-mod_tools&action=post_tools"); - } - - $plugins->run_hooks("admin_config_mod_tools_edit_post_tool"); - - if($mybb->request_method == 'post') - { - if(trim($mybb->input['title']) == "") - { - $errors[] = $lang->error_missing_title; - } - - if(trim($mybb->input['description']) == "") - { - $errors[] = $lang->error_missing_description; - } - - if($mybb->input['forum_type'] == 2) - { - if(count($mybb->input['forum_1_forums']) < 1) - { - $errors[] = $lang->error_no_forums_selected; - } - } - else - { - $mybb->input['forum_1_forums'] = ''; - } - - if($mybb->input['group_type'] == 2) - { - if(count($mybb->input['group_1_groups']) < 1) - { - $errors[] = $lang->error_no_groups_selected; - } - } - else - { - $mybb->input['group_1_groups'] = ''; - } - - if($mybb->input['approvethread'] != '' && $mybb->input['approvethread'] != 'approve' && $mybb->input['approvethread'] != 'unapprove' && $mybb->input['approvethread'] != 'toggle') - { - $mybb->input['approvethread'] = ''; - } - - if($mybb->input['softdeletethread'] != '' && $mybb->input['softdeletethread'] != 'softdelete' && $mybb->input['softdeletethread'] != 'restore' && $mybb->input['softdeletethread'] != 'toggle') - { - $mybb->input['softdeletethread'] = ''; - } - - if($mybb->input['openthread'] != '' && $mybb->input['openthread'] != 'open' && $mybb->input['openthread'] != 'close' && $mybb->input['openthread'] != 'toggle') - { - $mybb->input['openthread'] = ''; - } - - if($mybb->input['stickthread'] != '' && $mybb->input['stickthread'] != 'stick' && $mybb->input['stickthread'] != 'unstick' && $mybb->input['stickthread'] != 'toggle') - { - $mybb->input['stickthread'] = ''; - } - - if($mybb->input['move_type'] == 2) - { - if(!$mybb->input['move_1_forum']) - { - $errors[] = $lang->error_no_move_forum_selected; - } - else - { - // Check that the destination forum is not a category - $query = $db->simple_select("forums", "type", "fid = '".$mybb->get_input('move_1_forum', MyBB::INPUT_INT)."'"); - if($db->fetch_field($query, "type") == "c") - { - $errors[] = $lang->error_forum_is_category; - } - } - } - else - { - $mybb->input['move_1_forum'] = ''; - $mybb->input['move_2_redirect'] = 0; - $mybb->input['move_3_redirecttime'] = ''; - } - - if($mybb->input['copy_type'] == 2) - { - if(!$mybb->input['copy_1_forum']) - { - $errors[] = $lang->error_no_copy_forum_selected; - } - else - { - $query = $db->simple_select("forums", "type", "fid = '".$mybb->get_input('copy_1_forum', MyBB::INPUT_INT)."'"); - if($db->fetch_field($query, "type") == "c") - { - $errors[] = $lang->error_forum_is_category; - } - } - } - else - { - $mybb->input['copy_1_forum'] = ''; - } - - if($mybb->input['approveposts'] != '' && $mybb->input['approveposts'] != 'approve' && $mybb->input['approveposts'] != 'unapprove' && $mybb->input['approveposts'] != 'toggle') - { - $mybb->input['approveposts'] = ''; - } - - if($mybb->input['softdeleteposts'] != '' && $mybb->input['softdeleteposts'] != 'approve' && $mybb->input['softdeleteposts'] != 'unapprove' && $mybb->input['softdeleteposts'] != 'toggle') - { - $mybb->input['softdeleteposts'] = ''; - } - - if($mybb->input['splitposts'] < -2) - { - $mybb->input['splitposts'] = -1; - } - - if($mybb->input['splitpostsclose'] == 1) - { - $mybb->input['splitpostsclose'] = 'close'; - } - else - { - $mybb->input['splitpostsclose'] = ''; - } - - if($mybb->input['splitpostsstick'] == 1) - { - $mybb->input['splitpostsstick'] = 'stick'; - } - else - { - $mybb->input['splitpostsstick'] = ''; - } - - if($mybb->input['splitpostsunapprove'] == 1) - { - $mybb->input['splitpostsunapprove'] = 'unapprove'; - } - else - { - $mybb->input['splitpostsunapprove'] = ''; - } - - if(!$errors) - { - $thread_options = array( - 'confirmation' => $mybb->get_input('confirmation', MyBB::INPUT_INT), - 'deletethread' => $mybb->get_input('deletethread', MyBB::INPUT_INT), - 'softdeletethread' => $mybb->input['softdeletethread'], - 'approvethread' => $mybb->input['approvethread'], - 'openthread' => $mybb->input['openthread'], - 'stickthread' => $mybb->input['stickthread'], - 'movethread' => $mybb->get_input('move_1_forum', MyBB::INPUT_INT), - 'movethreadredirect' => $mybb->get_input('move_2_redirect', MyBB::INPUT_INT), - 'movethreadredirectexpire' => $mybb->get_input('move_3_redirecttime', MyBB::INPUT_INT), - 'copythread' => $mybb->get_input('copy_1_forum', MyBB::INPUT_INT), - 'newsubject' => $mybb->input['newsubject'], - 'addreply' => $mybb->input['newreply'], - 'replysubject' => $mybb->input['newreplysubject'], - 'pm_subject' => $mybb->input['pm_subject'], - 'pm_message' => $mybb->input['pm_message'], - 'threadprefix' => $mybb->get_input('threadprefix', MyBB::INPUT_INT) - ); - - if(stripos($mybb->input['splitpostsnewsubject'], '{subject}') === false) - { - $mybb->input['splitpostsnewsubject'] = '{subject}'.$mybb->input['splitpostsnewsubject']; - } - - $post_options = array( - 'deleteposts' => $mybb->get_input('deleteposts', MyBB::INPUT_INT), - 'softdeleteposts' => $mybb->input['softdeleteposts'], - 'mergeposts' =>$mybb->get_input('mergeposts', MyBB::INPUT_INT), - 'approveposts' => $mybb->input['approveposts'], - 'splitposts' => $mybb->get_input('splitposts', MyBB::INPUT_INT), - 'splitpostsclose' => $mybb->input['splitpostsclose'], - 'splitpostsstick' => $mybb->input['splitpostsstick'], - 'splitpostsunapprove' => $mybb->input['splitpostsunapprove'], - 'splitthreadprefix' => $mybb->get_input('splitthreadprefix', MyBB::INPUT_INT), - 'splitpostsnewsubject' => $mybb->input['splitpostsnewsubject'], - 'splitpostsaddreply' => $mybb->input['splitpostsaddreply'], - 'splitpostsreplysubject' => $mybb->input['splitpostsreplysubject'] - ); - - $update_tool['type'] = 'p'; - $update_tool['threadoptions'] = $db->escape_string(my_serialize($thread_options)); - $update_tool['postoptions'] = $db->escape_string(my_serialize($post_options)); - $update_tool['name'] = $db->escape_string($mybb->input['title']); - $update_tool['description'] = $db->escape_string($mybb->input['description']); - $update_tool['forums'] = ''; - $update_tool['groups'] = ''; - - if($mybb->input['forum_type'] == 2) - { - if(is_array($mybb->input['forum_1_forums'])) - { - $checked = array(); - - foreach($mybb->input['forum_1_forums'] as $fid) - { - $checked[] = (int)$fid; - } - - $update_tool['forums'] = implode(',', $checked); - } - } - else - { - $update_tool['forums'] = "-1"; - } - - if($mybb->input['group_type'] == 2) - { - if(is_array($mybb->input['group_1_groups'])) - { - $checked = array(); - - foreach($mybb->input['group_1_groups'] as $gid) - { - $checked[] = (int)$gid; - } - - $update_tool['groups'] = implode(',', $checked); - } - } - else - { - $update_tool['groups'] = "-1"; - } - - $plugins->run_hooks("admin_config_mod_tools_edit_post_tool_commit"); - - $db->update_query("modtools", $update_tool, "tid = '{$mybb->input['tid']}'"); - - // Log admin action - log_admin_action($mybb->input['tid'], $mybb->input['title']); - $cache->update_forumsdisplay(); - - flash_message($lang->success_mod_tool_updated, 'success'); - admin_redirect("index.php?module=config-mod_tools&action=post_tools"); - } - } - - $page->add_breadcrumb_item($lang->edit_post_tool); - $page->output_header($lang->mod_tools." - ".$lang->edit_post_tool); - - $sub_tabs['edit_post_tool'] = array( - "title" => $lang->edit_post_tool, - "description" => $lang->edit_post_tool_desc, - "link" => "index.php?module=config-mod_tools" - ); - - $page->output_nav_tabs($sub_tabs, 'edit_post_tool'); - - $form = new Form("index.php?module=config-mod_tools&action=edit_post_tool", 'post'); - echo $form->generate_hidden_field("tid", $mybb->input['tid']); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $query = $db->simple_select("modtools", "*", "tid = '{$mybb->input['tid']}'"); - $modtool = $db->fetch_array($query); - $thread_options = my_unserialize($modtool['threadoptions']); - $post_options = my_unserialize($modtool['postoptions']); - - $mybb->input['title'] = $modtool['name']; - $mybb->input['description'] = $modtool['description']; - $mybb->input['forum_1_forums'] = explode(",", $modtool['forums']); - $mybb->input['group_1_groups'] = explode(",", $modtool['groups']); - - if(!$modtool['forums'] || $modtool['forums'] == -1) - { - $forum_checked[1] = "checked=\"checked\""; - $forum_checked[2] = ''; - } - else - { - $forum_checked[1] = ''; - $forum_checked[2] = "checked=\"checked\""; - } - - if(!$modtool['groups'] || $modtool['groups'] == -1) - { - $group_checked[1] = "checked=\"checked\""; - $group_checked[2] = ''; - } - else - { - $group_checked[1] = ''; - $group_checked[2] = "checked=\"checked\""; - } - - $mybb->input['confirmation'] = $thread_options['confirmation']; - $mybb->input['approvethread'] = $thread_options['approvethread']; - $mybb->input['softdeletethread'] = $thread_options['softdeletethread']; - $mybb->input['openthread'] = $thread_options['openthread']; - $mybb->input['stickthread'] = $thread_options['stickthread']; - $mybb->input['move_1_forum'] = $thread_options['movethread']; - $mybb->input['move_2_redirect'] = $thread_options['movethreadredirect']; - $mybb->input['move_3_redirecttime'] = $thread_options['movethreadredirectexpire']; - - if(!$thread_options['movethread']) - { - $move_checked[1] = "checked=\"checked\""; - $move_checked[2] = ''; - } - else - { - $move_checked[1] = ''; - $move_checked[2] = "checked=\"checked\""; - } - - if(!$thread_options['copythread']) - { - $copy_checked[1] = "checked=\"checked\""; - $copy_checked[2] = ''; - } - else - { - $copy_checked[1] = ''; - $copy_checked[2] = "checked=\"checked\""; - } - - $mybb->input['copy_1_forum'] = $thread_options['copythread']; - $mybb->input['deletethread'] = $thread_options['deletethread']; - $mybb->input['threadprefix'] = $thread_options['threadprefix']; - $mybb->input['newsubject'] = $thread_options['newsubject']; - $mybb->input['newreply'] = $thread_options['addreply']; - $mybb->input['newreplysubject'] = $thread_options['replysubject']; - $mybb->input['pm_subject'] = $thread_options['pm_subject']; - $mybb->input['pm_message'] = $thread_options['pm_message']; - - if($post_options['splitposts'] == '-1') - { - $do_not_split_checked = ' selected="selected"'; - $split_same_checked = ''; - } - else if($post_options['splitposts'] == '-2') - { - $do_not_split_checked = ''; - $split_same_checked = ' selected="selected"'; - } - - $mybb->input['softdeleteposts'] = $post_options['softdeleteposts']; - $mybb->input['deleteposts'] = $post_options['deleteposts']; - $mybb->input['mergeposts'] = $post_options['mergeposts']; - $mybb->input['approveposts'] = $post_options['approveposts']; - - if($post_options['splitpostsclose'] == 'close') - { - $mybb->input['splitpostsclose'] = '1'; - } - else - { - $mybb->input['splitpostsclose'] = '0'; - } - - if($post_options['splitpostsstick'] == 'stick') - { - $mybb->input['splitpostsstick'] = '1'; - } - else - { - $mybb->input['splitpostsstick'] = '0'; - } - - if($post_options['splitpostsunapprove'] == 'unapprove') - { - $mybb->input['splitpostsunapprove'] = '1'; - } - else - { - $mybb->input['splitpostsunapprove'] = '0'; - } - - $mybb->input['splitposts'] = $post_options['splitposts']; - $mybb->input['splitthreadprefix'] = $post_options['splitthreadprefix']; - $mybb->input['splitpostsnewsubject'] = $post_options['splitpostsnewsubject']; - $mybb->input['splitpostsaddreply'] = $post_options['splitpostsaddreply']; - $mybb->input['splitpostsreplysubject'] = $post_options['splitpostsreplysubject']; - } - - $form_container = new FormContainer($lang->general_options); - $form_container->output_row($lang->name." *", '', $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_description." *", '', $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - - $actions = " -
-
-
-
- - - - - -
{$lang->forums_colon}".$form->generate_forum_select('forum_1_forums[]', $mybb->input['forum_1_forums'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_in_forums." *", '', $actions); - - $actions = "
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('group_1_groups[]', $mybb->input['group_1_groups'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_to_groups." *", '', $actions); - $form_container->output_row($lang->show_confirmation." *", '', $form->generate_yes_no_radio('confirmation', $mybb->input['confirmation'], array('style' => 'width: 2em;'))); - $form_container->end(); - - $approve_unapprove = array( - '' => $lang->no_change, - 'approve' => $lang->approve, - 'unapprove' => $lang->unapprove, - 'toggle' => $lang->toggle - ); - - $form_container = new FormContainer($lang->inline_post_moderation); - - $softdelete_restore = array( - '' => $lang->no_change, - 'restore' => $lang->restore, - 'softdelete' => $lang->softdelete, - 'toggle' => $lang->toggle - ); - - $form_container->output_row($lang->softdelete_restore_posts." *", '', $form->generate_select_box('softdeleteposts', $softdelete_restore, $mybb->input['softdeleteposts'], array('id' => 'softdeleteposts')), 'softdeleteposts'); - $form_container->output_row($lang->delete_posts." *", '', $form->generate_yes_no_radio('deleteposts', $mybb->input['deleteposts'])); - $form_container->output_row($lang->merge_posts." *", $lang->merge_posts_desc, $form->generate_yes_no_radio('mergeposts', $mybb->input['mergeposts'])); - $form_container->output_row($lang->approve_unapprove_posts." *", '', $form->generate_select_box('approveposts', $approve_unapprove, $mybb->input['approveposts'], array('id' => 'approveposts')), 'approveposts'); - $form_container->end(); - - $selectoptions = "\n"; - $selectoptions .= "\n"; - - $form_container = new FormContainer($lang->split_posts); - $form_container->output_row($lang->split_posts2." *", '', $form->generate_forum_select('splitposts', $mybb->input['splitposts'])); - $form_container->output_row($lang->close_split_thread." *", '', $form->generate_yes_no_radio('splitpostsclose', $mybb->input['splitpostsclose'])); - $form_container->output_row($lang->stick_split_thread." *", '', $form->generate_yes_no_radio('splitpostsstick', $mybb->input['splitpostsstick'])); - $form_container->output_row($lang->unapprove_split_thread." *", '', $form->generate_yes_no_radio('splitpostsunapprove', $mybb->input['splitpostsunapprove'])); - - $splitthreadprefix = build_prefixes(); - if(!empty($splitthreadprefix)) - { - $split_thread_prefixes = array( - '0' => $lang->no_prefix - ); - - foreach($splitthreadprefix as $prefix) - { - $split_thread_prefixes[$prefix['pid']] = $prefix['prefix']; - } - - $form_container->output_row($lang->split_thread_prefix." *", '', $form->generate_select_box('splitthreadprefix', $split_thread_prefixes, array($mybb->get_input('splitthreadprefix', MyBB::INPUT_INT)), array('id' => 'splitthreadprefix')), 'splitthreadprefix'); - } - - $form_container->output_row($lang->split_thread_subject, $lang->split_thread_subject_desc, $form->generate_text_box('splitpostsnewsubject', $mybb->input['splitpostsnewsubject'], array('id' => 'splitpostsnewsubject ')), 'newreplysubject'); - $form_container->output_row($lang->add_new_split_reply, $lang->add_new_split_reply_desc, $form->generate_text_area('splitpostsaddreply', $mybb->input['splitpostsaddreply'], array('id' => 'splitpostsaddreply')), 'splitpostsaddreply'); - $form_container->output_row($lang->split_reply_subject, $lang->split_reply_subject_desc, $form->generate_text_box('splitpostsreplysubject', $mybb->input['splitpostsreplysubject'], array('id' => 'splitpostsreplysubject')), 'splitpostsreplysubject'); - $form_container->end(); - - $open_close = array( - '' => $lang->no_change, - 'open' => $lang->open, - 'close' => $lang->close, - 'toggle' => $lang->toggle - ); - - $stick_unstick = array( - '' => $lang->no_change, - 'stick' => $lang->stick, - 'unstick' => $lang->unstick, - 'toggle' => $lang->toggle - ); - - $form_container = new FormContainer($lang->thread_moderation); - $form_container->output_row($lang->approve_unapprove." *", '', $form->generate_select_box('approvethread', $approve_unapprove, $mybb->input['approvethread'], array('id' => 'approvethread')), 'approvethread'); - $form_container->output_row($lang->open_close_thread." *", '', $form->generate_select_box('openthread', $open_close, $mybb->input['openthread'], array('id' => 'openthread')), 'openthread'); - $form_container->output_row($lang->stick_unstick_thread." *", '', $form->generate_select_box('stickthread', $stick_unstick, $mybb->input['stickthread'], array('id' => 'stickthread')), 'stickthread'); - - - $actions = " -
-
-
-
- - - - - - - - - - - - - -
{$lang->forum_to_move_to}".$form->generate_forum_select('move_1_forum', $mybb->input['move_1_forum'])."
{$lang->leave_redirect}".$form->generate_yes_no_radio('move_2_redirect', $mybb->input['move_2_redirect'])."
{$lang->delete_redirect_after}".$form->generate_numeric_field('move_3_redirecttime', $mybb->input['move_3_redirecttime'], array('style' => 'width: 3em;', 'min' => 0))." {$lang->days}
-
-
- "; - $form_container->output_row($lang->move_thread." *", $lang->move_thread_desc, $actions); - - $actions = " -
-
-
-
- - - - - -
{$lang->forum_to_copy_to}".$form->generate_forum_select('copy_1_forum', $mybb->input['copy_1_forum'])."
-
-
- "; - $form_container->output_row($lang->copy_thread." *", '', $actions); - $form_container->output_row($lang->softdelete_restore_thread." *", '', $form->generate_select_box('softdeletethread', $softdelete_restore, $mybb->input['softdeletethread'], array('id' => 'softdeletethread')), 'softdeletethread'); - $form_container->output_row($lang->delete_thread." *", '', $form->generate_yes_no_radio('deletethread', $mybb->input['deletethread'])); - - $threadprefixes = build_prefixes(); - if(!empty($threadprefixes)) - { - $thread_prefixes = array( - '-1' => $lang->no_change, - '0' => $lang->no_prefix - ); - - foreach($threadprefixes as $prefix) - { - $thread_prefixes[$prefix['pid']] = $prefix['prefix']; - } - - $form_container->output_row($lang->apply_thread_prefix." *", '', $form->generate_select_box('threadprefix', $thread_prefixes, array($mybb->get_input('threadprefix', MyBB::INPUT_INT)), array('id' => 'threadprefix')), 'threadprefix'); - } - - $form_container->output_row($lang->new_subject." *", $lang->new_subject_desc, $form->generate_text_box('newsubject', $mybb->input['newsubject'])); - $form_container->end(); - - $form_container = new FormContainer($lang->add_new_reply); - $form_container->output_row($lang->add_new_reply, $lang->add_new_reply_desc, $form->generate_text_area('newreply', $mybb->input['newreply']), 'newreply'); - $form_container->output_row($lang->reply_subject, $lang->reply_subject_desc, $form->generate_text_box('newreplysubject', $mybb->input['newreplysubject'], array('id' => 'newreplysubject')), 'newreplysubject'); - $form_container->end(); - - $form_container = new FormContainer($lang->send_private_message); - $form_container->output_row($lang->private_message_message, $lang->private_message_message_desc, $form->generate_text_area('pm_message', $mybb->input['pm_message'], array('id' => 'pm_message')), 'pm_message'); - $form_container->output_row($lang->private_message_subject, $lang->private_message_subject_desc, $form->generate_text_box('pm_subject', $mybb->input['pm_subject'], array('id' => 'pm_subject')), 'pm_subject'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_post_tool); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "add_post_tool") -{ - $plugins->run_hooks("admin_config_mod_tools_add_post_tool"); - - if($mybb->request_method == 'post') - { - if(trim($mybb->input['title']) == "") - { - $errors[] = $lang->error_missing_title; - } - - if(trim($mybb->input['description']) == "") - { - $errors[] = $lang->error_missing_description; - } - - if($mybb->input['forum_type'] == 2) - { - $forum_checked[1] = ''; - $forum_checked[2] = "checked=\"checked\""; - - if(count($mybb->input['forum_1_forums']) < 1) - { - $errors[] = $lang->error_no_forums_selected; - } - } - else - { - $forum_checked[1] = "checked=\"checked\""; - $forum_checked[2] = ''; - - $mybb->input['forum_1_forums'] = ''; - } - - if($mybb->input['group_type'] == 2) - { - $group_checked[1] = ''; - $group_checked[2] = "checked=\"checked\""; - - if(count($mybb->input['group_1_groups']) < 1) - { - $errors[] = $lang->error_no_groups_selected; - } - } - else - { - $group_checked[1] = "checked=\"checked\""; - $group_checked[2] = ''; - - $mybb->input['group_1_groups'] = ''; - } - - if($mybb->input['approvethread'] != '' && $mybb->input['approvethread'] != 'approve' && $mybb->input['approvethread'] != 'unapprove' && $mybb->input['approvethread'] != 'toggle') - { - $mybb->input['approvethread'] = ''; - } - - if($mybb->input['softdeletethread'] != '' && $mybb->input['softdeletethread'] != 'softdelete' && $mybb->input['softdeletethread'] != 'restore' && $mybb->input['softdeletethread'] != 'toggle') - { - $mybb->input['softdeletethread'] = ''; - } - - if($mybb->input['openthread'] != '' && $mybb->input['openthread'] != 'open' && $mybb->input['openthread'] != 'close' && $mybb->input['openthread'] != 'toggle') - { - $mybb->input['openthread'] = ''; - } - - if($mybb->input['stickthread'] != '' && $mybb->input['stickthread'] != 'stick' && $mybb->input['stickthread'] != 'unstick' && $mybb->input['stickthread'] != 'toggle') - { - $mybb->input['stickthread'] = ''; - } - - if(!$mybb->get_input('threadprefix', MyBB::INPUT_INT)) - { - $mybb->input['threadprefix'] = ''; - } - - if($mybb->input['move_type'] == 2) - { - $move_checked[1] = ''; - $move_checked[2] = "checked=\"checked\""; - - if(!$mybb->input['move_1_forum']) - { - $errors[] = $lang->error_no_move_forum_selected; - } - else - { - // Check that the destination forum is not a category - $query = $db->simple_select("forums", "type", "fid = '".$mybb->get_input('move_1_forum', MyBB::INPUT_INT)."'"); - if($db->fetch_field($query, "type") == "c") - { - $errors[] = $lang->error_forum_is_category; - } - } - } - else - { - $move_checked[1] = "checked=\"checked\""; - $move_checked[2] = ''; - - $mybb->input['move_1_forum'] = ''; - $mybb->input['move_2_redirect'] = 0; - $mybb->input['move_3_redirecttime'] = ''; - } - - if($mybb->input['copy_type'] == 2) - { - $copy_checked[1] = ''; - $copy_checked[2] = "checked=\"checked\""; - - if(!$mybb->input['copy_1_forum']) - { - $errors[] = $lang->error_no_copy_forum_selected; - } - else - { - $query = $db->simple_select("forums", "type", "fid = '".$mybb->get_input('copy_1_forum', MyBB::INPUT_INT)."'"); - if($db->fetch_field($query, "type") == "c") - { - $errors[] = $lang->error_forum_is_category; - } - } - } - else - { - $copy_checked[1] = 'checked=\"checked\"'; - $copy_checked[2] = ''; - - $mybb->input['copy_1_forum'] = ''; - } - - if($mybb->input['approveposts'] != '' && $mybb->input['approveposts'] != 'approve' && $mybb->input['approveposts'] != 'unapprove' && $mybb->input['approveposts'] != 'toggle') - { - $mybb->input['approveposts'] = ''; - } - - if($mybb->input['softdeleteposts'] != '' && $mybb->input['softdeleteposts'] != 'softdelete' && $mybb->input['softdeleteposts'] != 'restore' && $mybb->input['softdeleteposts'] != 'toggle') - { - $mybb->input['softdeleteposts'] = ''; - } - - if($mybb->input['splitposts'] < -2) - { - $mybb->input['splitposts'] = -1; - } - - if($mybb->input['splitpostsclose'] == 1) - { - $mybb->input['splitpostsclose'] = 'close'; - } - else - { - $mybb->input['splitpostsclose'] = ''; - } - - if($mybb->input['splitpostsstick'] == 1) - { - $mybb->input['splitpostsstick'] = 'stick'; - } - else - { - $mybb->input['splitpostsstick'] = ''; - } - - if($mybb->input['splitpostsunapprove'] == 1) - { - $mybb->input['splitpostsunapprove'] = 'unapprove'; - } - else - { - $mybb->input['splitpostsunapprove'] = ''; - } - - if(!$mybb->get_input('splitthreadprefix', MyBB::INPUT_INT)) - { - $mybb->input['splitthreadprefix'] = ''; - } - - if(!$errors) - { - $thread_options = array( - 'confirmation' => $mybb->get_input('confirmation', MyBB::INPUT_INT), - 'deletethread' => $mybb->get_input('deletethread', MyBB::INPUT_INT), - 'softdeletethread' => $mybb->input['softdeletethread'], - 'approvethread' => $mybb->input['approvethread'], - 'openthread' => $mybb->input['openthread'], - 'stickthread' => $mybb->input['stickthread'], - 'movethread' => $mybb->get_input('move_1_forum', MyBB::INPUT_INT), - 'movethreadredirect' => $mybb->get_input('move_2_redirect', MyBB::INPUT_INT), - 'movethreadredirectexpire' => $mybb->get_input('move_3_redirecttime', MyBB::INPUT_INT), - 'copythread' => $mybb->get_input('copy_1_forum', MyBB::INPUT_INT), - 'newsubject' => $mybb->input['newsubject'], - 'addreply' => $mybb->input['newreply'], - 'replysubject' => $mybb->input['newreplysubject'], - 'pm_subject' => $mybb->input['pm_subject'], - 'pm_message' => $mybb->input['pm_message'], - 'threadprefix' => $mybb->get_input('threadprefix', MyBB::INPUT_INT) - ); - - if(stripos($mybb->input['splitpostsnewsubject'], '{subject}') === false) - { - $mybb->input['splitpostsnewsubject'] = '{subject}'.$mybb->input['splitpostsnewsubject']; - } - - $post_options = array( - 'deleteposts' => $mybb->get_input('deleteposts', MyBB::INPUT_INT), - 'softdeleteposts' => $mybb->input['softdeleteposts'], - 'mergeposts' => $mybb->get_input('mergeposts', MyBB::INPUT_INT), - 'approveposts' => $mybb->input['approveposts'], - 'splitposts' => $mybb->get_input('splitposts', MyBB::INPUT_INT), - 'splitpostsclose' => $mybb->input['splitpostsclose'], - 'splitpostsstick' => $mybb->input['splitpostsstick'], - 'splitpostsunapprove' => $mybb->input['splitpostsunapprove'], - 'splitthreadprefix' => $mybb->get_input('splitthreadprefix', MyBB::INPUT_INT), - 'splitpostsnewsubject' => $mybb->input['splitpostsnewsubject'], - 'splitpostsaddreply' => $mybb->input['splitpostsaddreply'], - 'splitpostsreplysubject' => $mybb->input['splitpostsreplysubject'] - ); - - $new_tool['type'] = 'p'; - $new_tool['threadoptions'] = $db->escape_string(my_serialize($thread_options)); - $new_tool['postoptions'] = $db->escape_string(my_serialize($post_options)); - $new_tool['name'] = $db->escape_string($mybb->input['title']); - $new_tool['description'] = $db->escape_string($mybb->input['description']); - $new_tool['forums'] = ''; - $new_tool['groups'] = ''; - - if($mybb->input['forum_type'] == 2) - { - if(is_array($mybb->input['forum_1_forums'])) - { - $checked = array(); - - foreach($mybb->input['forum_1_forums'] as $fid) - { - $checked[] = (int)$fid; - } - - $new_tool['forums'] = implode(',', $checked); - } - } - else - { - $new_tool['forums'] = "-1"; - } - - if($mybb->input['group_type'] == 2) - { - if(is_array($mybb->input['group_1_groups'])) - { - $checked = array(); - - foreach($mybb->input['group_1_groups'] as $gid) - { - $checked[] = (int)$gid; - } - - $new_tool['groups'] = implode(',', $checked); - } - } - else - { - $new_tool['groups'] = "-1"; - } - - $tid = $db->insert_query("modtools", $new_tool); - - $plugins->run_hooks("admin_config_mod_tools_add_post_tool_commit"); - - // Log admin action - log_admin_action($tid, $mybb->input['title']); - $cache->update_forumsdisplay(); - - flash_message($lang->success_mod_tool_created, 'success'); - admin_redirect("index.php?module=config-mod_tools&action=post_tools"); - } - } - - $page->add_breadcrumb_item($lang->add_new_post_tool); - $page->output_header($lang->mod_tools." - ".$lang->add_new_post_tool); - - $sub_tabs['thread_tools'] = array( - 'title' => $lang->thread_tools, - 'link' => "index.php?module=config-mod_tools" - ); - $sub_tabs['add_thread_tool'] = array( - 'title'=> $lang->add_new_thread_tool, - 'link' => "index.php?module=config-mod_tools&action=add_thread_tool" - ); - $sub_tabs['post_tools'] = array( - 'title' => $lang->post_tools, - 'link' => "index.php?module=config-mod_tools&action=post_tools", - ); - $sub_tabs['add_post_tool'] = array( - 'title'=> $lang->add_new_post_tool, - 'link' => "index.php?module=config-mod_tools&action=add_post_tool", - 'description' => $lang->add_post_tool_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_post_tool'); - - $form = new Form("index.php?module=config-mod_tools&action=add_post_tool", 'post'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['title'] = ''; - $mybb->input['description'] = ''; - $mybb->input['forum_1_forums'] = ''; - $forum_checked[1] = "checked=\"checked\""; - $forum_checked[2] = ''; - $mybb->input['group_1_groups'] = ''; - $group_checked[1] = "checked=\"checked\""; - $group_checked[2] = ''; - $mybb->input['confirmation'] = '0'; - $mybb->input['approvethread'] = ''; - $mybb->input['softdeletethread'] = ''; - $mybb->input['openthread'] = ''; - $mybb->input['stickthread'] = ''; - $mybb->input['move_1_forum'] = ''; - $mybb->input['move_2_redirect'] = '0'; - $mybb->input['move_3_redirecttime'] = ''; - $move_checked[1] = "checked=\"checked\""; - $move_checked[2] = ''; - $copy_checked[1] = "checked=\"checked\""; - $copy_checked[2] = ''; - $mybb->input['copy_1_forum'] = ''; - $mybb->input['deletethread'] = '0'; - $mybb->input['threadprefix'] = '-1'; - $mybb->input['newsubject'] = '{subject}'; - $mybb->input['newreply'] = ''; - $mybb->input['newreplysubject'] = '{subject}'; - $do_not_split_checked = ' selected="selected"'; - $split_same_checked = ''; - $mybb->input['deleteposts'] = '0'; - $mybb->input['mergeposts'] = '0'; - $mybb->input['approveposts'] = ''; - $mybb->input['softdeleteposts'] = ''; - $mybb->input['splitposts'] = '-1'; - $mybb->input['splitpostsclose'] = '0'; - $mybb->input['splitpostsstick'] = '0'; - $mybb->input['splitpostsunapprove'] = '0'; - $mybb->input['splitthreadprefix'] = '0'; - $mybb->input['splitpostsnewsubject'] = '{subject}'; - $mybb->input['splitpostsaddreply'] = ''; - $mybb->input['splitpostsreplysubject'] = '{subject}'; - } - - $form_container = new FormContainer($lang->general_options); - $form_container->output_row($lang->name." *", '', $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_description." *", '', $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - - $actions = " -
-
-
-
- - - - - -
{$lang->forums_colon}".$form->generate_forum_select('forum_1_forums[]', $mybb->input['forum_1_forums'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_in_forums." *", '', $actions); - - $actions = "
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('group_1_groups[]', $mybb->input['group_1_groups'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_to_groups." *", '', $actions); - $form_container->output_row($lang->show_confirmation." *", '', $form->generate_yes_no_radio('confirmation', $mybb->input['confirmation'], array('style' => 'width: 2em;'))); - $form_container->end(); - - $approve_unapprove = array( - '' => $lang->no_change, - 'approve' => $lang->approve, - 'unapprove' => $lang->unapprove, - 'toggle' => $lang->toggle - ); - - $form_container = new FormContainer($lang->inline_post_moderation); - - $softdelete_restore = array( - '' => $lang->no_change, - 'restore' => $lang->restore, - 'softdelete' => $lang->softdelete, - 'toggle' => $lang->toggle - ); - - $form_container->output_row($lang->softdelete_restore_posts." *", '', $form->generate_select_box('softdeleteposts', $softdelete_restore, $mybb->input['softdeleteposts'], array('id' => 'softdeleteposts')), 'softdeleteposts'); - $form_container->output_row($lang->delete_posts." *", '', $form->generate_yes_no_radio('deleteposts', $mybb->input['deleteposts'])); - $form_container->output_row($lang->merge_posts." *", $lang->merge_posts_desc, $form->generate_yes_no_radio('mergeposts', $mybb->input['mergeposts'])); - $form_container->output_row($lang->approve_unapprove_posts." *", '', $form->generate_select_box('approveposts', $approve_unapprove, $mybb->input['approveposts'], array('id' => 'approveposts')), 'approveposts'); - $form_container->end(); - - $selectoptions = "\n"; - $selectoptions .= "\n"; - - $form_container = new FormContainer($lang->split_posts); - $form_container->output_row($lang->split_posts2." *", '', $form->generate_forum_select('splitposts', $mybb->input['splitposts'])); - $form_container->output_row($lang->close_split_thread." *", '', $form->generate_yes_no_radio('splitpostsclose', $mybb->input['splitpostsclose'])); - $form_container->output_row($lang->stick_split_thread." *", '', $form->generate_yes_no_radio('splitpostsstick', $mybb->input['splitpostsstick'])); - $form_container->output_row($lang->unapprove_split_thread." *", '', $form->generate_yes_no_radio('splitpostsunapprove', $mybb->input['splitpostsunapprove'])); - - $splitthreadprefix = build_prefixes(); - if(!empty($splitthreadprefix)) - { - $split_thread_prefixes = array( - '0' => $lang->no_prefix - ); - - foreach($splitthreadprefix as $prefix) - { - $split_thread_prefixes[$prefix['pid']] = $prefix['prefix']; - } - - $form_container->output_row($lang->split_thread_prefix." *", '', $form->generate_select_box('splitthreadprefix', $split_thread_prefixes, array($mybb->get_input('splitthreadprefix', MyBB::INPUT_INT)), array('id' => 'splitthreadprefix')), 'splitthreadprefix'); - } - - $form_container->output_row($lang->split_thread_subject, $lang->split_thread_subject_desc, $form->generate_text_box('splitpostsnewsubject', $mybb->input['splitpostsnewsubject'], array('id' => 'splitpostsnewsubject ')), 'newreplysubject'); - $form_container->output_row($lang->add_new_split_reply, $lang->add_new_split_reply_desc, $form->generate_text_area('splitpostsaddreply', $mybb->input['splitpostsaddreply'], array('id' => 'splitpostsaddreply')), 'splitpostsaddreply'); - $form_container->output_row($lang->split_reply_subject, $lang->split_reply_subject_desc, $form->generate_text_box('splitpostsreplysubject', $mybb->input['splitpostsreplysubject'], array('id' => 'splitpostsreplysubject')), 'splitpostsreplysubject'); - $form_container->end(); - - $open_close = array( - '' => $lang->no_change, - 'open' => $lang->open, - 'close' => $lang->close, - 'toggle' => $lang->toggle - ); - - $stick_unstick = array( - '' => $lang->no_change, - 'stick' => $lang->stick, - 'unstick' => $lang->unstick, - 'toggle' => $lang->toggle - ); - - - $form_container = new FormContainer($lang->thread_moderation); - $form_container->output_row($lang->approve_unapprove." *", '', $form->generate_select_box('approvethread', $approve_unapprove, $mybb->input['approvethread'], array('id' => 'approvethread')), 'approvethread'); - $form_container->output_row($lang->open_close_thread." *", '', $form->generate_select_box('openthread', $open_close, $mybb->input['openthread'], array('id' => 'openthread')), 'openthread'); - $form_container->output_row($lang->stick_unstick_thread." *", '', $form->generate_select_box('stickthread', $stick_unstick, $mybb->input['stickthread'], array('id' => 'stickthread')), 'stickthread'); - - - $actions = " -
-
-
-
- - - - - - - - - - - - - -
{$lang->forum_to_move_to}".$form->generate_forum_select('move_1_forum', $mybb->input['move_1_forum'])."
{$lang->leave_redirect}".$form->generate_yes_no_radio('move_2_redirect', $mybb->input['move_2_redirect'])."
{$lang->delete_redirect_after}".$form->generate_numeric_field('move_3_redirecttime', $mybb->input['move_3_redirecttime'], array('style' => 'width: 3em;', 'min' => 0))." {$lang->days}
-
-
- "; - $form_container->output_row($lang->move_thread." *", $lang->move_thread_desc, $actions); - - $actions = " -
-
-
-
- - - - - -
{$lang->forum_to_copy_to}".$form->generate_forum_select('copy_1_forum', $mybb->input['copy_1_forum'])."
-
-
- "; - $form_container->output_row($lang->copy_thread." *", '', $actions); - $form_container->output_row($lang->softdelete_restore_thread." *", '', $form->generate_select_box('softdeletethread', $softdelete_restore, $mybb->input['softdeletethread'], array('id' => 'softdeletethread')), 'softdeletethread'); - $form_container->output_row($lang->delete_thread." *", '', $form->generate_yes_no_radio('deletethread', $mybb->input['deletethread'])); - - $threadprefixes = build_prefixes(); - if(!empty($threadprefixes)) - { - $thread_prefixes = array( - '-1' => $lang->no_change, - '0' => $lang->no_prefix - ); - - foreach($threadprefixes as $prefix) - { - $thread_prefixes[$prefix['pid']] = $prefix['prefix']; - } - - $form_container->output_row($lang->apply_thread_prefix." *", '', $form->generate_select_box('threadprefix', $thread_prefixes, $mybb->input['threadprefix'], array('id' => 'threadprefix')), 'threadprefix'); - } - - $form_container->output_row($lang->new_subject." *", $lang->new_subject_desc, $form->generate_text_box('newsubject', $mybb->input['newsubject'])); - $form_container->end(); - - $form_container = new FormContainer($lang->add_new_reply); - $form_container->output_row($lang->add_new_reply, $lang->add_new_reply_desc, $form->generate_text_area('newreply', $mybb->input['newreply'], array('id' => 'newreply')), 'newreply'); - $form_container->output_row($lang->reply_subject, $lang->reply_subject_desc, $form->generate_text_box('newreplysubject', $mybb->input['newreplysubject'], array('id' => 'newreplysubject')), 'newreplysubject'); - $form_container->end(); - - $form_container = new FormContainer($lang->send_private_message); - $form_container->output_row($lang->private_message_message, $lang->private_message_message_desc, $form->generate_text_area('pm_message', $mybb->input['pm_message'], array('id' => 'pm_message')), 'pm_message'); - $form_container->output_row($lang->private_message_subject, $lang->private_message_subject_desc, $form->generate_text_box('pm_subject', $mybb->input['pm_subject'], array('id' => 'pm_subject')), 'pm_subject'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_post_tool); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_mod_tools_start"); - - $page->output_header($lang->mod_tools." - ".$lang->thread_tools); - - $sub_tabs['thread_tools'] = array( - 'title' => $lang->thread_tools, - 'link' => "index.php?module=config-mod_tools", - 'description' => $lang->thread_tools_desc - ); - $sub_tabs['add_thread_tool'] = array( - 'title'=> $lang->add_new_thread_tool, - 'link' => "index.php?module=config-mod_tools&action=add_thread_tool" - ); - $sub_tabs['post_tools'] = array( - 'title' => $lang->post_tools, - 'link' => "index.php?module=config-mod_tools&action=post_tools", - ); - $sub_tabs['add_post_tool'] = array( - 'title'=> $lang->add_new_post_tool, - 'link' => "index.php?module=config-mod_tools&action=add_post_tool" - ); - - $page->output_nav_tabs($sub_tabs, 'thread_tools'); - - $table = new Table; - $table->construct_header($lang->title); - $table->construct_header($lang->controls, array('class' => "align_center", 'colspan' => 2)); - - $query = $db->simple_select('modtools', 'tid, name, description, type', "type='t'", array('order_by' => 'name')); - while($tool = $db->fetch_array($query)) - { - $table->construct_cell("".htmlspecialchars_uni($tool['name'])."
".htmlspecialchars_uni($tool['description']).""); - $table->construct_cell("{$lang->edit}", array('width' => 100, 'class' => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_thread_tool_deletion}')\">{$lang->delete}", array('width' => 100, 'class' => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_thread_tools, array('colspan' => 3)); - $table->construct_row(); - } - - $table->output($lang->thread_tools); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/config/module_meta.php b/html/forums/admin/modules/config/module_meta.php deleted file mode 100644 index 24bc7e8..0000000 --- a/html/forums/admin/modules/config/module_meta.php +++ /dev/null @@ -1,128 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -/** - * @return bool true - */ -function config_meta() -{ - global $page, $lang, $plugins; - - $sub_menu = array(); - $sub_menu['10'] = array("id" => "settings", "title" => $lang->bbsettings, "link" => "index.php?module=config-settings"); - $sub_menu['20'] = array("id" => "banning", "title" => $lang->banning, "link" => "index.php?module=config-banning"); - $sub_menu['30'] = array("id" => "profile_fields", "title" => $lang->custom_profile_fields, "link" => "index.php?module=config-profile_fields"); - $sub_menu['40'] = array("id" => "smilies", "title" => $lang->smilies, "link" => "index.php?module=config-smilies"); - $sub_menu['50'] = array("id" => "badwords", "title" => $lang->word_filters, "link" => "index.php?module=config-badwords"); - $sub_menu['60'] = array("id" => "mycode", "title" => $lang->mycode, "link" => "index.php?module=config-mycode"); - $sub_menu['70'] = array("id" => "languages", "title" => $lang->languages, "link" => "index.php?module=config-languages"); - $sub_menu['80'] = array("id" => "post_icons", "title" => $lang->post_icons, "link" => "index.php?module=config-post_icons"); - $sub_menu['90'] = array("id" => "help_documents", "title" => $lang->help_documents, "link" => "index.php?module=config-help_documents"); - $sub_menu['100'] = array("id" => "plugins", "title" => $lang->plugins, "link" => "index.php?module=config-plugins"); - $sub_menu['110'] = array("id" => "attachment_types", "title" => $lang->attachment_types, "link" => "index.php?module=config-attachment_types"); - $sub_menu['120'] = array("id" => "mod_tools", "title" => $lang->moderator_tools, "link" => "index.php?module=config-mod_tools"); - $sub_menu['130'] = array("id" => "spiders", "title" => $lang->spiders_bots, "link" => "index.php?module=config-spiders"); - $sub_menu['140'] = array("id" => "calendars", "title" => $lang->calendars, "link" => "index.php?module=config-calendars"); - $sub_menu['150'] = array("id" => "warning", "title" => $lang->warning_system, "link" => "index.php?module=config-warning"); - $sub_menu['160'] = array("id" => "thread_prefixes", "title" => $lang->thread_prefixes, "link" => "index.php?module=config-thread_prefixes"); - $sub_menu['170'] = array("id" => "questions", "title" => $lang->security_questions, "link" => "index.php?module=config-questions"); - $sub_menu['180'] = array("id" => "report_reasons", "title" => $lang->report_reasons, "link" => "index.php?module=config-report_reasons"); - - $sub_menu = $plugins->run_hooks("admin_config_menu", $sub_menu); - - $page->add_menu_item($lang->configuration, "config", "index.php?module=config", 10, $sub_menu); - - return true; -} - -/** - * @param string $action - * - * @return string - */ -function config_action_handler($action) -{ - global $page, $plugins; - - $page->active_module = "config"; - - $actions = array( - 'plugins' => array('active' => 'plugins', 'file' => 'plugins.php'), - 'smilies' => array('active' => 'smilies', 'file' => 'smilies.php'), - 'banning' => array('active' => 'banning', 'file' => 'banning.php'), - 'badwords' => array('active' => 'badwords', 'file' => 'badwords.php'), - 'profile_fields' => array('active' => 'profile_fields', 'file' => 'profile_fields.php'), - 'spiders' => array('active' => 'spiders', 'file' => 'spiders.php'), - 'attachment_types' => array('active' => 'attachment_types', 'file' => 'attachment_types.php'), - 'languages' => array('active' => 'languages', 'file' => 'languages.php'), - 'post_icons' => array('active' => 'post_icons', 'file' => 'post_icons.php'), - 'help_documents' => array('active' => 'help_documents', 'file' => 'help_documents.php'), - 'calendars' => array('active' => 'calendars', 'file' => 'calendars.php'), - 'warning' => array('active' => 'warning', 'file' => 'warning.php'), - 'mod_tools' => array('active' => 'mod_tools', 'file' => 'mod_tools.php'), - 'mycode' => array('active' => 'mycode', 'file' => 'mycode.php'), - 'settings' => array('active' => 'settings', 'file' => 'settings.php'), - 'thread_prefixes' => array('active' => 'thread_prefixes', 'file' => 'thread_prefixes.php'), - 'questions' => array('active' => 'questions', 'file' => 'questions.php'), - 'report_reasons' => array('active' => 'report_reasons', 'file' => 'report_reasons.php') - ); - - $actions = $plugins->run_hooks("admin_config_action_handler", $actions); - - if(isset($actions[$action])) - { - $page->active_action = $actions[$action]['active']; - return $actions[$action]['file']; - } - else - { - $page->active_action = "settings"; - return "settings.php"; - } -} - -/** - * @return array - */ -function config_admin_permissions() -{ - global $lang, $plugins; - - $admin_permissions = array( - "settings" => $lang->can_manage_settings, - "banning" => $lang->can_manage_banned_accounts, - "profile_fields" => $lang->can_manage_custom_profile_fields, - "smilies" => $lang->can_manage_smilies, - "badwords" => $lang->can_manage_bad_words, - "mycode" => $lang->can_manage_custom_mycode, - "languages" => $lang->can_manage_language_packs, - "post_icons" => $lang->can_manage_post_icons, - "help_documents" => $lang->can_manage_help_documents, - "plugins" => $lang->can_manage_plugins, - "attachment_types" => $lang->can_manage_attachment_types, - "spiders" => $lang->can_manage_spiders_bots, - "calendars" => $lang->can_manage_calendars, - "warning" => $lang->can_manage_warning_system, - "mod_tools" => $lang->can_manage_mod_tools, - "thread_prefixes" => $lang->can_manage_thread_prefixes, - "questions" => $lang->can_manage_security_questions, - "report_reasons" => $lang->can_manage_report_reasons - ); - - $admin_permissions = $plugins->run_hooks("admin_config_permissions", $admin_permissions); - - return array("name" => $lang->configuration, "permissions" => $admin_permissions, "disporder" => 10); -} diff --git a/html/forums/admin/modules/config/mycode.php b/html/forums/admin/modules/config/mycode.php deleted file mode 100644 index 79774cc..0000000 --- a/html/forums/admin/modules/config/mycode.php +++ /dev/null @@ -1,488 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->mycode, "index.php?module=config-mycode"); - -$plugins->run_hooks("admin_config_mycode_begin"); - -if($mybb->input['action'] == "toggle_status") -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=config-mycode"); - } - - $query = $db->simple_select("mycode", "*", "cid='".$mybb->get_input('cid', MyBB::INPUT_INT)."'"); - $mycode = $db->fetch_array($query); - - if(!$mycode['cid']) - { - flash_message($lang->error_invalid_mycode, 'error'); - admin_redirect("index.php?module=config-mycode"); - } - - $plugins->run_hooks("admin_config_mycode_toggle_status"); - - if($mycode['active'] == 1) - { - $new_status = 0; - $phrase = $lang->success_deactivated_mycode; - } - else - { - $new_status = 1; - $phrase = $lang->success_activated_mycode; - } - $mycode_update = array( - 'active' => $new_status, - ); - - $plugins->run_hooks("admin_config_mycode_toggle_status_commit"); - - $db->update_query("mycode", $mycode_update, "cid='{$mycode['cid']}'"); - - $cache->update_mycode(); - - // Log admin action - log_admin_action($mycode['cid'], $mycode['title'], $new_status); - - flash_message($phrase, 'success'); - admin_redirect('index.php?module=config-mycode'); -} - -if($mybb->input['action'] == "xmlhttp_test_mycode" && $mybb->request_method == "post") -{ - $plugins->run_hooks("admin_config_mycode_xmlhttp_test_mycode_start"); - - // Send no cache headers - header("Expires: Sat, 1 Jan 2000 01:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: no-cache, must-revalidate"); - header("Pragma: no-cache"); - header("Content-type: text/html"); - - $sandbox = test_regex($mybb->input['regex'], $mybb->input['replacement'], $mybb->input['test_value']); - - $plugins->run_hooks("admin_config_mycode_xmlhttp_test_mycode_end"); - - echo $sandbox['actual']; - exit; -} - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_config_mycode_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(!trim($mybb->input['regex'])) - { - $errors[] = $lang->error_missing_regex; - } - - $regex = str_replace("\x0", "", $mybb->input['regex']); - - if(check_existing_regex($regex)) - { - $errors[] = $lang->error_regex_already_available; - } - - if(!trim($mybb->input['replacement'])) - { - $errors[] = $lang->error_missing_replacement; - } - - if($mybb->input['test']) - { - $errors[] = $lang->changes_not_saved; - $sandbox = test_regex($mybb->input['regex'], $mybb->input['replacement'], $mybb->input['test_value']); - } - - if(!$errors) - { - $new_mycode = array( - 'title' => $db->escape_string($mybb->input['title']), - 'description' => $db->escape_string($mybb->input['description']), - 'regex' => $db->escape_string($regex), - 'replacement' => $db->escape_string($mybb->input['replacement']), - 'active' => $mybb->get_input('active', MyBB::INPUT_INT), - 'parseorder' => $mybb->get_input('parseorder', MyBB::INPUT_INT) - ); - - $cid = $db->insert_query("mycode", $new_mycode); - - $plugins->run_hooks("admin_config_mycode_add_commit"); - - $cache->update_mycode(); - - // Log admin action - log_admin_action($cid, htmlspecialchars_uni($mybb->input['title'])); - - flash_message($lang->success_added_mycode, 'success'); - admin_redirect('index.php?module=config-mycode'); - } - } - - $sub_tabs['mycode'] = array( - 'title' => $lang->mycode, - 'link' => "index.php?module=config-mycode", - 'description' => $lang->mycode_desc - ); - - $sub_tabs['add_new_mycode'] = array( - 'title' => $lang->add_new_mycode, - 'link' => "index.php?module=config-mycode&action=add", - 'description' => $lang->add_new_mycode_desc - ); - - $page->extra_header .= " - "; - - $page->add_breadcrumb_item($lang->add_new_mycode); - $page->output_header($lang->custom_mycode." - ".$lang->add_new_mycode); - $page->output_nav_tabs($sub_tabs, 'add_new_mycode'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['active'] = 1; - } - - $form = new Form("index.php?module=config-mycode&action=add", "post", "add"); - $form_container = new FormContainer($lang->add_mycode); - $form_container->output_row($lang->title." *", '', $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_description, '', $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->regular_expression." *", $lang->regular_expression_desc.'
'.$lang->example.' \[b\](.*?)\[/b\]', $form->generate_text_area('regex', $mybb->input['regex'], array('id' => 'regex')), 'regex'); - $form_container->output_row($lang->replacement." *", $lang->replacement_desc.'
'.$lang->example.' <strong>$1</strong>', $form->generate_text_area('replacement', $mybb->input['replacement'], array('id' => 'replacement')), 'replacement'); - $form_container->output_row($lang->enabled." *", '', $form->generate_yes_no_radio('active', $mybb->input['active'])); - $form_container->output_row($lang->parse_order, $lang->parse_order_desc, $form->generate_numeric_field('parseorder', $mybb->input['parseorder'], array('id' => 'parseorder', 'min' => 0)), 'parseorder'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_mycode); - $form->output_submit_wrapper($buttons); - - // Sandbox - echo "
\n"; - $form_container = new FormContainer($lang->sandbox); - $form_container->output_row($lang->sandbox_desc); - $form_container->output_row($lang->test_value, $lang->test_value_desc, $form->generate_text_area('test_value', $mybb->input['test_value'], array('id' => 'test_value'))."
".$form->generate_submit_button($lang->test, array('id' => 'test', 'name' => 'test')), 'test_value'); - $form_container->output_row($lang->result_html, $lang->result_html_desc, $form->generate_text_area('result_html', $sandbox['html'], array('id' => 'result_html', 'disabled' => 1)), 'result_html'); - $form_container->output_row($lang->result_actual, $lang->result_actual_desc, "
{$sandbox['actual']}
"); - $form_container->end(); - echo ''; - echo ''; - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("mycode", "*", "cid='".$mybb->get_input('cid', MyBB::INPUT_INT)."'"); - $mycode = $db->fetch_array($query); - - if(!$mycode['cid']) - { - flash_message($lang->error_invalid_mycode, 'error'); - admin_redirect("index.php?module=config-mycode"); - } - - $plugins->run_hooks("admin_config_mycode_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(!trim($mybb->input['regex'])) - { - $errors[] = $lang->error_missing_regex; - } - - $regex = str_replace("\x0", "", $mybb->input['regex']); - - if(check_existing_regex($regex, $mycode)) - { - $errors[] = $lang->error_regex_already_available; - } - - if(!trim($mybb->input['replacement'])) - { - $errors[] = $lang->error_missing_replacement; - } - - if($mybb->input['test']) - { - $errors[] = $lang->changes_not_saved; - $sandbox = test_regex($mybb->input['regex'], $mybb->input['replacement'], $mybb->input['test_value']); - } - - if(!$errors) - { - $updated_mycode = array( - 'title' => $db->escape_string($mybb->input['title']), - 'description' => $db->escape_string($mybb->input['description']), - 'regex' => $db->escape_string($regex), - 'replacement' => $db->escape_string($mybb->input['replacement']), - 'active' => $mybb->get_input('active', MyBB::INPUT_INT), - 'parseorder' => $mybb->get_input('parseorder', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_config_mycode_edit_commit"); - - $db->update_query("mycode", $updated_mycode, "cid='{$mycode['cid']}'"); - - $cache->update_mycode(); - - // Log admin action - log_admin_action($mycode['cid'], htmlspecialchars_uni($mybb->input['title'])); - - flash_message($lang->success_updated_mycode, 'success'); - admin_redirect('index.php?module=config-mycode'); - } - } - - $sub_tabs['edit_mycode'] = array( - 'title' => $lang->edit_mycode, - 'link' => "index.php?module=config-mycode&action=edit", - 'description' => $lang->edit_mycode_desc - ); - - $page->extra_header .= " - "; - - $page->add_breadcrumb_item($lang->edit_mycode); - $page->output_header($lang->custom_mycode." - ".$lang->edit_mycode); - $page->output_nav_tabs($sub_tabs, 'edit_mycode'); - - $form = new Form("index.php?module=config-mycode&action=edit", "post", "edit"); - echo $form->generate_hidden_field('cid', $mycode['cid']); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = array_merge($mybb->input, $mycode); - } - - $form_container = new FormContainer($lang->edit_mycode); - $form_container->output_row($lang->title." *", '', $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_description, '', $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->regular_expression." *", $lang->regular_expression_desc.'
'.$lang->example.' \[b\](.*?)\[/b\]', $form->generate_text_area('regex', $mybb->input['regex'], array('id' => 'regex')), 'regex'); - $form_container->output_row($lang->replacement." *", $lang->replacement_desc.'
'.$lang->example.' <strong>$1</strong>', $form->generate_text_area('replacement', $mybb->input['replacement'], array('id' => 'replacement')), 'replacement'); - $form_container->output_row($lang->enabled." *", '', $form->generate_yes_no_radio('active', $mybb->input['active'])); - $form_container->output_row($lang->parse_order, $lang->parse_order_desc, $form->generate_numeric_field('parseorder', $mybb->input['parseorder'], array('id' => 'parseorder', 'min' => 0)), 'parseorder'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_mycode); - - $form->output_submit_wrapper($buttons); - - // Sandbox - echo "
\n"; - $form_container = new FormContainer($lang->sandbox); - $form_container->output_row($lang->sandbox_desc); - $form_container->output_row($lang->test_value, $lang->test_value_desc, $form->generate_text_area('test_value', $mybb->input['test_value'], array('id' => 'test_value'))."
".$form->generate_submit_button($lang->test, array('id' => 'test', 'name' => 'test')), 'test_value'); - $form_container->output_row($lang->result_html, $lang->result_html_desc, $form->generate_text_area('result_html', $sandbox['html'], array('id' => 'result_html', 'disabled' => 1)), 'result_html'); - $form_container->output_row($lang->result_actual, $lang->result_actual_desc, "
{$sandbox['actual']}
"); - $form_container->end(); - echo ''; - echo ''; - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("mycode", "*", "cid='".$mybb->get_input('cid', MyBB::INPUT_INT)."'"); - $mycode = $db->fetch_array($query); - - if(!$mycode['cid']) - { - flash_message($lang->error_invalid_mycode, 'error'); - admin_redirect("index.php?module=config-mycode"); - } - - $plugins->run_hooks("admin_config_mycode_delete"); - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-mycode"); - } - - if($mybb->request_method == "post") - { - $db->delete_query("mycode", "cid='{$mycode['cid']}'"); - - $plugins->run_hooks("admin_config_mycode_delete_commit"); - - $cache->update_mycode(); - - // Log admin action - log_admin_action($mycode['cid'], htmlspecialchars_uni($mycode['title'])); - - flash_message($lang->success_deleted_mycode, 'success'); - admin_redirect("index.php?module=config-mycode"); - } - else - { - $page->output_confirm_action("index.php?module=config-mycode&action=delete&cid={$mycode['cid']}", $lang->confirm_mycode_deletion); - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_mycode_start"); - - $page->output_header($lang->custom_mycode); - - $sub_tabs['mycode'] = array( - 'title' => $lang->mycode, - 'link' => "index.php?module=config-mycode", - 'description' => $lang->mycode_desc - ); - - $sub_tabs['add_new_mycode'] = array( - 'title' => $lang->add_new_mycode, - 'link' => "index.php?module=config-mycode&action=add" - ); - - $page->output_nav_tabs($sub_tabs, 'mycode'); - - $table = new Table; - $table->construct_header($lang->title); - $table->construct_header($lang->controls, array('class' => 'align_center', 'width' => 150)); - - $query = $db->simple_select("mycode", "*", "", array('order_by' => 'parseorder')); - while($mycode = $db->fetch_array($query)) - { - if($mycode['active'] == 1) - { - $phrase = $lang->deactivate_mycode; - $icon = "style}/images/icons/bullet_on.png\" alt=\"({$lang->alt_enabled})\" title=\"{$lang->alt_enabled}\" style=\"vertical-align: middle;\" /> "; - } - else - { - $phrase = $lang->activate_mycode; - $icon = "style}/images/icons/bullet_off.png\" alt=\"({$lang->alt_disabled})\" title=\"{$lang->alt_disabled}\" style=\"vertical-align: middle;\" /> "; - } - - if($mycode['description']) - { - $mycode['description'] = "".htmlspecialchars_uni($mycode['description']).""; - } - - $table->construct_cell("
{$icon}".htmlspecialchars_uni($mycode['title'])."
{$mycode['description']}
"); - - $popup = new PopupMenu("mycode_{$mycode['cid']}", $lang->options); - $popup->add_item($lang->edit_mycode, "index.php?module=config-mycode&action=edit&cid={$mycode['cid']}"); - $popup->add_item($phrase, "index.php?module=config-mycode&action=toggle_status&cid={$mycode['cid']}&my_post_key={$mybb->post_code}"); - $popup->add_item($lang->delete_mycode, "index.php?module=config-mycode&action=delete&cid={$mycode['cid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_mycode_deletion}')"); - $table->construct_cell($popup->fetch(), array('class' => 'align_center')); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_mycode, array('colspan' => 2)); - $table->construct_row(); - } - - $table->output($lang->custom_mycode); - - $page->output_footer(); -} - -/** - * @param string $regex - * @param string $replacement - * @param string $test - * - * @return array - */ -function test_regex($regex, $replacement, $test) -{ - $array = array(); - $array['actual'] = @preg_replace("#".str_replace("\x0", "", $regex)."#si", $replacement, $test); - $array['html'] = htmlspecialchars_uni($array['actual']); - return $array; -} - -/** - * Checks if a regex is already available - * - * @param string $regex The regex to check - * @param array $current The currently edited MyCode - * - * @return bool True if already available, false otherwise - */ -function check_existing_regex($regex='', $current=array()) -{ - global $cache; - - if(!empty($current) && $current['regex'] == $regex) - { - return false; - } - - $mycodes = $cache->read('mycode'); - - foreach($mycodes as $mycode) - { - if($mycode['regex'] == $regex) - { - return true; - } - } - - return false; -} \ No newline at end of file diff --git a/html/forums/admin/modules/config/plugins.php b/html/forums/admin/modules/config/plugins.php deleted file mode 100644 index 9b9a151..0000000 --- a/html/forums/admin/modules/config/plugins.php +++ /dev/null @@ -1,715 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->plugins, "index.php?module=config-plugins"); - -$plugins->run_hooks("admin_config_plugins_begin"); - -if($mybb->input['action'] == "browse") -{ - $page->add_breadcrumb_item($lang->browse_plugins); - - $page->output_header($lang->browse_plugins); - - $sub_tabs['plugins'] = array( - 'title' => $lang->plugins, - 'link' => "index.php?module=config-plugins", - 'description' => $lang->plugins_desc - ); - $sub_tabs['update_plugins'] = array( - 'title' => $lang->plugin_updates, - 'link' => "index.php?module=config-plugins&action=check", - 'description' => $lang->plugin_updates_desc - ); - - $sub_tabs['browse_plugins'] = array( - 'title' => $lang->browse_plugins, - 'link' => "index.php?module=config-plugins&action=browse", - 'description' => $lang->browse_plugins_desc - ); - - $page->output_nav_tabs($sub_tabs, 'browse_plugins'); - - // Process search requests - require_once MYBB_ROOT."inc/class_xml.php"; - - $keywords = ""; - if($mybb->input['keywords']) - { - $keywords = "&keywords=".urlencode($mybb->input['keywords']); - } - - if($mybb->input['page']) - { - $url_page = "&page=".$mybb->get_input('page', MyBB::INPUT_INT); - } - else - { - $mybb->input['page'] = 1; - $url_page = ""; - } - - // Gets the major version code. i.e. 1410 -> 1400 or 121 -> 1200 - $major_version_code = round($mybb->version_code/100, 0)*100; - // Convert to mods site version codes - $search_version = ($major_version_code/100).'x'; - - $contents = fetch_remote_file("https://community.mybb.com/xmlbrowse.php?type=plugins&version={$search_version}{$keywords}{$url_page}", $post_data); - - if(!$contents) - { - $page->output_inline_error($lang->error_communication_problem); - $page->output_footer(); - exit; - } - - $table = new Table; - $table->construct_header($lang->plugin); - $table->construct_header($lang->latest_version, array("class" => "align_center", 'width' => 125)); - $table->construct_header($lang->controls, array("class" => "align_center", 'width' => 125)); - - $parser = new XMLParser($contents); - $tree = $parser->get_tree(); - - if(!is_array($tree) || !isset($tree['results'])) - { - $page->output_inline_error($lang->error_communication_problem); - $page->output_footer(); - exit; - } - - if(!empty($tree['results']['result'])) - { - if(array_key_exists("tag", $tree['results']['result'])) - { - $only_plugin = $tree['results']['result']; - unset($tree['results']['result']); - $tree['results']['result'][0] = $only_plugin; - } - - require_once MYBB_ROOT . '/inc/class_parser.php'; - $post_parser = new postParser(); - - foreach($tree['results']['result'] as $result) - { - $result['name']['value'] = htmlspecialchars_uni($result['name']['value']); - $result['description']['value'] = htmlspecialchars_uni($result['description']['value']); - $result['author']['value'] = $post_parser->parse_message($result['author']['value'], array( - 'allow_html' => true - ) - ); - $result['version']['value'] = htmlspecialchars_uni($result['version']['value']); - $result['download_url']['value'] = htmlspecialchars_uni(html_entity_decode($result['download_url']['value'])); - - $table->construct_cell("{$result['name']['value']}
{$result['description']['value']}
{$lang->created_by} {$result['author']['value']}"); - $table->construct_cell($result['version']['value'], array("class" => "align_center")); - $table->construct_cell("{$lang->download}", array("class" => "align_center")); - $table->construct_row(); - } - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->error_no_results_found, array("colspan" => 3)); - $table->construct_row(); - } - - $search = new Form("index.php?module=config-plugins&action=browse", 'post', 'search_form'); - echo "
"; - if($mybb->input['keywords']) - { - $default_class = ''; - $value = htmlspecialchars_uni($mybb->input['keywords']); - } - else - { - $default_class = "search_default"; - $value = $lang->search_for_plugins; - } - echo $search->generate_text_box('keywords', $value, array('id' => 'search_keywords', 'class' => "{$default_class} field150 field_small"))."\n"; - echo "search}\" />\n"; - echo "\n"; - echo "
\n"; - echo $search->end(); - - // Recommended plugins = Default; Otherwise search results & pagination - if($mybb->request_method == "post") - { - $table->output("{$lang->browse_all_plugins}".$lang->sprintf($lang->browse_results_for_mybb, $mybb->version)); - } - else - { - $table->output("{$lang->browse_all_plugins}".$lang->sprintf($lang->recommended_plugins_for_mybb, $mybb->version)); - } - - echo "
".draw_admin_pagination($mybb->input['page'], 15, $tree['results']['attributes']['total'], "index.php?module=config-plugins&action=browse{$keywords}&page={page}"); - - $page->output_footer(); -} - -if($mybb->input['action'] == "check") -{ - $plugins_list = get_plugins_list(); - - $plugins->run_hooks("admin_config_plugins_check"); - - $info = array(); - - if($plugins_list) - { - $active_hooks = $plugins->hooks; - foreach($plugins_list as $plugin_file) - { - require_once MYBB_ROOT."inc/plugins/".$plugin_file; - $codename = str_replace(".php", "", $plugin_file); - $infofunc = $codename."_info"; - if(!function_exists($infofunc)) - { - continue; - } - $plugininfo = $infofunc(); - $plugininfo['guid'] = trim($plugininfo['guid']); - $plugininfo['codename'] = trim($plugininfo['codename']); - - if($plugininfo['codename'] != "") - { - $info[] = $plugininfo['codename']; - $names[$plugininfo['codename']] = array('name' => $plugininfo['name'], 'version' => $plugininfo['version']); - } - elseif($plugininfo['guid'] != "") - { - $info[] = $plugininfo['guid']; - $names[$plugininfo['guid']] = array('name' => $plugininfo['name'], 'version' => $plugininfo['version']); - } - } - $plugins->hooks = $active_hooks; - } - - if(empty($info)) - { - flash_message($lang->error_vcheck_no_supported_plugins, 'error'); - admin_redirect("index.php?module=config-plugins"); - } - - $url = "https://community.mybb.com/version_check.php?"; - $url .= http_build_query(array("info" => $info))."&"; - require_once MYBB_ROOT."inc/class_xml.php"; - $contents = fetch_remote_file($url); - - if(!$contents) - { - flash_message($lang->error_vcheck_communications_problem, 'error'); - admin_redirect("index.php?module=config-plugins"); - } - - $parser = new XMLParser($contents); - $tree = $parser->get_tree(); - - if(!is_array($tree) || !isset($tree['plugins'])) - { - flash_message($lang->error_communication_problem, 'error'); - admin_redirect("index.php?module=config-plugins"); - } - - if(array_key_exists('error', $tree['plugins'])) - { - switch($tree['plugins'][0]['error']) - { - case "1": - $error_msg = $lang->error_no_input; - break; - case "2": - $error_msg = $lang->error_no_pids; - break; - default: - $error_msg = ""; - } - flash_message($lang->error_communication_problem.$error_msg, 'error'); - admin_redirect("index.php?module=config-plugins"); - } - - $table = new Table; - $table->construct_header($lang->plugin); - $table->construct_header($lang->your_version, array("class" => "align_center", 'width' => 125)); - $table->construct_header($lang->latest_version, array("class" => "align_center", 'width' => 125)); - $table->construct_header($lang->controls, array("class" => "align_center", 'width' => 125)); - - if(!is_array($tree['plugins']['plugin'])) - { - flash_message($lang->success_plugins_up_to_date, 'success'); - admin_redirect("index.php?module=config-plugins"); - } - - if(array_key_exists("tag", $tree['plugins']['plugin'])) - { - $only_plugin = $tree['plugins']['plugin']; - unset($tree['plugins']['plugin']); - $tree['plugins']['plugin'][0] = $only_plugin; - } - - foreach($tree['plugins']['plugin'] as $plugin) - { - $compare_by = array_key_exists("codename", $plugin['attributes']) ? "codename" : "guid"; - $is_vulnerable = array_key_exists("vulnerable", $plugin) ? true : false; - - if(version_compare($names[$plugin['attributes'][$compare_by]]['version'], $plugin['version']['value'], "<")) - { - $plugin['download_url']['value'] = htmlspecialchars_uni($plugin['download_url']['value']); - $plugin['vulnerable']['value'] = htmlspecialchars_uni($plugin['vulnerable']['value']); - $plugin['version']['value'] = htmlspecialchars_uni($plugin['version']['value']); - - if($is_vulnerable) - { - $table->construct_cell("
- {$lang->error_vcheck_vulnerable} {$names[$plugin['attributes'][$compare_by]]['name']} -
-

{$lang->error_vcheck_vulnerable_notes}

{$plugin['vulnerable']['value']}

"); - } - else - { - $table->construct_cell("{$names[$plugin['attributes'][$compare_by]]['name']}"); - } - $table->construct_cell("{$names[$plugin['attributes'][$compare_by]]['version']}", array("class" => "align_center")); - $table->construct_cell("{$plugin['version']['value']}", array("class" => "align_center")); - if($is_vulnerable) - { - $table->construct_cell("{$lang->deactivate}", array("class" => "align_center", "width" => 150)); - } - else - { - $table->construct_cell("{$lang->download}", array("class" => "align_center")); - } - $table->construct_row(); - } - } - - if($table->num_rows() == 0) - { - flash_message($lang->success_plugins_up_to_date, 'success'); - admin_redirect("index.php?module=config-plugins"); - } - - $page->add_breadcrumb_item($lang->plugin_updates); - - $page->output_header($lang->plugin_updates); - - $sub_tabs['plugins'] = array( - 'title' => $lang->plugins, - 'link' => "index.php?module=config-plugins", - ); - - $sub_tabs['update_plugins'] = array( - 'title' => $lang->plugin_updates, - 'link' => "index.php?module=config-plugins&action=check", - 'description' => $lang->plugin_updates_desc - ); - - $sub_tabs['browse_plugins'] = array( - 'title' => $lang->browse_plugins, - 'link' => "index.php?module=config-plugins&action=browse", - 'description' => $lang->browse_plugins_desc - ); - - $page->output_nav_tabs($sub_tabs, 'update_plugins'); - - $table->output($lang->plugin_updates); - - $page->output_footer(); -} - -// Activates or deactivates a specific plugin -if($mybb->input['action'] == "activate" || $mybb->input['action'] == "deactivate") -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=config-plugins"); - } - - if($mybb->input['action'] == "activate") - { - $plugins->run_hooks("admin_config_plugins_activate"); - } - else - { - $plugins->run_hooks("admin_config_plugins_deactivate"); - } - - $codename = $mybb->input['plugin']; - $codename = str_replace(array(".", "/", "\\"), "", $codename); - $file = basename($codename.".php"); - - // Check if the file exists and throw an error if it doesn't - if(!file_exists(MYBB_ROOT."inc/plugins/$file")) - { - flash_message($lang->error_invalid_plugin, 'error'); - admin_redirect("index.php?module=config-plugins"); - } - - $plugins_cache = $cache->read("plugins"); - $active_plugins = $plugins_cache['active']; - - require_once MYBB_ROOT."inc/plugins/$file"; - - $installed_func = "{$codename}_is_installed"; - $installed = true; - if(function_exists($installed_func) && $installed_func() != true) - { - $installed = false; - } - - $install_uninstall = false; - - if($mybb->input['action'] == "activate") - { - $message = $lang->success_plugin_activated; - - // Plugin is compatible with this version? - if($plugins->is_compatible($codename) == false) - { - flash_message($lang->sprintf($lang->plugin_incompatible, $mybb->version), 'error'); - admin_redirect("index.php?module=config-plugins"); - } - - // If not installed and there is a custom installation function - if($installed == false && function_exists("{$codename}_install")) - { - call_user_func("{$codename}_install"); - $message = $lang->success_plugin_installed; - $install_uninstall = true; - } - - if(function_exists("{$codename}_activate")) - { - call_user_func("{$codename}_activate"); - } - - $active_plugins[$codename] = $codename; - $executed[] = 'activate'; - } - else if($mybb->input['action'] == "deactivate") - { - $message = $lang->success_plugin_deactivated; - - if(function_exists("{$codename}_deactivate")) - { - call_user_func("{$codename}_deactivate"); - } - - if($mybb->input['uninstall'] == 1 && function_exists("{$codename}_uninstall")) - { - call_user_func("{$codename}_uninstall"); - $message = $lang->success_plugin_uninstalled; - $install_uninstall = true; - } - - unset($active_plugins[$codename]); - } - - // Update plugin cache - $plugins_cache['active'] = $active_plugins; - $cache->update("plugins", $plugins_cache); - - // Log admin action - log_admin_action($codename, $install_uninstall); - - if($mybb->input['action'] == "activate") - { - $plugins->run_hooks("admin_config_plugins_activate_commit"); - } - else - { - $plugins->run_hooks("admin_config_plugins_deactivate_commit"); - } - - flash_message($message, 'success'); - admin_redirect("index.php?module=config-plugins"); -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->plugins); - - $sub_tabs['plugins'] = array( - 'title' => $lang->plugins, - 'link' => "index.php?module=config-plugins", - 'description' => $lang->plugins_desc - ); - $sub_tabs['update_plugins'] = array( - 'title' => $lang->plugin_updates, - 'link' => "index.php?module=config-plugins&action=check", - 'description' => $lang->plugin_updates_desc - ); - - $sub_tabs['browse_plugins'] = array( - 'title' => $lang->browse_plugins, - 'link' => "index.php?module=config-plugins&action=browse", - 'description' => $lang->browse_plugins_desc - ); - - $page->output_nav_tabs($sub_tabs, 'plugins'); - - // Let's make things easier for our user - show them active - // and inactive plugins in different lists - $plugins_cache = $cache->read("plugins"); - $active_plugins = $plugins_cache['active']; - - $plugins_list = get_plugins_list(); - - $plugins->run_hooks("admin_config_plugins_plugin_list"); - - if(!empty($plugins_list)) - { - $a_plugins = $i_plugins = array(); - - foreach($plugins_list as $plugin_file) - { - require_once MYBB_ROOT."inc/plugins/".$plugin_file; - $codename = str_replace(".php", "", $plugin_file); - $infofunc = $codename."_info"; - - if(!function_exists($infofunc)) - { - continue; - } - - $plugininfo = $infofunc(); - $plugininfo['codename'] = $codename; - - if($active_plugins[$codename]) - { - // This is an active plugin - $plugininfo['is_active'] = 1; - - $a_plugins[] = $plugininfo; - continue; - } - - // Either installed and not active or completely inactive - $i_plugins[] = $plugininfo; - } - - $table = new Table; - $table->construct_header($lang->plugin); - $table->construct_header($lang->controls, array("colspan" => 2, "class" => "align_center", "width" => 300)); - - if(empty($a_plugins)) - { - $table->construct_cell($lang->no_active_plugins, array('colspan' => 3)); - $table->construct_row(); - } - else - { - build_plugin_list($a_plugins); - } - - $table->output($lang->active_plugin); - - $table = new Table; - $table->construct_header($lang->plugin); - $table->construct_header($lang->controls, array("colspan" => 2, "class" => "align_center", "width" => 300)); - - if(empty($i_plugins)) - { - $table->construct_cell($lang->no_inactive_plugins, array('colspan' => 3)); - $table->construct_row(); - } - else - { - build_plugin_list($i_plugins); - } - - $table->output($lang->inactive_plugin); - } - else - { - // No plugins - $table = new Table; - $table->construct_header($lang->plugin); - $table->construct_header($lang->controls, array("colspan" => 2, "class" => "align_center", "width" => 300)); - - $table->construct_cell($lang->no_plugins, array('colspan' => 3)); - $table->construct_row(); - - $table->output($lang->plugins); - } - - $page->output_footer(); -} - -/** - * @return array - */ -function get_plugins_list() -{ - // Get a list of the plugin files which exist in the plugins directory - $dir = @opendir(MYBB_ROOT."inc/plugins/"); - if($dir) - { - while($file = readdir($dir)) - { - $ext = get_extension($file); - if($ext == "php") - { - $plugins_list[] = $file; - } - } - @sort($plugins_list); - } - @closedir($dir); - - return $plugins_list; -} - -/** - * @param array $plugin_list - */ -function build_plugin_list($plugin_list) -{ - global $lang, $mybb, $plugins, $table; - - foreach($plugin_list as $plugininfo) - { - if($plugininfo['website']) - { - $plugininfo['name'] = "".$plugininfo['name'].""; - } - - if($plugininfo['authorsite']) - { - $plugininfo['author'] = "".$plugininfo['author'].""; - } - - if($plugins->is_compatible($plugininfo['codename']) == false) - { - $compatibility_warning = "".$lang->sprintf($lang->plugin_incompatible, $mybb->version).""; - } - else - { - $compatibility_warning = ""; - } - - $installed_func = "{$plugininfo['codename']}_is_installed"; - $install_func = "{$plugininfo['codename']}_install"; - $uninstall_func = "{$plugininfo['codename']}_uninstall"; - - $installed = true; - $install_button = false; - $uninstall_button = false; - - if(function_exists($installed_func) && $installed_func() != true) - { - $installed = false; - } - - if(function_exists($install_func)) - { - $install_button = true; - } - - if(function_exists($uninstall_func)) - { - $uninstall_button = true; - } - - $table->construct_cell("{$plugininfo['name']} ({$plugininfo['version']})
{$plugininfo['description']}
{$lang->created_by} {$plugininfo['author']}"); - - // Plugin is not installed at all - if($installed == false) - { - if($compatibility_warning) - { - $table->construct_cell("{$compatibility_warning}", array("class" => "align_center", "colspan" => 2)); - } - else - { - $table->construct_cell("post_code}\">{$lang->install_and_activate}", array("class" => "align_center", "colspan" => 2)); - } - } - // Plugin is activated and installed - else if($plugininfo['is_active']) - { - $table->construct_cell("post_code}\">{$lang->deactivate}", array("class" => "align_center", "width" => 150)); - if($uninstall_button) - { - $table->construct_cell("post_code}\">{$lang->uninstall}", array("class" => "align_center", "width" => 150)); - } - else - { - $table->construct_cell(" ", array("class" => "align_center", "width" => 150)); - } - } - // Plugin is installed but not active - else if($installed == true) - { - if($compatibility_warning && !$uninstall_button) - { - $table->construct_cell("{$compatibility_warning}", array("class" => "align_center", "colspan" => 2)); - } - else - { - $table->construct_cell("post_code}\">{$lang->activate}", array("class" => "align_center", "width" => 150)); - if($uninstall_button) - { - $table->construct_cell("post_code}\">{$lang->uninstall}", array("class" => "align_center", "width" => 150)); - } - else - { - $table->construct_cell(" ", array("class" => "align_center", "width" => 150)); - } - } - } - $table->construct_row(); - } -} diff --git a/html/forums/admin/modules/config/post_icons.php b/html/forums/admin/modules/config/post_icons.php deleted file mode 100644 index f8ba7cb..0000000 --- a/html/forums/admin/modules/config/post_icons.php +++ /dev/null @@ -1,499 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->post_icons, "index.php?module=config-post_icons"); - -$plugins->run_hooks("admin_config_post_icons_begin"); - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_config_post_icons_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - - if(!trim($mybb->input['path'])) - { - $errors[] = $lang->error_missing_path; - } - - if(!$errors) - { - $new_icon = array( - 'name' => $db->escape_string($mybb->input['name']), - 'path' => $db->escape_string($mybb->input['path']) - ); - - $iid = $db->insert_query("icons", $new_icon); - - $plugins->run_hooks("admin_config_post_icons_add_commit"); - - $cache->update_posticons(); - - // Log admin action - log_admin_action($iid, htmlspecialchars_uni($mybb->input['name'])); - - flash_message($lang->success_post_icon_added, 'success'); - admin_redirect('index.php?module=config-post_icons'); - } - } - - $page->add_breadcrumb_item($lang->add_post_icon); - $page->output_header($lang->post_icons." - ".$lang->add_post_icon); - - $sub_tabs['manage_icons'] = array( - 'title' => $lang->manage_post_icons, - 'link' => "index.php?module=config-post_icons" - ); - - $sub_tabs['add_icon'] = array( - 'title' => $lang->add_post_icon, - 'link' => "index.php?module=config-post_icons&action=add", - 'description' => $lang->add_post_icon_desc - ); - - $sub_tabs['add_multiple'] = array( - 'title' => $lang->add_multiple_post_icons, - 'link' => "index.php?module=config-post_icons&action=add_multiple" - ); - - $page->output_nav_tabs($sub_tabs, 'add_icon'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['path'] = 'images/icons/'; - } - - $form = new Form("index.php?module=config-post_icons&action=add", "post", "add"); - $form_container = new FormContainer($lang->add_post_icon); - $form_container->output_row($lang->name." *", $lang->name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->image_path." *", $lang->image_path_desc, $form->generate_text_box('path', $mybb->input['path'], array('id' => 'path')), 'path'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_post_icon); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "add_multiple") -{ - $plugins->run_hooks("admin_config_post_icons_add_multiple"); - - if($mybb->request_method == "post") - { - if($mybb->input['step'] == 1) - { - if(!trim($mybb->input['pathfolder'])) - { - $errors[] = $lang->error_missing_path_multiple; - } - - $path = $mybb->input['pathfolder']; - $dir = @opendir(MYBB_ROOT.$path); - if(!$dir) - { - $errors[] = $lang->error_invalid_path; - } - - if(substr($path, -1, 1) !== "/") - { - $path .= "/"; - } - - $query = $db->simple_select("icons"); - - $aicons = array(); - while($icon = $db->fetch_array($query)) - { - $aicons[$icon['path']] = 1; - } - - $icons = array(); - if(!$errors) - { - while($file = readdir($dir)) - { - if($file != ".." && $file != ".") - { - $ext = get_extension($file); - if($ext == "gif" || $ext == "jpg" || $ext == "jpeg" || $ext == "png" || $ext == "bmp") - { - if(!$aicons[$path.$file]) - { - $icons[] = $file; - } - } - } - } - closedir($dir); - - if(count($icons) == 0) - { - $errors[] = $lang->error_no_images; - } - } - - // Check for errors again (from above statement)! - if(!$errors) - { - // We have no errors so let's proceed! - $page->add_breadcrumb_item($lang->add_multiple_post_icons); - $page->output_header($lang->post_icons." - ".$lang->add_multiple_post_icons); - - $sub_tabs['manage_icons'] = array( - 'title' => $lang->manage_post_icons, - 'link' => "index.php?module=config-post_icons" - ); - - $sub_tabs['add_icon'] = array( - 'title' => $lang->add_post_icon, - 'link' => "index.php?module=config-post_icons&action=add" - ); - - $sub_tabs['add_multiple'] = array( - 'title' => $lang->add_multiple_post_icons, - 'link' => "index.php?module=config-post_icons&action=add_multiple", - 'description' => $lang->add_multiple_post_icons_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_multiple'); - - $form = new Form("index.php?module=config-post_icons&action=add_multiple", "post", "add_multiple"); - echo $form->generate_hidden_field("step", "2"); - echo $form->generate_hidden_field("pathfolder", $path); - - $form_container = new FormContainer($lang->add_multiple_post_icons); - $form_container->output_row_header($lang->image, array("class" => "align_center", 'width' => '10%')); - $form_container->output_row_header($lang->name); - $form_container->output_row_header($lang->add, array("class" => "align_center", 'width' => '5%')); - - foreach($icons as $key => $file) - { - $ext = get_extension($file); - $find = str_replace(".".$ext, "", $file); - $name = ucfirst($find); - - $form_container->output_cell("\"\"
{$file}", array("class" => "align_center", "width" => 1)); - $form_container->output_cell($form->generate_text_box("name[{$file}]", $name, array('id' => 'name', 'style' => 'width: 98%'))); - $form_container->output_cell($form->generate_check_box("include[{$file}]", 1, "", array('checked' => 1)), array("class" => "align_center")); - $form_container->construct_row(); - } - - if($form_container->num_rows() == 0) - { - flash_message($lang->error_no_images, 'error'); - admin_redirect("index.php?module=config-post_icons&action=add_multiple"); - } - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_post_icons); - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); - exit; - } - } - else - { - $path = $mybb->input['pathfolder']; - reset($mybb->input['include']); - $name = $mybb->input['name']; - - if(empty($mybb->input['include'])) - { - flash_message($lang->error_none_included, 'error'); - admin_redirect("index.php?module=config-post_icons&action=add_multiple"); - } - - foreach($mybb->input['include'] as $image => $insert) - { - if($insert) - { - $new_icon = array( - 'name' => $db->escape_string($name[$image]), - 'path' => $db->escape_string($path.$image) - ); - - $db->insert_query("icons", $new_icon); - } - } - - $plugins->run_hooks("admin_config_post_icons_add_multiple_commit"); - - $cache->update_posticons(); - - // Log admin action - log_admin_action(); - - flash_message($lang->success_post_icons_added, 'success'); - admin_redirect("index.php?module=config-post_icons"); - } - } - - $page->add_breadcrumb_item($lang->add_multiple_post_icons); - $page->output_header($lang->post_icons." - ".$lang->add_multiple_post_icons); - - $sub_tabs['manage_icons'] = array( - 'title' => $lang->manage_post_icons, - 'link' => "index.php?module=config-post_icons" - ); - - $sub_tabs['add_icon'] = array( - 'title' => $lang->add_post_icon, - 'link' => "index.php?module=config-post_icons&action=add" - ); - - $sub_tabs['add_multiple'] = array( - 'title' => $lang->add_multiple_post_icons, - 'link' => "index.php?module=config-post_icons&action=add_multiple", - 'description' => $lang->add_multiple_post_icons_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_multiple'); - - $form = new Form("index.php?module=config-post_icons&action=add_multiple", "post", "add_multiple"); - echo $form->generate_hidden_field("step", "1"); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer($lang->add_multiple_post_icons); - $form_container->output_row($lang->path_to_images." *", $lang->path_to_images_desc, $form->generate_text_box('pathfolder', $mybb->input['pathfolder'], array('id' => 'pathfolder')), 'pathfolder'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->show_post_icons); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("icons", "*", "iid='".$mybb->get_input('iid', MyBB::INPUT_INT)."'"); - $icon = $db->fetch_array($query); - - if(!$icon['iid']) - { - flash_message($lang->error_invalid_post_icon, 'error'); - admin_redirect("index.php?module=config-post_icons"); - } - - $plugins->run_hooks("admin_config_post_icons_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - - if(!trim($mybb->input['path'])) - { - $errors[] = $lang->error_missing_path; - } - - if(!$errors) - { - $updated_icon = array( - 'name' => $db->escape_string($mybb->input['name']), - 'path' => $db->escape_string($mybb->input['path']) - ); - - $plugins->run_hooks("admin_config_post_icons_edit_commit"); - - $db->update_query("icons", $updated_icon, "iid='{$icon['iid']}'"); - - $cache->update_posticons(); - - // Log admin action - log_admin_action($icon['iid'], htmlspecialchars_uni($mybb->input['name'])); - - flash_message($lang->success_post_icon_updated, 'success'); - admin_redirect('index.php?module=config-post_icons'); - } - } - - $page->add_breadcrumb_item($lang->edit_post_icon); - $page->output_header($lang->post_icons." - ".$lang->edit_post_icon); - - $sub_tabs['edit_icon'] = array( - 'title' => $lang->edit_post_icon, - 'link' => "index.php?module=config-post_icons", - 'description' => $lang->edit_post_icon_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_icon'); - - $form = new Form("index.php?module=config-post_icons&action=edit", "post", "edit"); - echo $form->generate_hidden_field("iid", $icon['iid']); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = array_merge($mybb->input, $icon); - } - - $form_container = new FormContainer($lang->edit_post_icon); - $form_container->output_row($lang->name." *", $lang->name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->image_path." *", $lang->image_path_desc, $form->generate_text_box('path', $mybb->input['path'], array('id' => 'path')), 'path'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_post_icon); - $buttons[] = $form->generate_reset_button($lang->reset); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("icons", "*", "iid='".$mybb->get_input('iid', MyBB::INPUT_INT)."'"); - $icon = $db->fetch_array($query); - - if(!$icon['iid']) - { - flash_message($lang->error_invalid_post_icon, 'error'); - admin_redirect("index.php?module=config-post_icons"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-post_icons"); - } - - $plugins->run_hooks("admin_config_post_icons_delete"); - - if($mybb->request_method == "post") - { - $db->delete_query("icons", "iid='{$icon['iid']}'"); - - $plugins->run_hooks("admin_config_post_icons_delete_commit"); - - $cache->update_posticons(); - - // Log admin action - log_admin_action($icon['iid'], htmlspecialchars_uni($icon['name'])); - - flash_message($lang->success_post_icon_deleted, 'success'); - admin_redirect("index.php?module=config-post_icons"); - } - else - { - $page->output_confirm_action("index.php?module=config-post_icons&action=delete&iid={$icon['iid']}", $lang->confirm_post_icon_deletion); - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_post_icons_start"); - - $page->output_header($lang->post_icons); - - $sub_tabs['manage_icons'] = array( - 'title' => $lang->manage_post_icons, - 'link' => "index.php?module=config-post_icons", - 'description' => $lang->manage_post_icons_desc - ); - - $sub_tabs['add_icon'] = array( - 'title' => $lang->add_post_icon, - 'link' => "index.php?module=config-post_icons&action=add" - ); - - $sub_tabs['add_multiple'] = array( - 'title' => $lang->add_multiple_post_icons, - 'link' => "index.php?module=config-post_icons&action=add_multiple" - ); - - $page->output_nav_tabs($sub_tabs, 'manage_icons'); - - $pagenum = $mybb->get_input('page', MyBB::INPUT_INT); - if($pagenum) - { - $start = ($pagenum - 1) * 20; - } - else - { - $start = 0; - $pagenum = 1; - } - - $table = new Table; - $table->construct_header($lang->image, array('class' => "align_center", 'width' => 1)); - $table->construct_header($lang->name, array('width' => "70%")); - $table->construct_header($lang->controls, array('class' => "align_center", 'colspan' => 2)); - - $query = $db->simple_select("icons", "*", "", array('limit_start' => $start, 'limit' => 20, 'order_by' => 'name')); - while($icon = $db->fetch_array($query)) - { - $icon['path'] = str_replace("{theme}", "images", $icon['path']); - if(my_validate_url($icon['path'], true)) - { - $image = $icon['path']; - } - else - { - $image = "../".$icon['path']; - } - - $table->construct_cell("\"\"", array("class" => "align_center")); - $table->construct_cell(htmlspecialchars_uni($icon['name'])); - - $table->construct_cell("{$lang->edit}", array("class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_post_icon_deletion}')\">{$lang->delete}", array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_post_icons, array('colspan' => 4)); - $table->construct_row(); - } - - $table->output($lang->manage_post_icons); - - $query = $db->simple_select("icons", "COUNT(iid) AS icons"); - $total_rows = $db->fetch_field($query, "icons"); - - echo "
".draw_admin_pagination($pagenum, "20", $total_rows, "index.php?module=config-post_icons&page={page}"); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/config/profile_fields.php b/html/forums/admin/modules/config/profile_fields.php deleted file mode 100644 index 1dd230a..0000000 --- a/html/forums/admin/modules/config/profile_fields.php +++ /dev/null @@ -1,795 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->custom_profile_fields, "index.php?module=config-profile_fields"); - -$plugins->run_hooks("admin_config_profile_fields_begin"); - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_config_profile_fields_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - - if(!trim($mybb->input['description'])) - { - $errors[] = $lang->error_missing_description; - } - - if(!trim($mybb->input['fieldtype'])) - { - $errors[] = $lang->error_missing_fieldtype; - } - - if(!$errors) - { - $type = $mybb->input['fieldtype']; - $options = preg_replace("#(\r\n|\r|\n)#s", "\n", trim($mybb->input['options'])); - if($type != "text" && $type != "textarea") - { - $thing = "$type\n$options"; - } - else - { - $thing = $type; - } - - foreach(array('viewableby', 'editableby') as $key) - { - if($mybb->input[$key] == 'all') - { - $mybb->input[$key] = -1; - } - elseif($mybb->input[$key] == 'custom') - { - if(isset($mybb->input['select'][$key]) && is_array($mybb->input['select'][$key])) - { - foreach($mybb->input['select'][$key] as &$val) - { - $val = (int)$val; - } - unset($val); - - $mybb->input[$key] = implode(',', (array)$mybb->input['select'][$key]); - } - else - { - $mybb->input[$key] = ''; - } - } - else - { - $mybb->input[$key] = ''; - } - } - - $new_profile_field = array( - "name" => $db->escape_string($mybb->input['name']), - "description" => $db->escape_string($mybb->input['description']), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "type" => $db->escape_string($thing), - "regex" => $db->escape_string($mybb->input['regex']), - "length" => $mybb->get_input('length', MyBB::INPUT_INT), - "maxlength" => $mybb->get_input('maxlength', MyBB::INPUT_INT), - "required" => $mybb->get_input('required', MyBB::INPUT_INT), - "registration" => $mybb->get_input('registration', MyBB::INPUT_INT), - "profile" => $mybb->get_input('profile', MyBB::INPUT_INT), - "viewableby" => $db->escape_string($mybb->input['viewableby']), - "editableby" => $db->escape_string($mybb->input['editableby']), - "postbit" => $mybb->get_input('postbit', MyBB::INPUT_INT), - "postnum" => $mybb->get_input('postnum', MyBB::INPUT_INT), - "allowhtml" => $mybb->get_input('allowhtml', MyBB::INPUT_INT), - "allowmycode" => $mybb->get_input('allowmycode', MyBB::INPUT_INT), - "allowsmilies" => $mybb->get_input('allowsmilies', MyBB::INPUT_INT), - "allowimgcode" => $mybb->get_input('allowimgcode', MyBB::INPUT_INT), - "allowvideocode" => $mybb->get_input('allowvideocode', MyBB::INPUT_INT) - ); - - $fid = $db->insert_query("profilefields", $new_profile_field); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."userfields ADD fid{$fid} TEXT"); - - $plugins->run_hooks("admin_config_profile_fields_add_commit"); - - $cache->update_profilefields(); - - // Log admin action - log_admin_action($fid, htmlspecialchars_uni($mybb->input['name'])); - - flash_message($lang->success_profile_field_added, 'success'); - admin_redirect("index.php?module=config-profile_fields"); - } - } - - $page->add_breadcrumb_item($lang->add_new_profile_field); - $page->output_header($lang->custom_profile_fields." - ".$lang->add_new_profile_field); - - $sub_tabs['custom_profile_fields'] = array( - 'title' => $lang->custom_profile_fields, - 'link' => "index.php?module=config-profile_fields" - ); - - $sub_tabs['add_profile_field'] = array( - 'title' => $lang->add_new_profile_field, - 'link' => "index.php?module=config-profile_fields&action=add", - 'description' => $lang->add_new_profile_field_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_profile_field'); - $form = new Form("index.php?module=config-profile_fields&action=add", "post", "add"); - - if($errors) - { - switch($mybb->input['viewableby']) - { - case 'all': - $mybb->input['viewableby'] = -1; - break; - case 'custom': - $mybb->input['viewableby'] = implode(',', (array)$mybb->input['select']['viewableby']); - break; - default: - $mybb->input['viewableby'] = ''; - break; - } - - switch($mybb->input['editableby']) - { - case 'all': - $mybb->input['editableby'] = -1; - break; - case 'custom': - $mybb->input['editableby'] = implode(',', (array)$mybb->input['select']['editableby']); - break; - default: - $mybb->input['editableby'] = ''; - break; - } - - $page->output_inline_error($errors); - } - else - { - $mybb->input['fieldtype'] = 'textbox'; - $mybb->input['required'] = 0; - $mybb->input['registration'] = 0; - $mybb->input['editable'] = 1; - $mybb->input['hidden'] = 0; - $mybb->input['postbit'] = 0; - } - - if(empty($mybb->input['viewableby'])) - { - $mybb->input['viewableby'] = ''; - } - - if(empty($mybb->input['editableby'])) - { - $mybb->input['editableby'] = ''; - } - - $form_container = new FormContainer($lang->add_new_profile_field); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->short_description." *", "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $select_list = array( - "text" => $lang->text, - "textarea" => $lang->textarea, - "select" => $lang->select, - "multiselect" => $lang->multiselect, - "radio" => $lang->radio, - "checkbox" => $lang->checkbox - ); - $form_container->output_row($lang->field_type." *", $lang->field_type_desc, $form->generate_select_box('fieldtype', $select_list, $mybb->input['fieldtype'], array('id' => 'fieldtype')), 'fieldtype'); - $form_container->output_row($lang->field_regex, $lang->field_regex_desc, $form->generate_text_box('regex', $mybb->input['regex'], array('id' => 'regex')), 'regex', array(), array('id' => 'row_regex')); - $form_container->output_row($lang->maximum_length, $lang->maximum_length_desc, $form->generate_numeric_field('maxlength', $mybb->input['maxlength'], array('id' => 'maxlength', 'min' => 0)), 'maxlength', array(), array('id' => 'row_maxlength')); - $form_container->output_row($lang->field_length, $lang->field_length_desc, $form->generate_numeric_field('length', $mybb->input['length'], array('id' => 'length', 'min' => 0)), 'length', array(), array('id' => 'row_fieldlength')); - $form_container->output_row($lang->selectable_options, $lang->selectable_options_desc, $form->generate_text_area('options', $mybb->input['options'], array('id' => 'options')), 'options', array(), array('id' => 'row_options')); - $form_container->output_row($lang->min_posts_enabled, $lang->min_posts_enabled_desc, $form->generate_numeric_field('postnum', $mybb->input['postnum'], array('id' => 'postnum', 'min' => 0)), 'postnum'); - $form_container->output_row($lang->display_order." *", $lang->display_order_desc, $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->output_row($lang->required." *", $lang->required_desc, $form->generate_yes_no_radio('required', $mybb->input['required'])); - $form_container->output_row($lang->show_on_registration." *", $lang->show_on_registration_desc, $form->generate_yes_no_radio('registration', $mybb->input['registration'])); - $form_container->output_row($lang->display_on_profile." *", $lang->display_on_profile_desc, $form->generate_yes_no_radio('profile', $mybb->input['profile'])); - $form_container->output_row($lang->display_on_postbit." *", $lang->display_on_postbit_desc, $form->generate_yes_no_radio('postbit', $mybb->input['postbit'])); - - $selected_values = ''; - if($mybb->input['viewableby'] != '' && $mybb->input['viewableby'] != -1) - { - $selected_values = explode(',', $mybb->get_input('viewableby')); - - foreach($selected_values as &$value) - { - $value = (int)$value; - } - unset($value); - } - - $group_checked = array('all' => '', 'custom' => '', 'none' => ''); - if($mybb->input['viewableby'] == -1) - { - $group_checked['all'] = 'checked="checked"'; - } - elseif($mybb->input['viewableby'] != '') - { - $group_checked['custom'] = 'checked="checked"'; - } - else - { - $group_checked['none'] = 'checked="checked"'; - } - - print_selection_javascript(); - - $select_code = " -
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('select[viewableby][]', $selected_values, array('id' => 'viewableby', 'multiple' => true, 'size' => 5))."
-
-
-
- "; - $form_container->output_row($lang->viewableby, $lang->viewableby_desc, $select_code, '', array(), array('id' => 'row_viewableby')); - - $selected_values = ''; - if($mybb->input['editableby'] != '' && $mybb->input['editableby'] != -1) - { - $selected_values = explode(',', $mybb->get_input('editableby')); - - foreach($selected_values as &$value) - { - $value = (int)$value; - } - unset($value); - } - - $group_checked = array('all' => '', 'custom' => '', 'none' => ''); - if($mybb->input['editableby'] == -1) - { - $group_checked['all'] = 'checked="checked"'; - } - elseif($mybb->input['editableby'] != '') - { - $group_checked['custom'] = 'checked="checked"'; - } - else - { - $group_checked['none'] = 'checked="checked"'; - } - - print_selection_javascript(); - - $select_code = " -
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('select[editableby][]', $selected_values, array('id' => 'editableby', 'multiple' => true, 'size' => 5))."
-
-
-
- "; - $form_container->output_row($lang->editableby, $lang->editableby_desc, $select_code, '', array(), array('id' => 'row_editableby')); - - $parser_options = array( - $form->generate_check_box('allowhtml', 1, $lang->parse_allowhtml, array('checked' => $mybb->input['allowhtml'], 'id' => 'allowhtml')), - $form->generate_check_box('allowmycode', 1, $lang->parse_allowmycode, array('checked' => $mybb->input['allowmycode'], 'id' => 'allowmycode')), - $form->generate_check_box('allowsmilies', 1, $lang->parse_allowsmilies, array('checked' => $mybb->input['allowsmilies'], 'id' => 'allowsmilies')), - $form->generate_check_box('allowimgcode', 1, $lang->parse_allowimgcode, array('checked' => $mybb->input['allowimgcode'], 'id' => 'allowimgcode')), - $form->generate_check_box('allowvideocode', 1, $lang->parse_allowvideocode, array('checked' => $mybb->input['allowvideocode'], 'id' => 'allowvideocode')) - ); - $form_container->output_row($lang->parser_options, '', implode('
', $parser_options), '', array(), array('id' => 'row_parser_options')); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_profile_field); - - $form->output_submit_wrapper($buttons); - $form->end(); - - echo ' - '; - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("profilefields", "*", "fid = '".$mybb->get_input('fid', MyBB::INPUT_INT)."'"); - $profile_field = $db->fetch_array($query); - - if(!$profile_field['fid']) - { - flash_message($lang->error_invalid_fid, 'error'); - admin_redirect("index.php?module=config-profile_fields"); - } - - $plugins->run_hooks("admin_config_profile_fields_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - - if(!trim($mybb->input['description'])) - { - $errors[] = $lang->error_missing_description; - } - - if(!trim($mybb->input['fieldtype'])) - { - $errors[] = $lang->error_missing_fieldtype; - } - - $type = $mybb->input['fieldtype']; - $options = preg_replace("#(\r\n|\r|\n)#s", "\n", trim($mybb->input['options'])); - if($type != "text" && $type != "textarea") - { - $type = "$type\n$options"; - } - - if(!$errors) - { - foreach(array('viewableby', 'editableby') as $key) - { - if($mybb->input[$key] == 'all') - { - $mybb->input[$key] = -1; - } - elseif($mybb->input[$key] == 'custom') - { - if(isset($mybb->input['select'][$key]) && is_array($mybb->input['select'][$key])) - { - foreach($mybb->input['select'][$key] as &$val) - { - $val = (int)$val; - } - unset($val); - - $mybb->input[$key] = implode(',', (array)$mybb->input['select'][$key]); - } - else - { - $mybb->input[$key] = ''; - } - } - else - { - $mybb->input[$key] = ''; - } - } - - $updated_profile_field = array( - "name" => $db->escape_string($mybb->input['name']), - "description" => $db->escape_string($mybb->input['description']), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "type" => $db->escape_string($type), - "regex" => $db->escape_string($mybb->input['regex']), - "length" => $mybb->get_input('length', MyBB::INPUT_INT), - "maxlength" => $mybb->get_input('maxlength', MyBB::INPUT_INT), - "required" => $mybb->get_input('required', MyBB::INPUT_INT), - "registration" => $mybb->get_input('registration', MyBB::INPUT_INT), - "profile" => $mybb->get_input('profile', MyBB::INPUT_INT), - "viewableby" => $db->escape_string($mybb->input['viewableby']), - "editableby" => $db->escape_string($mybb->input['editableby']), - "postbit" => $mybb->get_input('postbit', MyBB::INPUT_INT), - "postnum" => $mybb->get_input('postnum', MyBB::INPUT_INT), - "allowhtml" => $mybb->get_input('allowhtml', MyBB::INPUT_INT), - "allowmycode" => $mybb->get_input('allowmycode', MyBB::INPUT_INT), - "allowsmilies" => $mybb->get_input('allowsmilies', MyBB::INPUT_INT), - "allowimgcode" => $mybb->get_input('allowimgcode', MyBB::INPUT_INT), - "allowvideocode" => $mybb->get_input('allowvideocode', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_config_profile_fields_edit_commit"); - - $db->update_query("profilefields", $updated_profile_field, "fid='{$profile_field['fid']}'"); - - $cache->update_profilefields(); - - // Log admin action - log_admin_action($profile_field['fid'], htmlspecialchars_uni($mybb->input['name'])); - - flash_message($lang->success_profile_field_saved, 'success'); - admin_redirect("index.php?module=config-profile_fields"); - } - } - - $page->add_breadcrumb_item($lang->edit_profile_field); - $page->output_header($lang->custom_profile_fields." - ".$lang->edit_profile_field); - - $sub_tabs['edit_profile_field'] = array( - 'title' => $lang->edit_profile_field, - 'link' => "index.php?module=config-profile_fields&action=edit&fid={$profile_field['fid']}", - 'description' => $lang->edit_profile_field_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_profile_field'); - $form = new Form("index.php?module=config-profile_fields&action=edit", "post", "edit"); - - - echo $form->generate_hidden_field("fid", $profile_field['fid']); - - if($errors) - { - switch($mybb->input['viewableby']) - { - case 'all': - $mybb->input['viewableby'] = -1; - break; - case 'custom': - $mybb->input['viewableby'] = implode(',', (array)$mybb->input['select']['viewableby']); - break; - default: - $mybb->input['viewableby'] = ''; - break; - } - - switch($mybb->input['editableby']) - { - case 'all': - $mybb->input['editableby'] = -1; - break; - case 'custom': - $mybb->input['editableby'] = implode(',', (array)$mybb->input['select']['editableby']); - break; - default: - $mybb->input['editableby'] = ''; - break; - } - - $page->output_inline_error($errors); - } - else - { - $type = explode("\n", $profile_field['type'], "2"); - - $mybb->input = $profile_field; - $mybb->input['fieldtype'] = $type[0]; - $mybb->input['options'] = $type[1]; - } - - if(empty($mybb->input['viewableby'])) - { - $mybb->input['viewableby'] = ''; - } - - if(empty($mybb->input['editableby'])) - { - $mybb->input['editableby'] = ''; - } - - $form_container = new FormContainer($lang->edit_profile_field); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->short_description." *", "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $select_list = array( - "text" => $lang->text, - "textarea" => $lang->textarea, - "select" => $lang->select, - "multiselect" => $lang->multiselect, - "radio" => $lang->radio, - "checkbox" => $lang->checkbox - ); - $form_container->output_row($lang->field_type." *", $lang->field_type_desc, $form->generate_select_box('fieldtype', $select_list, $mybb->input['fieldtype'], array('id' => 'fieldtype')), 'fieldtype'); - $form_container->output_row($lang->field_regex, $lang->field_regex_desc, $form->generate_text_box('regex', $mybb->input['regex'], array('id' => 'regex')), 'regex', array(), array('id' => 'row_regex')); - $form_container->output_row($lang->maximum_length, $lang->maximum_length_desc, $form->generate_numeric_field('maxlength', $mybb->input['maxlength'], array('id' => 'maxlength', 'min' => 0)), 'maxlength', array(), array('id' => 'row_maxlength')); - $form_container->output_row($lang->field_length, $lang->field_length_desc, $form->generate_numeric_field('length', $mybb->input['length'], array('id' => 'length', 'min' => 0)), 'length', array(), array('id' => 'row_fieldlength')); - $form_container->output_row($lang->selectable_options, $lang->selectable_options_desc, $form->generate_text_area('options', $mybb->input['options'], array('id' => 'options')), 'options', array(), array('id' => 'row_options')); - $form_container->output_row($lang->min_posts_enabled, $lang->min_posts_enabled_desc, $form->generate_numeric_field('postnum', $mybb->input['postnum'], array('id' => 'postnum', 'min' => 0)), 'postnum'); - $form_container->output_row($lang->display_order." *", $lang->display_order_desc, $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->output_row($lang->required." *", $lang->required_desc, $form->generate_yes_no_radio('required', $mybb->input['required'])); - $form_container->output_row($lang->show_on_registration." *", $lang->show_on_registration_desc, $form->generate_yes_no_radio('registration', $mybb->input['registration'])); - $form_container->output_row($lang->display_on_profile." *", $lang->display_on_profile_desc, $form->generate_yes_no_radio('profile', $mybb->input['profile'])); - $form_container->output_row($lang->display_on_postbit." *", $lang->display_on_postbit_desc, $form->generate_yes_no_radio('postbit', $mybb->input['postbit'])); - - $selected_values = ''; - if($mybb->input['viewableby'] != '' && $mybb->input['viewableby'] != -1) - { - $selected_values = explode(',', $mybb->get_input('viewableby')); - - foreach($selected_values as &$value) - { - $value = (int)$value; - } - unset($value); - } - - $group_checked = array('all' => '', 'custom' => '', 'none' => ''); - if($mybb->input['viewableby'] == -1) - { - $group_checked['all'] = 'checked="checked"'; - } - elseif($mybb->input['viewableby'] != '') - { - $group_checked['custom'] = 'checked="checked"'; - } - else - { - $group_checked['none'] = 'checked="checked"'; - } - - print_selection_javascript(); - - $select_code = " -
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('select[viewableby][]', $selected_values, array('id' => 'viewableby', 'multiple' => true, 'size' => 5))."
-
-
-
- "; - $form_container->output_row($lang->viewableby, $lang->viewableby_desc, $select_code, '', array(), array('id' => 'row_viewableby')); - - $selected_values = ''; - if($mybb->input['editableby'] != '' && $mybb->input['editableby'] != -1) - { - $selected_values = explode(',', $mybb->get_input('editableby')); - - foreach($selected_values as &$value) - { - $value = (int)$value; - } - unset($value); - } - - $group_checked = array('all' => '', 'custom' => '', 'none' => ''); - if($mybb->input['editableby'] == -1) - { - $group_checked['all'] = 'checked="checked"'; - } - elseif($mybb->input['editableby'] != '') - { - $group_checked['custom'] = 'checked="checked"'; - } - else - { - $group_checked['none'] = 'checked="checked"'; - } - - print_selection_javascript(); - - $select_code = " -
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('select[editableby][]', $selected_values, array('id' => 'editableby', 'multiple' => true, 'size' => 5))."
-
-
-
- "; - $form_container->output_row($lang->editableby, $lang->editableby_desc, $select_code, '', array(), array('id' => 'row_editableby')); - - $parser_options = array( - $form->generate_check_box('allowhtml', 1, $lang->parse_allowhtml, array('checked' => $mybb->input['allowhtml'], 'id' => 'allowhtml')), - $form->generate_check_box('allowmycode', 1, $lang->parse_allowmycode, array('checked' => $mybb->input['allowmycode'], 'id' => 'allowmycode')), - $form->generate_check_box('allowsmilies', 1, $lang->parse_allowsmilies, array('checked' => $mybb->input['allowsmilies'], 'id' => 'allowsmilies')), - $form->generate_check_box('allowimgcode', 1, $lang->parse_allowimgcode, array('checked' => $mybb->input['allowimgcode'], 'id' => 'allowimgcode')), - $form->generate_check_box('allowvideocode', 1, $lang->parse_allowvideocode, array('checked' => $mybb->input['allowvideocode'], 'id' => 'allowvideocode')) - ); - $form_container->output_row($lang->parser_options, '', implode('
', $parser_options), '', array(), array('id' => 'row_parser_options')); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_profile_field); - - $form->output_submit_wrapper($buttons); - $form->end(); - - echo ' - '; - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("profilefields", "*", "fid='".$mybb->get_input('fid', MyBB::INPUT_INT)."'"); - $profile_field = $db->fetch_array($query); - - // Does the profile field not exist? - if(!$profile_field['fid']) - { - flash_message($lang->error_invalid_fid, 'error'); - admin_redirect("index.php?module=config-profile_fields"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-profile_fields"); - } - - $plugins->run_hooks("admin_config_profile_fields_delete"); - - if($mybb->request_method == "post") - { - // Delete the profile field - $db->delete_query("profilefields", "fid='{$profile_field['fid']}'"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."userfields DROP fid{$profile_field['fid']}"); - - $plugins->run_hooks("admin_config_profile_fields_delete_commit"); - - $cache->update_profilefields(); - - // Log admin action - log_admin_action($profile_field['fid'], htmlspecialchars_uni($profile_field['name'])); - - flash_message($lang->success_profile_field_deleted, 'success'); - admin_redirect("index.php?module=config-profile_fields"); - } - else - { - $page->output_confirm_action("index.php?module=config-profile_fields&action=delete&fid={$profile_field['fid']}", $lang->confirm_profile_field_deletion); - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_profile_fields_start"); - - $page->output_header($lang->custom_profile_fields); - - $sub_tabs['custom_profile_fields'] = array( - 'title' => $lang->custom_profile_fields, - 'link' => "index.php?module=config-profile_fields", - 'description' => $lang->custom_profile_fields_desc - ); - - $sub_tabs['add_profile_field'] = array( - 'title' => $lang->add_new_profile_field, - 'link' => "index.php?module=config-profile_fields&action=add", - ); - - - $page->output_nav_tabs($sub_tabs, 'custom_profile_fields'); - - $table = new Table; - $table->construct_header($lang->name); - $table->construct_header($lang->required, array("class" => "align_center")); - $table->construct_header($lang->registration, array("class" => "align_center")); - $table->construct_header($lang->editable, array("class" => "align_center")); - $table->construct_header($lang->profile, array("class" => "align_center")); - $table->construct_header($lang->postbit, array("class" => "align_center")); - $table->construct_header($lang->controls, array("class" => "align_center")); - - $query = $db->simple_select("profilefields", "*", "", array('order_by' => 'disporder')); - while($field = $db->fetch_array($query)) - { - if($field['required']) - { - $required = $lang->yes; - } - else - { - $required = $lang->no; - } - - if($field['registration']) - { - $registration = $lang->yes; - } - else - { - $registration = $lang->no; - } - - if($field['editableby'] == '') - { - $editable = $lang->no; - } - else - { - $editable = $lang->yes; - } - - if($field['profile']) - { - $profile = $lang->yes; - } - else - { - $profile = $lang->no; - } - - if($field['postbit']) - { - $postbit = $lang->yes; - } - else - { - $postbit = $lang->no; - } - - $table->construct_cell("".htmlspecialchars_uni($field['name'])."
".htmlspecialchars_uni($field['description'])."", array('width' => '35%')); - $table->construct_cell($required, array("class" => "align_center", 'width' => '10%')); - $table->construct_cell($registration, array("class" => "align_center", 'width' => '10%')); - $table->construct_cell($editable, array("class" => "align_center", 'width' => '10%')); - $table->construct_cell($profile, array("class" => "align_center", 'width' => '10%')); - $table->construct_cell($postbit, array("class" => "align_center", 'width' => '10%')); - - $popup = new PopupMenu("field_{$field['fid']}", $lang->options); - $popup->add_item($lang->edit_field, "index.php?module=config-profile_fields&action=edit&fid={$field['fid']}"); - $popup->add_item($lang->delete_field, "index.php?module=config-profile_fields&action=delete&fid={$field['fid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_profile_field_deletion}')"); - $table->construct_cell($popup->fetch(), array("class" => "align_center", 'width' => '20%')); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_profile_fields, array('colspan' => 7)); - $table->construct_row(); - } - - $table->output($lang->custom_profile_fields); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/config/questions.php b/html/forums/admin/modules/config/questions.php deleted file mode 100644 index 71586a6..0000000 --- a/html/forums/admin/modules/config/questions.php +++ /dev/null @@ -1,350 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->security_questions, "index.php?module=config-questions"); - -$plugins->run_hooks("admin_config_questions_begin"); - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_config_questions_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['question'])) - { - $errors[] = $lang->error_missing_question; - } - - if(!trim($mybb->input['answer'])) - { - $errors[] = $lang->error_missing_answer; - } - - if(!$errors) - { - $answer = preg_replace("#(\r\n|\r|\n)#s", "\n", trim($mybb->input['answer'])); - - $new_question = array( - "question" => $db->escape_string($mybb->input['question']), - "answer" => $db->escape_string($answer), - "active" => $mybb->get_input('active', MyBB::INPUT_INT) - ); - $qid = $db->insert_query("questions", $new_question); - - $plugins->run_hooks("admin_config_questions_add_commit"); - - // Log admin action - log_admin_action($qid, $mybb->input['question']); - - flash_message($lang->success_question_created, 'success'); - admin_redirect("index.php?module=config-questions"); - } - } - - $page->add_breadcrumb_item($lang->add_new_question); - $page->output_header($lang->security_questions." - ".$lang->add_new_question); - - $sub_tabs['security_questions'] = array( - 'title' => $lang->security_questions, - 'link' => "index.php?module=config-questions" - ); - - $sub_tabs['add_new_question'] = array( - 'title' => $lang->add_new_question, - 'link' => "index.php?module=config-questions&action=add", - 'description' => $lang->add_new_question_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_new_question'); - - $form = new Form("index.php?module=config-questions&action=add", "post", "add"); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['active'] = '1'; - } - - $form_container = new FormContainer($lang->add_new_question); - $form_container->output_row($lang->question." *", $lang->question_desc, $form->generate_text_area('question', $mybb->input['question'], array('id' => 'question')), 'question'); - $form_container->output_row($lang->answers." *", $lang->answers_desc, $form->generate_text_area('answer', $mybb->input['answer'], array('id' => 'answer')), 'answer'); - $form_container->output_row($lang->active." *", "", $form->generate_yes_no_radio('active', $mybb->input['active'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_question); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("questions", "*", "qid='".$mybb->get_input('qid', MyBB::INPUT_INT)."'"); - $question = $db->fetch_array($query); - - if(!$question['qid']) - { - flash_message($lang->error_invalid_question, 'error'); - admin_redirect("index.php?module=config-questions"); - } - - $plugins->run_hooks("admin_config_questions_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['question'])) - { - $errors[] = $lang->error_missing_question; - } - - if(!trim($mybb->input['answer'])) - { - $errors[] = $lang->error_missing_answer; - } - - if(!$errors) - { - $answer = preg_replace("#(\r\n|\r|\n)#s", "\n", trim($mybb->input['answer'])); - - $updated_question = array( - "question" => $db->escape_string($mybb->input['question']), - "answer" => $db->escape_string($answer), - "active" => $mybb->get_input('active', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_config_questions_edit_commit"); - - $db->update_query("questions", $updated_question, "qid='{$question['qid']}'"); - - // Log admin action - log_admin_action($question['qid'], $mybb->input['question']); - - flash_message($lang->success_question_updated, 'success'); - admin_redirect("index.php?module=config-questions"); - } - } - - $page->add_breadcrumb_item($lang->edit_question); - $page->output_header($lang->security_questions." - ".$lang->edit_question); - - $sub_tabs['edit_question'] = array( - 'title' => $lang->edit_question, - 'link' => "index.php?module=config-questions&action=edit&qid={$question['qid']}", - 'description' => $lang->edit_question_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_question'); - - $form = new Form("index.php?module=config-questions&action=edit&qid={$question['qid']}", "post", "add"); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = $question; - } - - $form_container = new FormContainer($lang->edit_question); - $form_container->output_row($lang->question." *", $lang->question_desc, $form->generate_text_area('question', $mybb->input['question'], array('id' => 'question')), 'question'); - $form_container->output_row($lang->answers." *", $lang->answers_desc, $form->generate_text_area('answer', $mybb->input['answer'], array('id' => 'answer')), 'answer'); - $form_container->output_row($lang->active." *", "", $form->generate_yes_no_radio('active', $mybb->input['active'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_question); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-questions"); - } - - $query = $db->simple_select("questions", "*", "qid='".$mybb->get_input('qid', MyBB::INPUT_INT)."'"); - $question = $db->fetch_array($query); - - if(!$question['qid']) - { - flash_message($lang->error_invalid_question, 'error'); - admin_redirect("index.php?module=config-questions"); - } - - $plugins->run_hooks("admin_config_questions_delete"); - - if($mybb->request_method == "post") - { - $db->delete_query("questions", "qid='{$question['qid']}'"); - $db->delete_query("questionsessions", "qid='{$question['qid']}'"); - - $plugins->run_hooks("admin_config_questions_delete_commit"); - - // Log admin action - log_admin_action($question['qid'], $question['question']); - - flash_message($lang->success_question_deleted, 'success'); - admin_redirect("index.php?module=config-questions"); - } - else - { - $page->output_confirm_action("index.php?module=config-questions&action=delete&qid={$question['qid']}", $lang->confirm_question_deletion); - } -} - -if($mybb->input['action'] == "disable") -{ - $query = $db->simple_select("questions", "*", "qid='".$mybb->get_input('qid', MyBB::INPUT_INT)."'"); - $question = $db->fetch_array($query); - - if(!$question['qid']) - { - flash_message($lang->error_invalid_question, 'error'); - admin_redirect("index.php?module=config-questions"); - } - - $plugins->run_hooks("admin_config_questions_disable"); - - $update_question = array( - "active" => 0 - ); - - $plugins->run_hooks("admin_config_questions_disable_commit"); - - $db->update_query("questions", $update_question, "qid = '{$question['qid']}'"); - - // Log admin action - log_admin_action($question['qid'], $question['question']); - - flash_message($lang->success_question_disabled, 'success'); - admin_redirect("index.php?module=config-questions"); -} - -if($mybb->input['action'] == "enable") -{ - $query = $db->simple_select("questions", "*", "qid='".$mybb->get_input('qid', MyBB::INPUT_INT)."'"); - $question = $db->fetch_array($query); - - if(!$question['qid']) - { - flash_message($lang->error_invalid_question, 'error'); - admin_redirect("index.php?module=config-questions"); - } - - $plugins->run_hooks("admin_config_questions_enable"); - - $update_question = array( - "active" => 1 - ); - - $plugins->run_hooks("admin_config_questions_enable_commit"); - - $db->update_query("questions", $update_question, "qid = '{$question['qid']}'"); - - // Log admin action - log_admin_action($question['qid'], $question['question']); - - flash_message($lang->success_question_enabled, 'success'); - admin_redirect("index.php?module=config-questions"); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_questions_start"); - - $page->output_header($lang->security_questions); - - $sub_tabs['security_questions'] = array( - 'title' => $lang->security_questions, - 'link' => "index.php?module=config-questions", - 'description' => $lang->security_questions_desc - ); - $sub_tabs['add_new_question'] = array( - 'title' => $lang->add_new_question, - 'link' => "index.php?module=config-questions&action=add", - ); - - $page->output_nav_tabs($sub_tabs, 'security_questions'); - - $table = new Table; - $table->construct_header($lang->question); - $table->construct_header($lang->answers, array("width" => "35%")); - $table->construct_header($lang->shown, array("width" => "5%", "class" => "align_center")); - $table->construct_header($lang->correct, array("width" => "5%", "class" => "align_center")); - $table->construct_header($lang->incorrect, array("width" => "5%", "class" => "align_center")); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - $query = $db->simple_select("questions", "*", "", array('order_by' => 'question')); - while($questions = $db->fetch_array($query)) - { - $questions['question'] = htmlspecialchars_uni($questions['question']); - $questions['answer'] = htmlspecialchars_uni($questions['answer']); - $questions['answer'] = preg_replace("#(\n)#s", "
", trim($questions['answer'])); - $questions['shown'] = my_number_format($questions['shown']); - $questions['correct'] = my_number_format($questions['correct']); - $questions['incorrect'] = my_number_format($questions['incorrect']); - - if($questions['active'] == 1) - { - $icon = "style}/images/icons/bullet_on.png\" alt=\"({$lang->alt_enabled})\" title=\"{$lang->alt_enabled}\" style=\"vertical-align: middle;\" /> "; - } - else - { - $icon = "style}/images/icons/bullet_off.png\" alt=\"({$lang->alt_disabled})\" title=\"{$lang->alt_disabled}\" style=\"vertical-align: middle;\" /> "; - } - - $table->construct_cell("
{$icon}{$questions['question']}
"); - $table->construct_cell($questions['answer']); - $table->construct_cell($questions['shown'], array("class" => "align_center")); - $table->construct_cell($questions['correct'], array("class" => "align_center")); - $table->construct_cell($questions['incorrect'], array("class" => "align_center")); - $popup = new PopupMenu("questions_{$questions['qid']}", $lang->options); - $popup->add_item($lang->edit_question, "index.php?module=config-questions&action=edit&qid={$questions['qid']}"); - if($questions['active'] == 1) - { - $popup->add_item($lang->disable_question, "index.php?module=config-questions&action=disable&qid={$questions['qid']}&my_post_key={$mybb->post_code}"); - } - else - { - $popup->add_item($lang->enable_question, "index.php?module=config-questions&action=enable&qid={$questions['qid']}&my_post_key={$mybb->post_code}"); - } - $popup->add_item($lang->delete_question, "index.php?module=config-questions&action=delete&qid={$questions['qid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_question_deletion}')"); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_security_questions, array('colspan' => 6)); - $table->construct_row(); - } - - $table->output($lang->security_questions); - - $page->output_footer(); -} - diff --git a/html/forums/admin/modules/config/report_reasons.php b/html/forums/admin/modules/config/report_reasons.php deleted file mode 100644 index e201d16..0000000 --- a/html/forums/admin/modules/config/report_reasons.php +++ /dev/null @@ -1,449 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->report_reasons, "index.php?module=config-report_reasons"); - -$content_types = array('post', 'profile', 'reputation'); - -$content_types = $plugins->run_hooks("report_content_types", $content_types); - -$plugins->run_hooks("admin_config_report_reasons_begin"); - -if($mybb->input['action'] == "add") -{ - cast_content_inputs(); - - $plugins->run_hooks("admin_config_report_reasons_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if($mybb->input['extra'] != 0 && $mybb->input['extra'] != 1) - { - $errors[] = $lang->error_missing_extra; - } - - if(!$errors) - { - if($mybb->input['appliesto'] != 'all') - { - $appliesto = array(); - asort($content_types); - foreach($content_types as $content) - { - if($mybb->input["appliesto_{$content}"] == 1) - { - $appliesto[] = $content; - } - } - $appliesto = implode(",", $appliesto); - } - else - { - $appliesto = 'all'; - } - - $new_reason = array( - "title" => $db->escape_string($mybb->input['title']), - "appliesto" => $db->escape_string($appliesto), - "extra" => $mybb->input['extra'] - ); - $rid = $db->insert_query("reportreasons", $new_reason); - - $plugins->run_hooks("admin_config_report_reasons_add_commit"); - - $cache->update_reportreasons(); - - // Log admin action - log_admin_action($rid, $mybb->input['title']); - - flash_message($lang->success_reason_created, 'success'); - admin_redirect("index.php?module=config-report_reasons"); - } - } - - $page->add_breadcrumb_item($lang->add_new_reason); - $page->output_header($lang->report_reasons." - ".$lang->add_new_reason); - - $sub_tabs['report_reasons'] = array( - 'title' => $lang->report_reasons, - 'link' => "index.php?module=config-report_reasons" - ); - - $sub_tabs['add_new_reason'] = array( - 'title' => $lang->add_new_reason, - 'link' => "index.php?module=config-report_reasons&action=add", - 'description' => $lang->add_new_reason_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_new_reason'); - - $form = new Form("index.php?module=config-report_reasons&action=add", "post", "add"); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['extra'] = 0; - } - - $form_container = new FormContainer($lang->add_new_reason); - $form_container->output_row($lang->reason_title." *", $lang->reason_title_desc, $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->applies_to." *", $lang->applies_to_desc, generate_content_select()); - $form_container->output_row($lang->requires_extra." *", $lang->requires_extra_desc, $form->generate_yes_no_radio('extra', $mybb->input['extra'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_reason); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("reportreasons", "*", "rid='".$mybb->get_input('rid', MyBB::INPUT_INT)."'"); - $reason = $db->fetch_array($query); - - if(!$reason['rid']) - { - flash_message($lang->error_invalid_reason, 'error'); - admin_redirect("index.php?module=config-report_reasons"); - } - elseif($reason['rid'] == 1) - { - flash_message($lang->error_cannot_modify_reason, 'error'); - admin_redirect("index.php?module=config-report_reasons"); - } - - cast_content_inputs(); - - $plugins->run_hooks("admin_config_report_reasons_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if($mybb->input['extra'] != 0 && $mybb->input['extra'] != 1) - { - $errors[] = $lang->error_missing_extra; - } - - if(!$errors) - { - if($mybb->input['appliesto'] != 'all') - { - $appliesto = array(); - asort($content_types); - foreach($content_types as $content) - { - if($mybb->input["appliesto_{$content}"] == 1) - { - $appliesto[] = $content; - } - } - $appliesto = implode(",", $appliesto); - } - else - { - $appliesto = 'all'; - } - - $updated_reason = array( - "title" => $db->escape_string($mybb->input['title']), - "appliesto" => $db->escape_string($appliesto), - "extra" => $mybb->input['extra'] - ); - - $plugins->run_hooks("admin_config_report_reasons_edit_commit"); - - $db->update_query("reportreasons", $updated_reason, "rid='{$reason['rid']}'"); - - $cache->update_reportreasons(); - - // Log admin action - log_admin_action($reason['rid'], $mybb->input['title']); - - flash_message($lang->success_reason_updated, 'success'); - admin_redirect("index.php?module=config-report_reasons"); - } - } - - $page->add_breadcrumb_item($lang->edit_reason); - $page->output_header($lang->report_reasons." - ".$lang->edit_reason); - - $sub_tabs['edit_reason'] = array( - 'title' => $lang->edit_reason, - 'link' => "index.php?module=config-report_reasons&action=edit&rid={$reason['rid']}", - 'description' => $lang->edit_reason_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_reason'); - - $form = new Form("index.php?module=config-report_reasons&action=edit&rid={$reason['rid']}", "post", "add"); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = $reason; - $appliesto = explode(",", $reason['appliesto']); - foreach($appliesto as $content) - { - $mybb->input["appliesto_{$content}"] = 1; - } - } - - $form_container = new FormContainer($lang->add_new_reason); - $form_container->output_row($lang->reason_title." *", $lang->reason_title_desc, $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->applies_to." *", $lang->applies_to_desc, generate_content_select()); - $form_container->output_row($lang->requires_extra." *", $lang->requires_extra_desc, $form->generate_yes_no_radio('extra', $mybb->input['extra'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_reason); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-report_reasons"); - } - - $query = $db->simple_select("reportreasons", "*", "rid='".$mybb->get_input('rid', MyBB::INPUT_INT)."'"); - $reason = $db->fetch_array($query); - - if(!$reason['rid']) - { - flash_message($lang->error_invalid_reason, 'error'); - admin_redirect("index.php?module=config-report_reasons"); - } - elseif($reason['rid'] == 1) - { - flash_message($lang->error_cannot_delete_reason, 'error'); - admin_redirect("index.php?module=config-report_reasons"); - } - - $plugins->run_hooks("admin_config_report_reasons_delete"); - - if($mybb->request_method == "post") - { - - // Change the reason of associated reports to Other and carry over the title - $updated_report = array( - 'reasonid' => 1, - 'reason' => $db->escape_string($reason['title']) - ); - $db->update_query("reportedcontent", $updated_report, "reasonid='{$reason['rid']}'"); - - $db->delete_query("reportreasons", "rid='{$reason['rid']}'"); - - $plugins->run_hooks("admin_config_report_reasons_delete_commit"); - - // Log admin action - log_admin_action($reason['rid'], $reason['title']); - - flash_message($lang->success_reason_deleted, 'success'); - admin_redirect("index.php?module=config-report_reasons"); - } - else - { - $page->output_confirm_action("index.php?module=config-report_reasons&action=delete&rid={$reason['rid']}", $lang->confirm_reason_deletion); - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_report_reasons_start"); - - if($mybb->request_method == "post") - { - if(!empty($mybb->input['disporder'])) - { - foreach($mybb->input['disporder'] as $rid => $order) - { - $db->update_query("reportreasons", array('disporder' => (int)$order), "rid='".(int)$rid."'"); - } - - $plugins->run_hooks("admin_config_report_reasons_start_commit"); - - //$cache->update_reportreasons(); - - flash_message($lang->success_reasons_disporder_updated, 'success'); - admin_redirect("index.php?module=config-report_reasons"); - } - } - - $page->output_header($lang->report_reasons); - - $sub_tabs['report_reasons'] = array( - 'title' => $lang->report_reasons, - 'link' => "index.php?module=config-report_reasons", - 'description' => $lang->report_reasons_desc - ); - $sub_tabs['add_new_reason'] = array( - 'title' => $lang->add_new_reason, - 'link' => "index.php?module=config-report_reasons&action=add", - ); - - $page->output_nav_tabs($sub_tabs, 'report_reasons'); - - $form = new Form("index.php?module=config-report_reasons", "post", "reasons"); - - $form_container = new FormContainer($lang->report_reasons); - $form_container->output_row_header($lang->reason_title); - $form_container->output_row_header($lang->applies_to, array("width" => "35%")); - $form_container->output_row_header($lang->extra_comment, array("width" => "10%", "class" => "align_center")); - $form_container->output_row_header($lang->order, array("width" => "5%", "class" => "align_center")); - $form_container->output_row_header($lang->controls, array("class" => "align_center", "width" => 150)); - - $query = $db->simple_select("reportreasons", "*", "", array('order_by' => 'disporder')); - while($reasons = $db->fetch_array($query)) - { - $reasons['title'] = $lang->parse($reasons['title']); - - $reasons['appliesto'] = explode(",", $reasons['appliesto']); - - $appliesto = array(); - foreach($reasons['appliesto'] as $content) - { - $key = "report_content_".$content; - $appliesto[] = $lang->$key; - } - $reasons['appliesto'] = implode(", ", $appliesto); - - if($reasons['extra'] == 1) - { - $icon = "style}/images/icons/bullet_on.png\" alt=\"({$lang->yes})\" title=\"{$lang->yes}\" style=\"vertical-align: middle;\" /> "; - } - else - { - $icon = "style}/images/icons/bullet_off.png\" alt=\"({$lang->no})\" title=\"{$lang->no}\" style=\"vertical-align: middle;\" /> "; - } - - $form_container->output_cell(htmlspecialchars_uni($reasons['title'])); - $form_container->output_cell(htmlspecialchars_uni($reasons['appliesto'])); - $form_container->output_cell("
{$icon}
", array("class" => "align_center")); - $form_container->output_cell("", array("class" => "align_center")); - $popup = new PopupMenu("reasons_{$reasons['rid']}", $lang->options); - $popup->add_item($lang->edit_reason, "index.php?module=config-report_reasons&action=edit&rid={$reasons['rid']}"); - $popup->add_item($lang->delete_reason, "index.php?module=config-report_reasons&action=delete&rid={$reasons['rid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_reason_deletion}')"); - $form_container->output_cell($popup->fetch(), array("class" => "align_center")); - $form_container->construct_row(); - } - - if($form_container->num_rows() == 0) - { - $form_container->construct_cell($lang->no_report_reasons, array('colspan' => 5)); - $form_container->construct_row(); - } - - $form_container->end(); - - $buttons = array(); - $buttons[] = $form->generate_submit_button($lang->update_reasons_order); - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -function generate_content_select() -{ - global $mybb, $lang; - - $checked = array('all' => '', 'custom' => '', 'none' => ''); - if($mybb->input['appliesto'] == 'all') - { - $checked['all'] = 'checked="checked"'; - } - elseif($mybb->input['appliesto'] == '') - { - $checked['none'] = 'checked="checked"'; - } - else - { - $checked['custom'] = 'checked="checked"'; - } - - print_selection_javascript(); - - return "
-
-
-
- - - - - -
{$lang->content_colon}".implode("
", generate_content_choices())."
-
-
-
- "; -} - -function generate_content_choices() -{ - global $mybb, $lang, $form, $content_types; - - asort($content_types); - - $content_choices = array(); - foreach($content_types as $content) - { - $key = "report_content_{$content}"; - $content_choices[] = $form->generate_check_box("appliesto_{$content}", 1, $lang->$key, array('id' => "appliesto_{$content}", 'checked' => $mybb->input["appliesto_{$content}"])); - } - - return $content_choices; -} - -function cast_content_inputs() -{ - global $mybb, $content_types; - - asort($content_types); - - foreach($content_types as $content) - { - $key = "appliesto_{$content}"; - $mybb->input[$key] = $mybb->get_input($key, MyBB::INPUT_INT); - } - - $mybb->input['extra'] = $mybb->get_input('extra', MyBB::INPUT_INT); -} \ No newline at end of file diff --git a/html/forums/admin/modules/config/settings.php b/html/forums/admin/modules/config/settings.php deleted file mode 100644 index a937cef..0000000 --- a/html/forums/admin/modules/config/settings.php +++ /dev/null @@ -1,1777 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->board_settings, "index.php?module=config-settings"); - -$plugins->run_hooks("admin_config_settings_begin"); - -// Creating a new setting group -if($mybb->input['action'] == "addgroup") -{ - $plugins->run_hooks("admin_config_settings_addgroup"); - - if($mybb->request_method == "post") - { - // Validate title - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_group_title; - } - - // Validate identifier - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_group_name; - } - $query = $db->simple_select("settinggroups", "title", "name='".$db->escape_string($mybb->input['name'])."'"); - if($db->num_rows($query) > 0) - { - $dup_group_title = $db->fetch_field($query, 'title'); - $errors[] = $lang->sprintf($lang->error_duplicate_group_name, $dup_group_title); - } - - if(!$errors) - { - $new_setting_group = array( - "name" => $db->escape_string($mybb->input['name']), - "title" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "isdefault" => 0 - ); - $gid = $db->insert_query("settinggroups", $new_setting_group); - - $plugins->run_hooks("admin_config_settings_addgroup_commit"); - - // Log admin action - log_admin_action($gid, $mybb->input['name']); - - flash_message($lang->success_setting_group_added, 'success'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - } - - $page->add_breadcrumb_item($lang->add_new_setting_group); - $page->output_header($lang->board_settings." - ".$lang->add_new_setting_group); - - $sub_tabs['change_settings'] = array( - 'title' => $lang->change_settings, - 'link' => "index.php?module=config-settings" - ); - - $sub_tabs['add_setting'] = array( - 'title' => $lang->add_new_setting, - 'link' => "index.php?module=config-settings&action=add" - ); - - $sub_tabs['add_setting_group'] = array( - 'title' => $lang->add_new_setting_group, - 'link' => "index.php?module=config-settings&action=addgroup", - 'description' => $lang->add_new_setting_group_desc - ); - - $sub_tabs['modify_setting'] = array( - 'title' => $lang->modify_existing_settings, - 'link' => "index.php?module=config-settings&action=manage" - ); - - $page->output_nav_tabs($sub_tabs, 'add_setting_group'); - - $form = new Form("index.php?module=config-settings&action=addgroup", "post", "add"); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer($lang->add_new_setting_group); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->description, "", $form->generate_text_area('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->display_order, "", $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->output_row($lang->name." *", $lang->group_name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->insert_new_setting_group); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -// Edit setting group -if($mybb->input['action'] == "editgroup") -{ - $query = $db->simple_select("settinggroups", "*", "gid='".$mybb->get_input('gid', MyBB::INPUT_INT)."'"); - $group = $db->fetch_array($query); - - // Does the setting not exist? - if(!$group['gid']) - { - flash_message($lang->error_invalid_gid2, 'error'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - // Prevent editing of default - if($group['isdefault'] == 1) - { - flash_message($lang->error_cannot_edit_default, 'error'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - - $plugins->run_hooks("admin_config_settings_editgroup"); - - // Do edit? - if($mybb->request_method == "post") - { - // Validate title - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_group_title; - } - - // Validate identifier - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_group_name; - } - $query = $db->simple_select("settinggroups", "title", "name='".$db->escape_string($mybb->input['name'])."' AND gid != '{$group['gid']}'"); - if($db->num_rows($query) > 0) - { - $dup_group_title = $db->fetch_field($query, 'title'); - $errors[] = $lang->sprintf($lang->error_duplicate_group_name, $dup_group_title); - } - - if(!$errors) - { - $update_setting_group = array( - "name" => $db->escape_string($mybb->input['name']), - "title" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - ); - - $plugins->run_hooks("admin_config_settings_editgroup_commit"); - - $db->update_query("settinggroups", $update_setting_group, "gid='{$group['gid']}'"); - - // Log admin action - log_admin_action($group['gid'], $mybb->input['name']); - - flash_message($lang->success_setting_group_updated, 'success'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - } - - $page->add_breadcrumb_item($lang->edit_setting_group); - $page->output_header($lang->board_settings." - ".$lang->edit_setting_group); - - $sub_tabs['edit_setting_group'] = array( - 'title' => $lang->edit_setting_group, - 'link' => "index.php?module=config-settings&action=editgroup&gid={$group['gid']}", - 'description' => $lang->edit_setting_group_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_setting_group'); - - $form = new Form("index.php?module=config-settings&action=editgroup", "post", "editgroup"); - - echo $form->generate_hidden_field("gid", $group['gid']); - - if($errors) - { - $group_data = $mybb->input; - $page->output_inline_error($errors); - } - else - { - $group_data = $group; - } - - $form_container = new FormContainer($lang->edit_setting_group); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $group_data['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->description, "", $form->generate_text_area('description', $group_data['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->display_order, "", $form->generate_numeric_field('disporder', $group_data['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->output_row($lang->name." *", $lang->group_name_desc, $form->generate_text_box('name', $group_data['name'], array('id' => 'name')), 'name'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->update_setting_group); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -// Delete Setting Group -if($mybb->input['action'] == "deletegroup") -{ - $query = $db->simple_select("settinggroups", "*", "gid='".$mybb->get_input('gid', MyBB::INPUT_INT)."'"); - $group = $db->fetch_array($query); - - // Does the setting group not exist? - if(!$group['gid']) - { - flash_message($lang->error_invalid_gid2, 'error'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - // Prevent deletion of default - if($group['isdefault'] == 1) - { - flash_message($lang->error_cannot_edit_default, 'error'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-settings&action=manage"); - } - - $plugins->run_hooks("admin_config_settings_deletegroup"); - - if($mybb->request_method == "post") - { - // Delete the setting group and its settings - $db->delete_query("settinggroups", "gid='{$group['gid']}'"); - $db->delete_query("settings", "gid='{$group['gid']}'"); - - rebuild_settings(); - - $plugins->run_hooks("admin_config_settings_deletegroup_commit"); - - // Log admin action - log_admin_action($group['gid'], $group['name']); - - flash_message($lang->success_setting_group_deleted, 'success'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - else - { - $page->output_confirm_action("index.php?module=config-settings&action=deletegroup&gid={$group['gid']}", $lang->confirm_setting_group_deletion); - } -} - -// Creating a new setting -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_config_settings_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - $query = $db->simple_select("settinggroups", "gid", "gid='".$mybb->get_input('gid', MyBB::INPUT_INT)."'"); - $gid = $db->fetch_field($query, 'gid'); - if(!$gid) - { - $errors[] = $lang->error_invalid_gid; - } - - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - $query = $db->simple_select("settings", "title", "name='".$db->escape_string($mybb->input['name'])."'"); - if($db->num_rows($query) > 0) - { - $dup_setting_title = $db->fetch_field($query, 'title'); - $errors[] = $lang->sprintf($lang->error_duplicate_name, $dup_setting_title); - } - - // do some type filtering - $mybb->input['type'] = str_replace("\n", "", $mybb->input['type']); - if(strtolower(substr($mybb->input['type'], 0, 3)) == "php") - { - $mybb->input['type'] = ""; - } - - if(!$mybb->input['type']) - { - $errors[] = $lang->error_invalid_type; - } - - if(!$errors) - { - if($mybb->input['type'] == "custom") - { - $options_code = $mybb->input['extra']; - } - else if($mybb->input['extra']) - { - $options_code = "{$mybb->input['type']}\n{$mybb->input['extra']}"; - } - else - { - $options_code = $mybb->input['type']; - } - - $mybb->input['name'] = str_replace("\\", '', $mybb->input['name']); - $mybb->input['name'] = str_replace('$', '', $mybb->input['name']); - $mybb->input['name'] = str_replace("'", '', $mybb->input['name']); - - if($options_code == "numeric") - { - $value = $mybb->get_input('value', MyBB::INPUT_INT); - } - else - { - $value = $db->escape_string($mybb->input['value']); - } - - $new_setting = array( - "name" => $db->escape_string($mybb->input['name']), - "title" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "optionscode" => $db->escape_string($options_code), - "value" => $value, - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "gid" => $mybb->get_input('gid', MyBB::INPUT_INT) - ); - - $sid = $db->insert_query("settings", $new_setting); - rebuild_settings(); - - $plugins->run_hooks("admin_config_settings_add_commit"); - - // Log admin action - log_admin_action($sid, $mybb->input['title']); - - flash_message($lang->success_setting_added, 'success'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - } - - $page->add_breadcrumb_item($lang->add_new_setting); - $page->output_header($lang->board_settings." - ".$lang->add_new_setting); - - $sub_tabs['change_settings'] = array( - 'title' => $lang->change_settings, - 'link' => "index.php?module=config-settings" - ); - - $sub_tabs['add_setting'] = array( - 'title' => $lang->add_new_setting, - 'link' => "index.php?module=config-settings&action=add", - 'description' => $lang->add_new_setting_desc - ); - - $sub_tabs['add_setting_group'] = array( - 'title' => $lang->add_new_setting_group, - 'link' => "index.php?module=config-settings&action=addgroup" - ); - - $sub_tabs['modify_setting'] = array( - 'title' => $lang->modify_existing_settings, - 'link' => "index.php?module=config-settings&action=manage" - ); - - $page->output_nav_tabs($sub_tabs, 'add_setting'); - - $form = new Form("index.php?module=config-settings&action=add", "post", "add"); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer($lang->add_new_setting); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->description, "", $form->generate_text_area('description', $mybb->input['description'], array('id' => 'description')), 'description'); - - $query = $db->simple_select("settinggroups", "*", "", array('order_by' => 'disporder')); - while($group = $db->fetch_array($query)) - { - $group_lang_var = "setting_group_{$group['name']}"; - if($lang->$group_lang_var) - { - $options[$group['gid']] = htmlspecialchars_uni($lang->$group_lang_var); - } - else - { - $options[$group['gid']] = htmlspecialchars_uni($group['title']); - } - } - $form_container->output_row($lang->group." *", "", $form->generate_select_box("gid", $options, $mybb->input['gid'], array('id' => 'gid')), 'gid'); - $form_container->output_row($lang->display_order, "", $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - - $form_container->output_row($lang->name." *", $lang->name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - - $setting_types = array( - "text" => $lang->text, - "numeric" => $lang->numeric_text, - "textarea" => $lang->textarea, - "yesno" => $lang->yesno, - "onoff" => $lang->onoff, - "select" => $lang->select, - "forumselect" => $lang->forum_selection_box, - "forumselectsingle" => $lang->forum_selection_single, - "groupselect" => $lang->group_selection_box, - "groupselectsingle" => $lang->group_selection_single, - "radio" => $lang->radio, - "checkbox" => $lang->checkbox, - "language" => $lang->language_selection_box, - "adminlanguage" => $lang->adminlanguage, - "cpstyle" => $lang->cpstyle - //"php" => $lang->php // Internal Use Only - ); - - $form_container->output_row($lang->type." *", "", $form->generate_select_box("type", $setting_types, $mybb->input['type'], array('id' => 'type')), 'type'); - $form_container->output_row($lang->extra, $lang->extra_desc, $form->generate_text_area('extra', $mybb->input['extra'], array('id' => 'extra')), 'extra', array(), array('id' => 'row_extra')); - $form_container->output_row($lang->value, "", $form->generate_text_area('value', $mybb->input['value'], array('id' => 'value')), 'value'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->insert_new_setting); - $form->output_submit_wrapper($buttons); - $form->end(); - - echo ' - '; - - $page->output_footer(); -} - -// Editing a particular setting -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("settings", "*", "sid='".$mybb->get_input('sid', MyBB::INPUT_INT)."'"); - $setting = $db->fetch_array($query); - - // Does the setting not exist? - if(!$setting['sid']) - { - flash_message($lang->error_invalid_sid, 'error'); - admin_redirect("index.php?module=config-settings"); - } - - // Prevent editing of default - if($setting['isdefault'] == 1) - { - flash_message($lang->error_cannot_edit_default, 'error'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - - $plugins->run_hooks("admin_config_settings_edit"); - - $type = explode("\n", $setting['optionscode'], 2); - $type = trim($type[0]); - if($type == "php") - { - flash_message($lang->error_cannot_edit_php, 'error'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - $query = $db->simple_select("settings", "title", "name='".$db->escape_string($mybb->input['name'])."' AND sid != '{$setting['sid']}'"); - if($db->num_rows($query) > 0) - { - $dup_setting_title = $db->fetch_field($query, 'title'); - $errors[] = $lang->sprintf($lang->error_duplicate_name, $dup_setting_title); - } - - // do some type filtering - $mybb->input['type'] = str_replace("\n", "", $mybb->input['type']); - if(strtolower(substr($mybb->input['type'], 0, 3)) == "php") - { - $mybb->input['type'] = ""; - } - - if(!$mybb->input['type']) - { - $errors[] = $lang->error_invalid_type; - } - - if(!$errors) - { - if($mybb->input['type'] == "custom") - { - $options_code = $mybb->input['extra']; - } - else if($mybb->input['extra']) - { - $options_code = "{$mybb->input['type']}\n{$mybb->input['extra']}"; - } - else - { - $options_code = $mybb->input['type']; - } - - $mybb->input['name'] = str_replace("\\", '', $mybb->input['name']); - $mybb->input['name'] = str_replace('$', '', $mybb->input['name']); - $mybb->input['name'] = str_replace("'", '', $mybb->input['name']); - - if($options_code == "numeric") - { - $value = $mybb->get_input('value', MyBB::INPUT_INT); - } - else - { - $value = $db->escape_string($mybb->input['value']); - } - - $updated_setting = array( - "name" => $db->escape_string($mybb->input['name']), - "title" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "optionscode" => $db->escape_string($options_code), - "value" => $value, - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "gid" => $mybb->get_input('gid', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_config_settings_edit_commit"); - - $db->update_query("settings", $updated_setting, "sid='{$setting['sid']}'"); - rebuild_settings(); - - // Log admin action - log_admin_action($setting['sid'], $mybb->input['title']); - - flash_message($lang->success_setting_updated, 'success'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - } - - $page->add_breadcrumb_item($lang->edit_setting); - $page->output_header($lang->board_settings." - ".$lang->edit_setting); - - $sub_tabs['change_settings'] = array( - 'title' => $lang->change_settings, - 'link' => "index.php?module=config-settings", - ); - - $sub_tabs['add_setting'] = array( - 'title' => $lang->add_new_setting, - 'link' => "index.php?module=config-settings&action=add" - ); - - $sub_tabs['add_setting_group'] = array( - 'title' => $lang->add_new_setting_group, - 'link' => "index.php?module=config-settings&action=addgroup" - ); - - $sub_tabs['modify_setting'] = array( - 'title' => $lang->modify_existing_settings, - 'link' => "index.php?module=config-settings&action=manage", - 'description' => $lang->modify_existing_settings_desc - ); - - $page->output_nav_tabs($sub_tabs, 'modify_setting'); - - $form = new Form("index.php?module=config-settings&action=edit", "post", "edit"); - - echo $form->generate_hidden_field("sid", $setting['sid']); - - if($errors) - { - $setting_data = $mybb->input; - $page->output_inline_error($errors); - } - else - { - $setting_data = $setting; - $type = explode("\n", $setting['optionscode'], 2); - $setting_data['type'] = trim($type[0]); - $setting_data['extra'] = trim($type[1]); - } - - $form_container = new FormContainer($lang->modify_setting); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $setting_data['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->description, "", $form->generate_text_area('description', $setting_data['description'], array('id' => 'description')), 'description'); - - $query = $db->simple_select("settinggroups", "*", "", array('order_by' => 'disporder')); - while($group = $db->fetch_array($query)) - { - $group_lang_var = "setting_group_{$group['name']}"; - if($lang->$group_lang_var) - { - $options[$group['gid']] = htmlspecialchars_uni($lang->$group_lang_var); - } - else - { - $options[$group['gid']] = htmlspecialchars_uni($group['title']); - } - } - $form_container->output_row($lang->group." *", "", $form->generate_select_box("gid", $options, $setting_data['gid'], array('id' => 'gid')), 'gid'); - $form_container->output_row($lang->display_order, "", $form->generate_numeric_field('disporder', $setting_data['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->end(); - - $form_container = new FormContainer($lang->setting_configuration, 1); - $form_container->output_row($lang->name." *", $lang->name_desc, $form->generate_text_box('name', $setting_data['name'], array('id' => 'name')), 'name'); - - $setting_types = array( - "text" => $lang->text, - "numeric" => $lang->numeric_text, - "textarea" => $lang->textarea, - "yesno" => $lang->yesno, - "onoff" => $lang->onoff, - "select" => $lang->select, - "forumselect" => $lang->forum_selection_box, - "forumselectsingle" => $lang->forum_selection_single, - "groupselect" => $lang->group_selection_box, - "groupselectsingle" => $lang->group_selection_single, - "radio" => $lang->radio, - "checkbox" => $lang->checkbox, - "language" => $lang->language_selection_box, - "adminlanguage" => $lang->adminlanguage, - "cpstyle" => $lang->cpstyle - //"php" => $lang->php // Internal Use Only - ); - - $form_container->output_row($lang->type." *", "", $form->generate_select_box("type", $setting_types, $setting_data['type'], array('id' => 'type')), 'type'); - $form_container->output_row($lang->extra, $lang->extra_desc, $form->generate_text_area('extra', $setting_data['extra'], array('id' => 'extra')), 'extra', array(), array('id' => 'row_extra')); - $form_container->output_row($lang->value, '', $form->generate_text_area('value', $setting_data['value'], array('id' => 'value')), 'value'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->update_setting); - $form->output_submit_wrapper($buttons); - $form->end(); - - echo ' - '; - - $page->output_footer(); -} - -// Delete Setting -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("settings", "*", "sid='".$mybb->get_input('sid', MyBB::INPUT_INT)."'"); - $setting = $db->fetch_array($query); - - // Does the setting not exist? - if(!$setting['sid']) - { - flash_message($lang->error_invalid_sid, 'error'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - - // Prevent editing of default - if($setting['isdefault'] == 1) - { - flash_message($lang->error_cannot_edit_default, 'error'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-settings&action=manage"); - } - - $plugins->run_hooks("admin_config_settings_delete"); - - if($mybb->request_method == "post") - { - // Delete the setting - $db->delete_query("settings", "sid='{$setting['sid']}'"); - - rebuild_settings(); - - $plugins->run_hooks("admin_config_settings_delete_commit"); - - // Log admin action - log_admin_action($setting['sid'], $setting['title']); - - flash_message($lang->success_setting_deleted, 'success'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - else - { - $page->output_confirm_action("index.php?module=config-settings&action=delete&sid={$setting['sid']}", $lang->confirm_setting_deletion); - } -} - -// Modify Existing Settings -if($mybb->input['action'] == "manage") -{ - $plugins->run_hooks("admin_config_settings_manage"); - - // Update orders - if($mybb->request_method == "post") - { - if(is_array($mybb->input['group_disporder'])) - { - foreach($mybb->input['group_disporder'] as $gid => $new_order) - { - $gid = (int)$gid; - $update_group = array('disporder' => (int)$new_order); - $db->update_query("settinggroups", $update_group, "gid={$gid}"); - } - } - - if(is_array($mybb->input['setting_disporder'])) - { - foreach($mybb->input['setting_disporder'] as $sid => $new_order) - { - $sid = (int)$sid; - $update_setting = array('disporder' => (int)$new_order); - $db->update_query("settings", $update_setting, "sid={$sid}"); - } - } - - $plugins->run_hooks("admin_config_settings_manage_commit"); - - // Log admin action - log_admin_action(); - - flash_message($lang->success_display_orders_updated, 'success'); - admin_redirect("index.php?module=config-settings&action=manage"); - } - - $page->add_breadcrumb_item($lang->modify_existing_settings); - $page->output_header($lang->board_settings." - ".$lang->modify_existing_settings); - - $sub_tabs['change_settings'] = array( - 'title' => $lang->change_settings, - 'link' => "index.php?module=config-settings", - ); - - $sub_tabs['add_setting'] = array( - 'title' => $lang->add_new_setting, - 'link' => "index.php?module=config-settings&action=add" - ); - - $sub_tabs['add_setting_group'] = array( - 'title' => $lang->add_new_setting_group, - 'link' => "index.php?module=config-settings&action=addgroup" - ); - - $sub_tabs['modify_setting'] = array( - 'title' => $lang->modify_existing_settings, - 'link' => "index.php?module=config-settings&action=manage", - 'description' => $lang->modify_existing_settings_desc - ); - - $page->output_nav_tabs($sub_tabs, 'modify_setting'); - - // Cache settings - $settings_cache = array(); - $query = $db->simple_select("settings", "sid, name, title, disporder, gid, isdefault", "", array('order_by' => 'disporder', 'order_dir' => 'asc')); - while($setting = $db->fetch_array($query)) - { - $settings_cache[$setting['gid']][] = $setting; - } - - $form = new Form("index.php?module=config-settings&action=manage", "post", "edit"); - - $table = new Table; - - $table->construct_header($lang->setting_group_setting); - $table->construct_header($lang->order, array('class' => 'align_center', 'style' => 'width: 5%')); - $table->construct_header($lang->controls, array('class' => 'align_center', 'style' => 'width: 200px')); - - // Generate table - $query = $db->simple_select("settinggroups", "*", "", array('order_by' => 'disporder', 'order_dir' => 'asc')); - while($group = $db->fetch_array($query)) - { - // Make setting group row - // Translated? - $group_lang_var = "setting_group_{$group['name']}"; - if($lang->$group_lang_var) - { - $group_title = htmlspecialchars_uni($lang->$group_lang_var); - } - else - { - $group_title = htmlspecialchars_uni($group['title']); - } - $table->construct_cell("{$group_title}", array('id' => "group{$group['gid']}")); - $table->construct_cell($form->generate_numeric_field("group_disporder[{$group['gid']}]", $group['disporder'], array('style' => 'width: 80%; font-weight: bold', 'class' => 'align_center', 'min' => 0))); - // Only show options if not a default setting group - if($group['isdefault'] != 1) - { - $popup = new PopupMenu("group_{$group['gid']}", $lang->options); - $popup->add_item($lang->edit_setting_group, "index.php?module=config-settings&action=editgroup&gid={$group['gid']}"); - $popup->add_item($lang->delete_setting_group, "index.php?module=config-settings&action=deletegroup&gid={$group['gid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_setting_group_deletion}')"); - $table->construct_cell($popup->fetch(), array('class' => 'align_center')); - } - else - { - $table->construct_cell(''); - } - $table->construct_row(array('class' => 'alt_row', 'no_alt_row' => 1)); - - // Make rows for each setting in the group - if(is_array($settings_cache[$group['gid']])) - { - foreach($settings_cache[$group['gid']] as $setting) - { - $setting_lang_var = "setting_{$setting['name']}"; - if($lang->$setting_lang_var) - { - $setting_title = htmlspecialchars_uni($lang->$setting_lang_var); - } - else - { - $setting_title = htmlspecialchars_uni($setting['title']); - } - $table->construct_cell($setting_title, array('style' => 'padding-left: 40px;')); - $table->construct_cell($form->generate_numeric_field("setting_disporder[{$setting['sid']}]", $setting['disporder'], array('style' => 'width: 80%', 'class' => 'align_center', 'min' => 0))); - // Only show options if not a default setting group or is a custom setting - if($group['isdefault'] != 1 || $setting['isdefault'] != 1) - { - $popup = new PopupMenu("setting_{$setting['sid']}", $lang->options); - $popup->add_item($lang->edit_setting, "index.php?module=config-settings&action=edit&sid={$setting['sid']}"); - $popup->add_item($lang->delete_setting, "index.php?module=config-settings&action=delete&sid={$setting['sid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_setting_deletion}')"); - $table->construct_cell($popup->fetch(), array('class' => 'align_center')); - } - else - { - $table->construct_cell(''); - } - $table->construct_row(array('no_alt_row' => 1, 'class' => "group{$group['gid']}")); - } - } - } - - $table->output($lang->modify_existing_settings); - - $buttons[] = $form->generate_submit_button($lang->save_display_orders); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -// Change settings for a specified group. -if($mybb->input['action'] == "change") -{ - $plugins->run_hooks("admin_config_settings_change"); - - if($mybb->request_method == "post") - { - if(!is_writable(MYBB_ROOT.'inc/settings.php')) - { - flash_message($lang->error_chmod_settings_file, 'error'); - admin_redirect("index.php?module=config-settings"); - } - - // Not allowed to be hidden captcha fields - $disallowed_fields = array( - 'username', - 'password', - 'password2', - 'email', - 'email2', - 'imagestring', - 'imagehash', - 'answer', - 'question_id', - 'allownotices', - 'hideemail', - 'receivepms', - 'pmnotice', - 'emailpmnotify', - 'invisible', - 'subscriptionmethod', - 'timezoneoffset', - 'dstcorrection', - 'language', - 'step', - 'action', - 'agree', - 'regtime', - 'regcheck1', - 'regcheck2', - 'regsubmit' - ); - - $is_current_hiddencaptcha_wrong = in_array($mybb->settings['hiddencaptchaimagefield'], $disallowed_fields); - if(in_array($mybb->input['upsetting']['hiddencaptchaimagefield'], $disallowed_fields) || $is_current_hiddencaptcha_wrong) - { - if(isset($mybb->input['upsetting']['hiddencaptchaimagefield']) && $mybb->input['upsetting']['hiddencaptchaimagefield'] != $mybb->settings['hiddencaptchaimagefield'] && !$is_current_hiddencaptcha_wrong) - { - $wrong_value = $mybb->input['upsetting']['hiddencaptchaimagefield']; - $mybb->input['upsetting']['hiddencaptchaimagefield'] = $mybb->settings['hiddencaptchaimagefield']; - } - else - { - $wrong_value = $mybb->settings['hiddencaptchaimagefield']; - $mybb->input['upsetting']['hiddencaptchaimagefield'] = 'email3'; - } - - $lang->success_settings_updated .= $lang->sprintf($lang->success_settings_updated_hiddencaptchaimage, htmlspecialchars_uni($mybb->input['upsetting']['hiddencaptchaimagefield']), htmlspecialchars_uni($wrong_value)); - } - - // Have we opted for a reCAPTCHA and not set a public/private key? - if((isset($mybb->input['upsetting']['captchaimage']) && in_array($mybb->input['upsetting']['captchaimage'], array(2, 4)) && (!$mybb->input['upsetting']['captchaprivatekey'] || !$mybb->input['upsetting']['captchapublickey'])) - || (in_array($mybb->settings['captchaimage'], array(2, 4)) && (!$mybb->settings['captchaprivatekey'] || !$mybb->settings['captchapublickey']))) - { - $mybb->input['upsetting']['captchaimage'] = 1; - $lang->success_settings_updated .= $lang->success_settings_updated_captchaimage; - } - - // Get settings which optionscode is a forum/group select, checkbox or numeric - // We cannot rely on user input to decide this - $checkbox_settings = $forum_group_select = array(); - $query = $db->simple_select('settings', 'name, optionscode', "optionscode IN('forumselect', 'groupselect') OR optionscode LIKE 'checkbox%' OR optionscode LIKE 'numeric%'"); - - while($multisetting = $db->fetch_array($query)) - { - $options = array(); - - if(substr($multisetting['optionscode'], 0, 8) == 'checkbox') - { - $checkbox_settings[] = $multisetting['name']; - - // All checkboxes deselected = no $mybb->input['upsetting'] for them, we need to initialize it manually then, but only on pages where the setting is shown - if(empty($mybb->input['upsetting'][$multisetting['name']]) && isset($mybb->input["isvisible_{$multisetting['name']}"])) - { - $mybb->input['upsetting'][$multisetting['name']] = array(); - } - } - elseif(substr($multisetting['optionscode'], 0, 7) == 'numeric') - { - if(isset($mybb->input['upsetting'][$multisetting['name']])) - { - $type = explode("\n", $multisetting['optionscode']); - for($i=1; $i < count($type); $i++) - { - $optionsexp = explode("=", $type[$i]); - $opt = array_map('trim', $optionsexp); - if(in_array($opt[0], array('min', 'max', 'step'))) - { - if($opt[0] != 'step' || $opt[1] != 'any') - { - $opt[1] = (float)$opt[1]; - } - $options[$opt[0]] = $opt[1]; - } - } - - $value = (float)$mybb->input['upsetting'][$multisetting['name']]; - - if(isset($options['min'])) - { - $value = max($value, $options['min']); - } - - if(isset($options['max'])) - { - $value = min($value, $options['max']); - } - - $mybb->input['upsetting'][$multisetting['name']] = $value; - } - } - else - { - $forum_group_select[] = $multisetting['name']; - } - } - - // Administrator is changing the login method. - if($mybb->settings['username_method'] == 1 || $mybb->settings['username_method'] == 2 || $mybb->input['upsetting']['username_method'] == 1 || $mybb->input['upsetting']['username_method'] == 2) - { - $query = $db->simple_select('users', 'email, COUNT(email) AS duplicates', "email!=''", array('group_by' => 'email HAVING duplicates>1')); - if($db->num_rows($query)) - { - $mybb->input['upsetting']['username_method'] = 0; - $lang->success_settings_updated .= $lang->success_settings_updated_username_method; - } - else - { - $mybb->input['upsetting']['allowmultipleemails'] = 0; - $lang->success_settings_updated .= $lang->success_settings_updated_allowmultipleemails; - } - } - - if(is_array($mybb->input['upsetting'])) - { - foreach($mybb->input['upsetting'] as $name => $value) - { - if($forum_group_select && in_array($name, $forum_group_select)) - { - if($value == 'all') - { - $value = -1; - } - elseif($value == 'custom') - { - if(isset($mybb->input['select'][$name]) && is_array($mybb->input['select'][$name])) - { - foreach($mybb->input['select'][$name] as &$val) - { - $val = (int)$val; - } - unset($val); - - $value = implode(',', $mybb->input['select'][$name]); - } - else - { - $value = ''; - } - } - else - { - $value = ''; - } - } - elseif($checkbox_settings && in_array($name, $checkbox_settings)) - { - $value = ''; - - if(is_array($mybb->input['upsetting'][$name])) - { - $value = implode(',', $mybb->input['upsetting'][$name]); - } - } - - $db->update_query("settings", array('value' => $db->escape_string($value)), "name='".$db->escape_string($name)."'"); - } - } - - // Check if we need to create our fulltext index after changing the search mode - if($mybb->settings['searchtype'] != $mybb->input['upsetting']['searchtype'] && $mybb->input['upsetting']['searchtype'] == "fulltext") - { - if(!$db->is_fulltext("posts") && $db->supports_fulltext_boolean("posts")) - { - $db->create_fulltext_index("posts", "message"); - } - if(!$db->is_fulltext("posts") && $db->supports_fulltext("threads")) - { - $db->create_fulltext_index("threads", "subject"); - } - } - - // If the delayedthreadviews setting was changed, enable or disable the tasks for it. - if(isset($mybb->input['upsetting']['delayedthreadviews']) && $mybb->settings['delayedthreadviews'] != $mybb->input['upsetting']['delayedthreadviews']) - { - $db->update_query("tasks", array('enabled' => (int)$mybb->input['upsetting']['delayedthreadviews']), "file='threadviews'"); - } - - // Have we changed our cookie prefix? If so, update our adminsid so we're not logged out - if(isset($mybb->input['upsetting']['cookieprefix']) && $mybb->input['upsetting']['cookieprefix'] != $mybb->settings['cookieprefix']) - { - my_unsetcookie("adminsid"); - $mybb->settings['cookieprefix'] = $mybb->input['upsetting']['cookieprefix']; - my_setcookie("adminsid", $admin_session['sid'], '', true); - } - - if(isset($mybb->input['upsetting']['statstopreferrer']) && $mybb->input['upsetting']['statstopreferrer'] != $mybb->settings['statstopreferrer']) - { - $cache->update_statistics(); - } - - $statslimit = $mybb->settings['statslimit']; - - rebuild_settings(); - - if(isset($mybb->input['upsetting']['statslimit']) && $mybb->input['upsetting']['statslimit'] != $statslimit) - { - $cache->update_most_replied_threads(); - $cache->update_most_viewed_threads(); - } - - $plugins->run_hooks("admin_config_settings_change_commit"); - - // Log admin action - log_admin_action(); - - flash_message($lang->success_settings_updated, 'success'); - admin_redirect("index.php?module=config-settings"); - } - - // What type of page - $cache_groups = $cache_settings = array(); - if(isset($mybb->input['search'])) - { - // Search - - // Search for settings - $search = $db->escape_string_like($mybb->input['search']); - $query = $db->query(" - SELECT s.* - FROM ".TABLE_PREFIX."settings s - LEFT JOIN ".TABLE_PREFIX."settinggroups g ON(s.gid=g.gid) - WHERE s.name LIKE '%{$search}%' OR s.title LIKE '%{$search}%' OR s.description LIKE '%{$search}%' OR g.name LIKE '%{$search}%' OR g.title LIKE '%{$search}%' OR g.description LIKE '%{$search}%' - ORDER BY s.disporder - "); - while($setting = $db->fetch_array($query)) - { - $cache_settings[$setting['gid']][$setting['sid']] = $setting; - } - - if(!$db->num_rows($query)) - { - if(isset($mybb->input['ajax_search'])) - { - echo json_encode(array("errors" => array($lang->error_no_settings_found))); - exit; - } - else - { - flash_message($lang->error_no_settings_found, 'error'); - admin_redirect("index.php?module=config-settings"); - } - } - - // Cache groups - $groups = array_keys($cache_settings); - $groups = implode(',', $groups); - $query = $db->simple_select("settinggroups", "*", "gid IN ({$groups})", array('order_by' => 'disporder')); - while($group = $db->fetch_array($query)) - { - $cache_groups[$group['gid']] = $group; - } - - // Page header only if not AJAX - if(!isset($mybb->input['ajax_search'])) - { - $page->add_breadcrumb_item($lang->settings_search); - $page->output_header($lang->board_settings." - {$lang->settings_search}"); - } - - $form = new Form("index.php?module=config-settings&action=change", "post", "change"); - - echo $form->generate_hidden_field("gid", $group['gid']); - } - elseif($mybb->input['gid']) - { - // Group listing - // Cache groups - $query = $db->simple_select("settinggroups", "*", "gid = '".$mybb->get_input('gid', MyBB::INPUT_INT)."'"); - $groupinfo = $db->fetch_array($query); - $cache_groups[$groupinfo['gid']] = $groupinfo; - - if(!$db->num_rows($query)) - { - $page->output_error($lang->error_invalid_gid2); - } - - // Cache settings - $query = $db->simple_select("settings", "*", "gid='".$mybb->get_input('gid', MyBB::INPUT_INT)."'", array('order_by' => 'disporder')); - while($setting = $db->fetch_array($query)) - { - $cache_settings[$setting['gid']][$setting['sid']] = $setting; - } - - if(!$db->num_rows($query)) - { - flash_message($lang->error_no_settings_found, 'error'); - admin_redirect("index.php?module=config-settings"); - } - - $group_lang_var = "setting_group_{$groupinfo['name']}"; - if(isset($lang->$group_lang_var)) - { - $groupinfo['title'] = $lang->$group_lang_var; - } - - // Page header - $page->add_breadcrumb_item($groupinfo['title']); - $page->output_header($lang->board_settings." - {$groupinfo['title']}"); - - $form = new Form("index.php?module=config-settings&action=change", "post", "change"); - - echo $form->generate_hidden_field("gid", $groupinfo['gid']); - } - else - { - // All settings list - // Cache groups - $query = $db->simple_select("settinggroups", "*", "", array('order_by' => 'disporder')); - while($group = $db->fetch_array($query)) - { - $cache_groups[$group['gid']] = $group; - } - - if(!$db->num_rows($query)) - { - $page->output_error($lang->error_invalid_gid2); - } - - // Cache settings - $query = $db->simple_select("settings", "*", "", array('order_by' => 'disporder')); - while($setting = $db->fetch_array($query)) - { - $cache_settings[$setting['gid']][$setting['sid']] = $setting; - } - - // Page header - $page->add_breadcrumb_item($lang->show_all_settings); - $page->output_header($lang->board_settings." - {$lang->show_all_settings}"); - - $form = new Form("index.php?module=config-settings&action=change", "post", "change"); - } - - // Build rest of page - $buttons[] = $form->generate_submit_button($lang->save_settings); - foreach($cache_groups as $groupinfo) - { - $group_lang_var = "setting_group_{$groupinfo['name']}"; - if(isset($lang->$group_lang_var)) - { - $groupinfo['title'] = $lang->$group_lang_var; - } - - $form_container = new FormContainer($groupinfo['title']); - - if(empty($cache_settings[$groupinfo['gid']])) - { - $form_container->output_cell($lang->error_no_settings_found); - $form_container->construct_row(); - - $form_container->end(); - echo '
'; - - continue; - } - - foreach($cache_settings[$groupinfo['gid']] as $setting) - { - $options = ""; - $type = explode("\n", $setting['optionscode']); - $type[0] = trim($type[0]); - $element_name = "upsetting[{$setting['name']}]"; - $element_id = "setting_{$setting['name']}"; - if($type[0] == "text" || $type[0] == "") - { - $setting_code = $form->generate_text_box($element_name, $setting['value'], array('id' => $element_id)); - } - else if($type[0] == "numeric") - { - $field_options = array('id' => $element_id); - if(count($type) > 1) - { - for($i=1; $i < count($type); $i++) - { - $optionsexp = explode("=", $type[$i]); - $opt = array_map('trim', $optionsexp); - if(in_array($opt[0], array('min', 'max', 'step'))) - { - if($opt[0] != 'step' || $opt[1] != 'any') - { - $opt[1] = (float)$opt[1]; - } - $field_options[$opt[0]] = $opt[1]; - } - } - } - $setting_code = $form->generate_numeric_field($element_name, $setting['value'], $field_options); - } - else if($type[0] == "textarea") - { - $setting_code = $form->generate_text_area($element_name, $setting['value'], array('id' => $element_id)); - } - else if($type[0] == "yesno") - { - $setting_code = $form->generate_yes_no_radio($element_name, $setting['value'], true, array('id' => $element_id.'_yes', 'class' => $element_id), array('id' => $element_id.'_no', 'class' => $element_id)); - } - else if($type[0] == "onoff") - { - $setting_code = $form->generate_on_off_radio($element_name, $setting['value'], true, array('id' => $element_id.'_on', 'class' => $element_id), array('id' => $element_id.'_off', 'class' => $element_id)); - } - else if($type[0] == "cpstyle") - { - $dir = @opendir(MYBB_ROOT.$config['admin_dir']."/styles"); - - $folders = array(); - while($folder = readdir($dir)) - { - if($file != "." && $file != ".." && @file_exists(MYBB_ROOT.$config['admin_dir']."/styles/$folder/main.css")) - { - $folders[$folder] = ucfirst($folder); - } - } - closedir($dir); - ksort($folders); - $setting_code = $form->generate_select_box($element_name, $folders, $setting['value'], array('id' => $element_id)); - } - else if($type[0] == "language") - { - $languages = $lang->get_languages(); - $setting_code = $form->generate_select_box($element_name, $languages, $setting['value'], array('id' => $element_id)); - } - else if($type[0] == "adminlanguage") - { - $languages = $lang->get_languages(1); - $setting_code = $form->generate_select_box($element_name, $languages, $setting['value'], array('id' => $element_id)); - } - else if($type[0] == "passwordbox") - { - $setting_code = $form->generate_password_box($element_name, $setting['value'], array('id' => $element_id)); - } - else if($type[0] == "php") - { - $setting['optionscode'] = substr($setting['optionscode'], 3); - eval("\$setting_code = \"".$setting['optionscode']."\";"); - } - else if($type[0] == "forumselect") - { - $selected_values = ''; - if($setting['value'] != '' && $setting['value'] != -1) - { - $selected_values = explode(',', (string)$setting['value']); - - foreach($selected_values as &$value) - { - $value = (int)$value; - } - unset($value); - } - - $forum_checked = array('all' => '', 'custom' => '', 'none' => ''); - if($setting['value'] == -1) - { - $forum_checked['all'] = 'checked="checked"'; - } - elseif($setting['value'] != '') - { - $forum_checked['custom'] = 'checked="checked"'; - } - else - { - $forum_checked['none'] = 'checked="checked"'; - } - - print_selection_javascript(); - - $setting_code = " -
-
-
-
- - - - - -
{$lang->forums_colon}".$form->generate_forum_select('select['.$setting['name'].'][]', $selected_values, array('id' => $element_id, 'multiple' => true, 'size' => 5))."
-
-
-
- "; - } - else if($type[0] == "forumselectsingle") - { - $selected_value = (int)$setting['value']; // No need to check if empty, int will give 0 - $setting_code = $form->generate_forum_select($element_name, $selected_value, array('id' => $element_id, 'main_option' => $lang->none)); - } - else if($type[0] == "groupselect") - { - $selected_values = ''; - if($setting['value'] != '' && $setting['value'] != -1) - { - $selected_values = explode(',', (string)$setting['value']); - - foreach($selected_values as &$value) - { - $value = (int)$value; - } - unset($value); - } - - $group_checked = array('all' => '', 'custom' => '', 'none' => ''); - if($setting['value'] == -1) - { - $group_checked['all'] = 'checked="checked"'; - } - elseif($setting['value'] != '') - { - $group_checked['custom'] = 'checked="checked"'; - } - else - { - $group_checked['none'] = 'checked="checked"'; - } - - print_selection_javascript(); - - $setting_code = " -
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('select['.$setting['name'].'][]', $selected_values, array('id' => $element_id, 'multiple' => true, 'size' => 5))."
-
-
-
- "; - } - else if($type[0] == "groupselectsingle") - { - $selected_value = (int)$setting['value']; // No need to check if empty, int will give 0 - $setting_code = $form->generate_group_select($element_name, $selected_value, array('id' => $element_id, 'main_option' => $lang->none)); - } - else - { - $typecount = count($type); - - if($type[0] == 'checkbox') - { - $multivalue = explode(',', $setting['value']); - } - - for($i = 0; $i < $typecount; $i++) - { - $optionsexp = explode("=", $type[$i]); - if(!isset($optionsexp[1])) - { - continue; - } - $title_lang = "setting_{$setting['name']}_{$optionsexp[0]}"; - if(isset($lang->$title_lang)) - { - $optionsexp[1] = $lang->$title_lang; - } - - if($type[0] == "select") - { - $option_list[$optionsexp[0]] = htmlspecialchars_uni($optionsexp[1]); - } - else if($type[0] == "radio") - { - if($setting['value'] == $optionsexp[0]) - { - $option_list[$i] = $form->generate_radio_button($element_name, $optionsexp[0], htmlspecialchars_uni($optionsexp[1]), array('id' => $element_id.'_'.$i, "checked" => 1, 'class' => $element_id)); - } - else - { - $option_list[$i] = $form->generate_radio_button($element_name, $optionsexp[0], htmlspecialchars_uni($optionsexp[1]), array('id' => $element_id.'_'.$i, 'class' => $element_id)); - } - } - else if($type[0] == "checkbox") - { - if(in_array($optionsexp[0], $multivalue)) - { - $option_list[$i] = $form->generate_check_box("{$element_name}[]", $optionsexp[0], htmlspecialchars_uni($optionsexp[1]), array('id' => $element_id.'_'.$i, "checked" => 1, 'class' => $element_id)); - } - else - { - $option_list[$i] = $form->generate_check_box("{$element_name}[]", $optionsexp[0], htmlspecialchars_uni($optionsexp[1]), array('id' => $element_id.'_'.$i, 'class' => $element_id)); - } - } - } - - if($type[0] == "select") - { - $setting_code = $form->generate_select_box($element_name, $option_list, $setting['value'], array('id' => $element_id)); - } - else - { - $setting_code = implode("
", $option_list); - - if($type[0] == 'checkbox') - { - $setting_code .= $form->generate_hidden_field("isvisible_{$setting['name']}", 1); - } - } - $option_list = array(); - } - - // Do we have a custom language variable for this title or description? - $title_lang = "setting_".$setting['name']; - $desc_lang = $title_lang."_desc"; - if(isset($lang->$title_lang)) - { - $setting['title'] = $lang->$title_lang; - } - if(isset($lang->$desc_lang)) - { - $setting['description'] = $lang->$desc_lang; - } - $form_container->output_row(htmlspecialchars_uni($setting['title']), $setting['description'], $setting_code, '', array(), array('id' => 'row_'.$element_id)); - } - $form_container->end(); - - $form->output_submit_wrapper($buttons); - echo '
'; - } - $form->end(); - - print_setting_peekers(); - - if(!isset($mybb->input['ajax_search'])) - { - $page->output_footer(); - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_settings_start"); - - $page->extra_header .= << - - -EOF; - - $page->output_header($lang->board_settings); - if(isset($message)) - { - $page->output_inline_message($message); - } - - $sub_tabs['change_settings'] = array( - 'title' => $lang->change_settings, - 'link' => "index.php?module=config-settings", - 'description' => $lang->change_settings_desc - ); - - $sub_tabs['add_setting'] = array( - 'title' => $lang->add_new_setting, - 'link' => "index.php?module=config-settings&action=add" - ); - - $sub_tabs['add_setting_group'] = array( - 'title' => $lang->add_new_setting_group, - 'link' => "index.php?module=config-settings&action=addgroup" - ); - - $sub_tabs['modify_setting'] = array( - 'title' => $lang->modify_existing_settings, - 'link' => "index.php?module=config-settings&action=manage", - ); - - $page->output_nav_tabs($sub_tabs, 'change_settings'); - - // Search form - echo "
"; - $search = new Form("index.php", 'get', 'settings_search', 0, 'settings_search'); - echo $search->generate_hidden_field('module', 'config/settings'); - echo $search->generate_hidden_field('action', 'change'); - echo $search->generate_text_box('search', $lang->settings_search, array('id' => 'search', 'class' => 'search_default field150 field_small')); - echo "search}\" />"; - $search->end(); - echo "
\n"; - - echo '
 
'; - $table = new Table; - $table->construct_header($lang->setting_groups); - - switch($db->type) - { - case "pgsql": - $query = $db->query(" - SELECT g.*, COUNT(s.sid) AS settingcount - FROM ".TABLE_PREFIX."settinggroups g - LEFT JOIN ".TABLE_PREFIX."settings s ON (s.gid=g.gid) - WHERE g.isdefault = 1 - GROUP BY ".$db->build_fields_string("settinggroups", "g.")." - ORDER BY g.disporder - "); - break; - default: - $query = $db->query(" - SELECT g.*, COUNT(s.sid) AS settingcount - FROM ".TABLE_PREFIX."settinggroups g - LEFT JOIN ".TABLE_PREFIX."settings s ON (s.gid=g.gid) - WHERE g.isdefault = 1 - GROUP BY g.gid - ORDER BY g.disporder - "); - } - while($group = $db->fetch_array($query)) - { - $group_lang_var = "setting_group_{$group['name']}"; - if(isset($lang->$group_lang_var)) - { - $group_title = htmlspecialchars_uni($lang->$group_lang_var); - } - else - { - $group_title = htmlspecialchars_uni($group['title']); - } - - $group_desc_lang_var = "setting_group_{$group['name']}_desc"; - if(isset($lang->$group_desc_lang_var)) - { - $group_desc = htmlspecialchars_uni($lang->$group_desc_lang_var); - } - else - { - $group_desc = htmlspecialchars_uni($group['description']); - } - - $table->construct_cell("{$group_title} ({$group['settingcount']} {$lang->bbsettings})
{$group_desc}"); - $table->construct_row(); - } - - $table->output("{$lang->show_all_settings}{$lang->board_settings}"); - - // Plugin Settings - switch($db->type) - { - case "pgsql": - $query = $db->query(" - SELECT g.*, COUNT(s.sid) AS settingcount - FROM ".TABLE_PREFIX."settinggroups g - LEFT JOIN ".TABLE_PREFIX."settings s ON (s.gid=g.gid) - WHERE g.isdefault <> 1 - GROUP BY ".$db->build_fields_string("settinggroups", "g.")." - ORDER BY g.disporder - "); - break; - default: - $query = $db->query(" - SELECT g.*, COUNT(s.sid) AS settingcount - FROM ".TABLE_PREFIX."settinggroups g - LEFT JOIN ".TABLE_PREFIX."settings s ON (s.gid=g.gid) - WHERE g.isdefault <> 1 - GROUP BY g.gid - ORDER BY g.disporder - "); - } - - if($db->num_rows($query)) - { - $table = new Table; - $table->construct_header($lang->setting_groups); - - while($group = $db->fetch_array($query)) - { - $group_lang_var = "setting_group_{$group['name']}"; - if($lang->$group_lang_var) - { - $group_title = htmlspecialchars_uni($lang->$group_lang_var); - } - else - { - $group_title = htmlspecialchars_uni($group['title']); - } - - $group_desc_lang_var = "setting_group_{$group['name']}_desc"; - if($lang->$group_desc_lang_var) - { - $group_desc = htmlspecialchars_uni($lang->$group_desc_lang_var); - } - else - { - $group_desc = htmlspecialchars_uni($group['description']); - } - - $table->construct_cell("{$group_title} ({$group['settingcount']} {$lang->bbsettings})
{$group_desc}"); - $table->construct_row(); - } - - $table->output($lang->plugin_settings); - } - - echo '
'; - - echo ' - -'; - - print_setting_peekers(); - $page->output_footer(); -} - -/** - * Print all the peekers for all of the default settings - */ -function print_setting_peekers() -{ - global $plugins; - - $peekers = array( - 'new Peeker($(".setting_boardclosed"), $("#row_setting_boardclosed_reason"), 1, true)', - 'new Peeker($(".setting_gzipoutput"), $("#row_setting_gziplevel"), 1, true)', - 'new Peeker($(".setting_useerrorhandling"), $("#row_setting_errorlogmedium, #row_setting_errortypemedium, #row_setting_errorloglocation"), 1, true)', - 'new Peeker($("#setting_subforumsindex"), $("#row_setting_subforumsstatusicons"), /[^0+|]/, false)', - 'new Peeker($(".setting_showsimilarthreads"), $("#row_setting_similarityrating, #row_setting_similarlimit"), 1, true)', - 'new Peeker($(".setting_disableregs"), $("#row_setting_regtype, #row_setting_securityquestion, #row_setting_regtime, #row_setting_allowmultipleemails, #row_setting_hiddencaptchaimage, #row_setting_betweenregstime"), 0, true)', - 'new Peeker($(".setting_hiddencaptchaimage"), $("#row_setting_hiddencaptchaimagefield"), 1, true)', - 'new Peeker($("#setting_failedlogincount"), $("#row_setting_failedlogintime, #row_setting_failedlogintext"), /[^0+|]/, false)', - 'new Peeker($(".setting_postfloodcheck"), $("#row_setting_postfloodsecs"), 1, true)', - 'new Peeker($("#setting_postmergemins"), $("#row_setting_postmergefignore, #row_setting_postmergeuignore, #row_setting_postmergesep"), /[^0+|]/, false)', - 'new Peeker($(".setting_enablememberlist"), $("#row_setting_membersperpage, #row_setting_default_memberlist_sortby, #row_setting_default_memberlist_order, #row_setting_memberlistmaxavatarsize"), 1, true)', - 'new Peeker($(".setting_enablereputation"), $("#row_setting_repsperpage, #row_setting_posrep, #row_setting_neurep, #row_setting_negrep, #row_setting_postrep, #row_setting_multirep, #row_setting_maxreplength, #row_setting_minreplength"), 1, true)', - 'new Peeker($(".setting_enablewarningsystem"), $("#row_setting_allowcustomwarnings, #row_setting_canviewownwarning, #row_setting_maxwarningpoints, #row_setting_allowanonwarningpms"), 1, true)', - 'new Peeker($(".setting_enablepms"), $("#row_setting_pmsallowhtml, #row_setting_pmsallowmycode, #row_setting_pmsallowsmilies, #row_setting_pmsallowimgcode, #row_setting_pmsallowvideocode, #row_setting_pmquickreply, #row_setting_pmfloodsecs, #row_setting_showpmip, #row_setting_maxpmquotedepth"), 1, true)', - 'new Peeker($(".setting_smilieinserter"), $("#row_setting_smilieinsertertot, #row_setting_smilieinsertercols"), 1, true)', - 'new Peeker($("#setting_mail_handler"), $("#row_setting_smtp_host, #row_setting_smtp_port, #row_setting_smtp_user, #row_setting_smtp_pass, #row_setting_secure_smtp"), "smtp", false)', - 'new Peeker($("#setting_mail_handler"), $("#row_setting_mail_parameters"), "mail", false)', - 'new Peeker($("#setting_captchaimage"), $("#row_setting_captchapublickey, #row_setting_captchaprivatekey"), /(2|4)/, false)', - 'new Peeker($(".setting_contact"), $("#row_setting_contact_guests, #row_setting_contact_badwords, #row_setting_contact_maxsubjectlength, #row_setting_contact_minmessagelength, #row_setting_contact_maxmessagelength"), 1, true)', - 'new Peeker($(".setting_enablepruning"), $("#row_setting_enableprunebyposts, #row_setting_pruneunactived, #row_setting_prunethreads"), 1, true)', - 'new Peeker($(".setting_enableprunebyposts"), $("#row_setting_prunepostcount, #row_setting_dayspruneregistered, #row_setting_prunepostcountall"), 1, true)', - 'new Peeker($(".setting_pruneunactived"), $("#row_setting_dayspruneunactivated"), 1, true)', - 'new Peeker($(".setting_statsenabled"), $("#row_setting_statscachetime, #row_setting_statslimit, #row_setting_statstopreferrer"), 1, true)', - 'new Peeker($(".setting_purgespammergroups_forums_groups_check"), $("#row_setting_purgespammerpostlimit, #row_setting_purgespammerbandelete, #row_setting_purgespammerapikey"), /^(?!none)/, true)', - 'new Peeker($(".setting_purgespammerbandelete"),$("#row_setting_purgespammerbangroup, #row_setting_purgespammerbanreason"), "ban", true)', - 'new Peeker($("#setting_maxloginattempts"), $("#row_setting_loginattemptstimeout"), /[^0+|]/, false)', - 'new Peeker($(".setting_bbcodeinserter"), $("#row_setting_partialmode, #row_setting_smilieinserter"), 1, true)', - 'new Peeker($(".setting_portal"), $("#row_setting_portal_announcementsfid, #row_setting_portal_showwelcome, #row_setting_portal_showpms, #row_setting_portal_showstats, #row_setting_portal_showwol, #row_setting_portal_showsearch, #row_setting_portal_showdiscussions"), 1, true)', - 'new Peeker($(".setting_portal_announcementsfid_forums_groups_check"), $("#row_setting_portal_numannouncements"), /^(?!none)/, true)', - 'new Peeker($(".setting_portal_showdiscussions"), $("#row_setting_portal_showdiscussionsnum, #row_setting_portal_excludediscussion"), 1, true)', - 'new Peeker($(".setting_enableattachments"), $("#row_setting_maxattachments, #row_setting_attachthumbnails"), 1, true)', - 'new Peeker($(".setting_attachthumbnails"), $("#row_setting_attachthumbh, #row_setting_attachthumbw"), "yes", true)', - 'new Peeker($(".setting_showbirthdays"), $("#row_setting_showbirthdayspostlimit"), 1, true)', - 'new Peeker($("#setting_betweenregstime"), $("#row_setting_maxregsbetweentime"), /[^0+|]/, false)', - 'new Peeker($(".setting_usecdn"), $("#row_setting_cdnurl, #row_setting_cdnpath"), 1, true)', - 'new Peeker($("#setting_errorlogmedium"), $("#row_setting_errortypemedium"), /^(log|email|both)/, false)', - 'new Peeker($("#setting_errorlogmedium"), $("#row_setting_errorloglocation"), /^(log|both)/, false)', - 'new Peeker($(".setting_sigmycode"), $("#row_setting_sigcountmycode, #row_setting_sigimgcode"), 1, true)', - 'new Peeker($(".setting_pmsallowmycode"), $("#row_setting_pmsallowimgcode, #row_setting_pmsallowvideocode"), 1, true)' - ); - - $peekers = $plugins->run_hooks("admin_settings_print_peekers", $peekers); - - $setting_peekers = implode("\n ", $peekers); - - echo ' - '; -} diff --git a/html/forums/admin/modules/config/smilies.php b/html/forums/admin/modules/config/smilies.php deleted file mode 100644 index ee711e5..0000000 --- a/html/forums/admin/modules/config/smilies.php +++ /dev/null @@ -1,763 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->smilies, "index.php?module=config-smilies"); - -$plugins->run_hooks("admin_config_smilies_begin"); - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_config_smilies_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - - if(!trim($mybb->input['find'])) - { - $errors[] = $lang->error_missing_text_replacement; - } - - if(!trim($mybb->input['image'])) - { - $errors[] = $lang->error_missing_path; - } - - if(!trim($mybb->input['disporder'])) - { - $errors[] = $lang->error_missing_order; - } - else - { - $mybb->input['disporder'] = $mybb->get_input('disporder', MyBB::INPUT_INT); - $query = $db->simple_select('smilies', 'sid', 'disporder=\''.$mybb->input['disporder'].'\''); - $duplicate_disporder = $db->fetch_field($query, 'sid'); - - if($duplicate_disporder) - { - $errors[] = $lang->error_duplicate_order; - } - } - - if(!$errors) - { - $mybb->input['find'] = str_replace("\r\n", "\n", $mybb->input['find']); - $mybb->input['find'] = str_replace("\r", "\n", $mybb->input['find']); - $mybb->input['find'] = explode("\n", $mybb->input['find']); - foreach(array_merge(array_keys($mybb->input['find'], ""), array_keys($mybb->input['find'], " ")) as $key) - { - unset($mybb->input['find'][$key]); - } - $mybb->input['find'] = implode("\n", $mybb->input['find']); - - $new_smilie = array( - "name" => $db->escape_string($mybb->input['name']), - "find" => $db->escape_string($mybb->input['find']), - "image" => $db->escape_string($mybb->input['image']), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "showclickable" => $mybb->get_input('showclickable', MyBB::INPUT_INT) - ); - - $sid = $db->insert_query("smilies", $new_smilie); - - $plugins->run_hooks("admin_config_smilies_add_commit"); - - $cache->update_smilies(); - - // Log admin action - log_admin_action($sid, htmlspecialchars_uni($mybb->input['name'])); - - flash_message($lang->success_smilie_added, 'success'); - admin_redirect("index.php?module=config-smilies"); - } - } - - $page->add_breadcrumb_item($lang->add_smilie); - $page->output_header($lang->smilies." - ".$lang->add_smilie); - - $sub_tabs['manage_smilies'] = array( - 'title' => $lang->manage_smilies, - 'link' => "index.php?module=config-smilies", - ); - $sub_tabs['add_smilie'] = array( - 'title' => $lang->add_smilie, - 'link' => "index.php?module=config-smilies&action=add", - 'description' => $lang->add_smilie_desc - ); - $sub_tabs['add_multiple_smilies'] = array( - 'title' => $lang->add_multiple_smilies, - 'link' => "index.php?module=config-smilies&action=add_multiple", - ); - $sub_tabs['mass_edit'] = array( - 'title' => $lang->mass_edit, - 'link' => "index.php?module=config-smilies&action=mass_edit" - ); - - $page->output_nav_tabs($sub_tabs, 'add_smilie'); - $form = new Form("index.php?module=config-smilies&action=add", "post", "add"); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['image'] = 'images/smilies/'; - $mybb->input['showclickable'] = 1; - } - - if(!$mybb->input['disporder']) - { - $query = $db->simple_select("smilies", "max(disporder) as dispordermax"); - $mybb->input['disporder'] = $db->fetch_field($query, "dispordermax")+1; - } - - $form_container = new FormContainer($lang->add_smilie); - $form_container->output_row($lang->name." *", "", $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->text_replace." *", $lang->text_replace_desc, $form->generate_text_area('find', $mybb->input['find'], array('id' => 'find')), 'find'); - $form_container->output_row($lang->image_path." *", $lang->image_path_desc, $form->generate_text_box('image', $mybb->input['image'], array('id' => 'image')), 'image'); - $form_container->output_row($lang->display_order." *", $lang->display_order_desc, $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->output_row($lang->show_clickable." *", $lang->show_clickable_desc, $form->generate_yes_no_radio('showclickable', $mybb->input['showclickable'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_smilie); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("smilies", "*", "sid='".$mybb->get_input('sid', MyBB::INPUT_INT)."'"); - $smilie = $db->fetch_array($query); - - // Does the smilie not exist? - if(!$smilie['sid']) - { - flash_message($lang->error_invalid_smilie, 'error'); - admin_redirect("index.php?module=config-smilies"); - } - - $plugins->run_hooks("admin_config_smilies_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - - if(!trim($mybb->input['find'])) - { - $errors[] = $lang->error_missing_text_replacement; - } - - if(!trim($mybb->input['image'])) - { - $errors[] = $lang->error_missing_path; - } - - if(!trim($mybb->input['disporder'])) - { - $errors[] = $lang->error_missing_order; - } - else - { - $mybb->input['disporder'] = $mybb->get_input('disporder', MyBB::INPUT_INT); - $query = $db->simple_select("smilies", "sid", "disporder= '".$mybb->input['disporder']."' AND sid != '".$smilie['sid']."'"); - $duplicate_disporder = $db->fetch_field($query, 'sid'); - - if($duplicate_disporder) - { - $errors[] = $lang->error_duplicate_order; - } - } - - if(!$errors) - { - $mybb->input['find'] = str_replace("\r\n", "\n", $mybb->input['find']); - $mybb->input['find'] = str_replace("\r", "\n", $mybb->input['find']); - $mybb->input['find'] = explode("\n", $mybb->input['find']); - foreach(array_merge(array_keys($mybb->input['find'], ""), array_keys($mybb->input['find'], " ")) as $key) - { - unset($mybb->input['find'][$key]); - } - $mybb->input['find'] = implode("\n", $mybb->input['find']); - - $updated_smilie = array( - "name" => $db->escape_string($mybb->input['name']), - "find" => $db->escape_string($mybb->input['find']), - "image" => $db->escape_string($mybb->input['image']), - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "showclickable" => $mybb->get_input('showclickable', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_config_smilies_edit_commit"); - - $db->update_query("smilies", $updated_smilie, "sid = '{$smilie['sid']}'"); - - $cache->update_smilies(); - - // Log admin action - log_admin_action($smilie['sid'], htmlspecialchars_uni($mybb->input['name'])); - - flash_message($lang->success_smilie_updated, 'success'); - admin_redirect("index.php?module=config-smilies"); - } - } - - $page->add_breadcrumb_item($lang->edit_smilie); - $page->output_header($lang->smilies." - ".$lang->edit_smilie); - - $sub_tabs['edit_smilie'] = array( - 'title' => $lang->edit_smilie, - 'link' => "index.php?module=config-smilies&action=edit", - 'description' => $lang->edit_smilie_desc - ); - $sub_tabs['mass_edit'] = array( - 'title' => $lang->mass_edit, - 'link' => "index.php?module=config-smilies&action=mass_edit", - ); - - $page->output_nav_tabs($sub_tabs, 'edit_smilie'); - $form = new Form("index.php?module=config-smilies&action=edit", "post", "edit"); - - echo $form->generate_hidden_field("sid", $smilie['sid']); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = array_merge($mybb->input, $smilie); - } - - $form_container = new FormContainer($lang->edit_smilie); - $form_container->output_row($lang->name." *", "", $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->text_replace." *", $lang->text_replace_desc, $form->generate_text_area('find', $mybb->input['find'], array('id' => 'find')), 'find'); - $form_container->output_row($lang->image_path." *", $lang->image_path_desc, $form->generate_text_box('image', $mybb->input['image'], array('id' => 'image')), 'image'); - $form_container->output_row($lang->display_order." *", $lang->display_order_desc, $form->generate_numeric_field('disporder', $mybb->input['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->output_row($lang->show_clickable." *", $lang->show_clickable_desc, $form->generate_yes_no_radio('showclickable', $mybb->input['showclickable'])); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_smilie); - $buttons[] = $form->generate_reset_button($lang->reset); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("smilies", "*", "sid='".$mybb->get_input('sid', MyBB::INPUT_INT)."'"); - $smilie = $db->fetch_array($query); - - // Does the smilie not exist? - if(!$smilie['sid']) - { - flash_message($lang->error_invalid_smilie, 'error'); - admin_redirect("index.php?module=config-smilies"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-smilies"); - } - - $plugins->run_hooks("admin_config_smilies_delete"); - - if($mybb->request_method == "post") - { - // Delete the smilie - $db->delete_query("smilies", "sid='{$smilie['sid']}'"); - - $plugins->run_hooks("admin_config_smilies_delete_commit"); - - $cache->update_smilies(); - - // Log admin action - log_admin_action($smilie['sid'], htmlspecialchars_uni($smilie['name'])); - - flash_message($lang->success_smilie_updated, 'success'); - admin_redirect("index.php?module=config-smilies"); - } - else - { - $page->output_confirm_action("index.php?module=config-smilies&action=delete&sid={$smilie['sid']}", $lang->confirm_smilie_deletion); - }} - -if($mybb->input['action'] == "add_multiple") -{ - $plugins->run_hooks("admin_config_smilies_add_multiple"); - - if($mybb->request_method == "post") - { - if($mybb->input['step'] == 1) - { - $plugins->run_hooks("admin_config_smilies_add_multiple_step1"); - - if(!trim($mybb->input['pathfolder'])) - { - $errors[] = $lang->error_missing_path_multiple; - } - - $path = $mybb->input['pathfolder']; - $dir = @opendir(MYBB_ROOT.$path); - - if(!$dir) - { - $errors[] = $lang->error_invalid_path; - } - - if($path && !is_array($errors)) - { - if(substr($path, -1, 1) !== "/") - { - $path .= "/"; - } - - $query = $db->simple_select("smilies"); - - $asmilies = array(); - while($smilie = $db->fetch_array($query)) - { - $asmilies[$smilie['image']] = 1; - } - - $smilies = array(); - while($file = readdir($dir)) - { - if($file != ".." && $file != ".") - { - $ext = get_extension($file); - if($ext == "gif" || $ext == "jpg" || $ext == "jpeg" || $ext == "png" || $ext == "bmp") - { - if(!$asmilies[$path.$file]) - { - $smilies[] = $file; - } - } - } - } - closedir($dir); - - if(count($smilies) == 0) - { - $errors[] = $lang->error_no_smilies; - } - } - - if(!$errors) - { - $page->add_breadcrumb_item($lang->add_multiple_smilies); - $page->output_header($lang->smilies." - ".$lang->add_multiple_smilies); - - $sub_tabs['manage_smilies'] = array( - 'title' => $lang->manage_smilies, - 'link' => "index.php?module=config-smilies", - ); - $sub_tabs['add_smilie'] = array( - 'title' => $lang->add_smilie, - 'link' => "index.php?module=config-smilies&action=add" - ); - $sub_tabs['add_multiple_smilies'] = array( - 'title' => $lang->add_multiple_smilies, - 'link' => "index.php?module=config-smilies&action=add_multiple", - 'description' => $lang->add_multiple_smilies_desc - ); - $sub_tabs['mass_edit'] = array( - 'title' => $lang->mass_edit, - 'link' => "index.php?module=config-smilies&action=mass_edit" - ); - - $page->output_nav_tabs($sub_tabs, 'add_multiple_smilies'); - $form = new Form("index.php?module=config-smilies&action=add_multiple", "post", "add_multiple"); - echo $form->generate_hidden_field("step", "2"); - echo $form->generate_hidden_field("pathfolder", $path); - - $form_container = new FormContainer($lang->add_multiple_smilies); - $form_container->output_row_header($lang->image, array("class" => "align_center", 'width' => '10%')); - $form_container->output_row_header($lang->name); - $form_container->output_row_header($lang->text_replace, array('width' => '20%')); - $form_container->output_row_header($lang->include, array("class" => "align_center", 'width' => '5%')); - - foreach($smilies as $key => $file) - { - $ext = get_extension($file); - $find = str_replace(".".$ext, "", $file); - $name = ucfirst($find); - - $file = htmlspecialchars_uni($file); - - $form_container->output_cell("\"\"
{$file}", array("class" => "align_center", "width" => 1)); - $form_container->output_cell($form->generate_text_box("name[{$file}]", htmlspecialchars_uni($name), array('id' => 'name', 'style' => 'width: 98%'))); - $form_container->output_cell($form->generate_text_box("find[{$file}]", ":".$find.":", array('id' => 'find', 'style' => 'width: 95%'))); - $form_container->output_cell($form->generate_check_box("include[{$file}]", 1, "", array('checked' => 1)), array("class" => "align_center")); - $form_container->construct_row(); - } - - if($form_container->num_rows() == 0) - { - flash_message($lang->error_no_images, 'error'); - admin_redirect("index.php?module=config-smilies&action=add_multiple"); - } - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_smilies); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); - exit; - } - } - else - { - $plugins->run_hooks("admin_config_smilies_add_multiple_step2"); - - $path = $mybb->input['pathfolder']; - reset($mybb->input['include']); - $find = $mybb->input['find']; - $name = $mybb->input['name']; - - if(empty($mybb->input['include'])) - { - flash_message($lang->error_none_included, 'error'); - admin_redirect("index.php?module=config-smilies&action=add_multiple"); - } - - $query = $db->simple_select('smilies', 'MAX(disporder) as max_disporder'); - $disporder = $db->fetch_field($query, 'max_disporder'); - - foreach($mybb->input['include'] as $image => $insert) - { - $find[$image] = str_replace("\r\n", "\n", $find[$image]); - $find[$image] = str_replace("\r", "\n", $find[$image]); - $find[$image] = explode("\n", $find[$image]); - foreach(array_merge(array_keys($find[$image], ""), array_keys($find[$image], " ")) as $key) - { - unset($find[$image][$key]); - } - $find[$image] = implode("\n", $find[$image]); - - if($insert) - { - $new_smilie = array( - "name" => $db->escape_string($name[$image]), - "find" => $db->escape_string($find[$image]), - "image" => $db->escape_string($path.$image), - "disporder" => ++$disporder, - "showclickable" => 1 - ); - - $db->insert_query("smilies", $new_smilie); - } - } - - $plugins->run_hooks("admin_config_smilies_add_multiple_commit"); - - $cache->update_smilies(); - - // Log admin action - log_admin_action(); - - flash_message($lang->success_multiple_smilies_added, 'success'); - admin_redirect("index.php?module=config-smilies"); - } - } - - $page->add_breadcrumb_item($lang->add_multiple_smilies); - $page->output_header($lang->smilies." - ".$lang->add_multiple_smilies); - - $sub_tabs['manage_smilies'] = array( - 'title' => $lang->manage_smilies, - 'link' => "index.php?module=config-smilies", - ); - $sub_tabs['add_smilie'] = array( - 'title' => $lang->add_smilie, - 'link' => "index.php?module=config-smilies&action=add" - ); - $sub_tabs['add_multiple_smilies'] = array( - 'title' => $lang->add_multiple_smilies, - 'link' => "index.php?module=config-smilies&action=add_multiple", - 'description' => $lang->add_multiple_smilies_desc - ); - $sub_tabs['mass_edit'] = array( - 'title' => $lang->mass_edit, - 'link' => "index.php?module=config-smilies&action=mass_edit" - ); - - $page->output_nav_tabs($sub_tabs, 'add_multiple_smilies'); - $form = new Form("index.php?module=config-smilies&action=add_multiple", "post", "add_multiple"); - echo $form->generate_hidden_field("step", "1"); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer($lang->add_multiple_smilies); - $form_container->output_row($lang->path_to_images, $lang->path_to_images_desc, $form->generate_text_box('pathfolder', $mybb->input['pathfolder'], array('id' => 'pathfolder')), 'pathfolder'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->show_smilies); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "mass_edit") -{ - $plugins->run_hooks("admin_config_smilies_mass_edit"); - - if($mybb->request_method == "post") - { - foreach($mybb->input['name'] as $sid => $name) - { - $disporder = (int)$mybb->input['disporder'][$sid]; - - $sid = (int)$sid; - if($mybb->input['delete'][$sid] == 1) - { - // Dirty hack to get the disporder working. Note: this doesn't work in every case - unset($mybb->input['disporder'][$sid]); - - $db->delete_query("smilies", "sid = '{$sid}'", 1); - } - else - { - $mybb->input['find'][$sid] = str_replace("\r\n", "\n", $mybb->input['find'][$sid]); - $mybb->input['find'][$sid] = str_replace("\r", "\n", $mybb->input['find'][$sid]); - $mybb->input['find'][$sid] = explode("\n", $mybb->input['find'][$sid]); - foreach(array_merge(array_keys($mybb->input['find'][$sid], ""), array_keys($mybb->input['find'][$sid], " ")) as $key) - { - unset($mybb->input['find'][$sid][$key]); - } - $mybb->input['find'][$sid] = implode("\n", $mybb->input['find'][$sid]); - - $smilie = array( - "name" => $db->escape_string($mybb->input['name'][$sid]), - "find" => $db->escape_string($mybb->input['find'][$sid]), - "showclickable" => $db->escape_string($mybb->input['showclickable'][$sid]) - ); - - // $test contains all disporders except the actual one so we can check whether we have multiple disporders - $test = $mybb->input['disporder']; - unset($test[$sid]); - if(!in_array($disporder, $test)) - { - $smilie['disporder'] = $disporder; - } - - $db->update_query("smilies", $smilie, "sid = '{$sid}'"); - } - - $disporder_list[$disporder] = $disporder; - } - - $plugins->run_hooks("admin_config_smilies_mass_edit_commit"); - - $cache->update_smilies(); - - // Log admin action - log_admin_action(); - - flash_message($lang->success_multiple_smilies_updated, 'success'); - admin_redirect("index.php?module=config-smilies"); - } - - $page->add_breadcrumb_item($lang->mass_edit); - $page->output_header($lang->smilies." - ".$lang->mass_edit); - - $sub_tabs['manage_smilies'] = array( - 'title' => $lang->manage_smilies, - 'link' => "index.php?module=config-smilies", - ); - $sub_tabs['add_smilie'] = array( - 'title' => $lang->add_smilie, - 'link' => "index.php?module=config-smilies&action=add", - ); - $sub_tabs['add_multiple_smilies'] = array( - 'title' => $lang->add_multiple_smilies, - 'link' => "index.php?module=config-smilies&action=add_multiple", - ); - $sub_tabs['mass_edit'] = array( - 'title' => $lang->mass_edit, - 'link' => "index.php?module=config-smilies&action=mass_edit", - 'description' => $lang->mass_edit_desc - ); - - $page->output_nav_tabs($sub_tabs, 'mass_edit'); - - $form = new Form("index.php?module=config-smilies&action=mass_edit", "post", "mass_edit"); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['path'] = 'images/smilies/'; - $mybb->input['showclickable'] = 1; - } - - if(!$mybb->input['disporder']) - { - $query = $db->simple_select("smilies", "max(disporder) as dispordermax"); - $mybb->input['disporder'] = $db->fetch_field($query, "dispordermax")+1; - } - - $form_container = new FormContainer($lang->manage_smilies); - $form_container->output_row_header($lang->image, array("class" => "align_center", 'width' => '1')); - $form_container->output_row_header($lang->name); - $form_container->output_row_header($lang->text_replace, array('width' => '20%')); - $form_container->output_row_header($lang->order, array('width' => '5%')); - $form_container->output_row_header($lang->mass_edit_show_clickable, array("width" => 165)); - $form_container->output_row_header($lang->smilie_delete, array("class" => "align_center", 'width' => '5%')); - - $query = $db->simple_select("smilies", "*", "", array('order_by' => 'disporder')); - while($smilie = $db->fetch_array($query)) - { - $smilie['image'] = str_replace("{theme}", "images", $smilie['image']); - if(my_validate_url($smilie['image'], true)) - { - $image = htmlspecialchars_uni($smilie['image']); - } - else - { - $image = "../".htmlspecialchars_uni($smilie['image']); - } - - $form_container->output_cell("\"\"", array("class" => "align_center", "width" => 1)); - $form_container->output_cell($form->generate_text_box("name[{$smilie['sid']}]", $smilie['name'], array('id' => 'name', 'style' => 'width: 98%'))); - $form_container->output_cell($form->generate_text_area("find[{$smilie['sid']}]", $smilie['find'], array('id' => 'find', 'style' => 'width: 95%'))); - $form_container->output_cell($form->generate_numeric_field("disporder[{$smilie['sid']}]", $smilie['disporder'], array('id' => 'disporder', 'style' => 'width: 80%', 'min' => 0))); - $form_container->output_cell($form->generate_yes_no_radio("showclickable[{$smilie['sid']}]", $smilie['showclickable']), array("class" => "align_center")); - $form_container->output_cell($form->generate_check_box("delete[{$smilie['sid']}]", 1, $mybb->input['delete']), array("class" => "align_center")); - $form_container->construct_row(); - } - - if($form_container->num_rows() == 0) - { - $form_container->output_cell($lang->no_smilies, array('colspan' => 6)); - $form_container->construct_row(); - } - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_smilies); - $buttons[] = $form->generate_reset_button($lang->reset); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_smilies_start"); - - $page->output_header($lang->manage_smilies); - - $sub_tabs['manage_smilies'] = array( - 'title' => $lang->manage_smilies, - 'link' => "index.php?module=config-smilies", - 'description' => $lang->manage_smilies_desc - ); - $sub_tabs['add_smilie'] = array( - 'title' => $lang->add_smilie, - 'link' => "index.php?module=config-smilies&action=add", - ); - $sub_tabs['add_multiple_smilies'] = array( - 'title' => $lang->add_multiple_smilies, - 'link' => "index.php?module=config-smilies&action=add_multiple", - ); - $sub_tabs['mass_edit'] = array( - 'title' => $lang->mass_edit, - 'link' => "index.php?module=config-smilies&action=mass_edit", - ); - - $page->output_nav_tabs($sub_tabs, 'manage_smilies'); - - $pagenum = $mybb->get_input('page', MyBB::INPUT_INT); - if($pagenum) - { - $start = ($pagenum-1) * 20; - } - else - { - $start = 0; - $pagenum = 1; - } - - - $table = new Table; - $table->construct_header($lang->image, array("class" => "align_center", "width" => 1)); - $table->construct_header($lang->name, array("width" => "35%")); - $table->construct_header($lang->text_replace, array("width" => "35%")); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2)); - - $query = $db->simple_select("smilies", "*", "", array('limit_start' => $start, 'limit' => 20, 'order_by' => 'disporder')); - while($smilie = $db->fetch_array($query)) - { - $smilie['image'] = str_replace("{theme}", "images", $smilie['image']); - if(my_validate_url($smilie['image'], true)) - { - $image = htmlspecialchars_uni($smilie['image']); - } - else - { - $image = "../".htmlspecialchars_uni($smilie['image']); - } - - $table->construct_cell("\"\"", array("class" => "align_center")); - $table->construct_cell(htmlspecialchars_uni($smilie['name'])); - $table->construct_cell(nl2br(htmlspecialchars_uni($smilie['find']))); - - $table->construct_cell("{$lang->edit}", array("class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_smilie_deletion}')\">{$lang->delete}", array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_smilies, array('colspan' => 5)); - $table->construct_row(); - } - - $table->output($lang->manage_smilies); - - $query = $db->simple_select("smilies", "COUNT(sid) as smilies"); - $total_rows = $db->fetch_field($query, "smilies"); - - echo "
".draw_admin_pagination($pagenum, "20", $total_rows, "index.php?module=config-smilies&page={page}"); - - $page->output_footer(); -} \ No newline at end of file diff --git a/html/forums/admin/modules/config/spiders.php b/html/forums/admin/modules/config/spiders.php deleted file mode 100644 index 9a701a4..0000000 --- a/html/forums/admin/modules/config/spiders.php +++ /dev/null @@ -1,307 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->spiders_bots, "index.php?module=config-spiders"); - -$plugins->run_hooks("admin_config_spiders_begin"); - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_config_spiders_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - - if(!trim($mybb->input['useragent'])) - { - $errors[] = $lang->error_missing_agent; - } - - if(!$errors) - { - $new_spider = array( - "name" => $db->escape_string($mybb->input['name']), - "theme" => $mybb->get_input('theme', MyBB::INPUT_INT), - "language" => $db->escape_string($mybb->input['language']), - "usergroup" => $mybb->get_input('usergroup', MyBB::INPUT_INT), - "useragent" => $db->escape_string($mybb->input['useragent']), - "lastvisit" => 0 - ); - $sid = $db->insert_query("spiders", $new_spider); - - $plugins->run_hooks("admin_config_spiders_add_commit"); - - $cache->update_spiders(); - - // Log admin action - log_admin_action($sid, $mybb->input['name']); - - flash_message($lang->success_bot_created, 'success'); - admin_redirect("index.php?module=config-spiders"); - } - } - - $page->add_breadcrumb_item($lang->add_new_bot); - $page->output_header($lang->spiders_bots." - ".$lang->add_new_bot); - - $sub_tabs['spiders'] = array( - 'title' => $lang->spiders_bots, - 'link' => "index.php?module=config-spiders", - ); - $sub_tabs['add_spider'] = array( - 'title' => $lang->add_new_bot, - 'link' => "index.php?module=config-spiders&action=add", - 'description' => $lang->add_new_bot_desc - ); - - $page->output_nav_tabs($sub_tabs, "add_spider"); - - $form = new Form("index.php?module=config-spiders&action=add", "post"); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer($lang->add_new_bot); - $form_container->output_row($lang->name." *", $lang->name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->user_agent." *", $lang->user_agent_desc, $form->generate_text_box('useragent', $mybb->input['useragent'], array('id' => 'useragent')), 'useragent'); - - $languages = array('' => $lang->use_board_default); - $languages = array_merge($languages, $lang->get_languages()); - $form_container->output_row($lang->language_str, $lang->language_desc, $form->generate_select_box("language", $languages, $mybb->input['language'], array("id" => "language")), 'language'); - - $form_container->output_row($lang->theme, $lang->theme_desc, build_theme_select("theme", $mybb->input['theme'], 0, "", true, false, true)); - - $query = $db->simple_select("usergroups", "*", "", array("order_by" => "title", "order_dir" => "asc")); - - $usergroups = array(); - while($usergroup = $db->fetch_array($query)) - { - $usergroups[$usergroup['gid']] = $usergroup['title']; - } - if(!$mybb->input['usergroup']) - { - $mybb->input['usergroup'] = 1; - } - $form_container->output_row($lang->user_group, $lang->user_group_desc, $form->generate_select_box("usergroup", $usergroups, $mybb->input['usergroup'], array("id" => "usergroup")), 'usergroup'); - - - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->save_bot); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("spiders", "*", "sid='".$mybb->get_input('sid', MyBB::INPUT_INT)."'"); - $spider = $db->fetch_array($query); - - // Does the spider not exist? - if(!$spider['sid']) - { - flash_message($lang->error_invalid_bot, 'error'); - admin_redirect("index.php?module=config-spiders"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-spiders"); - } - - $plugins->run_hooks("admin_config_spiders_delete"); - - if($mybb->request_method == "post") - { - // Delete the spider - $db->delete_query("spiders", "sid='{$spider['sid']}'"); - - $plugins->run_hooks("admin_config_spiders_delete_commit"); - - $cache->update_spiders(); - - // Log admin action - log_admin_action($spider['sid'], $spider['name']); - - flash_message($lang->success_bot_deleted, 'success'); - admin_redirect("index.php?module=config-spiders"); - } - else - { - $page->output_confirm_action("index.php?module=config-spiders&action=delete&sid={$spider['sid']}", $lang->confirm_bot_deletion); - } -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("spiders", "*", "sid='".$mybb->get_input('sid', MyBB::INPUT_INT)."'"); - $spider = $db->fetch_array($query); - - // Does the spider not exist? - if(!$spider['sid']) - { - flash_message($lang->error_invalid_bot, 'error'); - admin_redirect("index.php?module=config-spiders"); - } - - $plugins->run_hooks("admin_config_spiders_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['name'])) - { - $errors[] = $lang->error_missing_name; - } - - if(!trim($mybb->input['useragent'])) - { - $errors[] = $lang->error_missing_agent; - } - - if(!$errors) - { - $updated_spider = array( - "name" => $db->escape_string($mybb->input['name']), - "theme" => $mybb->get_input('theme', MyBB::INPUT_INT), - "language" => $db->escape_string($mybb->input['language']), - "usergroup" => $mybb->get_input('usergroup', MyBB::INPUT_INT), - "useragent" => $db->escape_string($mybb->input['useragent']) - ); - - $plugins->run_hooks("admin_config_spiders_edit_commit"); - - $db->update_query("spiders", $updated_spider, "sid='{$spider['sid']}'"); - - $cache->update_spiders(); - - // Log admin action - log_admin_action($spider['sid'], $mybb->input['name']); - - flash_message($lang->success_bot_updated, 'success'); - admin_redirect("index.php?module=config-spiders"); - } - } - - $page->add_breadcrumb_item($lang->edit_bot); - $page->output_header($lang->spiders_bots." - ".$lang->edit_bot); - - $sub_tabs['edit_spider'] = array( - 'title' => $lang->edit_bot, - 'link' => "index.php?module=config-spiders&action=edit&sid={$spider['sid']}", - 'description' => $lang->edit_bot_desc - ); - - $page->output_nav_tabs($sub_tabs, "edit_spider"); - - $form = new Form("index.php?module=config-spiders&action=edit&sid={$spider['sid']}", "post"); - - if($errors) - { - $page->output_inline_error($errors); - $spider_data = $mybb->input; - } - else - { - $spider_data = $spider; - } - - $form_container = new FormContainer($lang->edit_bot); - $form_container->output_row($lang->name." *", $lang->name_desc, $form->generate_text_box('name', $spider_data['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->user_agent." *", $lang->user_agent_desc, $form->generate_text_box('useragent', $spider_data['useragent'], array('id' => 'useragent')), 'useragent'); - - $languages = array('' => $lang->use_board_default); - $languages = array_merge($languages, $lang->get_languages()); - $form_container->output_row($lang->language_str, $lang->language_desc, $form->generate_select_box("language", $languages, $spider_data['language'], array("id" => "language")), 'language'); - - $form_container->output_row($lang->theme, $lang->theme_desc, build_theme_select("theme", $spider_data['theme'], 0, "", true, false, true)); - - $query = $db->simple_select("usergroups", "*", "", array("order_by" => "title", "order_dir" => "asc")); - while($usergroup = $db->fetch_array($query)) - { - $usergroups[$usergroup['gid']] = $usergroup['title']; - } - if(!$spider_data['usergroup']) - { - $spider_data['usergroup'] = 1; - } - $form_container->output_row($lang->user_group, $lang->user_group_desc, $form->generate_select_box("usergroup", $usergroups, $spider_data['usergroup'], array("id" => "usergroup")), 'usergroup'); - - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->save_bot); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_spiders_start"); - - $page->output_header($lang->spiders_bots); - - $sub_tabs['spiders'] = array( - 'title' => $lang->spiders_bots, - 'link' => "index.php?module=config-spiders", - 'description' => $lang->spiders_bots_desc - ); - $sub_tabs['add_spider'] = array( - 'title' => $lang->add_new_bot, - 'link' => "index.php?module=config-spiders&action=add" - ); - - $page->output_nav_tabs($sub_tabs, "spiders"); - - $table = new Table; - $table->construct_header($lang->bot); - $table->construct_header($lang->last_visit, array("class" => "align_center", "width" => 200)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150, "colspan" => 2)); - - $query = $db->simple_select("spiders", "*", "", array("order_by" => "lastvisit", "order_dir" => "desc")); - while($spider = $db->fetch_array($query)) - { - $lastvisit = $lang->never; - $spider['name'] = htmlspecialchars_uni($spider['name']); - - if($spider['lastvisit']) - { - $lastvisit = my_date('relative', $spider['lastvisit']); - } - - $table->construct_cell("{$spider['name']}"); - $table->construct_cell($lastvisit, array("class" => "align_center", "width" => 200)); - $table->construct_cell("{$lang->edit}", array("class" => "align_center", "width" => 75)); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_bot_deletion}');\">{$lang->delete}", array("class" => "align_center", "width" => 75)); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_bots, array("colspan" => 4)); - $table->construct_row(); - } - - $table->output($lang->spiders_bots); - $page->output_footer(); -} diff --git a/html/forums/admin/modules/config/thread_prefixes.php b/html/forums/admin/modules/config/thread_prefixes.php deleted file mode 100644 index 9d1e9a2..0000000 --- a/html/forums/admin/modules/config/thread_prefixes.php +++ /dev/null @@ -1,536 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->thread_prefixes, 'index.php?module=config-thread_prefixes'); - -$sub_tabs = array( - "thread_prefixes" => array( - 'title' => $lang->thread_prefixes, - 'link' => 'index.php?module=config-thread_prefixes', - 'description' => $lang->thread_prefixes_desc - ), - "add_prefix" => array( - 'title'=> $lang->add_new_thread_prefix, - 'link' => 'index.php?module=config-thread_prefixes&action=add_prefix', - 'description' => $lang->add_new_thread_prefix_desc - ) -); - -$plugins->run_hooks('admin_config_thread_prefixes_begin'); - -if($mybb->input['action'] == 'add_prefix') -{ - $plugins->run_hooks('admin_config_thread_prefixes_add_prefix'); - - if($mybb->request_method == 'post') - { - if(trim($mybb->input['prefix']) == '') - { - $errors[] = $lang->error_missing_prefix; - } - - if(trim($mybb->input['displaystyle']) == '') - { - $errors[] = $lang->error_missing_display_style; - } - - if($mybb->input['forum_type'] == 2) - { - if(count($mybb->input['forum_1_forums']) < 1) - { - $errors[] = $lang->error_no_forums_selected; - } - - $forum_checked[2] = "checked=\"checked\""; - } - else - { - $forum_checked[1] = "checked=\"checked\""; - $mybb->input['forum_1_forums'] = ''; - } - - if($mybb->input['group_type'] == 2) - { - if(count($mybb->input['group_1_groups']) < 1) - { - $errors[] = $lang->error_no_groups_selected; - } - - $group_checked[2] = "checked=\"checked\""; - } - else - { - $group_checked[1] = "checked=\"checked\""; - $mybb->input['group_1_forums'] = ''; - } - - if(!$errors) - { - $new_prefix = array( - 'prefix' => $db->escape_string($mybb->input['prefix']), - 'displaystyle' => $db->escape_string($mybb->input['displaystyle']) - ); - - if($mybb->input['forum_type'] == 2) - { - if(is_array($mybb->input['forum_1_forums'])) - { - $checked = array(); - foreach($mybb->input['forum_1_forums'] as $fid) - { - $checked[] = (int)$fid; - } - - $new_prefix['forums'] = implode(',', $checked); - } - } - else - { - $new_prefix['forums'] = '-1'; - } - - if($mybb->input['group_type'] == 2) - { - if(is_array($mybb->input['group_1_groups'])) - { - $checked = array(); - foreach($mybb->input['group_1_groups'] as $gid) - { - $checked[] = (int)$gid; - } - - $new_prefix['groups'] = implode(',', $checked); - } - } - else - { - $new_prefix['groups'] = '-1'; - } - - $pid = $db->insert_query('threadprefixes', $new_prefix); - - $plugins->run_hooks('admin_config_thread_prefixes_add_prefix_commit'); - - // Log admin action - log_admin_action($pid, htmlspecialchars_uni($mybb->input['prefix'])); - $cache->update_threadprefixes(); - - flash_message($lang->success_thread_prefix_created, 'success'); - admin_redirect('index.php?module=config-thread_prefixes'); - } - } - - $page->add_breadcrumb_item($lang->add_new_thread_prefix); - $page->output_header($lang->thread_prefixes." - ".$lang->add_new_thread_prefix); - $page->output_nav_tabs($sub_tabs, 'add_prefix'); - - $form = new Form('index.php?module=config-thread_prefixes&action=add_prefix', 'post'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['prefix'] = ''; - $mybb->input['displaystyle'] = ''; - $mybb->input['forum_1_forums'] = ''; - $forum_checked[1] = "checked=\"checked\""; - $forum_checked[2] = ''; - $mybb->input['group_1_groups'] = ''; - $group_checked[1] = "checked=\"checked\""; - $group_checked[2] = ''; - } - - $form_container = new FormContainer($lang->prefix_options); - $form_container->output_row($lang->prefix.' *', $lang->prefix_desc, $form->generate_text_box('prefix', $mybb->input['prefix'], array('id' => 'prefix')), 'prefix'); - $form_container->output_row($lang->display_style.' *', $lang->display_style_desc, $form->generate_text_box('displaystyle', $mybb->input['displaystyle'], array('id' => 'displaystyle')), 'displaystyle'); - - $actions = " -
-
-
-
- - - - - -
{$lang->forums_colon}".$form->generate_forum_select('forum_1_forums[]', $mybb->input['forum_1_forums'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_in_forums.' *', '', $actions); - - $group_select = " -
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('group_1_groups[]', $mybb->input['group_1_groups'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_to_groups." *", '', $group_select); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_thread_prefix); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == 'edit_prefix') -{ - $prefix = build_prefixes($mybb->input['pid']); - if(empty($prefix['pid'])) - { - flash_message($lang->error_invalid_prefix, 'error'); - admin_redirect('index.php?module=config-thread_prefixes'); - } - - $plugins->run_hooks('admin_config_thread_prefixes_edit_prefix_start'); - - if($mybb->request_method == 'post') - { - if(trim($mybb->input['prefix']) == '') - { - $errors[] = $lang->error_missing_prefix; - } - - if(trim($mybb->input['displaystyle']) == '') - { - $errors[] = $lang->error_missing_display_style; - } - - if($mybb->input['forum_type'] == 2) - { - if(count($mybb->input['forum_1_forums']) < 1) - { - $errors[] = $lang->error_no_forums_selected; - } - - $forum_checked[2] = "checked=\"checked\""; - } - else - { - $forum_checked[1] = "checked=\"checked\""; - $mybb->input['forum_1_forums'] = ''; - } - - if($mybb->input['group_type'] == 2) - { - if(count($mybb->input['group_1_groups']) < 1) - { - $errors[] = $lang->error_no_groups_selected; - } - - $group_checked[2] = "checked=\"checked\""; - } - else - { - $group_checked[1] = "checked=\"checked\""; - $mybb->input['group_1_forums'] = ''; - } - - if(!$errors) - { - $update_prefix = array( - 'prefix' => $db->escape_string($mybb->input['prefix']), - 'displaystyle' => $db->escape_string($mybb->input['displaystyle']) - ); - - if($mybb->input['forum_type'] == 2) - { - if(is_array($mybb->input['forum_1_forums'])) - { - $checked = array(); - foreach($mybb->input['forum_1_forums'] as $fid) - { - $checked[] = (int)$fid; - } - - $update_prefix['forums'] = implode(',', $checked); - } - } - else - { - $update_prefix['forums'] = '-1'; - } - - if($mybb->input['group_type'] == 2) - { - if(is_array($mybb->input['group_1_groups'])) - { - $checked = array(); - foreach($mybb->input['group_1_groups'] as $gid) - { - $checked[] = (int)$gid; - } - - $update_prefix['groups'] = implode(',', $checked); - } - } - else - { - $update_prefix['groups'] = '-1'; - } - - $plugins->run_hooks('admin_config_thread_prefixes_edit_prefix_commit'); - - $db->update_query('threadprefixes', $update_prefix, "pid='{$prefix['pid']}'"); - - // Log admin action - log_admin_action($prefix['pid'], htmlspecialchars_uni($mybb->input['prefix'])); - $cache->update_threadprefixes(); - - flash_message($lang->success_thread_prefix_updated, 'success'); - admin_redirect('index.php?module=config-thread_prefixes'); - } - } - - $page->add_breadcrumb_item($lang->edit_thread_prefix); - $page->output_header($lang->thread_prefixes.' - '.$lang->edit_thread_prefix); - - // Setup the edit prefix tab - unset($sub_tabs); - $sub_tabs['edit_prefix'] = array( - "title" => $lang->edit_prefix, - "link" => "index.php?module=config-thread_prefixes", - "description" => $lang->edit_prefix_desc - ); - $page->output_nav_tabs($sub_tabs, "edit_prefix"); - - $form = new Form('index.php?module=config-thread_prefixes&action=edit_prefix', 'post'); - echo $form->generate_hidden_field('pid', $prefix['pid']); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $query = $db->simple_select('threadprefixes', '*', "pid = '{$prefix['pid']}'"); - $threadprefix = $db->fetch_array($query); - - $mybb->input['prefix'] = $threadprefix['prefix']; - $mybb->input['displaystyle'] = $threadprefix['displaystyle']; - $mybb->input['forum_1_forums'] = explode(",", $threadprefix['forums']); - - if(!$threadprefix['forums'] || $threadprefix['forums'] == -1) - { - $forum_checked[1] = "checked=\"checked\""; - $forum_checked[2] = ''; - } - else - { - $forum_checked[1] = ''; - $forum_checked[2] = "checked=\"checked\""; - } - - $mybb->input['group_1_groups'] = explode(",", $threadprefix['groups']); - - if(!$threadprefix['groups'] || $threadprefix['groups'] == -1) - { - $group_checked[1] = "checked=\"checked\""; - $group_checked[2] = ''; - } - else - { - $group_checked[1] = ''; - $group_checked[2] = "checked=\"checked\""; - } - } - - $form_container = new FormContainer($lang->prefix_options); - $form_container->output_row($lang->prefix.' *', $lang->prefix_desc, $form->generate_text_box('prefix', $mybb->input['prefix'], array('id' => 'prefix')), 'prefix'); - $form_container->output_row($lang->display_style.' *', $lang->display_style_desc, $form->generate_text_box('displaystyle', $mybb->input['displaystyle'], array('id' => 'displaystyle')), 'displaystyle'); - - $actions = " -
-
-
-
- - - - - -
{$lang->forums_colon}".$form->generate_forum_select('forum_1_forums[]', $mybb->input['forum_1_forums'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_in_forums.' *', '', $actions); - - $group_select = " -
-
-
-
- - - - - -
{$lang->groups_colon}".$form->generate_group_select('group_1_groups[]', $mybb->input['group_1_groups'], array('multiple' => true, 'size' => 5))."
-
-
- "; - $form_container->output_row($lang->available_to_groups." *", '', $group_select); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_thread_prefix); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == 'delete_prefix') -{ - $prefix = build_prefixes($mybb->input['pid']); - if(empty($prefix['pid'])) - { - flash_message($lang->error_invalid_thread_prefix, 'error'); - admin_redirect('index.php?module=config-thread_prefixes'); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect('index.php?module=config-thread_prefixes'); - } - - $plugins->run_hooks('admin_config_thread_prefixes_delete_prefix'); - - if($mybb->request_method == 'post') - { - // Remove prefix from existing threads - $update_threads = array('prefix' => 0); - - // Delete prefix - $db->delete_query('threadprefixes', "pid='{$prefix['pid']}'"); - - $plugins->run_hooks('admin_config_thread_prefixes_delete_thread_prefix_commit'); - - $db->update_query('threads', $update_threads, "prefix='{$prefix['pid']}'"); - - // Log admin action - log_admin_action($prefix['pid'], htmlspecialchars_uni($prefix['prefix'])); - $cache->update_threadprefixes(); - - flash_message($lang->success_thread_prefix_deleted, 'success'); - admin_redirect('index.php?module=config-thread_prefixes'); - } - else - { - $page->output_confirm_action("index.php?module=config-thread_prefixes&action=delete_prefix&pid={$prefix['pid']}", $lang->confirm_thread_prefix_deletion); - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks('admin_config_thread_prefixes_start'); - - $page->output_header($lang->thread_prefixes); - $page->output_nav_tabs($sub_tabs, 'thread_prefixes'); - - $table = new Table; - $table->construct_header($lang->prefix); - $table->construct_header($lang->controls, array('class' => 'align_center', 'colspan' => 2)); - - $prefixes = build_prefixes(); - if(!empty($prefixes)) - { - foreach($prefixes as $prefix) - { - $table->construct_cell("".htmlspecialchars_uni($prefix['prefix']).""); - $table->construct_cell("{$lang->edit}", array('width' => 100, 'class' => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_thread_prefix_deletion}')\">{$lang->delete}", array('width' => 100, 'class' => 'align_center')); - $table->construct_row(); - } - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_thread_prefixes, array('colspan' => 3)); - $table->construct_row(); - } - - $table->output($lang->thread_prefixes); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/config/warning.php b/html/forums/admin/modules/config/warning.php deleted file mode 100644 index 1e4b911..0000000 --- a/html/forums/admin/modules/config/warning.php +++ /dev/null @@ -1,774 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -require_once MYBB_ROOT."inc/functions_warnings.php"; - -$page->add_breadcrumb_item($lang->warning_system, "index.php?module=config-warning"); - -if($mybb->input['action'] == "levels" || $mybb->input['action'] == "add_type" || $mybb->input['action'] == "add_level" || !$mybb->input['action']) -{ - $sub_tabs['manage_types'] = array( - 'title' => $lang->warning_types, - 'link' => "index.php?module=config-warning", - 'description' => $lang->warning_types_desc - ); - $sub_tabs['add_type'] = array( - 'title'=> $lang->add_warning_type, - 'link' => "index.php?module=config-warning&action=add_type", - 'description' => $lang->add_warning_type_desc - ); - $sub_tabs['manage_levels'] = array( - 'title' => $lang->warning_levels, - 'link' => "index.php?module=config-warning&action=levels", - 'description' => $lang->warning_levels_desc, - ); - $sub_tabs['add_level'] = array( - 'title'=> $lang->add_warning_level, - 'link' => "index.php?module=config-warning&action=add_level", - 'description' => $lang->add_warning_level_desc - ); -} - -$plugins->run_hooks("admin_config_warning_begin"); - -if($mybb->input['action'] == "add_level") -{ - $plugins->run_hooks("admin_config_warning_add_level"); - - if($mybb->request_method == "post") - { - if(!is_numeric($mybb->input['percentage']) || $mybb->input['percentage'] > 100 || $mybb->input['percentage'] < 0) - { - $errors[] = $lang->error_invalid_warning_percentage; - } - - if(!$mybb->input['action_type']) - { - $errors[] = $lang->error_missing_action_type; - } - - if(!$errors) - { - // Ban - if($mybb->input['action_type'] == 1) - { - $action = array( - "type" => 1, - "usergroup" => $mybb->get_input('action_1_usergroup', MyBB::INPUT_INT), - "length" => fetch_time_length($mybb->input['action_1_time'], $mybb->input['action_1_period']) - ); - } - // Suspend posting - else if($mybb->input['action_type'] == 2) - { - $action = array( - "type" => 2, - "length" => fetch_time_length($mybb->input['action_2_time'], $mybb->input['action_2_period']) - ); - } - // Moderate posts - else if($mybb->input['action_type'] == 3) - { - $action = array( - "type" => 3, - "length" => fetch_time_length($mybb->input['action_3_time'], $mybb->input['action_3_period']) - ); - } - $new_level = array( - "percentage" => $mybb->get_input('percentage', MyBB::INPUT_INT), - "action" => my_serialize($action) - ); - - $lid = $db->insert_query("warninglevels", $new_level); - - $plugins->run_hooks("admin_config_warning_add_level_commit"); - - // Log admin action - log_admin_action($lid, $mybb->input['percentage']); - - flash_message($lang->success_warning_level_created, 'success'); - admin_redirect("index.php?module=config-warning&action=levels"); - } - } - - $page->add_breadcrumb_item($lang->add_warning_level); - $page->output_header($lang->warning_levels." - ".$lang->add_warning_level); - - $page->output_nav_tabs($sub_tabs, 'add_level'); - $form = new Form("index.php?module=config-warning&action=add_level", "post"); - - - if($errors) - { - $page->output_inline_error($errors); - $action_checked[$mybb->input['action_type']] = "checked=\"checked\""; - } - - $form_container = new FormContainer($lang->add_warning_level); - $form_container->output_row($lang->warning_points_percentage, $lang->warning_points_percentage_desc, $form->generate_numeric_field('percentage', $mybb->input['percentage'], array('id' => 'percentage', 'min' => 0, 'max' => 100)), 'percentage'); - - $query = $db->simple_select("usergroups", "*", "isbannedgroup=1"); - while($group = $db->fetch_array($query)) - { - $banned_groups[$group['gid']] = $group['title']; - } - - $periods = array( - "hours" => $lang->expiration_hours, - "days" => $lang->expiration_days, - "weeks" => $lang->expiration_weeks, - "months" => $lang->expiration_months, - "never" => $lang->expiration_permanent - ); - - $actions = " -
-
-
- - - - - - - - - -
{$lang->banned_group}".$form->generate_select_box('action_1_usergroup', $banned_groups, $mybb->input['action_1_usergroup'])."
{$lang->ban_length}".$form->generate_numeric_field('action_1_time', $mybb->input['action_1_time'], array('style' => 'width: 3em;', 'min' => 0))." ".$form->generate_select_box('action_1_period', $periods, $mybb->input['action_1_period'])."
-
-
-
- - - - - -
{$lang->suspension_length}".$form->generate_numeric_field('action_2_time', $mybb->input['action_2_time'], array('style' => 'width: 3em;', 'min' => 0))." ".$form->generate_select_box('action_2_period', $periods, $mybb->input['action_2_period'])."
-
-
-
- - - - - -
{$lang->moderation_length}".$form->generate_numeric_field('action_3_time', $mybb->input['action_3_time'], array('style' => 'width: 3em;', 'min' => 0))." ".$form->generate_select_box('action_3_period', $periods, $mybb->input['action_3_period'])."
-
-
- "; - $form_container->output_row($lang->action_to_be_taken, $lang->action_to_be_taken_desc, $actions); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_warning_level); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit_level") -{ - $query = $db->simple_select("warninglevels", "*", "lid='".$mybb->get_input('lid', MyBB::INPUT_INT)."'"); - $level = $db->fetch_array($query); - - // Does the warning level not exist? - if(!$level['lid']) - { - flash_message($lang->error_invalid_warning_level, 'error'); - admin_redirect("index.php?module=config-warning"); - } - - $plugins->run_hooks("admin_config_warning_edit_level"); - - if($mybb->request_method == "post") - { - if(!is_numeric($mybb->input['percentage']) || $mybb->input['percentage'] > 100 || $mybb->input['percentage'] < 0) - { - $errors[] = $lang->error_invalid_warning_percentage; - } - - if(!$mybb->input['action_type']) - { - $errors[] = $lang->error_missing_action_type; - } - - if(!$errors) - { - // Ban - if($mybb->input['action_type'] == 1) - { - $action = array( - "type" => 1, - "usergroup" => $mybb->get_input('action_1_usergroup', MyBB::INPUT_INT), - "length" => fetch_time_length($mybb->input['action_1_time'], $mybb->input['action_1_period']) - ); - } - // Suspend posting - else if($mybb->input['action_type'] == 2) - { - $action = array( - "type" => 2, - "length" => fetch_time_length($mybb->input['action_2_time'], $mybb->input['action_2_period']) - ); - } - // Moderate posts - else if($mybb->input['action_type'] == 3) - { - $action = array( - "type" => 3, - "length" => fetch_time_length($mybb->input['action_3_time'], $mybb->input['action_3_period']) - ); - } - $updated_level = array( - "percentage" => $mybb->get_input('percentage', MyBB::INPUT_INT), - "action" => my_serialize($action) - ); - - $plugins->run_hooks("admin_config_warning_edit_level_commit"); - - $db->update_query("warninglevels", $updated_level, "lid='{$level['lid']}'"); - - // Log admin action - log_admin_action($level['lid'], $mybb->input['percentage']); - - flash_message($lang->success_warning_level_updated, 'success'); - admin_redirect("index.php?module=config-warning&action=levels"); - } - } - - $page->add_breadcrumb_item($lang->edit_warning_level); - $page->output_header($lang->warning_levels." - ".$lang->edit_warning_level); - - $sub_tabs['edit_level'] = array( - 'link' => "index.php?module=config-warning&action=edit_level&lid={$level['lid']}", - 'title' => $lang->edit_warning_level, - 'description' => $lang->edit_warning_level_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_level'); - $form = new Form("index.php?module=config-warning&action=edit_level&lid={$level['lid']}", "post"); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = array_merge($mybb->input, array( - "percentage" => $level['percentage'], - ) - ); - $action = my_unserialize($level['action']); - if($action['type'] == 1) - { - $mybb->input['action_1_usergroup'] = $action['usergroup']; - $length = fetch_friendly_expiration($action['length']); - $mybb->input['action_1_time'] = $length['time']; - $mybb->input['action_1_period'] = $length['period']; - } - else if($action['type'] == 2) - { - $length = fetch_friendly_expiration($action['length']); - $mybb->input['action_2_time'] = $length['time']; - $mybb->input['action_2_period'] = $length['period']; - } - else if($action['type'] == 3) - { - $length = fetch_friendly_expiration($action['length']); - $mybb->input['action_3_time'] = $length['time']; - $mybb->input['action_3_period'] = $length['period']; - } - $action_checked[$action['type']] = "checked=\"checked\""; - } - - $form_container = new FormContainer($lang->edit_warning_level); - $form_container->output_row($lang->warning_points_percentage, $lang->warning_points_percentage_desc, $form->generate_numeric_field('percentage', $mybb->input['percentage'], array('id' => 'percentage', 'min' => 0, 'max' => 100)), 'percentage'); - - $query = $db->simple_select("usergroups", "*", "isbannedgroup=1"); - while($group = $db->fetch_array($query)) - { - $banned_groups[$group['gid']] = $group['title']; - } - - $periods = array( - "hours" => $lang->expiration_hours, - "days" => $lang->expiration_days, - "weeks" => $lang->expiration_weeks, - "months" => $lang->expiration_months, - "never" => $lang->expiration_permanent - ); - - $actions = " -
-
-
- - - - - - - - - -
{$lang->banned_group}".$form->generate_select_box('action_1_usergroup', $banned_groups, $mybb->input['action_1_usergroup'])."
{$lang->ban_length}".$form->generate_numeric_field('action_1_time', $mybb->input['action_1_time'], array('style' => 'width: 3em;', 'min' => 0))." ".$form->generate_select_box('action_1_period', $periods, $mybb->input['action_1_period'])."
-
-
-
- - - - - -
{$lang->suspension_length}".$form->generate_numeric_field('action_2_time', $mybb->input['action_2_time'], array('style' => 'width: 3em;', 'min' => 0))." ".$form->generate_select_box('action_2_period', $periods, $mybb->input['action_2_period'])."
-
-
-
- - - - - -
{$lang->moderation_length}".$form->generate_numeric_field('action_3_time', $mybb->input['action_3_time'], array('style' => 'width: 3em;', 'min' => 0))." ".$form->generate_select_box('action_3_period', $periods, $mybb->input['action_3_period'])."
-
-
- "; - $form_container->output_row($lang->action_to_be_taken, $lang->action_to_be_taken_desc, $actions); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_warning_level); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete_level") -{ - $query = $db->simple_select("warninglevels", "*", "lid='".$mybb->get_input('lid', MyBB::INPUT_INT)."'"); - $level = $db->fetch_array($query); - - // Does the warning level not exist? - if(!$level['lid']) - { - flash_message($lang->error_invalid_warning_level, 'error'); - admin_redirect("index.php?module=config-warning"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-warning"); - } - - $plugins->run_hooks("admin_config_warning_delete_level"); - - if($mybb->request_method == "post") - { - // Delete the level - $db->delete_query("warninglevels", "lid='{$level['lid']}'"); - - $plugins->run_hooks("admin_config_warning_delete_level_commit"); - - // Log admin action - log_admin_action($level['lid'], $level['percentage']); - - flash_message($lang->success_warning_level_deleted, 'success'); - admin_redirect("index.php?module=config-warning"); - } - else - { - $page->output_confirm_action("index.php?module=config-warning&action=delete_level&lid={$level['lid']}", $lang->confirm_warning_level_deletion); - } -} - -if($mybb->input['action'] == "add_type") -{ - $plugins->run_hooks("admin_config_warning_add_type"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_type_title; - } - - if(!is_numeric($mybb->input['points']) || $mybb->input['points'] > $mybb->settings['maxwarningpoints'] || $mybb->input['points'] <= 0) - { - $errors[] = $lang->sprintf($lang->error_missing_type_points, $mybb->settings['maxwarningpoints']); - } - - if(!$errors) - { - $new_type = array( - "title" => $db->escape_string($mybb->input['title']), - "points" => $mybb->get_input('points', MyBB::INPUT_INT), - "expirationtime" => fetch_time_length($mybb->input['expire_time'], $mybb->input['expire_period']) - ); - - $tid = $db->insert_query("warningtypes", $new_type); - - $plugins->run_hooks("admin_config_warning_add_type_commit"); - - // Log admin action - log_admin_action($tid, $mybb->input['title']); - - flash_message($lang->success_warning_type_created, 'success'); - admin_redirect("index.php?module=config-warning"); - } - } - else - { - $mybb->input = array_merge($mybb->input, array( - "points" => "2", - "expire_time" => 1, - "expire_period" => "days" - ) - ); - } - - $page->add_breadcrumb_item($lang->add_warning_type); - $page->output_header($lang->warning_types." - ".$lang->add_warning_type); - - $page->output_nav_tabs($sub_tabs, 'add_type'); - $form = new Form("index.php?module=config-warning&action=add_type", "post"); - - - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer($lang->add_warning_type); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->points_to_add." *", $lang->points_to_add_desc, $form->generate_numeric_field('points', $mybb->input['points'], array('id' => 'points', 'min' => 0, 'max' => $mybb->settings['maxwarningpoints'])), 'points'); - $expiration_periods = array( - "hours" => $lang->expiration_hours, - "days" => $lang->expiration_days, - "weeks" => $lang->expiration_weeks, - "months" => $lang->expiration_months, - "never" => $lang->expiration_never - ); - $form_container->output_row($lang->warning_expiry, $lang->warning_expiry_desc, $form->generate_numeric_field('expire_time', $mybb->input['expire_time'], array('id' => 'expire_time', 'min' => 0))." ".$form->generate_select_box('expire_period', $expiration_periods, $mybb->input['expire_period'], array('id' => 'expire_period')), 'expire_time'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_warning_type); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit_type") -{ - $query = $db->simple_select("warningtypes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $type = $db->fetch_array($query); - - // Does the warning type not exist? - if(!$type['tid']) - { - flash_message($lang->error_invalid_warning_type, 'error'); - admin_redirect("index.php?module=config-warning"); - } - - $plugins->run_hooks("admin_config_warning_edit_type"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_type_title; - } - - if(!is_numeric($mybb->input['points']) || $mybb->input['points'] > $mybb->settings['maxwarningpoints'] || $mybb->input['points'] < 0) - { - $errors[] = $lang->sprintf($lang->error_missing_type_points, $mybb->settings['maxwarningpoints']); - } - - if(!$errors) - { - $updated_type = array( - "title" => $db->escape_string($mybb->input['title']), - "points" => $mybb->get_input('points', MyBB::INPUT_INT), - "expirationtime" => fetch_time_length($mybb->input['expire_time'], $mybb->input['expire_period']) - ); - - $plugins->run_hooks("admin_config_warning_edit_type_commit"); - - $db->update_query("warningtypes", $updated_type, "tid='{$type['tid']}'"); - - // Log admin action - log_admin_action($type['tid'], $mybb->input['title']); - - flash_message($lang->success_warning_type_updated, 'success'); - admin_redirect("index.php?module=config-warning"); - } - } - else - { - $expiration = fetch_friendly_expiration($type['expirationtime']); - $mybb->input = array_merge($mybb->input, array( - "title" => $type['title'], - "points" => $type['points'], - "expire_time" => $expiration['time'], - "expire_period" => $expiration['period'] - ) - ); - } - - $page->add_breadcrumb_item($lang->edit_warning_type); - $page->output_header($lang->warning_types." - ".$lang->edit_warning_type); - - $sub_tabs['edit_type'] = array( - 'link' => "index.php?module=config-warning&action=edit_type&tid={$type['tid']}", - 'title' => $lang->edit_warning_type, - 'description' => $lang->edit_warning_type_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_type'); - $form = new Form("index.php?module=config-warning&action=edit_type&tid={$type['tid']}", "post"); - - - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer($lang->edit_warning_type); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->points_to_add." *", $lang->points_to_add_desc, $form->generate_numeric_field('points', $mybb->input['points'], array('id' => 'points', 'min' => 0, 'max' => $mybb->settings['maxwarningpoints'])), 'points'); - $expiration_periods = array( - "hours" => $lang->expiration_hours, - "days" => $lang->expiration_days, - "weeks" => $lang->expiration_weeks, - "months" => $lang->expiration_months, - "never" => $lang->expiration_never - ); - $form_container->output_row($lang->warning_expiry, $lang->warning_expiry_desc, $form->generate_numeric_field('expire_time', $mybb->input['expire_time'], array('id' => 'expire_time', 'min' => 0))." ".$form->generate_select_box('expire_period', $expiration_periods, $mybb->input['expire_period'], array('id' => 'expire_period')), 'expire_time'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_warning_type); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete_type") -{ - $query = $db->simple_select("warningtypes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $type = $db->fetch_array($query); - - // Does the warning type not exist? - if(!$type['tid']) - { - flash_message($lang->error_invalid_warning_type, 'error'); - admin_redirect("index.php?module=config-warning"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=config-warning"); - } - - $plugins->run_hooks("admin_config_warning_delete_type"); - - if($mybb->request_method == "post") - { - // Delete the type - $db->delete_query("warningtypes", "tid='{$type['tid']}'"); - - $plugins->run_hooks("admin_config_warning_delete_type_commit"); - - // Log admin action - log_admin_action($type['tid'], $type['title']); - - flash_message($lang->success_warning_type_deleted, 'success'); - admin_redirect("index.php?module=config-warning"); - } - else - { - $page->output_confirm_action("index.php?module=config-warning&action=delete_type&tid={$type['tid']}", $lang->confirm_warning_type_deletion); - } -} - -if($mybb->input['action'] == "levels") -{ - $plugins->run_hooks("admin_config_warning_levels"); - - $page->output_header($lang->warning_levels); - - $page->output_nav_tabs($sub_tabs, 'manage_levels'); - - $table = new Table; - $table->construct_header($lang->percentage, array('width' => '5%', 'class' => 'align_center')); - $table->construct_header($lang->action_to_take); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2)); - - $query = $db->simple_select("warninglevels", "*", "", array('order_by' => 'percentage')); - while($level = $db->fetch_array($query)) - { - $table->construct_cell("{$level['percentage']}%", array("class" => "align_center")); - $action = my_unserialize($level['action']); - $period = fetch_friendly_expiration($action['length']); - - // Get the right language for the ban period - $lang_str = "expiration_".$period['period']; - $period_str = $lang->$lang_str; - - if($action['type'] == 1) - { - $type = "move_banned_group"; - $group_name = $groupscache[$action['usergroup']]['title']; - } - elseif($action['type'] == 2) - { - $type = "suspend_posting"; - } - elseif($action['type'] == 3) - { - $type = "moderate_new_posts"; - } - - if($period['period'] == "never") - { - $type .= "_permanent"; - - if($group_name) - { - // Permanently banned? Oh noes... switch group to the first sprintf replacement... - $period['time'] = $group_name; - } - } - - // If this level is permanently in place, then $period_str and $group_name do not apply below... - $type = $lang->sprintf($lang->$type, $period['time'], $period_str, $group_name); - - $table->construct_cell($type); - $table->construct_cell("{$lang->edit}", array("width" => 100, "class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_warning_level_deletion}')\">{$lang->delete}", array("width" => 100, "class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_warning_levels, array('colspan' => 4)); - $table->construct_row(); - $no_results = true; - } - - $table->output($lang->warning_levels); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_config_warning_start"); - - $page->output_header($lang->warning_types); - - $page->output_nav_tabs($sub_tabs, 'manage_types'); - - $table = new Table; - $table->construct_header($lang->warning_type); - $table->construct_header($lang->points, array('width' => '5%', 'class' => 'align_center')); - $table->construct_header($lang->expires_after, array('width' => '25%', 'class' => 'align_center')); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2)); - - $query = $db->simple_select("warningtypes", "*", "", array('order_by' => 'title')); - while($type = $db->fetch_array($query)) - { - $type['name'] = htmlspecialchars_uni($type['title']); - $table->construct_cell("{$type['title']}"); - $table->construct_cell("{$type['points']}", array("class" => "align_center")); - $expiration = fetch_friendly_expiration($type['expirationtime']); - $lang_str = "expiration_".$expiration['period']; - if($type['expirationtime'] > 0) - { - $table->construct_cell("{$expiration['time']} {$lang->$lang_str}", array("class" => "align_center")); - } - else - { - $table->construct_cell($lang->never, array("class" => "align_center")); - } - $table->construct_cell("{$lang->edit}", array("width" => 100, "class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_warning_type_deletion}')\">{$lang->delete}", array("width" => 100, "class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_warning_types, array('colspan' => 5)); - $table->construct_row(); - $no_results = true; - } - - $table->output($lang->warning_types); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/forum/announcements.php b/html/forums/admin/modules/forum/announcements.php deleted file mode 100644 index 2393f33..0000000 --- a/html/forums/admin/modules/forum/announcements.php +++ /dev/null @@ -1,952 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->forum_announcements, "index.php?module=forum-announcements"); - -if($mybb->input['action'] == "add" || !$mybb->input['action']) -{ - $sub_tabs['forum_announcements'] = array( - 'title' => $lang->forum_announcements, - 'link' => "index.php?module=forum-announcements", - 'description' => $lang->forum_announcements_desc - ); - - $sub_tabs['add_announcement'] = array( - 'title' => $lang->add_announcement, - 'link' => "index.php?module=forum-announcements&action=add", - 'description' => $lang->add_announcement_desc - ); -} -else if($mybb->input['action'] == "edit") -{ - $sub_tabs['forum_announcements'] = array( - 'title' => $lang->forum_announcements, - 'link' => "index.php?module=forum-announcements", - 'description' => $lang->forum_announcements_desc - ); - - $sub_tabs['update_announcement'] = array( - 'title' => $lang->update_announcement, - 'link' => "index.php?module=forum-announcements&action=add", - 'description' => $lang->update_announcement_desc - ); -} - -$plugins->run_hooks("admin_forum_announcements_begin"); - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_forum_announcements_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(!trim($mybb->input['message'])) - { - $errors[] = $lang->error_missing_message; - } - - if(!trim($mybb->input['fid'])) - { - $errors[] = $lang->error_missing_forum; - } - - if(!checkdate($mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT))) - { - $errors[] = $lang->error_invalid_start_date; - } - - // End before startdate? - $startdate = @explode(" ", $mybb->input['starttime_time']); - $startdate = @explode(":", $startdate[0]); - $enddate = @explode(" ", $mybb->input['endtime_time']); - $enddate = @explode(":", $enddate[0]); - - if(stristr($mybb->input['starttime_time'], "pm")) - { - $startdate[0] = 12+$startdate[0]; - if($startdate[0] >= 24) - { - $startdate[0] = "00"; - } - } - - if(stristr($mybb->input['endtime_time'], "pm")) - { - $enddate[0] = 12+$enddate[0]; - if($enddate[0] >= 24) - { - $enddate[0] = "00"; - } - } - - $startdate = gmmktime((int)$startdate[0], (int)$startdate[1], 0, $mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT)); - - if($mybb->input['endtime_type'] != "2") - { - $enddate = gmmktime((int)$enddate[0], (int)$enddate[1], 0, $mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT)); - if(!checkdate($mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT))) - { - $errors[] = $lang->error_invalid_end_date; - } - if($enddate <= $startdate) - { - $errors[] = $lang->error_end_before_start; - } - } - - if(!$errors) - { - if(isset($mybb->input['preview'])) - { - $parser_options = array(); - $parser_options['allow_html'] = $mybb->get_input('allowhtml', MyBB::INPUT_INT); - $parser_options['allow_mycode'] = $mybb->get_input('allowmycode', MyBB::INPUT_INT); - $parser_options['allow_smilies'] = $mybb->get_input('allowsmilies', MyBB::INPUT_INT); - $parser_options['allow_imgcode'] = 1; - $parser_options['allow_videocode'] = 1; - $parser_options['me_username'] = htmlspecialchars_uni($mybb->user['username']); - $parser_options['filter_badwords'] = 1; - - // Set up the message parser if it doesn't already exist. - if(!is_object($parser)) - { - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - } - - $preview['message'] = $parser->parse_message($mybb->input['message'], $parser_options); - $preview['subject'] = htmlspecialchars_uni($mybb->input['title']); - } - else - { - $months = array('01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'); - if(!in_array($mybb->input['starttime_month'], $months)) - { - $mybb->input['starttime_month'] = 1; - } - - if($mybb->input['endtime_type'] == "2") - { - $enddate = '0'; - } - else - { - if(!in_array($mybb->input['endtime_month'], $months)) - { - $mybb->input['endtime_month'] = 1; - } - } - - $insert_announcement = array( - "fid" => $mybb->input['fid'], - "uid" => $mybb->user['uid'], - "subject" => $db->escape_string($mybb->input['title']), - "message" => $db->escape_string($mybb->input['message']), - "startdate" => $startdate, - "enddate" => $enddate, - "allowhtml" => $mybb->get_input('allowhtml', MyBB::INPUT_INT), - "allowmycode" => $mybb->get_input('allowmycode', MyBB::INPUT_INT), - "allowsmilies" => $mybb->get_input('allowsmilies', MyBB::INPUT_INT) - ); - - $aid = $db->insert_query("announcements", $insert_announcement); - - $plugins->run_hooks("admin_forum_announcements_add_commit"); - - // Log admin action - log_admin_action($aid, $mybb->input['title']); - $cache->update_forumsdisplay(); - - flash_message($lang->success_added_announcement, 'success'); - admin_redirect("index.php?module=forum-announcements"); - } - } - } - - $page->add_breadcrumb_item($lang->add_an_announcement); - $page->output_header($lang->add_an_announcement); - $page->output_nav_tabs($sub_tabs, "add_announcement"); - - $form = new Form("index.php?module=forum-announcements&action=add", "post"); - if($errors) - { - $page->output_inline_error($errors); - } - - $default_options = array( - 'starttime_time', - 'starttime_day', - 'starttime_month', - 'starttime_year', - 'endtime_type', - 'endtime_time', - 'endtime_day', - 'endtime_month', - 'endtime_year', - 'title', - 'message', - 'fid', - 'allowhtml', - 'allowmycode', - 'allowsmilies' - ); - - foreach($default_options as $option) - { - if(!isset($mybb->input[$option])) - { - $mybb->input[$option] = ''; - } - } - - if($mybb->input['endtime_type'] == "1") - { - $endtime_checked[1] = "checked=\"checked\""; - $endtime_checked[2] = ""; - } - else - { - $endtime_checked[1] = ""; - $endtime_checked[2] = "checked=\"checked\""; - } - - if(!$mybb->input['starttime_time']) - { - $mybb->input['starttime_time'] = gmdate($mybb->settings['timeformat'], TIME_NOW); - } - - if(!$mybb->input['endtime_time']) - { - $mybb->input['endtime_time'] = gmdate($mybb->settings['timeformat'], TIME_NOW); - } - - if($mybb->input['starttime_day']) - { - $startday = $mybb->get_input('starttime_day', MyBB::INPUT_INT); - } - else - { - $startday = gmdate("j", TIME_NOW); - } - - if($mybb->input['endtime_day']) - { - $endday = $mybb->get_input('endtime_day', MyBB::INPUT_INT); - } - else - { - $endday = gmdate("j", TIME_NOW); - } - - $startdateday = $enddateday = $startdatemonth = $enddatemonth = ''; - - // Days - for($i = 1; $i <= 31; ++$i) - { - if($startday == $i) - { - $startdateday .= "\n"; - } - else - { - $startdateday .= "\n"; - } - - if($endday == $i) - { - $enddateday .= "\n"; - } - else - { - $enddateday .= "\n"; - } - } - - // Months - for($i = 1; $i <= 12; ++$i) - { - $endmonthsel[$i] = $startmonthsel[$i] = ''; - } - - if($mybb->input['starttime_month']) - { - $startmonth = $mybb->get_input('starttime_month', MyBB::INPUT_INT); - $startmonthsel[$startmonth] = "selected=\"selected\""; - } - else - { - $startmonth = gmdate("m", TIME_NOW); - $startmonthsel[$startmonth] = "selected=\"selected\""; - } - - if($mybb->input['endtime_month']) - { - $endmonth = $mybb->get_input('endtime_month', MyBB::INPUT_INT); - $endmonthsel[$endmonth] = "selected=\"selected\""; - } - else - { - $endmonth = gmdate("m", TIME_NOW); - $endmonthsel[$endmonth] = "selected=\"selected\""; - } - - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - - if($mybb->input['starttime_year']) - { - $startdateyear = $mybb->get_input('starttime_year', MyBB::INPUT_INT); - } - else - { - $startdateyear = gmdate("Y", TIME_NOW); - } - - if($mybb->input['endtime_year']) - { - $enddateyear = $mybb->get_input('endtime_year', MyBB::INPUT_INT); - } - else - { - $enddateyear = gmdate("Y", TIME_NOW) + 1; - } - - if(isset($preview)) - { - $form_container = new FormContainer($lang->announcement_preview); - $form_container->output_row($preview['subject'], "", $preview['message'], 'preview'); - $form_container->end(); - } - - $form_container = new FormContainer($lang->add_an_announcement); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->start_date." *", $lang->start_date_desc, "\n   \n\n   \n\n - {$lang->time} ".$form->generate_text_box('starttime_time', $mybb->input['starttime_time'], array('id' => 'starttime_time', 'style' => 'width: 50px;'))); - - $actions = " -
-
-
- - - - -
\n   \n\n   \n\n - {$lang->time} ".$form->generate_text_box('endtime_time', $mybb->input['endtime_time'], array('id' => 'endtime_time', 'style' => 'width: 50px;'))."
-
-
-
- "; - $form_container->output_row($lang->end_date." *", $lang->end_date_desc, $actions); - - $form_container->output_row($lang->message." *", "", $form->generate_text_area('message', $mybb->input['message'], array('id' => 'message')), 'message'); - - $form_container->output_row($lang->forums_to_appear_in." *", $lang->forums_to_appear_in_desc, $form->generate_forum_select('fid', $mybb->input['fid'], array('size' => 5, 'main_option' => $lang->all_forums))); - - $form_container->output_row($lang->allow_html." *", "", $form->generate_yes_no_radio('allowhtml', $mybb->input['allowhtml'], array('style' => 'width: 2em;'))); - - $form_container->output_row($lang->allow_mycode." *", "", $form->generate_yes_no_radio('allowmycode', $mybb->input['allowmycode'], array('style' => 'width: 2em;'))); - - $form_container->output_row($lang->allow_smilies." *", "", $form->generate_yes_no_radio('allowsmilies', $mybb->input['allowsmilies'], array('style' => 'width: 2em;'))); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_announcement); - $buttons[] = $form->generate_submit_button($lang->preview_announcement, array('name' => 'preview')); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - if(!trim($mybb->input['aid'])) - { - flash_message($lang->error_invalid_announcement, 'error'); - admin_redirect("index.php?module=forum-announcements"); - } - - $plugins->run_hooks("admin_forum_announcements_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(!trim($mybb->input['message'])) - { - $errors[] = $lang->error_missing_message; - } - - if(!trim($mybb->input['fid'])) - { - $errors[] = $lang->error_missing_forum; - } - - if(!checkdate($mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT))) - { - $errors[] = $lang->error_invalid_start_date; - } - - // End before startdate? - $startdate = @explode(" ", $mybb->input['starttime_time']); - $startdate = @explode(":", $startdate[0]); - $enddate = @explode(" ", $mybb->input['endtime_time']); - $enddate = @explode(":", $enddate[0]); - - if(stristr($mybb->input['starttime_time'], "pm")) - { - $startdate[0] = 12+$startdate[0]; - if($startdate[0] >= 24) - { - $startdate[0] = "00"; - } - } - - if(stristr($mybb->input['endtime_time'], "pm")) - { - $enddate[0] = 12+$enddate[0]; - if($enddate[0] >= 24) - { - $enddate[0] = "00"; - } - } - - $startdate = gmmktime((int)$startdate[0], (int)$startdate[1], 0, $mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT)); - - if($mybb->input['endtime_type'] != "2") - { - $enddate = gmmktime((int)$enddate[0], (int)$enddate[1], 0, $mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT)); - if(!checkdate($mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT))) - { - $errors[] = $lang->error_invalid_end_date; - } - if($enddate <= $startdate) - { - $errors[] = $lang->error_end_before_start; - } - } - - if(!$errors) - { - if(isset($mybb->input['preview'])) - { - $parser_options = array(); - $parser_options['allow_html'] = $mybb->get_input('allowhtml', MyBB::INPUT_INT); - $parser_options['allow_mycode'] = $mybb->get_input('allowmycode', MyBB::INPUT_INT); - $parser_options['allow_smilies'] = $mybb->get_input('allowsmilies', MyBB::INPUT_INT); - $parser_options['allow_imgcode'] = 1; - $parser_options['allow_videocode'] = 1; - $parser_options['me_username'] = htmlspecialchars_uni($mybb->user['username']); - $parser_options['filter_badwords'] = 1; - - // Set up the message parser if it doesn't already exist. - if(!is_object($parser)) - { - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - } - - $preview = array(); - $preview['message'] = $parser->parse_message($mybb->input['message'], $parser_options); - $preview['subject'] = htmlspecialchars_uni($mybb->input['title']); - } - else - { - $months = array('01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'); - if(!in_array($mybb->input['starttime_month'], $months)) - { - $mybb->input['starttime_month'] = 1; - } - - if($mybb->input['endtime_type'] == "2") - { - $enddate = '0'; - } - else - { - if(!in_array($mybb->input['endtime_month'], $months)) - { - $mybb->input['endtime_month'] = 1; - } - } - - $update_announcement = array( - "fid" => $mybb->input['fid'], - "subject" => $db->escape_string($mybb->input['title']), - "message" => $db->escape_string($mybb->input['message']), - "startdate" => $startdate, - "enddate" => $enddate, - "allowhtml" => $mybb->get_input('allowhtml', MyBB::INPUT_INT), - "allowmycode" => $mybb->get_input('allowmycode', MyBB::INPUT_INT), - "allowsmilies" => $mybb->get_input('allowsmilies', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_forum_announcements_edit_commit"); - - $db->update_query("announcements", $update_announcement, "aid='{$mybb->input['aid']}'"); - - // Log admin action - log_admin_action($mybb->input['aid'], $mybb->input['title']); - $cache->update_forumsdisplay(); - - flash_message($lang->success_updated_announcement, 'success'); - admin_redirect("index.php?module=forum-announcements"); - } - } - } - - $page->add_breadcrumb_item($lang->update_an_announcement); - $page->output_header($lang->update_an_announcement); - $page->output_nav_tabs($sub_tabs, "update_announcement"); - - $form = new Form("index.php?module=forum-announcements&action=edit", "post"); - echo $form->generate_hidden_field("aid", $mybb->input['aid']); - - if($errors || isset($mybb->input['preview'])) - { - // Only show errors if we have any - if($errors) - { - $page->output_inline_error($errors); - } - - // Gather start and end date data - $startday = $mybb->input['starttime_day']; - $start_time = $mybb->input['starttime_time']; - $startmonth = $mybb->input['starttime_month']; - $startmonthsel[$startmonth] = 'selected="selected"'; - $startdateyear = $mybb->input['starttime_year']; - - if($mybb->input['endtime_type'] == 1) - { - // Set time - $endtime_checked[1] = 'checked="checked"'; - $endtime_checked[2] = ''; - - $endday = $mybb->input['endtime_day']; - $endtime = $mybb->input['endtime_time']; - $endmonth = $mybb->input['endtime_month']; - $endmonthsel[$endmonth] = 'selected'; - $enddateyear = $mybb->input['endtime_year']; - } - else - { - // Never - $endtime_checked[1] = ''; - $endtime_checked[2] = 'checked="checked"'; - - $endday = $startday; - $endmonth = $startmonth; - $endmonthsel[$endmonth] = 'selected'; - $enddateyear = $startdateyear + 1; - } - } - elseif(!isset($mybb->input['preview'])) - { - $query = $db->simple_select("announcements", "*", "aid='{$mybb->input['aid']}'"); - $announcement = $db->fetch_array($query); - - if(!$announcement) - { - flash_message($lang->error_invalid_announcement, 'error'); - admin_redirect("index.php?module=forum-announcements"); - } - - $mybb->input['starttime_time'] = gmdate( $mybb->settings['timeformat'], $announcement['startdate']); - - $startday = gmdate("j", $announcement['startdate']); - - $startmonth = gmdate("m", $announcement['startdate']); - $startmonthsel[$startmonth] = "selected=\"selected\""; - - $startdateyear = gmdate("Y", $announcement['startdate']); - - $mybb->input['title'] = $announcement['subject']; - $mybb->input['message'] = $announcement['message']; - $mybb->input['allowhtml'] = $announcement['allowhtml']; - $mybb->input['allowsmilies'] = $announcement['allowsmilies']; - $mybb->input['allowmycode'] = $announcement['allowmycode']; - $mybb->input['fid'] = $announcement['fid']; - - if($announcement['enddate']) - { - $endtime_checked[1] = "checked=\"checked\""; - $endtime_checked[2] = ""; - - $mybb->input['endtime_time'] = gmdate( $mybb->settings['timeformat'],$announcement['enddate']); - - $endday = gmdate("j", $announcement['enddate']); - - $endmonth = gmdate("m", $announcement['enddate']); - $endmonthsel[$endmonth] = "selected"; - - $enddateyear = gmdate("Y", $announcement['enddate']); - } - else - { - $endtime_checked[1] = ""; - $endtime_checked[2] = "checked=\"checked\""; - - $mybb->input['endtime_time'] = $mybb->input['starttime_time']; - $endday = $startday; - $endmonth = $startmonth; - $enddateyear = $startdateyear+1; - } - } - - for($i = 1; $i <= 31; ++$i) - { - if($startday == $i) - { - $startdateday .= "\n"; - } - else - { - $startdateday .= "\n"; - } - - if($endday == $i) - { - $enddateday .= "\n"; - } - else - { - $enddateday .= "\n"; - } - } - - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - $startdatemonth .= "\n"; - $enddatemonth .= "\n"; - - if(isset($preview)) - { - $form_container = new FormContainer($lang->announcement_preview); - $form_container->output_row($preview['subject'], "", $preview['message'], 'preview'); - $form_container->end(); - } - - $form_container = new FormContainer($lang->add_an_announcement); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->start_date." *", $lang->start_date_desc, "\n   \n\n   \n\n - {$lang->time} ".$form->generate_text_box('starttime_time', $mybb->input['starttime_time'], array('id' => 'starttime_time', 'style' => 'width: 50px;'))); - - $actions = " -
-
-
- - - - -
\n   \n\n   \n\n - {$lang->time} ".$form->generate_text_box('endtime_time', $mybb->input['endtime_time'], array('id' => 'endtime_time', 'style' => 'width: 50px;'))."
-
-
-
- "; - $form_container->output_row($lang->end_date." *", $lang->end_date_desc, $actions); - - $form_container->output_row($lang->message." *", "", $form->generate_text_area('message', $mybb->input['message'], array('id' => 'message')), 'message'); - - $form_container->output_row($lang->forums_to_appear_in." *", $lang->forums_to_appear_in_desc, $form->generate_forum_select('fid', $mybb->input['fid'], array('size' => 5, 'main_option' => $lang->all_forums))); - - $form_container->output_row($lang->allow_html." *", "", $form->generate_yes_no_radio('allowhtml', $mybb->input['allowhtml'], array('style' => 'width: 2em;'))); - - $form_container->output_row($lang->allow_mycode." *", "", $form->generate_yes_no_radio('allowmycode', $mybb->input['allowmycode'], array('style' => 'width: 2em;'))); - - $form_container->output_row($lang->allow_smilies." *", "", $form->generate_yes_no_radio('allowsmilies', $mybb->input['allowsmilies'], array('style' => 'width: 2em;'))); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_announcement); - $buttons[] = $form->generate_submit_button($lang->preview_announcement, array('name' => 'preview')); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("announcements", "*", "aid='{$mybb->input['aid']}'"); - $announcement = $db->fetch_array($query); - - // Does the announcement not exist? - if(!$announcement['aid']) - { - flash_message($lang->error_invalid_announcement, 'error'); - admin_redirect("index.php?module=forum-announcements"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=forum-announcements"); - } - - $plugins->run_hooks("admin_forum_announcements_delete"); - - if($mybb->request_method == "post") - { - $db->delete_query("announcements", "aid='{$announcement['aid']}'"); - - $plugins->run_hooks("admin_forum_announcements_delete_commit"); - - // Log admin action - log_admin_action($announcement['aid'], $announcement['subject']); - $cache->update_forumsdisplay(); - - flash_message($lang->success_announcement_deleted, 'success'); - admin_redirect("index.php?module=forum-announcements"); - } - else - { - $page->output_confirm_action("index.php?module=forum-announcements&action=delete&aid={$announcement['aid']}", $lang->confirm_announcement_deletion); - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_forum_announcements_start"); - - $page->output_header($lang->forum_announcements); - - $page->output_nav_tabs($sub_tabs, "forum_announcements"); - - // Fetch announcements into their proper arrays - $global_announcements = $announcements = array(); - $query = $db->simple_select("announcements", "aid, fid, subject, enddate"); - while($announcement = $db->fetch_array($query)) - { - if($announcement['fid'] == -1) - { - $global_announcements[$announcement['aid']] = $announcement; - continue; - } - $announcements[$announcement['fid']][$announcement['aid']] = $announcement; - } - - if(!empty($global_announcements)) - { - $table = new Table; - $table->construct_header($lang->announcement); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2, "width" => 150)); - - // Get the global announcements - foreach($global_announcements as $aid => $announcement) - { - if($announcement['enddate'] < TIME_NOW && $announcement['enddate'] != 0) - { - $icon = "style}/images/icons/bullet_off.png\" alt=\"(Expired)\" title=\"Expired Announcement\" style=\"vertical-align: middle;\" /> "; - } - else - { - $icon = "style}/images/icons/bullet_on.png\" alt=\"(Active)\" title=\"Active Announcement\" style=\"vertical-align: middle;\" /> "; - } - - $table->construct_cell($icon."".htmlspecialchars_uni($announcement['subject']).""); - $table->construct_cell("{$lang->edit}", array("class" => "align_center", "width" => 75)); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_announcement_deletion}')\">{$lang->delete}", array("class" => "align_center", "width" => 75)); - $table->construct_row(); - } - $table->output($lang->global_announcements); - } - - $table = new Table; - $table->construct_header($lang->announcement); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2, "width" => 200)); - - fetch_forum_announcements($table); - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_forums, array("colspan" => "3")); - $table->construct_row(); - } - - $table->output($lang->forum_announcements); - - $page->output_footer(); -} - -/** - * @param DefaultTable $table - * @param int $pid - * @param int $depth - */ -function fetch_forum_announcements(&$table, $pid=0, $depth=1) -{ - global $mybb, $db, $lang, $announcements, $page; - static $forums_by_parent; - - if(!is_array($forums_by_parent)) - { - $forum_cache = cache_forums(); - - foreach($forum_cache as $forum) - { - $forums_by_parent[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; - } - } - - if(!is_array($forums_by_parent[$pid])) - { - return; - } - - foreach($forums_by_parent[$pid] as $children) - { - foreach($children as $forum) - { - $forum['name'] = htmlspecialchars_uni($forum['name']); - if($forum['active'] == 0) - { - $forum['name'] = "".$forum['name'].""; - } - - if($forum['type'] == "c") - { - $forum['name'] = "".$forum['name'].""; - } - - $table->construct_cell("
{$forum['name']}
"); - $table->construct_cell("{$lang->add_announcement}", array("class" => "align_center", "colspan" => 2)); - $table->construct_row(); - - if(isset($announcements[$forum['fid']])) - { - foreach($announcements[$forum['fid']] as $aid => $announcement) - { - if($announcement['enddate'] < TIME_NOW && $announcement['enddate'] != 0) - { - $icon = "style}/images/icons/bullet_off.png\" alt=\"(Expired)\" title=\"Expired Announcement\" style=\"vertical-align: middle;\" /> "; - } - else - { - $icon = "style}/images/icons/bullet_on.png\" alt=\"(Active)\" title=\"Active Announcement\" style=\"vertical-align: middle;\" /> "; - } - - $table->construct_cell(""); - $table->construct_cell("{$lang->edit}", array("class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_announcement_deletion}')\">{$lang->delete}", array("class" => "align_center")); - $table->construct_row(); - } - } - - // Build the list for any sub forums of this forum - if(isset($forums_by_parent[$forum['fid']])) - { - fetch_forum_announcements($table, $forum['fid'], $depth+1); - } - } - } -} - diff --git a/html/forums/admin/modules/forum/attachments.php b/html/forums/admin/modules/forum/attachments.php deleted file mode 100644 index 50b28a2..0000000 --- a/html/forums/admin/modules/forum/attachments.php +++ /dev/null @@ -1,982 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->attachments, "index.php?module=forum-attachments"); - -if($mybb->input['action'] == "stats" || $mybb->input['action'] == "orphans" || !$mybb->input['action']) -{ - $sub_tabs['find_attachments'] = array( - 'title' => $lang->find_attachments, - 'link' => "index.php?module=forum-attachments", - 'description' => $lang->find_attachments_desc - ); - - $sub_tabs['find_orphans'] = array( - 'title' => $lang->find_orphans, - 'link' => "index.php?module=forum-attachments&action=orphans", - 'description' => $lang->find_orphans_desc - ); - - $sub_tabs['stats'] = array( - 'title' => $lang->attachment_stats, - 'link' => "index.php?module=forum-attachments&action=stats", - 'description' => $lang->attachment_stats_desc - ); -} - -$plugins->run_hooks("admin_forum_attachments_begin"); - -if($mybb->input['action'] == "delete") -{ - $plugins->run_hooks("admin_forum_attachments_delete"); - - if(!is_array($mybb->input['aids'])) - { - $mybb->input['aids'] = array($mybb->get_input('aid', MyBB::INPUT_INT)); - } - else - { - $mybb->input['aids'] = array_map("intval", $mybb->input['aids']); - } - - if(count($mybb->input['aids']) < 1) - { - flash_message($lang->error_nothing_selected, 'error'); - admin_redirect("index.php?module=forum-attachments"); - } - - if($mybb->request_method == "post") - { - require_once MYBB_ROOT."inc/functions_upload.php"; - - $query = $db->simple_select("attachments", "aid,pid,posthash, filename", "aid IN (".implode(",", $mybb->input['aids']).")"); - while($attachment = $db->fetch_array($query)) - { - if(!$attachment['pid']) - { - remove_attachment(null, $attachment['posthash'], $attachment['aid']); - // Log admin action - log_admin_action($attachment['aid'], $attachment['filename']); - } - else - { - remove_attachment($attachment['pid'], null, $attachment['aid']); - // Log admin action - log_admin_action($attachment['aid'], $attachment['filename'], $attachment['pid']); - } - } - - $plugins->run_hooks("admin_forum_attachments_delete_commit"); - - flash_message($lang->success_deleted, 'success'); - admin_redirect("index.php?module=forum-attachments"); - } - else - { - $aids = array(); - foreach($mybb->input['aids'] as $aid) - { - $aids .= "&aids[]=$aid"; - } - $page->output_confirm_action("index.php?module=forum-attachments&action=delete&aids={$aids}", $lang->confirm_delete); - } -} - -if($mybb->input['action'] == "stats") -{ - $plugins->run_hooks("admin_forum_attachments_stats"); - - $query = $db->simple_select("attachments", "COUNT(*) AS total_attachments, SUM(filesize) as disk_usage, SUM(downloads*filesize) as bandwidthused", "visible='1'"); - $attachment_stats = $db->fetch_array($query); - - $page->add_breadcrumb_item($lang->stats); - $page->output_header($lang->stats_attachment_stats); - - $page->output_nav_tabs($sub_tabs, 'stats'); - - if($attachment_stats['total_attachments'] == 0) - { - $page->output_inline_error(array($lang->error_no_attachments)); - $page->output_footer(); - exit; - } - - $table = new Table; - - $table->construct_cell($lang->num_uploaded, array('width' => '25%')); - $table->construct_cell(my_number_format($attachment_stats['total_attachments']), array('width' => '25%')); - $table->construct_cell($lang->space_used, array('width' => '200')); - $table->construct_cell(get_friendly_size($attachment_stats['disk_usage']), array('width' => '200')); - $table->construct_row(); - - $table->construct_cell($lang->bandwidth_used, array('width' => '25%')); - $table->construct_cell(get_friendly_size(round($attachment_stats['bandwidthused'])), array('width' => '25%')); - $table->construct_cell($lang->average_size, array('width' => '25%')); - $table->construct_cell(get_friendly_size(round($attachment_stats['disk_usage']/$attachment_stats['total_attachments'])), array('width' => '25%')); - $table->construct_row(); - - $table->output($lang->general_stats); - - // Fetch the most popular attachments - $table = new Table; - $table->construct_header($lang->attachments, array('colspan' => 2)); - $table->construct_header($lang->size, array('width' => '10%', 'class' => 'align_center')); - $table->construct_header($lang->posted_by, array('width' => '20%', 'class' => 'align_center')); - $table->construct_header($lang->thread, array('width' => '25%', 'class' => 'align_center')); - $table->construct_header($lang->downloads, array('width' => '10%', 'class' => 'align_center')); - $table->construct_header($lang->date_uploaded, array("class" => "align_center")); - - $query = $db->query(" - SELECT a.*, p.tid, p.fid, t.subject, p.uid, p.username, u.username AS user_username - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=a.uid) - ORDER BY a.downloads DESC - LIMIT 5 - "); - while($attachment = $db->fetch_array($query)) - { - build_attachment_row($attachment, $table); - } - $table->output($lang->popular_attachments); - - // Fetch the largest attachments - $table = new Table; - $table->construct_header($lang->attachments, array('colspan' => 2)); - $table->construct_header($lang->size, array('width' => '10%', 'class' => 'align_center')); - $table->construct_header($lang->posted_by, array('width' => '20%', 'class' => 'align_center')); - $table->construct_header($lang->thread, array('width' => '25%', 'class' => 'align_center')); - $table->construct_header($lang->downloads, array('width' => '10%', 'class' => 'align_center')); - $table->construct_header($lang->date_uploaded, array("class" => "align_center")); - - $query = $db->query(" - SELECT a.*, p.tid, p.fid, t.subject, p.uid, p.username, u.username AS user_username - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=a.uid) - ORDER BY a.filesize DESC - LIMIT 5 - "); - while($attachment = $db->fetch_array($query)) - { - build_attachment_row($attachment, $table); - } - $table->output($lang->largest_attachments); - - // Fetch users who've uploaded the most attachments - $table = new Table; - $table->construct_header($lang->username); - $table->construct_header($lang->total_size, array('width' => '20%', 'class' => 'align_center')); - - switch($db->type) - { - case "pgsql": - $query = $db->query(" - SELECT a.uid, u.username, SUM(a.filesize) as totalsize - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=a.uid) - GROUP BY a.uid, u.username - ORDER BY totalsize DESC - LIMIT 5 - "); - break; - default: - $query = $db->query(" - SELECT a.uid, u.username, SUM(a.filesize) as totalsize - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=a.uid) - GROUP BY a.uid - ORDER BY totalsize DESC - LIMIT 5 - "); - } - while($user = $db->fetch_array($query)) - { - if(!$user['uid']) - { - $user['username'] = $lang->na; - } - $table->construct_cell(build_profile_link(htmlspecialchars_uni($user['username']), $user['uid'], "_blank")); - $table->construct_cell("".get_friendly_size($user['totalsize'])."", array('class' => 'align_center')); - $table->construct_row(); - } - $table->output($lang->users_diskspace); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete_orphans" && $mybb->request_method == "post") -{ - $plugins->run_hooks("admin_forum_attachments_delete_orphans"); - - $success_count = $error_count = 0; - - // Deleting specific attachments from uploads directory - if(is_array($mybb->input['orphaned_files'])) - { - /** - * @param string $string - * - * @return string - */ - function clean_filename($string) - { - return str_replace(array(".."), "", $string); - } - $mybb->input['orphaned_files'] = array_map("clean_filename", $mybb->input['orphaned_files']); - foreach($mybb->input['orphaned_files'] as $file) - { - if(!@unlink(MYBB_ROOT.$mybb->settings['uploadspath']."/".$file)) - { - $error_count++; - } - else - { - $success_count++; - } - } - } - - // Deleting physical attachments which exist in database - if(is_array($mybb->input['orphaned_attachments'])) - { - $mybb->input['orphaned_attachments'] = array_map("intval", $mybb->input['orphaned_attachments']); - require_once MYBB_ROOT."inc/functions_upload.php"; - - $query = $db->simple_select("attachments", "aid,pid,posthash", "aid IN (".implode(",", $mybb->input['orphaned_attachments']).")"); - while($attachment = $db->fetch_array($query)) - { - if(!$attachment['pid']) - { - remove_attachment(null, $attachment['posthash'], $attachment['aid']); - } - else - { - remove_attachment($attachment['pid'], null, $attachment['aid']); - } - $success_count++; - } - } - - $plugins->run_hooks("admin_forum_attachments_delete_orphans_commit"); - - // Log admin action - log_admin_action(); - - $message = ''; - $status = 'success'; - if($error_count > 0) - { - $status = 'error'; - $message = $lang->sprintf($lang->error_count, $error_count); - } - - if($success_count > 0) - { - if($error_count > 0) - { - $message .= '
'.$lang->sprintf($lang->success_count, $success_count); - } - else - { - $message = $lang->success_orphan_deleted; - } - } - flash_message($message, $status); - admin_redirect('index.php?module=forum-attachments'); -} - -if($mybb->input['action'] == "orphans") -{ - $plugins->run_hooks("admin_forum_attachments_orphans"); - - // Oprhans are defined as: - // - Uploaded files in the uploads directory that don't exist in the database - // - Attachments for which the uploaded file is missing - // - Attachments for which the thread or post has been deleted - // - Files uploaded > 24h ago not attached to a real post - - // This process is quite intensive so we split it up in to 2 steps, one which scans the file system and the other which scans the database. - - // Finished second step, show results - if($mybb->input['step'] == 3) - { - $plugins->run_hooks("admin_forum_attachments_step3"); - - $reults = 0; - // Incoming attachments which exist as files but not in database - if($mybb->input['bad_attachments']) - { - $bad_attachments = my_unserialize($mybb->input['bad_attachments']); - $results = count($bad_attachments); - } - - $aids = array(); - if($mybb->input['missing_attachment_files']) - { - $missing_attachment_files = my_unserialize($mybb->input['missing_attachment_files']); - $aids = array_merge($aids, $missing_attachment_files); - } - - if($mybb->input['missing_threads']) - { - $missing_threads = my_unserialize($mybb->input['missing_threads']); - $aids = array_merge($aids, $missing_threads); - } - - if($mybb->input['incomplete_attachments']) - { - $incomplete_attachments = my_unserialize($mybb->input['incomplete_attachments']); - $aids = array_merge($aids, $incomplete_attachments); - } - - foreach($aids as $key => $aid) - { - $aids[$key] = (int)$aid; - } - - $results += count($aids); - - if($results == 0) - { - flash_message($lang->success_no_orphans, 'success'); - admin_redirect("index.php?module=forum-attachments"); - } - - $page->output_header($lang->orphan_results); - $page->output_nav_tabs($sub_tabs, 'find_orphans'); - - $form = new Form("index.php?module=forum-attachments&action=delete_orphans", "post"); - - $table = new Table; - $table->construct_header($form->generate_check_box('checkall', '1', '', array('class' => 'checkall')), array( 'width' => 1)); - $table->construct_header($lang->size_attachments, array('colspan' => 2)); - $table->construct_header($lang->reason_orphaned, array('width' => '20%', 'class' => 'align_center')); - $table->construct_header($lang->date_uploaded, array("class" => "align_center")); - - if(is_array($bad_attachments)) - { - foreach($bad_attachments as $file) - { - $file_path = MYBB_ROOT.$mybb->settings['uploadspath']."/".$file; - $filesize = get_friendly_size(filesize($file_path)); - $table->construct_cell($form->generate_check_box('orphaned_files[]', $file, '', array('checked' => true))); - $table->construct_cell(get_attachment_icon(get_extension($attachment['filename'])), array('width' => 1)); - $table->construct_cell("{$filesize}{$file}"); - $table->construct_cell($lang->reason_not_in_table, array('class' => 'align_center')); - $table->construct_cell(my_date('relative', filemtime($file_path)), array('class' => 'align_center')); - $table->construct_row(); - } - } - - if(count($aids) > 0) - { - $query = $db->simple_select("attachments", "*", "aid IN (".implode(",", $aids).")"); - while($attachment = $db->fetch_array($query)) - { - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - - if($missing_attachment_files[$attachment['aid']]) - { - $reason = $lang->reason_file_missing; - } - else if($missing_threads[$attachment['aid']]) - { - $reason = $lang->reason_thread_deleted; - } - else if($incomplete_attachments[$attachment['aid']]) - { - $reason = $lang->reason_post_never_made; - } - $table->construct_cell($form->generate_check_box('orphaned_attachments[]', $attachment['aid'], '', array('checked' => true))); - $table->construct_cell(get_attachment_icon(get_extension($attachment['filename'])), array('width' => 1)); - $table->construct_cell("".get_friendly_size($attachment['filesize'])."{$attachment['filename']}", array('class' => $cell_class)); - $table->construct_cell($reason, array('class' => 'align_center')); - if($attachment['dateuploaded']) - { - $table->construct_cell(my_date('relative', $attachment['dateuploaded']), array('class' => 'align_center')); - } - else - { - $table->construct_cell($lang->unknown, array('class' => 'align_center')); - } - $table->construct_row(); - } - } - - $table->output("{$lang->orphan_attachments_search} - {$results} {$lang->results}"); - - $buttons[] = $form->generate_submit_button($lang->button_delete_orphans); - $form->output_submit_wrapper($buttons); - $form->end(); - $page->output_footer(); - } - - // Running second step - scan the database - else if($mybb->input['step'] == 2) - { - $plugins->run_hooks("admin_forum_attachments_orphans_step2"); - - $page->output_header("{$lang->orphan_attachments_search} - {$lang->step2}"); - - $page->output_nav_tabs($sub_tabs, 'find_orphans'); - echo "

{$lang->step2of2}

"; - echo "

{$lang->step2of2_line1}

"; - echo "

{$lang->step_line2}

"; - echo "

style}/images/spinner_big.gif\" alt=\"{$lang->scanning}\" id=\"spinner\" />

"; - - $page->output_footer(false); - flush(); - - $missing_attachment_files = array(); - $missing_threads = array(); - $incomplete_attachments = array(); - - $query = $db->query(" - SELECT a.*, a.pid AS attachment_pid, p.pid - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - ORDER BY a.aid"); - while($attachment = $db->fetch_array($query)) - { - // Check if the attachment exists in the file system - if(!file_exists(MYBB_ROOT.$mybb->settings['uploadspath']."/{$attachment['attachname']}")) - { - $missing_attachment_files[$attachment['aid']] = $attachment['aid']; - } - // Check if the thread/post for this attachment is missing - else if(!$attachment['pid'] && $attachment['attachment_pid']) - { - $missing_threads[$attachment['aid']] = $attachment['aid']; - } - // Check if the attachment was uploaded > 24 hours ago but not assigned to a thread - else if(!$attachment['attachment_pid'] && $attachment['dateuploaded'] < TIME_NOW-60*60*24 && $attachment['dateuploaded'] != 0) - { - $incomplete_attachments[$attachment['aid']] = $attachment['aid']; - } - } - - // Now send the user to the final page - $form = new Form("index.php?module=forum-attachments&action=orphans&step=3", "post", "redirect_form", 0, ""); - // Scan complete - if($mybb->input['bad_attachments']) - { - echo $form->generate_hidden_field("bad_attachments", $mybb->input['bad_attachments']); - } - if(is_array($missing_attachment_files) && count($missing_attachment_files) > 0) - { - $missing_attachment_files = my_serialize($missing_attachment_files); - echo $form->generate_hidden_field("missing_attachment_files", $missing_attachment_files); - } - if(is_array($missing_threads) && count($missing_threads) > 0) - { - $missing_threads = my_serialize($missing_threads); - echo $form->generate_hidden_field("missing_threads", $missing_threads); - } - if(is_array($incomplete_attachments) && count($incomplete_attachments) > 0) - { - $incomplete_attachments = my_serialize($incomplete_attachments); - echo $form->generate_hidden_field("incomplete_attachments", $incomplete_attachments); - } - $form->end(); - echo ""; - exit; - } - // Running first step, scan the file system - else - { - $plugins->run_hooks("admin_forum_attachments_orphans_step1"); - - /** - * @param string $dir - */ - function scan_attachments_directory($dir="") - { - global $db, $mybb, $bad_attachments, $attachments_to_check; - - $real_dir = MYBB_ROOT.$mybb->settings['uploadspath']; - $false_dir = ""; - if($dir) - { - $real_dir .= "/".$dir; - $false_dir = $dir."/"; - } - - if($dh = opendir($real_dir)) - { - while(false !== ($file = readdir($dh))) - { - if($file == "." || $file == ".." || $file == ".svn") - { - continue; - } - - if(is_dir($real_dir.'/'.$file)) - { - scan_attachments_directory($false_dir.$file); - } - else if(my_substr($file, -7, 7) == ".attach") - { - $attachments_to_check["$false_dir$file"] = $false_dir.$file; - // In allotments of 20, query the database for these attachments - if(count($attachments_to_check) >= 20) - { - $attachments_to_check = array_map(array($db, "escape_string"), $attachments_to_check); - $attachment_names = "'".implode("','", $attachments_to_check)."'"; - $query = $db->simple_select("attachments", "aid, attachname", "attachname IN ($attachment_names)"); - while($attachment = $db->fetch_array($query)) - { - unset($attachments_to_check[$attachment['attachname']]); - } - - // Now anything left is bad! - if(count($attachments_to_check) > 0) - { - if($bad_attachments) - { - $bad_attachments = @array_merge($bad_attachments, $attachments_to_check); - } - else - { - $bad_attachments = $attachments_to_check; - } - } - $attachments_to_check = array(); - } - } - } - closedir($dh); - // Any reamining to check? - if(count($attachments_to_check) > 0) - { - $attachments_to_check = array_map(array($db, "escape_string"), $attachments_to_check); - $attachment_names = "'".implode("','", $attachments_to_check)."'"; - $query = $db->simple_select("attachments", "aid, attachname", "attachname IN ($attachment_names)"); - while($attachment = $db->fetch_array($query)) - { - unset($attachments_to_check[$attachment['attachname']]); - } - - // Now anything left is bad! - if(count($attachments_to_check) > 0) - { - if($bad_attachments) - { - $bad_attachments = @array_merge($bad_attachments, $attachments_to_check); - } - else - { - $bad_attachments = $attachments_to_check; - } - } - } - } - } - - $page->output_header("{$lang->orphan_attachments_search} - {$lang->step1}"); - - $page->output_nav_tabs($sub_tabs, 'find_orphans'); - echo "

{$lang->step1of2}

"; - echo "

{$lang->step1of2_line1}

"; - echo "

{$lang->step_line2}

"; - echo "

style}/images/spinner_big.gif\" alt=\"{$lang->scanning}\" id=\"spinner\" />

"; - - $page->output_footer(false); - - flush(); - - scan_attachments_directory(); - global $bad_attachments; - - $form = new Form("index.php?module=forum-attachments&action=orphans&step=2", "post", "redirect_form", 0, ""); - // Scan complete - if(is_array($bad_attachments) && count($bad_attachments) > 0) - { - $bad_attachments = my_serialize($bad_attachments); - echo $form->generate_hidden_field("bad_attachments", $bad_attachments); - } - $form->end(); - echo ""; - exit; - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_forum_attachments_start"); - - if($mybb->request_method == "post" || $mybb->input['results'] == 1) - { - $search_sql = '1=1'; - - // Build the search SQL for users - - // List of valid LIKE search fields - $user_like_fields = array("filename", "filetype"); - foreach($user_like_fields as $search_field) - { - if($mybb->input[$search_field]) - { - $search_sql .= " AND a.{$search_field} LIKE '%".$db->escape_string_like($mybb->input[$search_field])."%'"; - } - } - - $errors = array(); - - // Username matching - if($mybb->input['username']) - { - $user = get_user_by_username($mybb->input['username']); - - if(!$user['uid']) - { - $errors[] = $lang->error_invalid_username; - } - else - { - $search_sql .= " AND a.uid='{$user['uid']}'"; - } - } - - $forum_cache = cache_forums(); - - // Searching for attachments in a specific forum, we need to fetch all child forums too - if($mybb->input['forum']) - { - if(!is_array($mybb->input['forum'])) - { - $mybb->input['forum'] = array($mybb->input['forum']); - } - - $fid_in = array(); - foreach($mybb->input['forum'] as $fid) - { - if(!$forum_cache[$fid]) - { - $errors[] = $lang->error_invalid_forums; - break; - } - $child_forums = get_child_list($fid); - $child_forums[] = $fid; - $fid_in = array_merge($fid_in, $child_forums); - } - - if(count($fid_in) > 0) - { - $search_sql .= " AND p.fid IN (".implode(",", $fid_in).")"; - } - } - - // LESS THAN or GREATER THAN - $direction_fields = array( - "dateuploaded" => $mybb->get_input('dateuploaded', MyBB::INPUT_INT), - "filesize" => $mybb->get_input('filesize', MyBB::INPUT_INT), - "downloads" => $mybb->get_input('downloads', MyBB::INPUT_INT) - ); - - if($mybb->input['dateuploaded'] && $mybb->request_method == "post") - { - $direction_fields['dateuploaded'] = TIME_NOW-$direction_fields['dateuploaded']*60*60*24; - } - if($mybb->input['filesize'] && $mybb->request_method == "post") - { - $direction_fields['filesize'] *= 1024; - } - - foreach($direction_fields as $field_name => $field_content) - { - $direction_field = $field_name."_dir"; - if($mybb->input[$field_name] && $mybb->input[$direction_field]) - { - switch($mybb->input[$direction_field]) - { - case "greater_than": - $direction = ">"; - break; - case "less_than": - $direction = "<"; - break; - default: - $direction = "="; - } - $search_sql .= " AND a.{$field_name}{$direction}'".$field_content."'"; - } - } - if(!$errors) - { - // Lets fetch out how many results we have - $query = $db->query(" - SELECT COUNT(a.aid) AS num_results - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - WHERE {$search_sql} - "); - $num_results = $db->fetch_field($query, "num_results"); - - // No matching results then show an error - if(!$num_results) - { - $errors[] = $lang->error_no_results; - } - } - - // Now we fetch the results if there were 100% no errors - if(!$errors) - { - $mybb->input['perpage'] = $mybb->get_input('perpage', MyBB::INPUT_INT); - if(!$mybb->input['perpage']) - { - $mybb->input['perpage'] = 20; - } - - $mybb->input['page'] = $mybb->get_input('page', MyBB::INPUT_INT); - if($mybb->input['page']) - { - $start = ($mybb->input['page'] - 1) * $mybb->input['perpage']; - } - else - { - $start = 0; - $mybb->input['page'] = 1; - } - - switch($mybb->input['sortby']) - { - case "filesize": - $sort_field = "a.filesize"; - break; - case "downloads": - $sort_field = "a.downloads"; - break; - case "dateuploaded": - $sort_field = "a.dateuploaded"; - break; - case "username": - $sort_field = "u.username"; - break; - default: - $sort_field = "a.filename"; - $mybb->input['sortby'] = "filename"; - } - - if($mybb->input['order'] != "desc") - { - $mybb->input['order'] = "asc"; - } - - $page->add_breadcrumb_item($lang->results); - $page->output_header($lang->index_find_attachments); - - $page->output_nav_tabs($sub_tabs, 'find_attachments'); - - $form = new Form("index.php?module=forum-attachments&action=delete", "post"); - - $table = new Table; - $table->construct_header($form->generate_check_box('checkall', '1', '', array('class' => 'checkall')), array( 'width' => 1)); - $table->construct_header($lang->attachments, array('colspan' => 2)); - $table->construct_header($lang->size, array('width' => '10%', 'class' => 'align_center')); - $table->construct_header($lang->posted_by, array('width' => '20%', 'class' => 'align_center')); - $table->construct_header($lang->thread, array('width' => '25%', 'class' => 'align_center')); - $table->construct_header($lang->downloads, array('width' => '10%', 'class' => 'align_center')); - $table->construct_header($lang->date_uploaded, array("class" => "align_center")); - - // Fetch matching attachments - $query = $db->query(" - SELECT a.*, p.tid, p.fid, t.subject, p.uid, p.username, u.username AS user_username - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=a.uid) - WHERE {$search_sql} - ORDER BY {$sort_field} {$mybb->input['order']} - LIMIT {$start}, {$mybb->input['perpage']} - "); - while($attachment = $db->fetch_array($query)) - { - build_attachment_row($attachment, $table, true); - } - - // Need to draw pagination for this result set - if($num_results > $mybb->input['perpage']) - { - $pagination_url = "index.php?module=forum-attachments&results=1"; - $pagination_vars = array('perpage', 'sortby', 'order', 'filename', 'mimetype', 'username', 'fid', 'downloads', 'downloads_dir', 'dateuploaded', 'dateuploaded_dir', 'filesize', 'filesize_dir'); - foreach($pagination_vars as $var) - { - if($mybb->input[$var]) - { - $pagination_url .= "&{$var}=".urlencode($mybb->input[$var]); - } - } - $pagination = draw_admin_pagination($mybb->input['page'], $mybb->input['perpage'], $num_results, $pagination_url); - } - - echo $pagination; - $table->output($lang->results); - echo $pagination; - - $buttons[] = $form->generate_submit_button($lang->button_delete_attachments); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); - } - } - - $page->output_header($lang->find_attachments); - - $page->output_nav_tabs($sub_tabs, 'find_attachments'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=forum-attachments", "post"); - - $form_container = new FormContainer($lang->find_where); - $form_container->output_row($lang->name_contains, $lang->name_contains_desc, $form->generate_text_box('filename', $mybb->input['filename'], array('id' => 'filename')), 'filename'); - $form_container->output_row($lang->type_contains, "", $form->generate_text_box('mimetype', $mybb->input['mimetype'], array('id' => 'mimetype')), 'mimetype'); - $form_container->output_row($lang->forum_is, "", $form->generate_forum_select('forum[]', $mybb->input['forum'], array('multiple' => true, 'size' => 5, 'id' => 'forum')), 'forum'); - $form_container->output_row($lang->username_is, "", $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'username'); - - $more_options = array( - "less_than" => $lang->more_than, - "greater_than" => $lang->less_than - ); - - $greater_options = array( - "greater_than" => $lang->greater_than, - "is_exactly" => $lang->is_exactly, - "less_than" => $lang->less_than - ); - - $form_container->output_row($lang->date_posted_is, "", $form->generate_select_box('dateuploaded_dir', $more_options, $mybb->input['dateuploaded_dir'], array('id' => 'dateuploaded_dir'))." ".$form->generate_numeric_field('dateuploaded', $mybb->input['dateuploaded'], array('id' => 'dateuploaded', 'min' => 0))." {$lang->days_ago}", 'dateuploaded'); - $form_container->output_row($lang->file_size_is, "", $form->generate_select_box('filesize_dir', $greater_options, $mybb->input['filesize_dir'], array('id' => 'filesize_dir'))." ".$form->generate_numeric_field('filesize', $mybb->input['filesize'], array('id' => 'filesize', 'min' => 0))." {$lang->kb}", 'dateuploaded'); - $form_container->output_row($lang->download_count_is, "", $form->generate_select_box('downloads_dir', $greater_options, $mybb->input['downloads_dir'], array('id' => 'downloads_dir'))." ".$form->generate_numeric_field('downloads', $mybb->input['downloads'], array('id' => 'downloads', 'min' => 0))."", 'dateuploaded'); - $form_container->end(); - - $form_container = new FormContainer($lang->display_options); - $sort_options = array( - "filename" => $lang->filename, - "filesize" => $lang->filesize, - "downloads" => $lang->download_count, - "dateuploaded" => $lang->date_uploaded, - "username" => $lang->post_username - ); - $sort_directions = array( - "asc" => $lang->asc, - "desc" => $lang->desc - ); - $form_container->output_row($lang->sort_results_by, "", $form->generate_select_box('sortby', $sort_options, $mybb->input['sortby'], array('id' => 'sortby'))." {$lang->in} ".$form->generate_select_box('order', $sort_directions, $mybb->input['order'], array('id' => 'order')), 'sortby'); - $form_container->output_row($lang->results_per_page, "", $form->generate_numeric_field('perpage', $mybb->input['perpage'], array('id' => 'perpage', 'min' => 1)), 'perpage'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->button_find_attachments); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -/** - * @param array $attachment - * @param DefaultTable $table - * @param bool $use_form - */ -function build_attachment_row($attachment, &$table, $use_form=false) -{ - global $mybb, $form, $lang; - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - - // Here we do a bit of detection, we want to automatically check for removal any missing attachments and any not assigned to a post uploaded > 24hours ago - // Check if the attachment exists in the file system - $checked = false; - $title = $cell_class = ''; - if(!file_exists(MYBB_ROOT.$mybb->settings['uploadspath']."/{$attachment['attachname']}")) - { - $cell_class = "bad_attachment"; - $title = $lang->error_not_found; - $checked = true; - } - elseif(!$attachment['pid'] && $attachment['dateuploaded'] < TIME_NOW-60*60*24 && $attachment['dateuploaded'] != 0) - { - $cell_class = "bad_attachment"; - $title = $lang->error_not_attached; - $checked = true; - } - else if(!$attachment['tid'] && $attachment['pid']) - { - $cell_class = "bad_attachment"; - $title = $lang->error_does_not_exist; - $checked = true; - } - else if($attachment['visible'] == 0) - { - $cell_class = "invisible_attachment"; - } - - if($cell_class) - { - $cell_class .= " align_center"; - } - else - { - $cell_class = "align_center"; - } - - if($use_form == true && is_object($form)) - { - $table->construct_cell($form->generate_check_box('aids[]', $attachment['aid'], '', array('checked' => $checked))); - } - $table->construct_cell(get_attachment_icon(get_extension($attachment['filename'])), array('width' => 1)); - $table->construct_cell("{$attachment['filename']}"); - $table->construct_cell(get_friendly_size($attachment['filesize']), array('class' => $cell_class)); - - if($attachment['user_username']) - { - $attachment['username'] = $attachment['user_username']; - } - $table->construct_cell(build_profile_link(htmlspecialchars_uni($attachment['username']), $attachment['uid'], "_blank"), array("class" => "align_center")); - $table->construct_cell("".htmlspecialchars_uni($attachment['subject'])."", array("class" => "align_center")); - $table->construct_cell(my_number_format($attachment['downloads']), array("class" => "align_center")); - if($attachment['dateuploaded'] > 0) - { - $date = my_date('relative', $attachment['dateuploaded']); - } - else - { - $date = $lang->unknown; - } - $table->construct_cell($date, array("class" => "align_center")); - $table->construct_row(); -} diff --git a/html/forums/admin/modules/forum/index.html b/html/forums/admin/modules/forum/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/modules/forum/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/modules/forum/management.php b/html/forums/admin/modules/forum/management.php deleted file mode 100644 index 6633c09..0000000 --- a/html/forums/admin/modules/forum/management.php +++ /dev/null @@ -1,2933 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->forum_management, "index.php?module=forum-management"); - -if($mybb->input['action'] == "add" || $mybb->input['action'] == "edit" || $mybb->input['action'] == "copy" || $mybb->input['action'] == "permissions" || !$mybb->input['action']) -{ - if(!empty($mybb->input['fid']) && ($mybb->input['action'] == "management" || $mybb->input['action'] == "edit" || $mybb->input['action'] == "copy" || !$mybb->input['action'])) - { - $sub_tabs['view_forum'] = array( - 'title' => $lang->view_forum, - 'link' => "index.php?module=forum-management&fid=".$mybb->input['fid'], - 'description' => $lang->view_forum_desc - ); - - $sub_tabs['add_child_forum'] = array( - 'title' => $lang->add_child_forum, - 'link' => "index.php?module=forum-management&action=add&pid=".$mybb->input['fid'], - 'description' => $lang->view_forum_desc - ); - - $sub_tabs['edit_forum_settings'] = array( - 'title' => $lang->edit_forum_settings, - 'link' => "index.php?module=forum-management&action=edit&fid=".$mybb->input['fid'], - 'description' => $lang->edit_forum_settings_desc - ); - - $sub_tabs['copy_forum'] = array( - 'title' => $lang->copy_forum, - 'link' => "index.php?module=forum-management&action=copy&fid=".$mybb->input['fid'], - 'description' => $lang->copy_forum_desc - ); - } - else - { - $sub_tabs['forum_management'] = array( - 'title' => $lang->forum_management, - 'link' => "index.php?module=forum-management", - 'description' => $lang->forum_management_desc - ); - - $sub_tabs['add_forum'] = array( - 'title' => $lang->add_forum, - 'link' => "index.php?module=forum-management&action=add", - 'description' => $lang->add_forum_desc - ); - } -} - -$plugins->run_hooks("admin_forum_management_begin"); - -if($mybb->input['action'] == "copy") -{ - $plugins->run_hooks("admin_forum_management_copy"); - - if($mybb->request_method == "post") - { - $from = $mybb->get_input('from', MyBB::INPUT_INT); - $to = $mybb->get_input('to', MyBB::INPUT_INT); - - // Find the source forum - $query = $db->simple_select("forums", '*', "fid='{$from}'"); - $from_forum = $db->fetch_array($query); - if(!$db->num_rows($query)) - { - $errors[] = $lang->error_invalid_source_forum; - } - - if($to == -1) - { - // Create a new forum - if(empty($mybb->input['title'])) - { - $errors[] = $lang->error_new_forum_needs_name; - } - - if($mybb->input['pid'] == -1 && $mybb->input['type'] == 'f') - { - $errors[] = $lang->error_no_parent; - } - - if(!$errors) - { - $new_forum = $from_forum; - unset($new_forum['fid'], $new_forum['threads'], $new_forum['posts'], $new_forum['lastpost'], $new_forum['lastposter'], $new_forum['lastposteruid'], $new_forum['lastposttid'], $new_forum['lastpostsubject'], $new_forum['unapprovedthreads'], $new_forum['unapprovedposts']); - $new_forum['name'] = $db->escape_string($mybb->input['title']); - $new_forum['description'] = $db->escape_string($mybb->input['description']); - $new_forum['type'] = $db->escape_string($mybb->input['type']); - $new_forum['pid'] = $mybb->get_input('pid', MyBB::INPUT_INT); - $new_forum['rulestitle'] = $db->escape_string($new_forum['rulestitle']); - $new_forum['rules'] = $db->escape_string($new_forum['rules']); - $new_forum['parentlist'] = ''; - - $to = $db->insert_query("forums", $new_forum); - - // Generate parent list - $parentlist = make_parent_list($to); - $updatearray = array( - 'parentlist' => $parentlist - ); - $db->update_query("forums", $updatearray, "fid='{$to}'"); - } - } - elseif($mybb->input['copyforumsettings'] == 1) - { - // Copy settings to existing forum - $query = $db->simple_select("forums", '*', "fid='{$to}'"); - $to_forum = $db->fetch_array($query); - if(!$db->num_rows($query)) - { - $errors[] = $lang->error_invalid_destination_forum; - } - - if(!$errors) - { - $new_forum = $from_forum; - unset($new_forum['fid'], $new_forum['threads'], $new_forum['posts'], $new_forum['lastpost'], $new_forum['lastposter'], $new_forum['lastposteruid'], $new_forum['lastposttid'], $new_forum['lastpostsubject'], $new_forum['unapprovedthreads'], $new_forum['unapprovedposts']); - $new_forum['name'] = $db->escape_string($to_forum['name']); - $new_forum['description'] = $db->escape_string($to_forum['description']); - $new_forum['pid'] = $db->escape_string($to_forum['pid']); - $new_forum['parentlist'] = $db->escape_string($to_forum['parentlist']); - $new_forum['rulestitle'] = $db->escape_string($new_forum['rulestitle']); - $new_forum['rules'] = $db->escape_string($new_forum['rules']); - - $db->update_query("forums", $new_forum, "fid='{$to}'"); - } - } - - if(!$errors) - { - // Copy permissions - if(is_array($mybb->input['copygroups']) && count($mybb->input['copygroups'] > 0)) - { - foreach($mybb->input['copygroups'] as $gid) - { - $groups[] = (int)$gid; - } - $groups = implode(',', $groups); - $query = $db->simple_select("forumpermissions", '*', "fid='{$from}' AND gid IN ({$groups})"); - $db->delete_query("forumpermissions", "fid='{$to}' AND gid IN ({$groups})", 1); - while($permissions = $db->fetch_array($query)) - { - unset($permissions['pid']); - $permissions['fid'] = $to; - - $db->insert_query("forumpermissions", $permissions); - } - - // Log admin action - log_admin_action($from, $from_forum['name'], $to, $new_forum['name'], $groups); - } - else - { - // Log admin action (no group permissions) - log_admin_action($from, $from_forum['name'], $to, $new_forum['name']); - } - - $plugins->run_hooks("admin_forum_management_copy_commit"); - - $cache->update_forums(); - $cache->update_forumpermissions(); - - flash_message($lang->success_forum_copied, 'success'); - admin_redirect("index.php?module=forum-management&action=edit&fid={$to}"); - } - } - - $page->add_breadcrumb_item($lang->copy_forum); - $page->output_header($lang->copy_forum); - $page->output_nav_tabs($sub_tabs, 'copy_forum'); - - $form = new Form("index.php?module=forum-management&action=copy", "post"); - - if($errors) - { - $page->output_inline_error($errors); - $copy_data = $mybb->input; - } - else - { - $copy_data['type'] = "f"; - $copy_data['title'] = ""; - $copy_data['description'] = ""; - - if(!$mybb->input['pid']) - { - $copy_data['pid'] = "-1"; - } - else - { - $copy_data['pid'] = $mybb->get_input('pid', MyBB::INPUT_INT); - } - $copy_data['disporder'] = "1"; - $copy_data['from'] = $mybb->input['fid']; - $copy_data['copyforumsettings'] = 0; - $copy_data['pid'] = 0; - } - - $types = array( - 'f' => $lang->forum, - 'c' => $lang->category - ); - - $create_a_options_f = array( - 'id' => 'forum' - ); - - $create_a_options_c = array( - 'id' => 'category' - ); - - if($copy_data['type'] == "f") - { - $create_a_options_f['checked'] = true; - } - else - { - $create_a_options_c['checked'] = true; - } - - $usergroups = array(); - - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $usergroups[$usergroup['gid']] = htmlspecialchars_uni($usergroup['title']); - } - - $form_container = new FormContainer($lang->copy_forum); - $form_container->output_row($lang->source_forum." *", $lang->source_forum_desc, $form->generate_forum_select('from', $copy_data['from'], array('id' => 'from')), 'from'); - $form_container->output_row($lang->destination_forum." *", $lang->destination_forum_desc, $form->generate_forum_select('to', $copy_data['to'], array('id' => 'to', 'main_option' => $lang->copy_to_new_forum)), 'to'); - $form_container->output_row($lang->copy_settings_and_properties, $lang->copy_settings_and_properties_desc, $form->generate_yes_no_radio('copyforumsettings', $copy_data['copyforumsettings'])); - $form_container->output_row($lang->copy_user_group_permissions, $lang->copy_user_group_permissions_desc, $form->generate_select_box('copygroups[]', $usergroups, $mybb->input['copygroups'], array('id' => 'copygroups', 'multiple' => true, 'size' => 5)), 'copygroups'); - - $form_container->end(); - - $form_container = new FormContainer($lang->new_forum_settings); - $form_container->output_row($lang->forum_type, $lang->forum_type_desc, $form->generate_radio_button('type', 'f', $lang->forum, $create_a_options_f)."
\n".$form->generate_radio_button('type', 'c', $lang->category, $create_a_options_c)); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $copy_data['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->description, "", $form->generate_text_area('description', $copy_data['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->parent_forum." *", $lang->parent_forum_desc, $form->generate_forum_select('pid', $copy_data['pid'], array('id' => 'pid', 'main_option' => $lang->none)), 'pid'); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->copy_forum); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "editmod") -{ - $query = $db->simple_select("moderators", "*", "mid='".$mybb->get_input('mid', MyBB::INPUT_INT)."'"); - $mod_data = $db->fetch_array($query); - - if(!$mod_data['id']) - { - flash_message($lang->error_incorrect_moderator, 'error'); - admin_redirect("index.php?module=forum-management"); - } - - $plugins->run_hooks("admin_forum_management_editmod"); - - if($mod_data['isgroup']) - { - $fieldname = "title"; - } - else - { - $fieldname = "username"; - } - - if($mybb->request_method == "post") - { - $mid = $mybb->get_input('mid', MyBB::INPUT_INT); - if(!$mid) - { - flash_message($lang->error_incorrect_moderator, 'error'); - admin_redirect("index.php?module=forum-management"); - } - - if(!$errors) - { - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - $forum = get_forum($fid); - if($mod_data['isgroup']) - { - $mod = $groupscache[$mod_data['id']]; - } - else - { - $mod = get_user($mod_data['id']); - } - $update_array = array( - 'fid' => (int)$fid, - 'caneditposts' => $mybb->get_input('caneditposts', MyBB::INPUT_INT), - 'cansoftdeleteposts' => $mybb->get_input('cansoftdeleteposts', MyBB::INPUT_INT), - 'canrestoreposts' => $mybb->get_input('canrestoreposts', MyBB::INPUT_INT), - 'candeleteposts' => $mybb->get_input('candeleteposts', MyBB::INPUT_INT), - 'cansoftdeletethreads' => $mybb->get_input('cansoftdeletethreads', MyBB::INPUT_INT), - 'canrestorethreads' => $mybb->get_input('canrestorethreads', MyBB::INPUT_INT), - 'candeletethreads' => $mybb->get_input('candeletethreads', MyBB::INPUT_INT), - 'canviewips' => $mybb->get_input('canviewips', MyBB::INPUT_INT), - 'canviewunapprove' => $mybb->get_input('canviewunapprove', MyBB::INPUT_INT), - 'canviewdeleted' => $mybb->get_input('canviewdeleted', MyBB::INPUT_INT), - 'canopenclosethreads' => $mybb->get_input('canopenclosethreads', MyBB::INPUT_INT), - 'canstickunstickthreads' => $mybb->get_input('canstickunstickthreads', MyBB::INPUT_INT), - 'canapproveunapprovethreads' => $mybb->get_input('canapproveunapprovethreads', MyBB::INPUT_INT), - 'canapproveunapproveposts' => $mybb->get_input('canapproveunapproveposts', MyBB::INPUT_INT), - 'canapproveunapproveattachs' => $mybb->get_input('canapproveunapproveattachs', MyBB::INPUT_INT), - 'canmanagethreads' => $mybb->get_input('canmanagethreads', MyBB::INPUT_INT), - 'canmanagepolls' => $mybb->get_input('canmanagepolls', MyBB::INPUT_INT), - 'canpostclosedthreads' => $mybb->get_input('canpostclosedthreads', MyBB::INPUT_INT), - 'canmovetononmodforum' => $mybb->get_input('canmovetononmodforum', MyBB::INPUT_INT), - 'canusecustomtools' => $mybb->get_input('canusecustomtools', MyBB::INPUT_INT), - 'canmanageannouncements' => $mybb->get_input('canmanageannouncements', MyBB::INPUT_INT), - 'canmanagereportedposts' => $mybb->get_input('canmanagereportedposts', MyBB::INPUT_INT), - 'canviewmodlog' => $mybb->get_input('canviewmodlog', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_forum_management_editmod_commit"); - - $db->update_query("moderators", $update_array, "mid='".$mybb->get_input('mid', MyBB::INPUT_INT)."'"); - - $cache->update_moderators(); - - // Log admin action - log_admin_action($fid, $forum['name'], $mid, $mod[$fieldname]); - - flash_message($lang->success_moderator_updated, 'success'); - admin_redirect("index.php?module=forum-management&fid=".$mybb->get_input('fid', MyBB::INPUT_INT)."#tab_moderators"); - } - } - - if($mod_data['isgroup']) - { - $query = $db->simple_select("usergroups", "title", "gid='{$mod_data['id']}'"); - $mod_data[$fieldname] = $db->fetch_field($query, 'title'); - } - else - { - $query = $db->simple_select("users", "username", "uid='{$mod_data['id']}'"); - $mod_data[$fieldname] = $db->fetch_field($query, 'username'); - } - - $sub_tabs = array(); - - $sub_tabs['edit_mod'] = array( - 'title' => $lang->edit_mod, - 'link' => "index.php?module=forum-management&action=editmod&mid=".$mybb->input['mid'], - 'description' => $lang->edit_mod_desc - ); - - $page->add_breadcrumb_item($lang->forum_moderators, "index.php?module=forum-management&fid={$mod_data['fid']}#tab_moderators"); - $page->add_breadcrumb_item($lang->edit_forum); - $page->output_header($lang->edit_mod); - $page->output_nav_tabs($sub_tabs, 'edit_mod'); - - $form = new Form("index.php?module=forum-management&action=editmod", "post"); - echo $form->generate_hidden_field("mid", $mod_data['mid']); - - if($errors) - { - $page->output_inline_error($errors); - $mod_data = $mybb->input; - } - - $form_container = new FormContainer($lang->sprintf($lang->edit_mod_for, $mod_data[$fieldname])); - $form_container->output_row($lang->forum, $lang->forum_desc, $form->generate_forum_select('fid', $mod_data['fid'], array('id' => 'fid')), 'fid'); - - $moderator_permissions = array( - $form->generate_check_box('caneditposts', 1, $lang->can_edit_posts, array('checked' => $mod_data['caneditposts'], 'id' => 'caneditposts')), - $form->generate_check_box('cansoftdeleteposts', 1, $lang->can_soft_delete_posts, array('checked' => $mod_data['cansoftdeleteposts'], 'id' => 'cansoftdeleteposts')), - $form->generate_check_box('canrestoreposts', 1, $lang->can_restore_posts, array('checked' => $mod_data['canrestoreposts'], 'id' => 'canrestoreposts')), - $form->generate_check_box('candeleteposts', 1, $lang->can_delete_posts, array('checked' => $mod_data['candeleteposts'], 'id' => 'candeleteposts')), - $form->generate_check_box('cansoftdeletethreads', 1, $lang->can_soft_delete_threads, array('checked' => $mod_data['cansoftdeletethreads'], 'id' => 'cansoftdeletethreads')), - $form->generate_check_box('canrestorethreads', 1, $lang->can_restore_threads, array('checked' => $mod_data['canrestorethreads'], 'id' => 'canrestorethreads')), - $form->generate_check_box('candeletethreads', 1, $lang->can_delete_threads, array('checked' => $mod_data['candeletethreads'], 'id' => 'candeletethreads')), - $form->generate_check_box('canviewips', 1, $lang->can_view_ips, array('checked' => $mod_data['canviewips'], 'id' => 'canviewips')), - $form->generate_check_box('canviewunapprove', 1, $lang->can_view_unapprove, array('checked' => $mod_data['canviewunapprove'], 'id' => 'canviewunapprove')), - $form->generate_check_box('canviewdeleted', 1, $lang->can_view_deleted, array('checked' => $mod_data['canviewdeleted'], 'id' => 'canviewdeleted')), - $form->generate_check_box('canopenclosethreads', 1, $lang->can_open_close_threads, array('checked' => $mod_data['canopenclosethreads'], 'id' => 'canopenclosethreads')), - $form->generate_check_box('canstickunstickthreads', 1, $lang->can_stick_unstick_threads, array('checked' => $mod_data['canstickunstickthreads'], 'id' => 'canstickunstickthreads')), - $form->generate_check_box('canapproveunapprovethreads', 1, $lang->can_approve_unapprove_threads, array('checked' => $mod_data['canapproveunapprovethreads'], 'id' => 'canapproveunapprovethreads')), - $form->generate_check_box('canapproveunapproveposts', 1, $lang->can_approve_unapprove_posts, array('checked' => $mod_data['canapproveunapproveposts'], 'id' => 'canapproveunapproveposts')), - $form->generate_check_box('canapproveunapproveattachs', 1, $lang->can_approve_unapprove_attachments, array('checked' => $mod_data['canapproveunapproveattachs'], 'id' => 'canapproveunapproveattachs')), - $form->generate_check_box('canmanagethreads', 1, $lang->can_manage_threads, array('checked' => $mod_data['canmanagethreads'], 'id' => 'canmanagethreads')), - $form->generate_check_box('canmanagepolls', 1, $lang->can_manage_polls, array('checked' => $mod_data['canmanagepolls'], 'id' => 'canmanagepolls')), - $form->generate_check_box('canpostclosedthreads', 1, $lang->can_post_closed_threads, array('checked' => $mod_data['canpostclosedthreads'], 'id' => 'canpostclosedthreads')), - $form->generate_check_box('canmovetononmodforum', 1, $lang->can_move_to_other_forums, array('checked' => $mod_data['canmovetononmodforum'], 'id' => 'canmovetononmodforum')), - $form->generate_check_box('canusecustomtools', 1, $lang->can_use_custom_tools, array('checked' => $mod_data['canusecustomtools'], 'id' => 'canusecustomtools')) - ); - $form_container->output_row($lang->moderator_permissions, "", "
".implode("
", $moderator_permissions)."
"); - - $moderator_cp_permissions = array( - $form->generate_check_box('canmanageannouncements', 1, $lang->can_manage_announcements, array('checked' => $mod_data['canmanageannouncements'], 'id' => 'canmanageannouncements')), - $form->generate_check_box('canmanagereportedposts', 1, $lang->can_manage_reported_posts, array('checked' => $mod_data['canmanagereportedposts'], 'id' => 'canmanagereportedposts')), - $form->generate_check_box('canviewmodlog', 1, $lang->can_view_mod_log, array('checked' => $mod_data['canviewmodlog'], 'id' => 'canviewmodlog')) - ); - $form_container->output_row($lang->moderator_cp_permissions, $lang->moderator_cp_permissions_desc, "
".implode("
", $moderator_cp_permissions)."
"); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_mod); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "clear_permission") -{ - $pid = $mybb->get_input('pid', MyBB::INPUT_INT); - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - $gid = $mybb->get_input('gid', MyBB::INPUT_INT); - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=forum-management&fid={$fid}"); - } - - $plugins->run_hooks("admin_forum_management_clear_permission"); - - if($mybb->request_method == "post") - { - if((!$fid || !$gid) && $pid) - { - $query = $db->simple_select("forumpermissions", "fid, gid", "pid='{$pid}'"); - $result = $db->fetch_array($query); - $fid = $result['fid']; - $gid = $result['gid']; - } - - if($pid) - { - $db->delete_query("forumpermissions", "pid='{$pid}'"); - } - else - { - $db->delete_query("forumpermissions", "gid='{$gid}' AND fid='{$fid}'"); - } - - $plugins->run_hooks('admin_forum_management_clear_permission_commit'); - - $cache->update_forumpermissions(); - - flash_message($lang->success_custom_permission_cleared, 'success'); - admin_redirect("index.php?module=forum-management&fid={$fid}#tab_permissions"); - } - else - { - $page->output_confirm_action("index.php?module=forum-management&action=clear_permission&pid={$pid}&gid={$gid}&fid={$fid}", $lang->confirm_clear_custom_permission); - } -} - -if($mybb->input['action'] == "permissions") -{ - $plugins->run_hooks("admin_forum_management_permissions"); - - if($mybb->request_method == "post") - { - $pid = $mybb->get_input('pid', MyBB::INPUT_INT); - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - $gid = $mybb->get_input('gid', MyBB::INPUT_INT); - $forum = get_forum($fid); - - if((!$fid || !$gid) && $pid) - { - $query = $db->simple_select("forumpermissions", "fid, gid", "pid='{$pid}'"); - $result = $db->fetch_array($query); - $fid = $result['fid']; - $gid = $result['gid']; - $forum = get_forum($fid); - } - - $field_list = array(); - $fields_array = $db->show_fields_from("forumpermissions"); - if(is_array($mybb->input['permissions'])) - { - // User has set permissions for this group... - foreach($fields_array as $field) - { - if(strpos($field['Field'], 'can') !== false || strpos($field['Field'], 'mod') !== false) - { - if(array_key_exists($field['Field'], $mybb->input['permissions'])) - { - $update_array[$db->escape_string($field['Field'])] = (int)$mybb->input['permissions'][$field['Field']]; - } - else - { - $update_array[$db->escape_string($field['Field'])] = 0; - } - } - } - } - else - { - // Else, we assume that the group has no permissions... - foreach($fields_array as $field) - { - if(strpos($field['Field'], 'can') !== false || strpos($field['Field'], 'mod') !== false) - { - $update_array[$db->escape_string($field['Field'])] = 0; - } - } - } - - if($fid && !$pid) - { - $update_array['fid'] = $fid; - $update_array['gid'] = $mybb->get_input('gid', MyBB::INPUT_INT); - $db->insert_query("forumpermissions", $update_array); - } - - $plugins->run_hooks("admin_forum_management_permissions_commit"); - - if(!($fid && !$pid)) - { - $db->update_query("forumpermissions", $update_array, "pid='{$pid}'"); - } - - $cache->update_forumpermissions(); - - // Log admin action - log_admin_action($fid, $forum['name']); - - if($mybb->input['ajax'] == 1) - { - echo json_encode(""); - die; - } - else - { - flash_message($lang->success_forum_permissions_saved, 'success'); - admin_redirect("index.php?module=forum-management&fid={$fid}#tab_permissions"); - } - } - - if($mybb->input['ajax'] != 1) - { - $sub_tabs = array(); - - if($mybb->input['fid'] && $mybb->input['gid']) - { - $sub_tabs['edit_permissions'] = array( - 'title' => $lang->forum_permissions, - 'link' => "index.php?module=forum-management&action=permissions&fid=".$mybb->input['fid']."&gid=".$mybb->input['gid'], - 'description' => $lang->forum_permissions_desc - ); - - $page->add_breadcrumb_item($lang->forum_permissions2, "index.php?module=forum-management&fid=".$mybb->input['fid']."#tab_permissions"); - } - else - { - $query = $db->simple_select("forumpermissions", "fid", "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - $mybb->input['fid'] = $db->fetch_field($query, "fid"); - - $sub_tabs['edit_permissions'] = array( - 'title' => $lang->forum_permissions, - 'link' => "index.php?module=forum-management&action=permissions&pid=".$mybb->get_input('pid', MyBB::INPUT_INT), - 'description' => $lang->forum_permissions_desc - ); - - $page->add_breadcrumb_item($lang->forum_permissions2, "index.php?module=forum-management&fid=".$mybb->input['fid']."#tab_permissions"); - } - - $page->add_breadcrumb_item($lang->forum_permissions); - $page->output_header($lang->forum_permissions); - $page->output_nav_tabs($sub_tabs, 'edit_permissions'); - } - else - { - echo " -
- \n - -
"; - } - - if($mybb->input['pid'] || ($mybb->input['gid'] && $mybb->input['fid'])) - { - if($mybb->input['ajax'] != 1) - { - $form = new Form("index.php?module=forum-management&action=permissions", "post"); - } - else - { - $form = new Form("index.php?module=forum-management&action=permissions&ajax=1&pid=".$mybb->get_input('pid', MyBB::INPUT_INT)."&gid=".$mybb->get_input('gid', MyBB::INPUT_INT)."&fid=".$mybb->get_input('gid', MyBB::INPUT_INT), "post", "modal_form"); - } - echo $form->generate_hidden_field("usecustom", "1"); - - if($errors) - { - $page->output_inline_error($errors); - $permission_data = $mybb->input; - - $query = $db->simple_select("usergroups", "*", "gid='{$permission_data['gid']}'"); - $usergroup = $db->fetch_array($query); - - $query = $db->simple_select("forums", "*", "fid='{$permission_data['fid']}'"); - $forum = $db->fetch_array($query); - } - else - { - $pid = $mybb->get_input('pid', MyBB::INPUT_INT); - $gid = $mybb->get_input('gid', MyBB::INPUT_INT); - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - - if($pid) - { - $query = $db->simple_select("forumpermissions", "*", "pid='{$pid}'"); - } - else - { - $query = $db->simple_select("forumpermissions", "*", "fid='{$fid}' AND gid='{$gid}'", array('limit' => 1)); - } - - $permission_data = $db->fetch_array($query); - - if(!$fid) - { - $fid = $permission_data['fid']; - } - - if(!$gid) - { - $gid = $permission_data['gid']; - } - - if(!$pid) - { - $pid = $permission_data['pid']; - } - - $query = $db->simple_select("usergroups", "*", "gid='$gid'"); - $usergroup = $db->fetch_array($query); - - $query = $db->simple_select("forums", "*", "fid='$fid'"); - $forum = $db->fetch_array($query); - - $sperms = $permission_data; - - $sql = build_parent_list($fid); - $query = $db->simple_select("forumpermissions", "*", "$sql AND gid='$gid'"); - $customperms = $db->fetch_array($query); - - if($permission_data['pid']) - { - $permission_data['usecustom'] = 1; - echo $form->generate_hidden_field("pid", $pid); - } - else - { - echo $form->generate_hidden_field("fid", $fid); - echo $form->generate_hidden_field("gid", $gid); - if(!$customperms['pid']) - { - $permission_data = usergroup_permissions($gid); - } - else - { - $permission_data = forum_permissions($fid, 0, $gid); - } - } - } - - $groups = array( - 'canviewthreads' => 'viewing', - 'canview' => 'viewing', - 'canonlyviewownthreads' => 'viewing', - 'candlattachments' => 'viewing', - - 'canpostthreads' => 'posting_rating', - 'canpostreplys' => 'posting_rating', - 'canonlyreplyownthreads' => 'posting_rating', - 'canpostattachments' => 'posting_rating', - 'canratethreads' => 'posting_rating', - - 'caneditposts' => 'editing', - 'candeleteposts' => 'editing', - 'candeletethreads' => 'editing', - 'caneditattachments' => 'editing', - 'canviewdeletionnotice' => 'editing', - - 'modposts' => 'moderate', - 'modthreads' => 'moderate', - 'modattachments' => 'moderate', - 'mod_edit_posts' => 'moderate', - - 'canpostpolls' => 'polls', - 'canvotepolls' => 'polls', - 'cansearch' => 'misc', - ); - - $groups = $plugins->run_hooks("admin_forum_management_permission_groups", $groups); - - $tabs = array(); - foreach(array_unique(array_values($groups)) as $group) - { - $lang_group = "group_".$group; - $tabs[$group] = $lang->$lang_group; - } - - if($mybb->input['ajax'] == 1) - { - $page->output_tab_control($tabs, false, "tabs2"); - } - else - { - $page->output_tab_control($tabs); - } - - $field_list = array(); - $fields_array = $db->show_fields_from("forumpermissions"); - foreach($fields_array as $field) - { - if(strpos($field['Field'], 'can') !== false || strpos($field['Field'], 'mod') !== false) - { - if(array_key_exists($field['Field'], $groups)) - { - $field_list[$groups[$field['Field']]][] = $field['Field']; - } - else - { - $field_list['misc'][] = $field['Field']; - } - } - } - - foreach(array_unique(array_values($groups)) as $group) - { - $lang_group = "group_".$group; - echo "
\n"; - $form_container = new FormContainer("\"".htmlspecialchars_uni($usergroup['title'])."\" {$lang->custom_permissions_for} \"".htmlspecialchars_uni($forum['name'])."\""); - $fields = array(); - foreach($field_list[$group] as $field) - { - $lang_field = $group."_field_".$field; - $fields[] = $form->generate_check_box("permissions[{$field}]", 1, $lang->$lang_field, array('checked' => $permission_data[$field], 'id' => $field)); - } - $form_container->output_row("", "", "
".implode("
", $fields)."
"); - $form_container->end(); - echo "
"; - } - - if($mybb->input['ajax'] == 1) - { - $buttons[] = $form->generate_submit_button($lang->cancel, array('onclick' => '$.modal.close(); return false;')); - $buttons[] = $form->generate_submit_button($lang->save_permissions, array('id' => 'savePermissions')); - $form->output_submit_wrapper($buttons); - $form->end(); - echo "
"; - echo "
"; - } - else - { - $buttons[] = $form->generate_submit_button($lang->save_permissions); - $form->output_submit_wrapper($buttons); - - $form->end(); - } - } - - if($mybb->input['ajax'] != 1) - { - $page->output_footer(); - } -} - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_forum_management_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - $pid = $mybb->get_input('pid', MyBB::INPUT_INT); - $type = $mybb->input['type']; - - if($pid <= 0 && $type == "f") - { - $errors[] = $lang->error_no_parent; - } - - if(!$errors) - { - if($pid < 0) - { - $pid = 0; - } - $insert_array = array( - "name" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "linkto" => $db->escape_string($mybb->input['linkto']), - "type" => $db->escape_string($type), - "pid" => $pid, - "parentlist" => '', - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "active" => $mybb->get_input('active', MyBB::INPUT_INT), - "open" => $mybb->get_input('open', MyBB::INPUT_INT), - "allowhtml" => $mybb->get_input('allowhtml', MyBB::INPUT_INT), - "allowmycode" => $mybb->get_input('allowmycode', MyBB::INPUT_INT), - "allowsmilies" => $mybb->get_input('allowsmilies', MyBB::INPUT_INT), - "allowimgcode" => $mybb->get_input('allowimgcode', MyBB::INPUT_INT), - "allowvideocode" => $mybb->get_input('allowvideocode', MyBB::INPUT_INT), - "allowpicons" => $mybb->get_input('allowpicons', MyBB::INPUT_INT), - "allowtratings" => $mybb->get_input('allowtratings', MyBB::INPUT_INT), - "usepostcounts" => $mybb->get_input('usepostcounts', MyBB::INPUT_INT), - "usethreadcounts" => $mybb->get_input('usethreadcounts', MyBB::INPUT_INT), - "requireprefix" => $mybb->get_input('requireprefix', MyBB::INPUT_INT), - "password" => $db->escape_string($mybb->input['password']), - "showinjump" => $mybb->get_input('showinjump', MyBB::INPUT_INT), - "style" => $mybb->get_input('style', MyBB::INPUT_INT), - "overridestyle" => $mybb->get_input('overridestyle', MyBB::INPUT_INT), - "rulestype" => $mybb->get_input('rulestype', MyBB::INPUT_INT), - "rulestitle" => $db->escape_string($mybb->input['rulestitle']), - "rules" => $db->escape_string($mybb->input['rules']), - "defaultdatecut" => $mybb->get_input('defaultdatecut', MyBB::INPUT_INT), - "defaultsortby" => $db->escape_string($mybb->input['defaultsortby']), - "defaultsortorder" => $db->escape_string($mybb->input['defaultsortorder']), - ); - $fid = $db->insert_query("forums", $insert_array); - - $parentlist = make_parent_list($fid); - $db->update_query("forums", array("parentlist" => $parentlist), "fid='$fid'"); - - $inherit = $mybb->input['default_permissions']; - - foreach($mybb->input as $id => $permission) - { - if(strpos($id, 'fields_') === false) - { - continue; - } - - list(, $gid) = explode('fields_', $id); - - // If it isn't an array then it came from the javascript form - if(!is_array($permission)) - { - $permission = explode(',', $permission); - $permission = array_flip($permission); - foreach($permission as $name => $value) - { - $permission[$name] = 1; - } - } - - foreach(array('canview','canpostthreads','canpostreplys','canpostpolls') as $name) - { - if(in_array($name, $permission) || $permission[$name]) - { - $permissions[$name][$gid] = 1; - } - else - { - $permissions[$name][$gid] = 0; - } - } - } - - $canview = $permissions['canview']; - $canpostthreads = $permissions['canpostthreads']; - $canpostpolls = $permissions['canpostpolls']; - $canpostattachments = $permissions['canpostattachments']; - $canpostreplies = $permissions['canpostreplys']; - save_quick_perms($fid); - - $plugins->run_hooks("admin_forum_management_add_commit"); - - $cache->update_forums(); - - // Log admin action - log_admin_action($fid, $insert_array['name']); - - flash_message($lang->success_forum_added, 'success'); - admin_redirect("index.php?module=forum-management"); - } - } - - $page->extra_header .= "\n"; - - $page->add_breadcrumb_item($lang->add_forum); - $page->output_header($lang->add_forum); - $page->output_nav_tabs($sub_tabs, 'add_forum'); - - $form = new Form("index.php?module=forum-management&action=add", "post"); - - if($errors) - { - $page->output_inline_error($errors); - $forum_data = $mybb->input; - } - else - { - $forum_data['type'] = "f"; - $forum_data['title'] = ""; - $forum_data['description'] = ""; - - if(!$mybb->input['pid']) - { - $forum_data['pid'] = "-1"; - } - else - { - $forum_data['pid'] = $mybb->get_input('pid', MyBB::INPUT_INT); - } - $forum_data['disporder'] = "1"; - $forum_data['linkto'] = ""; - $forum_data['password'] = ""; - $forum_data['active'] = 1; - $forum_data['open'] = 1; - $forum_data['overridestyle'] = ""; - $forum_data['style'] = ""; - $forum_data['rulestype'] = ""; - $forum_data['rulestitle'] = ""; - $forum_data['rules'] = ""; - $forum_data['defaultdatecut'] = ""; - $forum_data['defaultsortby'] = ""; - $forum_data['defaultsortorder'] = ""; - $forum_data['allowhtml'] = ""; - $forum_data['allowmycode'] = 1; - $forum_data['allowsmilies'] = 1; - $forum_data['allowimgcode'] = 1; - $forum_data['allowvideocode'] = 1; - $forum_data['allowpicons'] = 1; - $forum_data['allowtratings'] = 1; - $forum_data['showinjump'] = 1; - $forum_data['usepostcounts'] = 1; - $forum_data['usethreadcounts'] = 1; - $forum_data['requireprefix'] = 0; - } - - $types = array( - 'f' => $lang->forum, - 'c' => $lang->category - ); - - $create_a_options_f = array( - 'id' => 'forum' - ); - - $create_a_options_c = array( - 'id' => 'category' - ); - - if($forum_data['type'] == "f") - { - $create_a_options_f['checked'] = true; - } - else - { - $create_a_options_c['checked'] = true; - } - - $form_container = new FormContainer($lang->add_forum); - $form_container->output_row($lang->forum_type, $lang->forum_type_desc, $form->generate_radio_button('type', 'f', $lang->forum, $create_a_options_f)."
\n".$form->generate_radio_button('type', 'c', $lang->category, $create_a_options_c)); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $forum_data['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->description, "", $form->generate_text_area('description', $forum_data['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->parent_forum." *", $lang->parent_forum_desc, $form->generate_forum_select('pid', $forum_data['pid'], array('id' => 'pid', 'main_option' => $lang->none)), 'pid'); - $form_container->output_row($lang->display_order, "", $form->generate_numeric_field('disporder', $forum_data['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->end(); - - echo ""; - echo "
"; - $form_container = new FormContainer("".$lang->additional_forum_options); - $form_container->output_row($lang->forum_link, $lang->forum_link_desc, $form->generate_text_box('linkto', $forum_data['linkto'], array('id' => 'linkto')), 'linkto'); - $form_container->output_row($lang->forum_password, $lang->forum_password_desc, $form->generate_text_box('password', $forum_data['password'], array('id' => 'password')), 'password'); - - $access_options = array( - $form->generate_check_box('active', 1, $lang->forum_is_active."
\n{$lang->forum_is_active_desc}", array('checked' => $forum_data['active'], 'id' => 'active')), - $form->generate_check_box('open', 1, $lang->forum_is_open."
\n{$lang->forum_is_open_desc}", array('checked' => $forum_data['open'], 'id' => 'open')) - ); - - $form_container->output_row($lang->access_options, "", "
".implode("
", $access_options)."
"); - - $styles = array( - '0' => $lang->use_default - ); - - $query = $db->simple_select("themes", "tid,name", "name!='((master))' AND name!='((master-backup))'", array('order_by' => 'name')); - while($style = $db->fetch_array($query)) - { - $styles[$style['tid']] = htmlspecialchars_uni($style['name']); - } - - $style_options = array( - $form->generate_check_box('overridestyle', 1, $lang->override_user_style, array('checked' => $forum_data['overridestyle'], 'id' => 'overridestyle')), - $lang->forum_specific_style."
\n".$form->generate_select_box('style', $styles, $forum_data['style'], array('id' => 'style')) - ); - - $form_container->output_row($lang->style_options, "", "
".implode("
", $style_options)."
"); - - $display_methods = array( - '0' => $lang->dont_display_rules, - '1' => $lang->display_rules_inline, - '3' => $lang->display_rules_inline_new, - '2' => $lang->display_rules_link - ); - - $forum_rules = array( - $lang->display_method."
\n".$form->generate_select_box('rulestype', $display_methods, $forum_data['rulestype'], array('checked' => $forum_data['rulestype'], 'id' => 'rulestype')), - $lang->title."
\n".$form->generate_text_box('rulestitle', $forum_data['rulestitle'], array('checked' => $forum_data['rulestitle'], 'id' => 'rulestitle')), - $lang->rules."
\n".$form->generate_text_area('rules', $forum_data['rules'], array('checked' => $forum_data['rules'], 'id' => 'rules')) - ); - - $form_container->output_row($lang->forum_rules, "", "
".implode("
", $forum_rules)."
"); - - $default_date_cut = array( - 0 => $lang->board_default, - 1 => $lang->datelimit_1day, - 5 => $lang->datelimit_5days, - 10 => $lang->datelimit_10days, - 20 => $lang->datelimit_20days, - 50 => $lang->datelimit_50days, - 75 => $lang->datelimit_75days, - 100 => $lang->datelimit_100days, - 365 => $lang->datelimit_lastyear, - 9999 => $lang->datelimit_beginning, - ); - - $default_sort_by = array( - "" => $lang->board_default, - "subject" => $lang->sort_by_subject, - "lastpost" => $lang->sort_by_lastpost, - "starter" => $lang->sort_by_starter, - "started" => $lang->sort_by_started, - "rating" => $lang->sort_by_rating, - "replies" => $lang->sort_by_replies, - "views" => $lang->sort_by_views, - ); - - $default_sort_order = array( - "" => $lang->board_default, - "asc" => $lang->sort_order_asc, - "desc" => $lang->sort_order_desc, - ); - - $view_options = array( - $lang->default_date_cut."
\n".$form->generate_select_box('defaultdatecut', $default_date_cut, $forum_data['defaultdatecut'], array('checked' => $forum_data['defaultdatecut'], 'id' => 'defaultdatecut')), - $lang->default_sort_by."
\n".$form->generate_select_box('defaultsortby', $default_sort_by, $forum_data['defaultsortby'], array('checked' => $forum_data['defaultsortby'], 'id' => 'defaultsortby')), - $lang->default_sort_order."
\n".$form->generate_select_box('defaultsortorder', $default_sort_order, $forum_data['defaultsortorder'], array('checked' => $forum_data['defaultsortorder'], 'id' => 'defaultsortorder')), - ); - - $form_container->output_row($lang->default_view_options, "", "
".implode("
", $view_options)."
"); - - $misc_options = array( - $form->generate_check_box('allowhtml', 1, $lang->allow_html, array('checked' => $forum_data['allowhtml'], 'id' => 'allowhtml')), - $form->generate_check_box('allowmycode', 1, $lang->allow_mycode, array('checked' => $forum_data['allowmycode'], 'id' => 'allowmycode')), - $form->generate_check_box('allowsmilies', 1, $lang->allow_smilies, array('checked' => $forum_data['allowsmilies'], 'id' => 'allowsmilies')), - $form->generate_check_box('allowimgcode', 1, $lang->allow_img_code, array('checked' => $forum_data['allowimgcode'], 'id' => 'allowimgcode')), - $form->generate_check_box('allowvideocode', 1, $lang->allow_video_code, array('checked' => $forum_data['allowvideocode'], 'id' => 'allowvideocode')), - $form->generate_check_box('allowpicons', 1, $lang->allow_post_icons, array('checked' => $forum_data['allowpicons'], 'id' => 'allowpicons')), - $form->generate_check_box('allowtratings', 1, $lang->allow_thread_ratings, array('checked' => $forum_data['allowtratings'], 'id' => 'allowtratings')), - $form->generate_check_box('showinjump', 1, $lang->show_forum_jump, array('checked' => $forum_data['showinjump'], 'id' => 'showinjump')), - $form->generate_check_box('usepostcounts', 1, $lang->use_postcounts, array('checked' => $forum_data['usepostcounts'], 'id' => 'usepostcounts')), - $form->generate_check_box('usethreadcounts', 1, $lang->use_threadcounts, array('checked' => $forum_data['usethreadcounts'], 'id' => 'usethreadcounts')), - $form->generate_check_box('requireprefix', 1, $lang->require_thread_prefix, array('checked' => $forum_data['requireprefix'], 'id' => 'requireprefix')) - ); - - $form_container->output_row($lang->misc_options, "", "
".implode("
", $misc_options)."
"); - $form_container->end(); - echo "
"; - - $query = $db->simple_select("usergroups", "*", "", array("order" => "name")); - while($usergroup = $db->fetch_array($query)) - { - $usergroups[$usergroup['gid']] = $usergroup; - } - - $cached_forum_perms = $cache->read("forumpermissions"); - $field_list = array( - 'canview' => $lang->permissions_canview, - 'canpostthreads' => $lang->permissions_canpostthreads, - 'canpostreplys' => $lang->permissions_canpostreplys, - 'canpostpolls' => $lang->permissions_canpostpolls, - ); - - $field_list2 = array( - 'canview' => $lang->perm_drag_canview, - 'canpostthreads' => $lang->perm_drag_canpostthreads, - 'canpostreplys' => $lang->perm_drag_canpostreplys, - 'canpostpolls' => $lang->perm_drag_canpostpolls, - ); - - $ids = array(); - - $form_container = new FormContainer($lang->forum_permissions); - $form_container->output_row_header($lang->permissions_group, array("class" => "align_center", 'style' => 'width: 40%')); - $form_container->output_row_header($lang->overview_allowed_actions, array("class" => "align_center")); - $form_container->output_row_header($lang->overview_disallowed_actions, array("class" => "align_center")); - - if($mybb->request_method == "post") - { - foreach($usergroups as $usergroup) - { - if(isset($mybb->input['fields_'.$usergroup['gid']])) - { - $input_permissions = $mybb->input['fields_'.$usergroup['gid']]; - if(!is_array($input_permissions)) - { - // Convering the comma separated list from Javascript form into a variable - $input_permissions = explode(',' , $input_permissions); - } - foreach($input_permissions as $input_permission) - { - $mybb->input['permissions'][$usergroup['gid']][$input_permission] = 1; - } - } - } - } - - foreach($usergroups as $usergroup) - { - $perms = array(); - if(isset($mybb->input['default_permissions']) && $mybb->input['default_permissions'][$usergroup['gid']]) - { - if(is_array($existing_permissions) && $existing_permissions[$usergroup['gid']]) - { - $perms = $existing_permissions[$usergroup['gid']]; - $default_checked = false; - } - elseif(is_array($cached_forum_perms) && $cached_forum_perms[$forum_data['fid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum_data['fid']][$usergroup['gid']]; - $default_checked = true; - } - else if(is_array($cached_forum_perms) && $cached_forum_perms[$forum_data['pid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum_data['pid']][$usergroup['gid']]; - $default_checked = true; - } - } - - if(!$perms) - { - $perms = $usergroup; - $default_checked = true; - } - - foreach($field_list as $forum_permission => $forum_perm_title) - { - if(isset($mybb->input['permissions'])) - { - if($mybb->input['default_permissions'][$usergroup['gid']]) - { - $default_checked = true; - } - else - { - $default_checked = false; - } - - if($mybb->input['permissions'][$usergroup['gid']][$forum_permission]) - { - $perms_checked[$forum_permission] = 1; - } - else - { - $perms_checked[$forum_permission] = 0; - } - } - else - { - if($perms[$forum_permission] == 1) - { - $perms_checked[$forum_permission] = 1; - } - else - { - $perms_checked[$forum_permission] = 0; - } - } - } - $usergroup['title'] = htmlspecialchars_uni($usergroup['title']); - - if($default_checked) - { - $inherited_text = $lang->inherited_permission; - } - else - { - $inherited_text = $lang->custom_permission; - } - - $form_container->output_cell("{$usergroup['title']}
".$form->generate_check_box("default_permissions[{$usergroup['gid']}]", 1, "", array("id" => "default_permissions_{$usergroup['gid']}", "checked" => $default_checked, "onclick" => $default_click))." "); - - $field_select = "
\n"; - $field_select .= "
    \n"; - foreach($perms_checked as $perm => $value) - { - if($value == 1) - { - $field_select .= "
  • {$field_list2[$perm]}
  • "; - } - } - $field_select .= "
\n"; - $field_select .= "
    \n"; - foreach($perms_checked as $perm => $value) - { - if($value == 0) - { - $field_select .= "
  • {$field_list2[$perm]}
  • "; - } - } - $field_select .= "
\n"; - $field_select .= $form->generate_hidden_field("fields_".$usergroup['gid'], @implode(",", @array_keys($perms_checked, '1')), array('id' => 'fields_'.$usergroup['gid'])); - $field_select = str_replace("'", "\\'", $field_select); - $field_select = str_replace("\n", "", $field_select); - - $field_select = "\n"; - - $field_selected = array(); - foreach($field_list as $forum_permission => $permission_title) - { - $field_options[$forum_permission] = $permission_title; - if($perms_checked[$forum_permission]) - { - $field_selected[] = $forum_permission; - } - } - - $field_select .= "\n"; - $form_container->output_cell($field_select, array('colspan' => 2)); - - $form_container->construct_row(); - - $ids[] = $usergroup['gid']; - } - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_forum); - $form->output_submit_wrapper($buttons); - $form->end(); - - // Write in our JS based field selector - echo "\n"; - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - if(!$mybb->input['fid']) - { - flash_message($lang->error_invalid_fid, 'error'); - admin_redirect("index.php?module=forum-management"); - } - - $query = $db->simple_select("forums", "*", "fid='{$mybb->input['fid']}'"); - $forum_data = $db->fetch_array($query); - if(!$forum_data) - { - flash_message($lang->error_invalid_fid, 'error'); - admin_redirect("index.php?module=forum-management"); - } - - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - - $plugins->run_hooks("admin_forum_management_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - $pid = $mybb->get_input('pid', MyBB::INPUT_INT); - - if($pid == $mybb->input['fid']) - { - $errors[] = $lang->error_forum_parent_itself; - } - else - { - $query = $db->simple_select('forums', 'parentlist', "fid='{$pid}'"); - $parents = explode(',', $db->fetch_field($query, 'parentlist')); - if(in_array($mybb->input['fid'], $parents)) - { - $errors[] = $lang->error_forum_parent_child; - } - } - - $type = $mybb->input['type']; - - if($pid <= 0 && $type == "f") - { - $errors[] = $lang->error_no_parent; - } - - if($type == 'c' && $forum_data['type'] == 'f') - { - $query = $db->simple_select('threads', 'COUNT(tid) as num_threads', "fid = '{$fid}'"); - if($db->fetch_field($query, "num_threads") > 0) - { - $errors[] = $lang->error_not_empty; - } - } - - if(!empty($mybb->input['linkto']) && empty($forum_data['linkto'])) - { - $query = $db->simple_select('threads', 'COUNT(tid) as num_threads', "fid = '{$fid}'", array("limit" => 1)); - if($db->fetch_field($query, "num_threads") > 0) - { - $errors[] = $lang->error_forum_link_not_empty; - } - } - - if(!$errors) - { - if($pid < 0) - { - $pid = 0; - } - $update_array = array( - "name" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "linkto" => $db->escape_string($mybb->input['linkto']), - "type" => $db->escape_string($type), - "pid" => $pid, - "disporder" => $mybb->get_input('disporder', MyBB::INPUT_INT), - "active" => $mybb->get_input('active', MyBB::INPUT_INT), - "open" => $mybb->get_input('open', MyBB::INPUT_INT), - "allowhtml" => $mybb->get_input('allowhtml', MyBB::INPUT_INT), - "allowmycode" => $mybb->get_input('allowmycode', MyBB::INPUT_INT), - "allowsmilies" => $mybb->get_input('allowsmilies', MyBB::INPUT_INT), - "allowimgcode" => $mybb->get_input('allowimgcode', MyBB::INPUT_INT), - "allowvideocode" => $mybb->get_input('allowvideocode', MyBB::INPUT_INT), - "allowpicons" => $mybb->get_input('allowpicons', MyBB::INPUT_INT), - "allowtratings" => $mybb->get_input('allowtratings', MyBB::INPUT_INT), - "usepostcounts" => $mybb->get_input('usepostcounts', MyBB::INPUT_INT), - "usethreadcounts" => $mybb->get_input('usethreadcounts', MyBB::INPUT_INT), - "requireprefix" => $mybb->get_input('requireprefix', MyBB::INPUT_INT), - "password" => $db->escape_string($mybb->input['password']), - "showinjump" => $mybb->get_input('showinjump', MyBB::INPUT_INT), - "style" => $mybb->get_input('style', MyBB::INPUT_INT), - "overridestyle" => $mybb->get_input('overridestyle', MyBB::INPUT_INT), - "rulestype" => $mybb->get_input('rulestype', MyBB::INPUT_INT), - "rulestitle" => $db->escape_string($mybb->input['rulestitle']), - "rules" => $db->escape_string($mybb->input['rules']), - "defaultdatecut" => $mybb->get_input('defaultdatecut', MyBB::INPUT_INT), - "defaultsortby" => $db->escape_string($mybb->input['defaultsortby']), - "defaultsortorder" => $db->escape_string($mybb->input['defaultsortorder']), - ); - $db->update_query("forums", $update_array, "fid='{$fid}'"); - if($pid != $forum_data['pid']) - { - // Update the parentlist of this forum. - $db->update_query("forums", array("parentlist" => make_parent_list($fid)), "fid='{$fid}'"); - - // Rebuild the parentlist of all of the subforums of this forum - switch($db->type) - { - case "sqlite": - case "pgsql": - $query = $db->simple_select("forums", "fid", "','||parentlist||',' LIKE '%,$fid,%'"); - break; - default: - $query = $db->simple_select("forums", "fid", "CONCAT(',',parentlist,',') LIKE '%,$fid,%'"); - } - - while($child = $db->fetch_array($query)) - { - $db->update_query("forums", array("parentlist" => make_parent_list($child['fid'])), "fid='{$child['fid']}'"); - } - } - - $inherit = $mybb->input['default_permissions']; - - foreach($mybb->input as $id => $permission) - { - // Make sure we're only skipping inputs that don't start with "fields_" and aren't fields_default_ or fields_inherit_ - if(strpos($id, 'fields_') === false || (strpos($id, 'fields_default_') !== false || strpos($id, 'fields_inherit_') !== false)) - { - continue; - } - - list(, $gid) = explode('fields_', $id); - - if($mybb->input['fields_default_'.$gid] == $permission && $mybb->input['fields_inherit_'.$gid] == 1) - { - $inherit[$gid] = 1; - continue; - } - $inherit[$gid] = 0; - - // If it isn't an array then it came from the javascript form - if(!is_array($permission)) - { - $permission = explode(',', $permission); - $permission = array_flip($permission); - foreach($permission as $name => $value) - { - $permission[$name] = 1; - } - } - - foreach(array('canview','canpostthreads','canpostreplys','canpostpolls') as $name) - { - if(in_array($name, $permission) || $permission[$name]) - { - $permissions[$name][$gid] = 1; - } - else - { - $permissions[$name][$gid] = 0; - } - } - } - - $cache->update_forums(); - - $canview = $permissions['canview']; - $canpostthreads = $permissions['canpostthreads']; - $canpostpolls = $permissions['canpostpolls']; - $canpostattachments = $permissions['canpostattachments']; - $canpostreplies = $permissions['canpostreplys']; - - save_quick_perms($fid); - - $plugins->run_hooks("admin_forum_management_edit_commit"); - - // Log admin action - log_admin_action($fid, $mybb->input['title']); - - flash_message($lang->success_forum_updated, 'success'); - admin_redirect("index.php?module=forum-management&fid={$fid}"); - } - } - - $page->extra_header .= "\n"; - - $page->add_breadcrumb_item($lang->edit_forum); - $page->output_header($lang->edit_forum); - - $page->output_nav_tabs($sub_tabs, 'edit_forum_settings'); - - $form = new Form("index.php?module=forum-management&action=edit", "post"); - echo $form->generate_hidden_field("fid", $fid); - - if($errors) - { - $page->output_inline_error($errors); - $forum_data = $mybb->input; - } - else - { - $forum_data['title'] = $forum_data['name']; - } - - $query = $db->simple_select("usergroups", "*", "", array("order_dir" => "name")); - while($usergroup = $db->fetch_array($query)) - { - $usergroups[$usergroup['gid']] = $usergroup; - } - - $query = $db->simple_select("forumpermissions", "*", "fid='{$fid}'"); - while($existing = $db->fetch_array($query)) - { - $existing_permissions[$existing['gid']] = $existing; - } - - $types = array( - 'f' => $lang->forum, - 'c' => $lang->category - ); - - $create_a_options_f = array( - 'id' => 'forum' - ); - - $create_a_options_c = array( - 'id' => 'category' - ); - - if($forum_data['type'] == "f") - { - $create_a_options_f['checked'] = true; - } - else - { - $create_a_options_c['checked'] = true; - } - - $form_container = new FormContainer($lang->edit_forum); - $form_container->output_row($lang->forum_type, $lang->forum_type_desc, $form->generate_radio_button('type', 'f', $lang->forum, $create_a_options_f)."
\n".$form->generate_radio_button('type', 'c', $lang->category, $create_a_options_c)); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $forum_data['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->description, "", $form->generate_text_area('description', $forum_data['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->parent_forum." *", $lang->parent_forum_desc, $form->generate_forum_select('pid', $forum_data['pid'], array('id' => 'pid', 'main_option' => $lang->none)), 'pid'); - $form_container->output_row($lang->display_order, "", $form->generate_numeric_field('disporder', $forum_data['disporder'], array('id' => 'disporder', 'min' => 0)), 'disporder'); - $form_container->end(); - - $form_container = new FormContainer($lang->additional_forum_options); - $form_container->output_row($lang->forum_link, $lang->forum_link_desc, $form->generate_text_box('linkto', $forum_data['linkto'], array('id' => 'linkto')), 'linkto'); - $form_container->output_row($lang->forum_password, $lang->forum_password_desc, $form->generate_text_box('password', $forum_data['password'], array('id' => 'password')), 'password'); - - $access_options = array( - $form->generate_check_box('active', 1, $lang->forum_is_active."
\n{$lang->forum_is_active_desc}", array('checked' => $forum_data['active'], 'id' => 'active')), - $form->generate_check_box('open', 1, $lang->forum_is_open."
\n{$lang->forum_is_open_desc}", array('checked' => $forum_data['open'], 'id' => 'open')) - ); - - $form_container->output_row($lang->access_options, "", "
".implode("
", $access_options)."
"); - - $styles = array( - '0' => $lang->use_default - ); - - $query = $db->simple_select("themes", "tid,name", "name!='((master))' AND name!='((master-backup))'", array('order_by' => 'name')); - while($style = $db->fetch_array($query)) - { - $styles[$style['tid']] = $style['name']; - } - - $style_options = array( - $form->generate_check_box('overridestyle', 1, $lang->override_user_style, array('checked' => $forum_data['overridestyle'], 'id' => 'overridestyle')), - $lang->forum_specific_style."
\n".$form->generate_select_box('style', $styles, $forum_data['style'], array('id' => 'style')) - ); - - $form_container->output_row($lang->style_options, "", "
".implode("
", $style_options)."
"); - - $display_methods = array( - '0' => $lang->dont_display_rules, - '1' => $lang->display_rules_inline, - '3' => $lang->display_rules_inline_new, - '2' => $lang->display_rules_link - ); - - $forum_rules = array( - $lang->display_method."
\n".$form->generate_select_box('rulestype', $display_methods, $forum_data['rulestype'], array('checked' => $forum_data['rulestype'], 'id' => 'rulestype')), - $lang->title."
\n".$form->generate_text_box('rulestitle', $forum_data['rulestitle'], array('checked' => $forum_data['rulestitle'], 'id' => 'rulestitle')), - $lang->rules."
\n".$form->generate_text_area('rules', $forum_data['rules'], array('checked' => $forum_data['rules'], 'id' => 'rules')) - ); - - $form_container->output_row($lang->forum_rules, "", "
".implode("
", $forum_rules)."
"); - - $default_date_cut = array( - 0 => $lang->board_default, - 1 => $lang->datelimit_1day, - 5 => $lang->datelimit_5days, - 10 => $lang->datelimit_10days, - 20 => $lang->datelimit_20days, - 50 => $lang->datelimit_50days, - 75 => $lang->datelimit_75days, - 100 => $lang->datelimit_100days, - 365 => $lang->datelimit_lastyear, - 9999 => $lang->datelimit_beginning, - ); - - $default_sort_by = array( - "" => $lang->board_default, - "subject" => $lang->sort_by_subject, - "lastpost" => $lang->sort_by_lastpost, - "starter" => $lang->sort_by_starter, - "started" => $lang->sort_by_started, - "rating" => $lang->sort_by_rating, - "replies" => $lang->sort_by_replies, - "views" => $lang->sort_by_views, - ); - - $default_sort_order = array( - "" => $lang->board_default, - "asc" => $lang->sort_order_asc, - "desc" => $lang->sort_order_desc, - ); - - $view_options = array( - $lang->default_date_cut."
\n".$form->generate_select_box('defaultdatecut', $default_date_cut, $forum_data['defaultdatecut'], array('checked' => $forum_data['defaultdatecut'], 'id' => 'defaultdatecut')), - $lang->default_sort_by."
\n".$form->generate_select_box('defaultsortby', $default_sort_by, $forum_data['defaultsortby'], array('checked' => $forum_data['defaultsortby'], 'id' => 'defaultsortby')), - $lang->default_sort_order."
\n".$form->generate_select_box('defaultsortorder', $default_sort_order, $forum_data['defaultsortorder'], array('checked' => $forum_data['defaultsortorder'], 'id' => 'defaultsortorder')), - ); - - $form_container->output_row($lang->default_view_options, "", "
".implode("
", $view_options)."
"); - - $misc_options = array( - $form->generate_check_box('allowhtml', 1, $lang->allow_html, array('checked' => $forum_data['allowhtml'], 'id' => 'allowhtml')), - $form->generate_check_box('allowmycode', 1, $lang->allow_mycode, array('checked' => $forum_data['allowmycode'], 'id' => 'allowmycode')), - $form->generate_check_box('allowsmilies', 1, $lang->allow_smilies, array('checked' => $forum_data['allowsmilies'], 'id' => 'allowsmilies')), - $form->generate_check_box('allowimgcode', 1, $lang->allow_img_code, array('checked' => $forum_data['allowimgcode'], 'id' => 'allowimgcode')), - $form->generate_check_box('allowvideocode', 1, $lang->allow_video_code, array('checked' => $forum_data['allowvideocode'], 'id' => 'allowvideocode')), - $form->generate_check_box('allowpicons', 1, $lang->allow_post_icons, array('checked' => $forum_data['allowpicons'], 'id' => 'allowpicons')), - $form->generate_check_box('allowtratings', 1, $lang->allow_thread_ratings, array('checked' => $forum_data['allowtratings'], 'id' => 'allowtratings')), - $form->generate_check_box('showinjump', 1, $lang->show_forum_jump, array('checked' => $forum_data['showinjump'], 'id' => 'showinjump')), - $form->generate_check_box('usepostcounts', 1, $lang->use_postcounts, array('checked' => $forum_data['usepostcounts'], 'id' => 'usepostcounts')), - $form->generate_check_box('usethreadcounts', 1, $lang->use_threadcounts, array('checked' => $forum_data['usethreadcounts'], 'id' => 'usethreadcounts')), - $form->generate_check_box('requireprefix', 1, $lang->require_thread_prefix, array('checked' => $forum_data['requireprefix'], 'id' => 'requireprefix')) - ); - - $form_container->output_row($lang->misc_options, "", "
".implode("
", $misc_options)."
"); - $form_container->end(); - - $cached_forum_perms = $cache->read("forumpermissions"); - $field_list = array( - 'canview' => $lang->permissions_canview, - 'canpostthreads' => $lang->permissions_canpostthreads, - 'canpostreplys' => $lang->permissions_canpostreplys, - 'canpostpolls' => $lang->permissions_canpostpolls, - ); - - $field_list2 = array( - 'canview' => $lang->perm_drag_canview, - 'canpostthreads' => $lang->perm_drag_canpostthreads, - 'canpostreplys' => $lang->perm_drag_canpostreplys, - 'canpostpolls' => $lang->perm_drag_canpostpolls, - ); - - $ids = array(); - - $form_container = new FormContainer($lang->sprintf($lang->forum_permissions_in, $forum_data['name'])); - $form_container->output_row_header($lang->permissions_group, array("class" => "align_center", 'style' => 'width: 30%')); - $form_container->output_row_header($lang->overview_allowed_actions, array("class" => "align_center")); - $form_container->output_row_header($lang->overview_disallowed_actions, array("class" => "align_center")); - $form_container->output_row_header($lang->controls, array("class" => "align_center", 'style' => 'width: 120px', 'colspan' => 2)); - - if($mybb->request_method == "post") - { - foreach($usergroups as $usergroup) - { - if(isset($mybb->input['fields_'.$usergroup['gid']])) - { - $input_permissions = $mybb->input['fields_'.$usergroup['gid']]; - if(!is_array($input_permissions)) - { - // Convering the comma separated list from Javascript form into a variable - $input_permissions = explode(',' , $input_permissions); - } - foreach($input_permissions as $input_permission) - { - $mybb->input['permissions'][$usergroup['gid']][$input_permission] = 1; - } - } - } - } - - foreach($usergroups as $usergroup) - { - $perms = array(); - if(isset($mybb->input['default_permissions'])) - { - if($mybb->input['default_permissions'][$usergroup['gid']]) - { - if(is_array($existing_permissions) && $existing_permissions[$usergroup['gid']]) - { - $perms = $existing_permissions[$usergroup['gid']]; - $default_checked = false; - } - elseif(is_array($cached_forum_perms) && $cached_forum_perms[$forum_data['fid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum_data['fid']][$usergroup['gid']]; - $default_checked = true; - } - else if(is_array($cached_forum_perms) && $cached_forum_perms[$forum_data['pid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum_data['pid']][$usergroup['gid']]; - $default_checked = true; - } - } - - if(!$perms) - { - $perms = $usergroup; - $default_checked = true; - } - } - else - { - if(is_array($existing_permissions) && $existing_permissions[$usergroup['gid']]) - { - $perms = $existing_permissions[$usergroup['gid']]; - $default_checked = false; - } - elseif(is_array($cached_forum_perms) && $cached_forum_perms[$forum_data['fid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum_data['fid']][$usergroup['gid']]; - $default_checked = true; - } - else if(is_array($cached_forum_perms) && $cached_forum_perms[$forum_data['pid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum_data['pid']][$usergroup['gid']]; - $default_checked = true; - } - - if(!$perms) - { - $perms = $usergroup; - $default_checked = true; - } - } - - foreach($field_list as $forum_permission => $forum_perm_title) - { - if(isset($mybb->input['permissions'])) - { - if($mybb->input['permissions'][$usergroup['gid']][$forum_permission]) - { - $perms_checked[$forum_permission] = 1; - } - else - { - $perms_checked[$forum_permission] = 0; - } - } - else - { - if($perms[$forum_permission] == 1) - { - $perms_checked[$forum_permission] = 1; - } - else - { - $perms_checked[$forum_permission] = 0; - } - } - } - $usergroup['title'] = htmlspecialchars_uni($usergroup['title']); - - if($default_checked) - { - $inherited_text = $lang->inherited_permission; - } - else - { - $inherited_text = $lang->custom_permission; - } - - $form_container->output_cell("{$usergroup['title']} ({$inherited_text})"); - - $field_select = "
\n"; - $field_select .= "
{$lang->enabled}
    \n"; - foreach($perms_checked as $perm => $value) - { - if($value == 1) - { - $field_select .= "
  • {$field_list2[$perm]}
  • "; - } - } - $field_select .= "
\n"; - $field_select .= "
{$lang->disabled}
    \n"; - foreach($perms_checked as $perm => $value) - { - if($value == 0) - { - $field_select .= "
  • {$field_list2[$perm]}
  • "; - } - } - $field_select .= "
\n"; - $field_select .= $form->generate_hidden_field("fields_".$usergroup['gid'], @implode(",", @array_keys($perms_checked, '1')), array('id' => 'fields_'.$usergroup['gid'])); - $field_select .= $form->generate_hidden_field("fields_inherit_".$usergroup['gid'], (int)$default_checked, array('id' => 'fields_inherit_'.$usergroup['gid'])); - $field_select .= $form->generate_hidden_field("fields_default_".$usergroup['gid'], @implode(",", @array_keys($perms_checked, '1')), array('id' => 'fields_default_'.$usergroup['gid'])); - $field_select = str_replace("'", "\\'", $field_select); - $field_select = str_replace("\n", "", $field_select); - - $field_select = "\n"; - - $field_selected = array(); - foreach($field_list as $forum_permission => $permission_title) - { - $field_options[$forum_permission] = $permission_title; - if($perms_checked[$forum_permission]) - { - $field_selected[] = $forum_permission; - } - } - - $field_select .= "\n"; - $form_container->output_cell($field_select, array('colspan' => 2)); - - if(!$default_checked) - { - $form_container->output_cell("{$lang->edit_permissions}", array("class" => "align_center")); - $form_container->output_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_clear_custom_permission}')\">{$lang->clear_custom_perms}", array("class" => "align_center")); - } - else - { - $form_container->output_cell("{$lang->set_custom_perms}", array("class" => "align_center", "colspan" => 2)); - } - - $form_container->construct_row(array('id' => 'row_'.$usergroup['gid'])); - - $ids[] = $usergroup['gid']; - } - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_forum); - $form->output_submit_wrapper($buttons); - $form->end(); - - // Write in our JS based field selector - echo "\n"; - - $page->output_footer(); -} - -if($mybb->input['action'] == "deletemod") -{ - $modid = $mybb->get_input('id', MyBB::INPUT_INT); - $isgroup = $mybb->get_input('isgroup', MyBB::INPUT_INT); - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - - $query = $db->simple_select("moderators", "*", "id='{$modid}' AND isgroup = '{$isgroup}' AND fid='{$fid}'"); - $mod = $db->fetch_array($query); - - // Does the forum not exist? - if(!$mod['mid']) - { - flash_message($lang->error_invalid_moderator, 'error'); - admin_redirect("index.php?module=forum-management&fid={$fid}"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=forum-management&fid={$fid}"); - } - - $plugins->run_hooks("admin_forum_management_deletemod"); - - if($mybb->request_method == "post") - { - $mid = $mod['mid']; - if($mybb->input['isgroup']) - { - $query = $db->query(" - SELECT m.*, g.title - FROM ".TABLE_PREFIX."moderators m - LEFT JOIN ".TABLE_PREFIX."usergroups g ON (g.gid=m.id) - WHERE m.mid='{$mid}' - "); - } - else - { - $query = $db->query(" - SELECT m.*, u.username, u.usergroup - FROM ".TABLE_PREFIX."moderators m - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=m.id) - WHERE m.mid='{$mid}' - "); - } - $mod = $db->fetch_array($query); - - $db->delete_query("moderators", "mid='{$mid}'"); - - $plugins->run_hooks("admin_forum_management_deletemod_commit"); - - $cache->update_moderators(); - - $forum = get_forum($fid); - - // Log admin action - if($isgroup) - { - log_admin_action($mid, $mod['title'], $forum['fid'], $forum['name']); - } - else - { - log_admin_action($mid, $mod['username'], $forum['fid'], $forum['name']); - } - - flash_message($lang->success_moderator_deleted, 'success'); - admin_redirect("index.php?module=forum-management&fid={$fid}#tab_moderators"); - } - else - { - $page->output_confirm_action("index.php?module=forum-management&action=deletemod&fid={$mod['fid']}&uid={$mod['uid']}", $lang->confirm_moderator_deletion); - } -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("forums", "*", "fid='{$mybb->input['fid']}'"); - $forum = $db->fetch_array($query); - - // Does the forum not exist? - if(!$forum['fid']) - { - flash_message($lang->error_invalid_forum, 'error'); - admin_redirect("index.php?module=forum-management"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=forum-management"); - } - - $plugins->run_hooks("admin_forum_management_delete"); - - if($mybb->request_method == "post") - { - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - $forum_info = get_forum($fid); - - $delquery = ""; - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("forums", "*", "','|| parentlist|| ',' LIKE '%,$fid,%'"); - break; - default: - $query = $db->simple_select("forums", "*", "CONCAT(',', parentlist, ',') LIKE '%,$fid,%'"); - } - while($forum = $db->fetch_array($query)) - { - $fids[$forum['fid']] = $fid; - $delquery .= " OR fid='{$forum['fid']}'"; - } - - require_once MYBB_ROOT.'inc/class_moderation.php'; - $moderation = new Moderation(); - - // Start pagination. Limit results to 50 - $query = $db->simple_select("threads", "tid", "fid='{$fid}' {$delquery}", array("limit" => 50)); - - while($tid = $db->fetch_field($query, 'tid')) - { - $moderation->delete_thread($tid); - } - - // Check whether all threads have been deleted - $query = $db->simple_select("threads", "tid", "fid='{$fid}' {$delquery}"); - - if($db->num_rows($query) > 0) - { - $page->output_header(); - - $form = new Form("index.php?module=forum-management", 'post'); - - echo $form->generate_hidden_field("fid", $fid); - echo $form->generate_hidden_field("action", "delete"); - echo "
\n"; - echo "

{$lang->confirm_proceed_deletion}

\n"; - echo "
\n"; - echo ""; - echo "

\n"; - echo $form->generate_submit_button($lang->proceed, array('class' => 'button_yes', 'id' => 'proceed_button')); - echo "

\n"; - echo "
\n"; - - $form->end(); - - $page->output_footer(); - exit; - } - - // End pagination - - // Delete the forum - $db->delete_query("forums", "fid='$fid'"); - - // Delete subforums - switch($db->type) - { - case "pgsql": - case "sqlite": - $db->delete_query("forums", "','||parentlist||',' LIKE '%,$fid,%'"); - break; - default: - $db->delete_query("forums", "CONCAT(',',parentlist,',') LIKE '%,$fid,%'"); - } - - $db->delete_query('moderators', "fid='{$fid}' {$delquery}"); - $db->delete_query('forumsubscriptions', "fid='{$fid}' {$delquery}"); - $db->delete_query('forumpermissions', "fid='{$fid}' {$delquery}"); - $db->delete_query('announcements', "fid='{$fid}' {$delquery}"); - $db->delete_query('forumsread', "fid='{$fid}' {$delquery}"); - - $plugins->run_hooks("admin_forum_management_delete_commit"); - - $cache->update_forums(); - $cache->update_moderators(); - $cache->update_forumpermissions(); - $cache->update_forumsdisplay(); - - // Log admin action - log_admin_action($forum_info['fid'], $forum_info['name']); - - flash_message($lang->success_forum_deleted, 'success'); - admin_redirect("index.php?module=forum-management"); - } - else - { - $page->output_confirm_action("index.php?module=forum-management&action=delete&fid={$forum['fid']}", $lang->confirm_forum_deletion); - } -} - -if(!$mybb->input['action']) -{ - if(!isset($mybb->input['fid'])) - { - $mybb->input['fid'] = 0; - } - - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - if($fid) - { - $forum = get_forum($fid); - } - - $plugins->run_hooks("admin_forum_management_start"); - - if($mybb->request_method == "post") - { - if($mybb->input['update'] == "permissions") - { - $inherit = array(); - foreach($mybb->input as $id => $permission) - { - // Make sure we're only skipping inputs that don't start with "fields_" and aren't fields_default_ or fields_inherit_ - if(strpos($id, 'fields_') === false || (strpos($id, 'fields_default_') !== false || strpos($id, 'fields_inherit_') !== false)) - { - continue; - } - - list(, $gid) = explode('fields_', $id); - - if($mybb->input['fields_default_'.$gid] == $permission && $mybb->input['fields_inherit_'.$gid] == 1) - { - $inherit[$gid] = 1; - continue; - } - $inherit[$gid] = 0; - - // If it isn't an array then it came from the javascript form - if(!is_array($permission)) - { - $permission = explode(',', $permission); - $permission = array_flip($permission); - foreach($permission as $name => $value) - { - $permission[$name] = 1; - } - } - foreach(array('canview','canpostthreads','canpostreplys','canpostpolls') as $name) - { - if($permission[$name]) - { - $permissions[$name][$gid] = 1; - } - else - { - $permissions[$name][$gid] = 0; - } - } - } - - $canview = $permissions['canview']; - $canpostthreads = $permissions['canpostthreads']; - $canpostpolls = $permissions['canpostpolls']; - $canpostattachments = $permissions['canpostattachments']; - $canpostreplies = $permissions['canpostreplys']; - - save_quick_perms($fid); - - $plugins->run_hooks("admin_forum_management_start_permissions_commit"); - - $cache->update_forums(); - - // Log admin action - log_admin_action('quickpermissions', $fid, $forum['name']); - - flash_message($lang->success_forum_permissions_updated, 'success'); - admin_redirect("index.php?module=forum-management&fid={$fid}#tab_permissions"); - } - elseif($mybb->input['add'] == "moderators") - { - $forum = get_forum($fid); - if(!$forum) - { - flash_message($lang->error_invalid_forum, 'error'); - admin_redirect("index.php?module=forum-management&fid={$fid}#tab_moderators"); - } - if(!empty($mybb->input['usergroup'])) - { - $isgroup = 1; - $gid = $mybb->get_input('usergroup', MyBB::INPUT_INT); - - if(!$groupscache[$gid]) - { - // Didn't select a valid moderator - flash_message($lang->error_moderator_not_found, 'error'); - admin_redirect("index.php?module=forum-management&fid={$fid}#tab_moderators"); - } - - $newmod = array( - "id" => $gid, - "name" => $groupscache[$gid]['title'] - ); - } - else - { - $options = array( - 'fields' => array('uid AS id', 'username AS name') - ); - $newmod = get_user_by_username($mybb->input['username'], $options); - - if(empty($newmod['id'])) - { - flash_message($lang->error_moderator_not_found, 'error'); - admin_redirect("index.php?module=forum-management&fid={$fid}#tab_moderators"); - } - - $isgroup = 0; - } - - if($newmod['id']) - { - $query = $db->simple_select("moderators", "id", "id='".$newmod['id']."' AND fid='".$fid."' AND isgroup='{$isgroup}'", array('limit' => 1)); - - if(!$db->num_rows($query)) - { - $new_mod = array( - "fid" => $fid, - "id" => $newmod['id'], - "isgroup" => $isgroup, - "caneditposts" => 1, - "cansoftdeleteposts" => 1, - "canrestoreposts" => 1, - "candeleteposts" => 1, - "cansoftdeletethreads" => 1, - "canrestorethreads" => 1, - "candeletethreads" => 1, - "canviewips" => 1, - "canviewunapprove" => 1, - "canviewdeleted" => 1, - "canopenclosethreads" => 1, - "canstickunstickthreads" => 1, - "canapproveunapprovethreads" => 1, - "canapproveunapproveposts" => 1, - "canapproveunapproveattachs" => 1, - "canmanagethreads" => 1, - "canmanagepolls" => 1, - "canpostclosedthreads" => 1, - "canmovetononmodforum" => 1, - "canusecustomtools" => 1, - "canmanageannouncements" => 1, - "canmanagereportedposts" => 1, - "canviewmodlog" => 1 - ); - - $mid = $db->insert_query("moderators", $new_mod); - - if(!$isgroup) - { - $db->update_query("users", array('usergroup' => 6), "uid='{$newmod['id']}' AND usergroup='2'"); - } - - $plugins->run_hooks("admin_forum_management_start_moderators_commit"); - - $cache->update_moderators(); - - // Log admin action - log_admin_action('addmod', $mid, $newmod['name'], $fid, $forum['name']); - - flash_message($lang->success_moderator_added, 'success'); - admin_redirect("index.php?module=forum-management&action=editmod&mid={$mid}"); - } - else - { - flash_message($lang->error_moderator_already_added, 'error'); - admin_redirect("index.php?module=forum-management&fid={$fid}#tab_moderators"); - } - } - else - { - flash_message($lang->error_moderator_not_found, 'error'); - admin_redirect("index.php?module=forum-management&fid={$fid}#tab_moderators"); - } - } - else - { - if(!empty($mybb->input['disporder']) && is_array($mybb->input['disporder'])) - { - foreach($mybb->input['disporder'] as $update_fid => $order) - { - $db->update_query("forums", array('disporder' => (int)$order), "fid='".(int)$update_fid."'"); - } - - $plugins->run_hooks("admin_forum_management_start_disporder_commit"); - - $cache->update_forums(); - - // Log admin action - log_admin_action('orders', $forum['fid'], $forum['name']); - - flash_message($lang->success_forum_disporder_updated, 'success'); - admin_redirect("index.php?module=forum-management&fid=".$mybb->input['fid']); - } - } - } - - $page->extra_header .= "\n"; - - if($fid) - { - $page->add_breadcrumb_item($lang->view_forum, "index.php?module=forum-management"); - } - - $page->output_header($lang->forum_management); - - if($fid) - { - $page->output_nav_tabs($sub_tabs, 'view_forum'); - } - else - { - $page->output_nav_tabs($sub_tabs, 'forum_management'); - } - - $form = new Form("index.php?module=forum-management", "post", "management"); - echo $form->generate_hidden_field("fid", $mybb->input['fid']); - - if($fid) - { - $tabs = array( - 'subforums' => $lang->subforums, - 'permissions' => $lang->forum_permissions, - 'moderators' => $lang->moderators, - ); - $tabs = $plugins->run_hooks("admin_forum_management_start_graph_tabs", $tabs); - $page->output_tab_control($tabs); - - echo "
\n"; - if(!isset($forum_cache) || !is_array($forum_cache)) - { - cache_forums(); - } - $form_container = new FormContainer($lang->sprintf($lang->in_forums, $forum_cache[$fid]['name'])); - } - else - { - $form_container = new FormContainer($lang->manage_forums); - } - $form_container->output_row_header($lang->forum); - $form_container->output_row_header($lang->order, array("class" => "align_center", 'width' => '5%')); - $form_container->output_row_header($lang->controls, array("class" => "align_center", 'style' => 'width: 200px')); - - build_admincp_forums_list($form_container, $fid); - - $submit_options = array(); - - if($form_container->num_rows() == 0) - { - $form_container->output_cell($lang->no_forums, array('colspan' => 3)); - $form_container->construct_row(); - $submit_options = array('disabled' => true); - } - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->update_forum_orders, $submit_options); - $buttons[] = $form->generate_reset_button($lang->reset); - - $form->output_submit_wrapper($buttons); - - if(!$fid) - { - $form->end(); - } - - if($fid) - { - echo "
\n"; - $form->end(); - - $query = $db->simple_select("usergroups", "*", "", array("order" => "name")); - while($usergroup = $db->fetch_array($query)) - { - $usergroups[$usergroup['gid']] = $usergroup; - } - - $query = $db->simple_select("forumpermissions", "*", "fid='{$fid}'"); - while($existing = $db->fetch_array($query)) - { - $existing_permissions[$existing['gid']] = $existing; - } - - $cached_forum_perms = $cache->read("forumpermissions"); - $field_list = array( - 'canview' => $lang->permissions_canview, - 'canpostthreads' => $lang->permissions_canpostthreads, - 'canpostreplys' => $lang->permissions_canpostreplys, - 'canpostpolls' => $lang->permissions_canpostpolls, - ); - - $field_list2 = array( - 'canview' => $lang->perm_drag_canview, - 'canpostthreads' => $lang->perm_drag_canpostthreads, - 'canpostreplys' => $lang->perm_drag_canpostreplys, - 'canpostpolls' => $lang->perm_drag_canpostpolls, - ); - - $ids = array(); - - $form = new Form("index.php?module=forum-management", "post", "management"); - echo $form->generate_hidden_field("fid", $mybb->input['fid']); - echo $form->generate_hidden_field("update", "permissions"); - - echo "
\n"; - - $form_container = new FormContainer($lang->sprintf($lang->forum_permissions_in, $forum_cache[$fid]['name'])); - $form_container->output_row_header($lang->permissions_group, array("class" => "align_center", 'style' => 'width: 30%')); - $form_container->output_row_header($lang->overview_allowed_actions, array("class" => "align_center")); - $form_container->output_row_header($lang->overview_disallowed_actions, array("class" => "align_center")); - $form_container->output_row_header($lang->controls, array("class" => "align_center", 'style' => 'width: 120px', 'colspan' => 2)); - foreach($usergroups as $usergroup) - { - $perms = array(); - if(isset($mybb->input['default_permissions'])) - { - if($mybb->input['default_permissions'][$usergroup['gid']]) - { - if(is_array($existing_permissions) && $existing_permissions[$usergroup['gid']]) - { - $perms = $existing_permissions[$usergroup['gid']]; - $default_checked = false; - } - elseif(is_array($cached_forum_perms) && $cached_forum_perms[$forum['fid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum['fid']][$usergroup['gid']]; - $default_checked = true; - } - else if(is_array($cached_forum_perms) && $cached_forum_perms[$forum['pid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum['pid']][$usergroup['gid']]; - $default_checked = true; - } - } - - if(!$perms) - { - $perms = $usergroup; - $default_checked = true; - } - } - else - { - if(isset($existing_permissions) && is_array($existing_permissions) && $existing_permissions[$usergroup['gid']]) - { - $perms = $existing_permissions[$usergroup['gid']]; - $default_checked = false; - } - elseif(is_array($cached_forum_perms) && isset($cached_forum_perms[$forum['fid']]) && $cached_forum_perms[$forum['fid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum['fid']][$usergroup['gid']]; - $default_checked = true; - } - else if(is_array($cached_forum_perms) && $cached_forum_perms[$forum['pid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum['pid']][$usergroup['gid']]; - $default_checked = true; - } - - if(!$perms) - { - $perms = $usergroup; - $default_checked = true; - } - } - foreach($field_list as $forum_permission => $forum_perm_title) - { - if(isset($mybb->input['permissions'])) - { - if($mybb->input['permissions'][$usergroup['gid']][$forum_permission]) - { - $perms_checked[$forum_permission] = 1; - } - else - { - $perms_checked[$forum_permission] = 0; - } - } - else - { - if($perms[$forum_permission] == 1) - { - $perms_checked[$forum_permission] = 1; - } - else - { - $perms_checked[$forum_permission] = 0; - } - } - } - $usergroup['title'] = htmlspecialchars_uni($usergroup['title']); - - if($default_checked == 1) - { - $inherited_text = $lang->inherited_permission; - } - else - { - $inherited_text = $lang->custom_permission; - } - - $form_container->output_cell("{$usergroup['title']} ({$inherited_text})"); - - $field_select = "
\n"; - $field_select .= "
    \n"; - foreach($perms_checked as $perm => $value) - { - if($value == 1) - { - $field_select .= "
  • {$field_list2[$perm]}
  • "; - } - } - $field_select .= "
\n"; - $field_select .= "
    \n"; - foreach($perms_checked as $perm => $value) - { - if($value == 0) - { - $field_select .= "
  • {$field_list2[$perm]}
  • "; - } - } - $field_select .= "
\n"; - $field_select .= $form->generate_hidden_field("fields_".$usergroup['gid'], @implode(",", @array_keys($perms_checked, '1')), array('id' => 'fields_'.$usergroup['gid'])); - $field_select .= $form->generate_hidden_field("fields_inherit_".$usergroup['gid'], (int)$default_checked, array('id' => 'fields_inherit_'.$usergroup['gid'])); - $field_select .= $form->generate_hidden_field("fields_default_".$usergroup['gid'], @implode(",", @array_keys($perms_checked, '1')), array('id' => 'fields_default_'.$usergroup['gid'])); - $field_select = str_replace("'", "\\'", $field_select); - $field_select = str_replace("\n", "", $field_select); - - $field_select = "\n"; - - $field_selected = array(); - foreach($field_list as $forum_permission => $permission_title) - { - $field_options[$forum_permission] = $permission_title; - if($perms_checked[$forum_permission]) - { - $field_selected[] = $forum_permission; - } - } - - $field_select .= "\n"; - $form_container->output_cell($field_select, array('colspan' => 2)); - - if(!$default_checked) - { - $form_container->output_cell("{$lang->edit_permissions}", array("class" => "align_center")); - $form_container->output_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_clear_custom_permission}')\">{$lang->clear_custom_perms}", array("class" => "align_center")); - } - else - { - $form_container->output_cell("{$lang->set_custom_perms}", array("class" => "align_center", "colspan" => 2)); - } - $form_container->construct_row(array('id' => 'row_'.$usergroup['gid'])); - - $ids[] = $usergroup['gid']; - } - $form_container->end(); - - $buttons = array(); - $buttons[] = $form->generate_submit_button($lang->update_forum_permissions); - $buttons[] = $form->generate_reset_button($lang->reset); - - $form->output_submit_wrapper($buttons); - - // Write in our JS based field selector - echo "\n"; - - echo "
\n"; - $form->end(); - echo "
\n"; - $form_container = new FormContainer($lang->sprintf($lang->moderators_assigned_to, $forum_cache[$fid]['name'])); - $form_container->output_row_header($lang->name, array('width' => '75%')); - $form_container->output_row_header($lang->controls, array("class" => "align_center", 'style' => 'width: 200px', 'colspan' => 2)); - $query = $db->query(" - SELECT m.mid, m.id, m.isgroup, u.username, g.title - FROM ".TABLE_PREFIX."moderators m - LEFT JOIN ".TABLE_PREFIX."users u ON (m.isgroup='0' AND m.id=u.uid) - LEFT JOIN ".TABLE_PREFIX."usergroups g ON (m.isgroup='1' AND m.id=g.gid) - WHERE fid='{$fid}' - ORDER BY m.isgroup DESC, u.username, g.title - "); - while($moderator = $db->fetch_array($query)) - { - if($moderator['isgroup']) - { - $moderator['img'] = "style}/images/icons/group.png\" alt=\"{$lang->group}\" title=\"{$lang->group}\" />"; - $form_container->output_cell("{$moderator['img']} ".htmlspecialchars_uni($moderator['title'])." ({$lang->usergroup} {$moderator['id']})"); - $form_container->output_cell("{$lang->edit}", array("class" => "align_center")); - $form_container->output_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_moderator_deletion}')\">{$lang->delete}", array("class" => "align_center")); - } - else - { - $moderator['img'] = "style}/images/icons/user.png\" alt=\"{$lang->user}\" title=\"{$lang->user}\" />"; - $form_container->output_cell("{$moderator['img']} ".htmlspecialchars_uni($moderator['username']).""); - $form_container->output_cell("{$lang->edit}", array("class" => "align_center")); - $form_container->output_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_moderator_deletion}')\">{$lang->delete}", array("class" => "align_center")); - } - $form_container->construct_row(); - } - - if($form_container->num_rows() == 0) - { - $form_container->output_cell($lang->no_moderators, array('colspan' => 3)); - $form_container->construct_row(); - } - $form_container->end(); - - // Users - $buttons = array(); - $form = new Form("index.php?module=forum-management", "post", "management"); - echo $form->generate_hidden_field("fid", $mybb->input['fid']); - echo $form->generate_hidden_field("add", "moderators"); - - // Usergroup Moderator - if(!is_array($usergroups)) - { - $usergroups = $groupscache; - } - - foreach($usergroups as $group) - { - $modgroups[$group['gid']] = $lang->usergroup." ".$group['gid'].": ".htmlspecialchars_uni($group['title']); - } - - if(!isset($mybb->input['usergroup'])) - { - $mybb->input['usergroup'] = ''; - } - - if(!isset($mybb->input['username'])) - { - $mybb->input['username'] = ''; - } - - $form_container = new FormContainer($lang->add_usergroup_as_moderator); - $form_container->output_row($lang->usergroup." *", $lang->moderator_usergroup_desc, $form->generate_select_box('usergroup', $modgroups, $mybb->input['usergroup'], array('id' => 'usergroup')), 'usergroup'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->add_usergroup_moderator); - $form->output_submit_wrapper($buttons); - $form->end(); - echo "
"; - - $form = new Form("index.php?module=forum-management", "post", "management"); - echo $form->generate_hidden_field("fid", $mybb->input['fid']); - echo $form->generate_hidden_field("add", "moderators"); - $form_container = new FormContainer($lang->add_user_as_moderator); - $form_container->output_row($lang->username." *", $lang->moderator_username_desc, $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'username'); - $form_container->end(); - - // Autocompletion for usernames - echo ' - - - '; - - $buttons = array($form->generate_submit_button($lang->add_user_moderator)); - $form->output_submit_wrapper($buttons); - $form->end(); - - echo "
\n"; - - $plugins->run_hooks("admin_forum_management_start_graph"); - } - - $page->output_footer(); -} - -/** - * @param DefaultFormContainer $form_container - * @param int $pid - * @param int $depth - */ -function build_admincp_forums_list(&$form_container, $pid=0, $depth=1) -{ - global $mybb, $lang, $db, $sub_forums; - static $forums_by_parent; - - if(!is_array($forums_by_parent)) - { - $forum_cache = cache_forums(); - - foreach($forum_cache as $forum) - { - $forums_by_parent[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; - } - } - - if(!is_array($forums_by_parent[$pid])) - { - return; - } - - foreach($forums_by_parent[$pid] as $children) - { - foreach($children as $forum) - { - $forum['name'] = preg_replace("#&(?!\#[0-9]+;)#si", "&", $forum['name']); // Fix & but allow unicode - - if($forum['active'] == 0) - { - $forum['name'] = "".$forum['name'].""; - } - - if($forum['type'] == "c" && ($depth == 1 || $depth == 2)) - { - $sub_forums = ''; - if(isset($forums_by_parent[$forum['fid']]) && $depth == 2) - { - build_admincp_forums_list($form_container, $forum['fid'], $depth+1); - } - if($sub_forums) - { - $sub_forums = "
{$lang->sub_forums}: {$sub_forums}"; - } - - $form_container->output_cell("
{$forum['name']}{$sub_forums}
"); - - $form_container->output_cell("", array("class" => "align_center")); - - $popup = new PopupMenu("forum_{$forum['fid']}", $lang->options); - $popup->add_item($lang->edit_forum, "index.php?module=forum-management&action=edit&fid={$forum['fid']}"); - $popup->add_item($lang->subforums, "index.php?module=forum-management&fid={$forum['fid']}"); - $popup->add_item($lang->moderators, "index.php?module=forum-management&fid={$forum['fid']}#tab_moderators"); - $popup->add_item($lang->permissions, "index.php?module=forum-management&fid={$forum['fid']}#tab_permissions"); - $popup->add_item($lang->add_child_forum, "index.php?module=forum-management&action=add&pid={$forum['fid']}"); - $popup->add_item($lang->copy_forum, "index.php?module=forum-management&action=copy&fid={$forum['fid']}"); - $popup->add_item($lang->delete_forum, "index.php?module=forum-management&action=delete&fid={$forum['fid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_forum_deletion}')"); - - $form_container->output_cell($popup->fetch(), array("class" => "align_center")); - - $form_container->construct_row(); - - // Does this category have any sub forums? - if($forums_by_parent[$forum['fid']]) - { - build_admincp_forums_list($form_container, $forum['fid'], $depth+1); - } - } - elseif($forum['type'] == "f" && ($depth == 1 || $depth == 2)) - { - if($forum['description']) - { - $forum['description'] = preg_replace("#&(?!\#[0-9]+;)#si", "&", $forum['description']); - $forum['description'] = "
".$forum['description'].""; - } - - $sub_forums = ''; - if(isset($forums_by_parent[$forum['fid']]) && $depth == 2) - { - build_admincp_forums_list($form_container, $forum['fid'], $depth+1); - } - if($sub_forums) - { - $sub_forums = "
{$lang->sub_forums}: {$sub_forums}"; - } - - $form_container->output_cell("
{$forum['name']}{$forum['description']}{$sub_forums}
"); - - $form_container->output_cell("", array("class" => "align_center")); - - $popup = new PopupMenu("forum_{$forum['fid']}", $lang->options); - $popup->add_item($lang->edit_forum, "index.php?module=forum-management&action=edit&fid={$forum['fid']}"); - $popup->add_item($lang->subforums, "index.php?module=forum-management&fid={$forum['fid']}"); - $popup->add_item($lang->moderators, "index.php?module=forum-management&fid={$forum['fid']}#tab_moderators"); - $popup->add_item($lang->permissions, "index.php?module=forum-management&fid={$forum['fid']}#tab_permissions"); - $popup->add_item($lang->add_child_forum, "index.php?module=forum-management&action=add&pid={$forum['fid']}"); - $popup->add_item($lang->copy_forum, "index.php?module=forum-management&action=copy&fid={$forum['fid']}"); - $popup->add_item($lang->delete_forum, "index.php?module=forum-management&action=delete&fid={$forum['fid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_forum_deletion}')"); - - $form_container->output_cell($popup->fetch(), array("class" => "align_center")); - - $form_container->construct_row(); - - if(isset($forums_by_parent[$forum['fid']]) && $depth == 1) - { - build_admincp_forums_list($form_container, $forum['fid'], $depth+1); - } - } - else if($depth == 3) - { - if($donecount < $mybb->settings['subforumsindex']) - { - $sub_forums .= "{$comma} {$forum['name']}"; - $comma = $lang->comma; - } - - // Have we reached our max visible subforums? put a nice message and break out of the loop - ++$donecount; - if($donecount == $mybb->settings['subforumsindex']) - { - if(subforums_count($forums_by_parent[$pid]) > $donecount) - { - $sub_forums .= $comma.$lang->sprintf($lang->more_subforums, (subforums_count($forums_by_parent[$pid]) - $donecount)); - return; - } - } - } - } - } -} - -/** - * @param int $gid - * @param int $fid - * - * @return string - */ -function retrieve_single_permissions_row($gid, $fid) -{ - global $mybb, $lang, $cache, $db; - - $query = $db->simple_select("usergroups", "*", "gid='{$gid}'"); - $usergroup = $db->fetch_array($query); - - $query = $db->simple_select("forums", "*", "fid='{$fid}'"); - $forum_data = $db->fetch_array($query); - - $query = $db->simple_select("forumpermissions", "*", "fid='{$fid}'"); - while($existing = $db->fetch_array($query)) - { - $existing_permissions[$existing['gid']] = $existing; - } - - $cached_forum_perms = $cache->read("forumpermissions"); - $field_list = array( - 'canview' => $lang->permissions_canview, - 'canpostthreads' => $lang->permissions_canpostthreads, - 'canpostreplys' => $lang->permissions_canpostreplys, - 'canpostpolls' => $lang->permissions_canpostpolls, - ); - - $field_list2 = array( - 'canview' => $lang->perm_drag_canview, - 'canpostthreads' => $lang->perm_drag_canpostthreads, - 'canpostreplys' => $lang->perm_drag_canpostreplys, - 'canpostpolls' => $lang->perm_drag_canpostpolls, - ); - - $form = new Form('', '', "", 0, "", true); - $form_container = new FormContainer(); - - $perms = array(); - - if(is_array($existing_permissions) && $existing_permissions[$usergroup['gid']]) - { - $perms = $existing_permissions[$usergroup['gid']]; - $default_checked = false; - } - elseif(is_array($cached_forum_perms) && $cached_forum_perms[$forum_data['fid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum_data['fid']][$usergroup['gid']]; - $default_checked = true; - } - else if(is_array($cached_forum_perms) && $cached_forum_perms[$forum_data['pid']][$usergroup['gid']]) - { - $perms = $cached_forum_perms[$forum_data['pid']][$usergroup['gid']]; - $default_checked = true; - } - - if(!$perms) - { - $perms = $usergroup; - $default_checked = true; - } - - foreach($field_list as $forum_permission => $forum_perm_title) - { - if($perms[$forum_permission] == 1) - { - $perms_checked[$forum_permission] = 1; - } - else - { - $perms_checked[$forum_permission] = 0; - } - } - - $usergroup['title'] = htmlspecialchars_uni($usergroup['title']); - - if($default_checked == 1) - { - $inherited_text = $lang->inherited_permission; - } - else - { - $inherited_text = $lang->custom_permission; - } - - $form_container->output_cell("{$usergroup['title']} ({$inherited_text})"); - - $field_select = "
\n"; - $field_select .= "
{$lang->enabled}
    \n"; - foreach($perms_checked as $perm => $value) - { - if($value == 1) - { - $field_select .= "
  • {$field_list2[$perm]}
  • "; - } - } - $field_select .= "
\n"; - $field_select .= "
{$lang->disabled}
    \n"; - foreach($perms_checked as $perm => $value) - { - if($value == 0) - { - $field_select .= "
  • {$field_list2[$perm]}
  • "; - } - } - $field_select .= "
\n"; - $field_select .= $form->generate_hidden_field("fields_".$usergroup['gid'], @implode(",", @array_keys($perms_checked, 1)), array('id' => 'fields_'.$usergroup['gid'])); - $field_select = str_replace("\n", "", $field_select); - - foreach($field_list as $forum_permission => $permission_title) - { - $field_options[$forum_permission] = $permission_title; - } - $form_container->output_cell($field_select, array('colspan' => 2)); - - if(!$default_checked) - { - $form_container->output_cell("{$lang->edit_permissions}", array("class" => "align_center")); - $form_container->output_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_clear_custom_permission}')\">{$lang->clear_custom_perms}", array("class" => "align_center")); - } - else - { - $form_container->output_cell("{$lang->set_custom_perms}", array("class" => "align_center", "colspan" => 2)); - } - $form_container->construct_row(); - return $form_container->output_row_cells(0, true); -} - diff --git a/html/forums/admin/modules/forum/moderation_queue.php b/html/forums/admin/modules/forum/moderation_queue.php deleted file mode 100644 index dab78ac..0000000 --- a/html/forums/admin/modules/forum/moderation_queue.php +++ /dev/null @@ -1,567 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->moderation_queue, "index.php?module=forum-moderation_queue"); - -$sub_tabs['threads'] = array( - 'title' => $lang->threads, - 'link' => "index.php?module=forum-moderation_queue&type=threads", - 'description' => $lang->threads_desc -); - -$sub_tabs['posts'] = array( - 'title' => $lang->posts, - 'link' => "index.php?module=forum-moderation_queue&type=posts", - 'description' => $lang->posts_desc -); - -$sub_tabs['attachments'] = array( - 'title' => $lang->attachments, - 'link' => "index.php?module=forum-moderation_queue&type=attachments", - 'description' => $lang->attachments_desc -); - -$plugins->run_hooks("admin_forum_moderation_queue_begin"); - -// Actually performing our moderation choices -if($mybb->request_method == "post") -{ - $plugins->run_hooks("admin_forum_moderation_queue_commit"); - - require_once MYBB_ROOT."inc/functions_upload.php"; - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation; - - if(is_array($mybb->input['threads'])) - { - $threads_to_approve = $threads_to_delete = array(); - // Fetch threads - $query = $db->simple_select("threads", "tid", "tid IN (".implode(",", array_map("intval", array_keys($mybb->input['threads'])))."){$flist}"); - while($thread = $db->fetch_array($query)) - { - $action = $mybb->input['threads'][$thread['tid']]; - if($action == "approve") - { - $threads_to_approve[] = $thread['tid']; - } - else if($action == "delete" && $mybb->settings['soft_delete'] != 1) - { - $moderation->delete_thread($thread['tid']); - } - else if($action == "delete") - { - $threads_to_delete[] = $thread['tid']; - } - } - if(!empty($threads_to_approve)) - { - $moderation->approve_threads($threads_to_approve); - } - if(!empty($threads_to_delete)) - { - $moderation->soft_delete_threads($threads_to_delete); - } - - $plugins->run_hooks("admin_forum_moderation_queue_threads_commit"); - - // Log admin action - log_admin_action('threads'); - - flash_message($lang->success_threads, 'success'); - admin_redirect("index.php?module=forum-moderation_queue&type=threads"); - } - else if(is_array($mybb->input['posts'])) - { - $posts_to_approve = $posts_to_delete = array(); - // Fetch posts - $query = $db->simple_select("posts", "pid", "pid IN (".implode(",", array_map("intval", array_keys($mybb->input['posts'])))."){$flist}"); - while($post = $db->fetch_array($query)) - { - $action = $mybb->input['posts'][$post['pid']]; - if($action == "approve") - { - $posts_to_approve[] = $post['pid']; - } - else if($action == "delete" && $mybb->settings['soft_delete'] != 1) - { - $moderation->delete_post($post['pid']); - } - else if($action == "delete") - { - $posts_to_delete[] = $post['pid']; - } - } - if(!empty($posts_to_approve)) - { - $moderation->approve_posts($posts_to_approve); - } - if(!empty($posts_to_delete)) - { - $moderation->soft_delete_posts($posts_to_delete); - } - - $plugins->run_hooks("admin_forum_moderation_queue_posts_commit"); - - // Log admin action - log_admin_action('posts'); - - flash_message($lang->success_posts, 'success'); - admin_redirect("index.php?module=forum-moderation_queue&type=posts"); - - } - else if(is_array($mybb->input['attachments'])) - { - $query = $db->simple_select("attachments", "aid, pid", "aid IN (".implode(",", array_map("intval", array_keys($mybb->input['attachments'])))."){$flist}"); - while($attachment = $db->fetch_array($query)) - { - $action = $mybb->input['attachments'][$attachment['aid']]; - if($action == "approve") - { - $db->update_query("attachments", array("visible" => 1), "aid='{$attachment['aid']}'"); - } - else if($action == "delete") - { - remove_attachment($attachment['pid'], '', $attachment['aid']); - } - } - - $plugins->run_hooks("admin_forum_moderation_queue_attachments_commit"); - - // Log admin action - log_admin_action('attachments'); - - flash_message($lang->success_attachments, 'success'); - admin_redirect("index.php?module=forum-moderation_queue&type=attachments"); - } -} - -$all_options = "\n"; - -// Threads awaiting moderation -if($mybb->input['type'] == "threads" || !$mybb->input['type']) -{ - $plugins->run_hooks("admin_forum_moderation_queue_threads"); - - $forum_cache = $cache->read("forums"); - - $query = $db->simple_select("threads", "COUNT(tid) AS unapprovedthreads", "visible=0"); - $unapproved_threads = $db->fetch_field($query, "unapprovedthreads"); - - if($unapproved_threads > 0) - { - // Figure out if we need to display multiple pages. - $per_page = 15; - if($mybb->input['page'] > 0) - { - $current_page = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($current_page-1)*$per_page; - $pages = $unapproved_threads / $per_page; - $pages = ceil($pages); - if($current_page > $pages) - { - $start = 0; - $current_page = 1; - } - } - else - { - $start = 0; - $current_page = 1; - } - - $pagination = draw_admin_pagination($current_page, $per_page, $unapproved_threads, "index.php?module=forum-moderation_queue&page={page}"); - - $page->add_breadcrumb_item($lang->threads_awaiting_moderation); - $page->output_header($lang->threads_awaiting_moderation); - $page->output_nav_tabs($sub_tabs, "threads"); - - $form = new Form("index.php?module=forum-moderation_queue", "post"); - - $table = new Table; - $table->construct_header($lang->subject); - $table->construct_header($lang->author, array("class" => "align_center", "width" => "20%")); - $table->construct_header($lang->posted, array("class" => "align_center", "width" => "20%")); - - $query = $db->query(" - SELECT t.tid, t.dateline, t.fid, t.subject, t.username AS threadusername, p.message AS postmessage, u.username AS username, t.uid - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=t.firstpost) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=t.uid) - WHERE t.visible='0' - ORDER BY t.lastpost DESC - LIMIT {$start}, {$per_page} - "); - while($thread = $db->fetch_array($query)) - { - $thread['subject'] = htmlspecialchars_uni($thread['subject']); - $thread['threadlink'] = get_thread_link($thread['tid']); - $thread['forumlink'] = get_forum_link($thread['fid']); - $forum_name = $forum_cache[$thread['fid']]['name']; - $threaddate = my_date('relative', $thread['dateline']); - - if($thread['username'] == "") - { - if($thread['threadusername'] != "") - { - $profile_link = $thread['threadusername']; - } - else - { - $profile_link = htmlspecialchars_uni($lang->guest); - } - } - else - { - $profile_link = build_profile_link(htmlspecialchars_uni($thread['username']), $thread['uid'], "_blank"); - } - - $thread['postmessage'] = nl2br(htmlspecialchars_uni($thread['postmessage'])); - - $table->construct_cell("{$thread['subject']}"); - $table->construct_cell($profile_link, array("class" => "align_center")); - $table->construct_cell($threaddate, array("class" => "align_center")); - $table->construct_row(); - - $controls = "
\n"; - $controls .= $form->generate_radio_button("threads[{$thread['tid']}]", "ignore", $lang->ignore, array('class' => 'radio_ignore', 'checked' => true))." "; - $controls .= $form->generate_radio_button("threads[{$thread['tid']}]", "delete", $lang->delete, array('class' => 'radio_delete', 'checked' => false))." "; - $controls .= $form->generate_radio_button("threads[{$thread['tid']}]", "approve", $lang->approve, array('class' => 'radio_approve', 'checked' => false)); - $controls .= "
"; - - $forum = "{$lang->forum} {$forum_name}
"; - - $table->construct_cell("
{$controls}
{$forum}
{$thread['postmessage']}
", array("colspan" => 3)); - $table->construct_row(); - } - - $table->output($lang->threads_awaiting_moderation); - echo $all_options; - echo $pagination; - - $buttons[] = $form->generate_submit_button($lang->perform_action); - $form->output_submit_wrapper($buttons); - $form->end(); - - echo ''; - - $page->output_footer(); - } -} - -// Posts awaiting moderation -if($mybb->input['type'] == "posts" || $mybb->input['type'] == "") -{ - $plugins->run_hooks("admin_forum_moderation_queue_posts"); - - $forum_cache = $cache->read("forums"); - - $query = $db->query(" - SELECT COUNT(pid) AS unapprovedposts - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.visible='0' AND t.firstpost != p.pid - "); - $unapproved_posts = $db->fetch_field($query, "unapprovedposts"); - - if($unapproved_posts > 0) - { - // Figure out if we need to display multiple pages. - $per_page = 15; - if($mybb->input['page'] > 0) - { - $current_page = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($current_page-1)*$per_page; - $pages = $unapproved_posts / $per_page; - $pages = ceil($pages); - if($current_page > $pages) - { - $start = 0; - $current_page = 1; - } - } - else - { - $start = 0; - $current_page = 1; - } - - $pagination = draw_admin_pagination($current_page, $per_page, $unapproved_posts, "index.php?module=forum-moderation_queue&type=posts&page={page}"); - - - $page->add_breadcrumb_item($lang->posts_awaiting_moderation); - $page->output_header($lang->posts_awaiting_moderation); - $page->output_nav_tabs($sub_tabs, "posts"); - - $form = new Form("index.php?module=forum-moderation_queue", "post"); - - $table = new Table; - $table->construct_header($lang->subject); - $table->construct_header($lang->author, array("class" => "align_center", "width" => "20%")); - $table->construct_header($lang->posted, array("class" => "align_center", "width" => "20%")); - - $query = $db->query(" - SELECT p.pid, p.subject, p.message, p.dateline, p.username AS postusername, t.subject AS threadsubject, t.tid, u.username, p.uid, t.fid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.visible='0' AND t.firstpost != p.pid - ORDER BY p.dateline DESC - LIMIT {$start}, {$per_page} - "); - while($post = $db->fetch_array($query)) - { - $altbg = alt_trow(); - $post['threadsubject'] = htmlspecialchars_uni($post['threadsubject']); - $post['subject'] = htmlspecialchars_uni($post['subject']); - - if(!$post['subject']) - { - $post['subject'] = $lang->re." ".$post['threadsubject']; - } - - $post['postlink'] = get_post_link($post['pid'], $post['tid']); - $post['threadlink'] = get_thread_link($post['tid']); - $post['forumlink'] = get_forum_link($post['fid']); - $forum_name = $forum_cache[$post['fid']]['name']; - $postdate = my_date('relative', $post['dateline']); - - if($post['username'] == "") - { - if($post['postusername'] != "") - { - $profile_link = $post['postusername']; - } - else - { - $profile_link = $lang->guest; - } - } - else - { - $profile_link = build_profile_link(htmlspecialchars_uni($post['username']), $post['uid'], "_blank"); - } - - $post['message'] = nl2br(htmlspecialchars_uni($post['message'])); - - $table->construct_cell("{$post['subject']}"); - $table->construct_cell($profile_link, array("class" => "align_center")); - $table->construct_cell($postdate, array("class" => "align_center")); - $table->construct_row(); - - $controls = "
\n"; - $controls .= $form->generate_radio_button("posts[{$post['pid']}]", "ignore", $lang->ignore, array('class' => 'radio_ignore', 'checked' => true))." "; - $controls .= $form->generate_radio_button("posts[{$post['pid']}]", "delete",$lang->delete, array('class' => 'radio_delete', 'checked' => false))." "; - $controls .= $form->generate_radio_button("posts[{$post['pid']}]", "approve", $lang->approve, array('class' => 'radio_approve', 'checked' => false)); - $controls .= "
"; - - $thread = "{$lang->thread} {$post['threadsubject']}"; - $forum = "{$lang->forum} {$forum_name}
"; - - $table->construct_cell("
{$controls}
{$forum}{$thread}
{$post['message']}
", array("colspan" => 3)); - $table->construct_row(); - } - - $table->output($lang->posts_awaiting_moderation); - echo $all_options; - echo $pagination; - - $buttons[] = $form->generate_submit_button($lang->perform_action); - $form->output_submit_wrapper($buttons); - $form->end(); - - echo ''; - - $page->output_footer(); - } - else if($mybb->input['type'] == "posts") - { - $page->output_header($lang->moderation_queue); - $page->output_nav_tabs($sub_tabs, "posts"); - echo "

{$lang->error_no_posts}

"; - $page->output_footer(); - } -} - -// Attachments awaiting moderation -if($mybb->input['type'] == "attachments" || $mybb->input['type'] == "") -{ - $plugins->run_hooks("admin_forum_moderation_queue_attachments"); - - $query = $db->query(" - SELECT COUNT(aid) AS unapprovedattachments - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE a.visible='0' - "); - $unapproved_attachments = $db->fetch_field($query, "unapprovedattachments"); - - if($unapproved_attachments > 0) - { - // Figure out if we need to display multiple pages. - $per_page = 15; - if($mybb->input['page'] > 0) - { - $current_page = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($current_page-1)*$per_page; - $pages = $unapproved_attachments / $per_page; - $pages = ceil($pages); - if($current_page > $pages) - { - $start = 0; - $current_page = 1; - } - } - else - { - $start = 0; - $current_page = 1; - } - - $pagination = draw_admin_pagination($current_page, $per_page, $unapproved_attachments, "index.php?module=forum-moderation_queue&type=attachments&page={page}"); - - $page->add_breadcrumb_item($lang->attachments_awaiting_moderation); - $page->output_header($lang->attachments_awaiting_moderation); - $page->output_nav_tabs($sub_tabs, "attachments"); - - $form = new Form("index.php?module=forum-moderation_queue", "post"); - - $table = new Table; - $table->construct_header($lang->filename); - $table->construct_header($lang->uploadedby, array("class" => "align_center", "width" => "20%")); - $table->construct_header($lang->posted, array("class" => "align_center", "width" => "20%")); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 3)); - - $query = $db->query(" - SELECT a.*, p.subject AS postsubject, p.dateline, p.uid, u.username, t.tid, t.subject AS threadsubject - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE a.visible='0' - ORDER BY a.dateuploaded DESC - LIMIT {$start}, {$per_page} - "); - - while($attachment = $db->fetch_array($query)) - { - if(!$attachment['dateuploaded']) $attachment['dateuploaded'] = $attachment['dateline']; - $attachdate = my_date('relative', $attachment['dateuploaded']); - - $attachment['postsubject'] = htmlspecialchars_uni($attachment['postsubject']); - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - $attachment['threadsubject'] = htmlspecialchars_uni($attachment['threadsubject']); - $attachment['filesize'] = get_friendly_size($attachment['filesize']); - - $link = get_post_link($attachment['pid'], $attachment['tid']) . "#pid{$attachment['pid']}"; - $thread_link = get_thread_link($attachment['tid']); - $profile_link = build_profile_link(htmlspecialchars_uni($attachment['username']), $attachment['uid'], "_blank"); - - $table->construct_cell("{$attachment['filename']} ({$attachment['filesize']})
{$lang->post} {$attachment['postsubject']}"); - $table->construct_cell($profile_link, array("class" => "align_center")); - $table->construct_cell($attachdate, array("class" => "align_center")); - - $table->construct_cell($form->generate_radio_button("attachments[{$attachment['aid']}]", "ignore", $lang->ignore, array('class' => 'radio_ignore', 'checked' => true)), array("class" => "align_center")); - $table->construct_cell($form->generate_radio_button("attachments[{$attachment['aid']}]", "delete", $lang->delete, array('class' => 'radio_delete', 'checked' => false)), array("class" => "align_center")); - $table->construct_cell($form->generate_radio_button("attachments[{$attachment['aid']}]", "approve", $lang->approve, array('class' => 'radio_approve', 'checked' => false)), array("class" => "align_center")); - $table->construct_row(); - } - $table->output($lang->attachments_awaiting_moderation); - echo $all_options; - echo $pagination; - - $buttons[] = $form->generate_submit_button($lang->perform_action); - $form->output_submit_wrapper($buttons); - $form->end(); - - echo ''; - - $page->output_footer(); - } - else if($mybb->input['type'] == "attachments") - { - $page->output_header($lang->moderation_queue); - $page->output_nav_tabs($sub_tabs, "attachments"); - echo "

{$lang->error_no_attachments}

"; - $page->output_footer(); - } -} - -// Still nothing? All queues are empty! :-D -$page->output_header($lang->moderation_queue); -echo "

{$lang->error_no_threads}

"; -$page->output_footer(); diff --git a/html/forums/admin/modules/forum/module_meta.php b/html/forums/admin/modules/forum/module_meta.php deleted file mode 100644 index 1980876..0000000 --- a/html/forums/admin/modules/forum/module_meta.php +++ /dev/null @@ -1,87 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -/** - * @return bool true - */ -function forum_meta() -{ - global $page, $lang, $plugins; - - $sub_menu = array(); - $sub_menu['10'] = array("id" => "management", "title" => $lang->forum_management, "link" => "index.php?module=forum-management"); - $sub_menu['20'] = array("id" => "announcements", "title" => $lang->forum_announcements, "link" => "index.php?module=forum-announcements"); - $sub_menu['30'] = array("id" => "moderation_queue", "title" => $lang->moderation_queue, "link" => "index.php?module=forum-moderation_queue"); - $sub_menu['40'] = array("id" => "attachments", "title" => $lang->attachments, "link" => "index.php?module=forum-attachments"); - - $sub_menu = $plugins->run_hooks("admin_forum_menu", $sub_menu); - - $page->add_menu_item($lang->forums_and_posts, "forum", "index.php?module=forum", 20, $sub_menu); - - return true; -} - -/** - * @param string $action - * - * @return string - */ -function forum_action_handler($action) -{ - global $page, $plugins; - - $page->active_module = "forum"; - - $actions = array( - 'moderation_queue' => array('active' => 'moderation_queue', 'file' => 'moderation_queue.php'), - 'announcements' => array('active' => 'announcements', 'file' => 'announcements.php'), - 'attachments' => array('active' => 'attachments', 'file' => 'attachments.php'), - 'management' => array('active' => 'management', 'file' => 'management.php') - ); - - $actions = $plugins->run_hooks("admin_forum_action_handler", $actions); - - if(isset($actions[$action])) - { - $page->active_action = $actions[$action]['active']; - return $actions[$action]['file']; - } - else - { - $page->active_action = "management"; - return "management.php"; - } -} - -/** - * @return array - */ -function forum_admin_permissions() -{ - global $lang, $plugins; - - $admin_permissions = array( - "management" => $lang->can_manage_forums, - "announcements" => $lang->can_manage_forum_announcements, - "moderation_queue" => $lang->can_moderate, - "attachments" => $lang->can_manage_attachments, - ); - - $admin_permissions = $plugins->run_hooks("admin_forum_permissions", $admin_permissions); - - return array("name" => $lang->forums_and_posts, "permissions" => $admin_permissions, "disporder" => 20); -} - diff --git a/html/forums/admin/modules/home/credits.php b/html/forums/admin/modules/home/credits.php deleted file mode 100644 index 7e4aaa6..0000000 --- a/html/forums/admin/modules/home/credits.php +++ /dev/null @@ -1,151 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->mybb_credits, "index.php?module=home-credits"); - -$plugins->run_hooks("admin_home_credits_begin"); - -if(!$mybb->input['action']) -{ - $page->output_header($lang->mybb_credits); - - $sub_tabs['credits'] = array( - 'title' => $lang->mybb_credits, - 'link' => "index.php?module=home-credits", - 'description' => $lang->mybb_credits_description - ); - - $sub_tabs['credits_about'] = array( - 'title' => $lang->about_the_team, - 'link' => "https://mybb.com/about/team", - 'link_target' => "_blank", - ); - - $sub_tabs['check_for_updates'] = array( - 'title' => $lang->check_for_updates, - 'link' => "index.php?module=home-credits&fetch_new=1", - ); - - $plugins->run_hooks("admin_home_credits_start"); - - $page->output_nav_tabs($sub_tabs, 'credits'); - - $mybb_credits = $cache->read('mybb_credits'); - - if($mybb->get_input('fetch_new', MyBB::INPUT_INT) == 1 || $mybb->get_input('fetch_new', MyBB::INPUT_INT) == -2 || ($mybb->get_input('fetch_new', MyBB::INPUT_INT) != -1 && (!is_array($mybb_credits) || $mybb_credits['last_check'] <= TIME_NOW - 60*60*24*14))) - { - $new_mybb_credits = array( - 'last_check' => TIME_NOW - ); - - require_once MYBB_ROOT."inc/class_xml.php"; - $contents = fetch_remote_file("https://mybb.com/mybb_team.xml"); - - if(!$contents) - { - flash_message($lang->error_communication, 'error'); - if($mybb->get_input('fetch_new', MyBB::INPUT_INT) == -2) - { - admin_redirect('index.php?module=tools-cache'); - } - admin_redirect('index.php?module=home-credits&fetch_new=-1'); - } - - $parser = new XMLParser($contents); - $tree = $parser->get_tree(); - $mybbgroup = array(); - foreach($tree['mybbgroup']['team'] as $team) - { - $members = array(); - foreach($team['member'] as $member) - { - $members[] = array( - 'name' => htmlspecialchars_uni($member['name']['value']), - 'username' => htmlspecialchars_uni($member['username']['value']), - 'profile' => htmlspecialchars_uni($member['profile']['value']), - 'lead' => (bool)$member['attributes']['lead'] or false - ); - } - $mybbgroup[] = array( - 'title' => htmlspecialchars_uni($team['attributes']['title']), - 'members' => $members - ); - } - $new_mybb_credits['credits'] = $mybbgroup; - - $cache->update('mybb_credits', $new_mybb_credits); - - if($mybb->get_input('fetch_new', MyBB::INPUT_INT) == -2) - { - $lang->load('tools_cache'); - flash_message($lang->success_cache_reloaded, 'success'); - admin_redirect('index.php?module=tools-cache'); - } - else - { - flash_message($lang->success_credits_updated, 'success'); - admin_redirect('index.php?module=home-credits&fetch_new=-1'); - } - } - - if(empty($mybb_credits) || (is_array($mybb_credits) && empty($mybb_credits['credits']))) - { - $table = new Table; - $table->construct_cell($lang->no_credits); - $table->construct_row(); - } - else - { - $largest_count = $i = 0; - $team_max = array(); - foreach($mybb_credits['credits'] as $team) - { - $count = count($team['members']); - $team_max[$i++] = $count; - if($largest_count < $count) - { - $largest_count = $count; - } - } - $largest_count -= 1; - - $table = new Table; - foreach($mybb_credits['credits'] as $team) - { - $table->construct_header($team['title'], array('width' => '16%')); - } - - for($i = 0; $i <= $largest_count; $i++) - { - foreach($team_max as $team => $max) - { - if($max < $i) - { - $table->construct_cell(" "); - } - else - { - $table->construct_cell("{$mybb_credits['credits'][$team]['members'][$i]['name']}"); - } - } - $table->construct_row(); - } - } - - $table->output($lang->mybb_credits); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/home/index.html b/html/forums/admin/modules/home/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/modules/home/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/modules/home/index.php b/html/forums/admin/modules/home/index.php deleted file mode 100644 index 5ce174e..0000000 --- a/html/forums/admin/modules/home/index.php +++ /dev/null @@ -1,388 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$plugins->run_hooks("admin_home_index_begin"); - -$sub_tabs['dashboard'] = array( - 'title' => $lang->dashboard, - 'link' => "index.php", - 'description' => $lang->dashboard_description -); - -$sub_tabs['version_check'] = array( - 'title' => $lang->version_check, - 'link' => "index.php?module=home&action=version_check", - 'description' => $lang->version_check_description -); - -if($mybb->input['action'] == "version_check") -{ - $plugins->run_hooks("admin_home_version_check_start"); - - $current_version = rawurlencode($mybb->version_code); - - $updated_cache = array( - "last_check" => TIME_NOW - ); - - require_once MYBB_ROOT."inc/class_xml.php"; - $contents = fetch_remote_file("https://mybb.com/version_check.php"); - - if(!$contents) - { - flash_message($lang->error_communication, 'error'); - admin_redirect('index.php'); - } - - $plugins->run_hooks("admin_home_version_check"); - - $page->add_breadcrumb_item($lang->version_check, "index.php?module=home-version_check"); - $page->output_header($lang->version_check); - $page->output_nav_tabs($sub_tabs, 'version_check'); - - // We do this because there is some weird symbols that show up in the xml file for unknown reasons - $pos = strpos($contents, "<"); - if($pos > 1) - { - $contents = substr($contents, $pos); - } - - $pos = strpos(strrev($contents), ">"); - if($pos > 1) - { - $contents = substr($contents, 0, (-1) * ($pos-1)); - } - - $parser = new XMLParser($contents); - $tree = $parser->get_tree(); - - $latest_code = (int)$tree['mybb']['version_code']['value']; - $latest_version = "".htmlspecialchars_uni($tree['mybb']['latest_version']['value'])." (".$latest_code.")"; - if($latest_code > $mybb->version_code) - { - $latest_version = "".$latest_version.""; - $version_warn = 1; - $updated_cache['latest_version'] = $latest_version; - $updated_cache['latest_version_code'] = $latest_code; - } - else - { - $latest_version = "".$latest_version.""; - } - - if($version_warn) - { - $page->output_error("

{$lang->error_out_of_date} {$lang->update_forum}

"); - } - else - { - $page->output_success("

{$lang->success_up_to_date}

"); - } - - $table = new Table; - $table->construct_header($lang->your_version); - $table->construct_header($lang->latest_version); - - $table->construct_cell("".$mybb->version." (".$mybb->version_code.")"); - $table->construct_cell($latest_version); - $table->construct_row(); - - $table->output($lang->version_check); - - require_once MYBB_ROOT."inc/class_feedparser.php"; - - $feed_parser = new FeedParser(); - $feed_parser->parse_feed("http://feeds.feedburner.com/MyBBDevelopmentBlog"); - - $updated_cache['news'] = array(); - - require_once MYBB_ROOT . '/inc/class_parser.php'; - $post_parser = new postParser(); - - if($feed_parser->error == '') - { - foreach($feed_parser->items as $item) - { - if(!isset($updated_cache['news'][2])) - { - $description = $item['description']; - $content = $item['content']; - - $description = $post_parser->parse_message($description, array( - 'allow_html' => true, - ) - ); - - $content = $post_parser->parse_message($content, array( - 'allow_html' => true, - ) - ); - - $description = preg_replace('##', '', $description); - $content = preg_replace('##', '', $content); - - $updated_cache['news'][] = array( - 'title' => htmlspecialchars_uni($item['title']), - 'description' => $description, - 'link' => htmlspecialchars_uni($item['link']), - 'author' => htmlspecialchars_uni($item['author']), - 'dateline' => $item['date_timestamp'], - ); - } - - $stamp = ''; - if($item['date_timestamp']) - { - $stamp = my_date('relative', $item['date_timestamp']); - } - - $link = htmlspecialchars_uni($item['link']); - - $table->construct_cell("".htmlspecialchars_uni($item['title'])."

{$content}{$stamp}

» {$lang->read_more}
"); - $table->construct_row(); - } - } - else - { - $table->construct_cell("{$lang->error_fetch_news} "); - $table->construct_row(); - } - - $cache->update("update_check", $updated_cache); - - $table->output($lang->latest_mybb_announcements); - $page->output_footer(); -} -elseif(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_home_index_start"); - - if($mybb->request_method == "post" && isset($mybb->input['adminnotes'])) - { - // Update Admin Notes cache - $update_cache = array( - "adminmessage" => $mybb->input['adminnotes'] - ); - - $cache->update("adminnotes", $update_cache); - - $plugins->run_hooks("admin_home_index_start_begin"); - - flash_message($lang->success_notes_updated, 'success'); - admin_redirect("index.php"); - } - - $page->add_breadcrumb_item($lang->dashboard); - $page->output_header($lang->dashboard); - - $sub_tabs['dashboard'] = array( - 'title' => $lang->dashboard, - 'link' => "index.php", - 'description' => $lang->dashboard_description - ); - - $page->output_nav_tabs($sub_tabs, 'dashboard'); - - // Load stats cache - $stats = $cache->read("stats"); - - $serverload = get_server_load(); - - // Get the number of users - $query = $db->simple_select("users", "COUNT(uid) AS numusers"); - $users = my_number_format($db->fetch_field($query, "numusers")); - - // Get the number of users awaiting validation - $awaitingusers = $cache->read('awaitingactivation'); - - if(!empty($awaitingusers['users'])) - { - $awaitingusers = (int)$awaitingusers['users']; - } - else - { - $awaitingusers = 0; - } - - if($awaitingusers < 1) - { - $awaitingusers = 0; - } - else - { - $awaitingusers = my_number_format($awaitingusers); - } - - // Get the number of new users for today - $timecut = TIME_NOW - 86400; - $query = $db->simple_select("users", "COUNT(uid) AS newusers", "regdate > '$timecut'"); - $newusers = my_number_format($db->fetch_field($query, "newusers")); - - // Get the number of active users today - $query = $db->simple_select("users", "COUNT(uid) AS activeusers", "lastvisit > '$timecut'"); - $activeusers = my_number_format($db->fetch_field($query, "activeusers")); - - // Get the number of threads - $threads = my_number_format($stats['numthreads']); - - // Get the number of unapproved threads - $unapproved_threads = my_number_format($stats['numunapprovedthreads']); - - // Get the number of new threads for today - $query = $db->simple_select("threads", "COUNT(*) AS newthreads", "dateline > '$timecut' AND visible='1' AND closed NOT LIKE 'moved|%'"); - $newthreads = my_number_format($db->fetch_field($query, "newthreads")); - - // Get the number of posts - $posts = my_number_format($stats['numposts']); - - // Get the number of unapproved posts - if($stats['numunapprovedposts'] < 0) - { - $stats['numunapprovedposts'] = 0; - } - - $unapproved_posts = my_number_format($stats['numunapprovedposts']); - - // Get the number of new posts for today - $query = $db->simple_select("posts", "COUNT(*) AS newposts", "dateline > '$timecut' AND visible='1'"); - $newposts = my_number_format($db->fetch_field($query, "newposts")); - - // Get the number of reported post - $query = $db->simple_select("reportedcontent", "COUNT(*) AS reported_posts", "type = 'post' OR type = ''"); - $reported_posts = my_number_format($db->fetch_field($query, "reported_posts")); - - // If report medium is MCP... - if($mybb->settings['reportmethod'] == "db") - { - // Get the number of reported posts that haven't been marked as read yet - $query = $db->simple_select("reportedcontent", "COUNT(*) AS new_reported_posts", "reportstatus='0' AND (type = 'post' OR type = '')"); - $new_reported_posts = my_number_format($db->fetch_field($query, "new_reported_posts")); - } - - // Get the number and total file size of attachments - $query = $db->simple_select("attachments", "COUNT(*) AS numattachs, SUM(filesize) as spaceused", "visible='1' AND pid > '0'"); - $attachs = $db->fetch_array($query); - $attachs['spaceused'] = get_friendly_size($attachs['spaceused']); - $approved_attachs = my_number_format($attachs['numattachs']); - - // Get the number of unapproved attachments - $query = $db->simple_select("attachments", "COUNT(*) AS numattachs", "visible='0' AND pid > '0'"); - $unapproved_attachs = my_number_format($db->fetch_field($query, "numattachs")); - - // Fetch the last time an update check was run - $update_check = $cache->read("update_check"); - - // If last update check was greater than two weeks ago (14 days) show an alert - if(isset($update_check['last_check']) && $update_check['last_check'] <= TIME_NOW-60*60*24*14) - { - $lang->last_update_check_two_weeks = $lang->sprintf($lang->last_update_check_two_weeks, "index.php?module=home&action=version_check"); - $page->output_error("

{$lang->last_update_check_two_weeks}

"); - } - - // If the update check contains information about a newer version, show an alert - if(isset($update_check['latest_version_code']) && $update_check['latest_version_code'] > $mybb->version_code) - { - $lang->new_version_available = $lang->sprintf($lang->new_version_available, "MyBB {$mybb->version}", "MyBB {$update_check['latest_version']}"); - $page->output_error("

{$lang->new_version_available}

"); - } - - $plugins->run_hooks("admin_home_index_output_message"); - - $adminmessage = $cache->read("adminnotes"); - - $table = new Table; - $table->construct_header($lang->mybb_server_stats, array("colspan" => 2)); - $table->construct_header($lang->forum_stats, array("colspan" => 2)); - - $table->construct_cell("{$lang->mybb_version}", array('width' => '25%')); - $table->construct_cell($mybb->version, array('width' => '25%')); - $table->construct_cell("{$lang->threads}", array('width' => '25%')); - $table->construct_cell("{$threads} {$lang->threads}
{$newthreads} {$lang->new_today}
{$unapproved_threads} {$lang->unapproved}", array('width' => '25%')); - $table->construct_row(); - - $table->construct_cell("{$lang->php_version}", array('width' => '25%')); - $table->construct_cell(PHP_VERSION, array('width' => '25%')); - $table->construct_cell("{$lang->posts}", array('width' => '25%')); - if($mybb->settings['reportmethod'] == "db") - { - $table->construct_cell("{$posts} {$lang->posts}
{$newposts} {$lang->new_today}
{$unapproved_posts} {$lang->unapproved}
{$reported_posts} {$lang->reported_posts}
{$new_reported_posts} {$lang->unread_reports}", array('width' => '25%')); - } - else - { - $table->construct_cell("{$posts} {$lang->posts}
{$newposts} {$lang->new_today}
{$unapproved_posts} {$lang->unapproved}
{$reported_posts} {$lang->reported_posts}", array('width' => '25%')); - } - $table->construct_row(); - - $table->construct_cell("{$lang->sql_engine}", array('width' => '25%')); - $table->construct_cell($db->short_title." ".$db->get_version(), array('width' => '25%')); - $table->construct_cell("{$lang->users}", array('width' => '25%')); - $table->construct_cell("{$users} {$lang->registered_users}
{$activeusers} {$lang->active_users}
{$newusers} {$lang->registrations_today}
{$awaitingusers} {$lang->awaiting_activation}", array('width' => '25%')); - $table->construct_row(); - - $table->construct_cell("{$lang->server_load}", array('width' => '25%')); - $table->construct_cell($serverload, array('width' => '25%')); - $table->construct_cell("{$lang->attachments}", array('width' => '25%')); - $table->construct_cell("{$approved_attachs} {$lang->attachments}
{$unapproved_attachs} {$lang->unapproved}
{$attachs['spaceused']} {$lang->used}", array('width' => '25%')); - $table->construct_row(); - - $table->output($lang->dashboard); - - echo ' -
'; - - $table = new Table; - $table->construct_header($lang->admin_notes_public); - - $form = new Form("index.php", "post"); - $table->construct_cell($form->generate_text_area("adminnotes", $adminmessage['adminmessage'], array('style' => 'width: 99%; height: 200px;'))); - $table->construct_row(); - - $table->output($lang->admin_notes); - - $buttons[] = $form->generate_submit_button($lang->save_notes); - $form->output_submit_wrapper($buttons); - $form->end(); - - echo '
-
'; - - // Latest news widget - $table = new Table; - $table->construct_header($lang->news_description); - - if(!empty($update_check['news']) && is_array($update_check['news'])) - { - foreach($update_check['news'] as $news_item) - { - $posted = my_date('relative', $news_item['dateline']); - $table->construct_cell("{$news_item['title']}
{$posted}"); - $table->construct_row(); - - $table->construct_cell($news_item['description']); - $table->construct_row(); - } - } - else - { - $table->construct_cell($lang->no_announcements); - $table->construct_row(); - } - - $table->output($lang->latest_mybb_announcements); - echo '
'; - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/home/module_meta.php b/html/forums/admin/modules/home/module_meta.php deleted file mode 100644 index f66d33e..0000000 --- a/html/forums/admin/modules/home/module_meta.php +++ /dev/null @@ -1,191 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -/** - * @return bool true - */ -function home_meta() -{ - global $page, $lang, $plugins; - - $sub_menu = array(); - $sub_menu['10'] = array("id" => "dashboard", "title" => $lang->dashboard, "link" => "index.php?module=home-dashboard"); - $sub_menu['20'] = array("id" => "preferences", "title" => $lang->preferences, "link" => "index.php?module=home-preferences"); - $sub_menu['30'] = array("id" => "docs", "title" => $lang->mybb_documentation, "link" => "https://docs.mybb.com"); - $sub_menu['40'] = array("id" => "credits", "title" => $lang->mybb_credits, "link" => "index.php?module=home-credits"); - $sub_menu = $plugins->run_hooks("admin_home_menu", $sub_menu); - - $page->add_menu_item($lang->home, "home", "index.php", 1, $sub_menu); - - return true; -} - -/** - * @param string $action - * - * @return string - */ -function home_action_handler($action) -{ - global $page, $db, $lang, $plugins; - - $page->active_module = "home"; - - $actions = array( - 'preferences' => array('active' => 'preferences', 'file' => 'preferences.php'), - 'credits' => array('active' => 'credits', 'file' => 'credits.php'), - 'version_check' => array('active' => 'version_check', 'file' => 'version_check.php'), - 'dashboard' => array('active' => 'dashboard', 'file' => 'index.php') - ); - - if(!isset($actions[$action])) - { - $page->active_action = "dashboard"; - } - else - { - $page->active_action = $actions[$action]['active']; - } - - $actions = $plugins->run_hooks("admin_home_action_handler", $actions); - - if($page->active_action == "dashboard") - { - // Quick Access - $sub_menu = array(); - $sub_menu['10'] = array("id" => "add_forum", "title" => $lang->add_new_forum, "link" => "index.php?module=forum-management&action=add", "module" => "forum", "action" => "management"); - $sub_menu['20'] = array("id" => "search", "title" => $lang->search_for_users, "link" => "index.php?module=user-users&action=search", "module" => "user", "action" => "users"); - $sub_menu['30'] = array("id" => "themes", "title" => $lang->themes, "link" => "index.php?module=style-themes", "module" => "style", "action" => "themes"); - $sub_menu['40'] = array("id" => "templates", "title" => $lang->templates, "link" => "index.php?module=style-templates", "module" => "style", "action" => "templates"); - $sub_menu['50'] = array("id" => "plugins", "title" => $lang->plugins, "link" => "index.php?module=config-plugins", "module" => "config", "action" => "plugins"); - $sub_menu['60'] = array("id" => "backupdb", "title" => $lang->database_backups, "link" => "index.php?module=tools-backupdb", "module" => "tools", "action" => "backupdb"); - - foreach($sub_menu as $id => $sub) - { - if(!check_admin_permissions(array("module" => $sub['module'], "action" => $sub['action']), false)) - { - unset($sub_menu[$id]); - } - } - - $sub_menu = $plugins->run_hooks("admin_home_menu_quick_access", $sub_menu); - - if(!empty($sub_menu)) - { - $sidebar = new SidebarItem($lang->quick_access); - $sidebar->add_menu_items($sub_menu, $page->active_action); - $page->sidebar .= $sidebar->get_markup(); - } - - // Online Administrators in the last 30 minutes - $timecut = TIME_NOW-60*30; - $query = $db->simple_select("adminsessions", "uid, ip, useragent", "lastactive > {$timecut}"); - $online_users = "
    "; - $online_admins = array(); - - // If there's only 1 user online, it has to be us. - if($db->num_rows($query) == 1) - { - $user = $db->fetch_array($query); - global $mybb; - - // Are we on a mobile device? - // Stolen from http://stackoverflow.com/a/10989424 - $user_type = "desktop"; - if(is_mobile($user["useragent"])) - { - $user_type = "mobile"; - } - - $online_admins[$mybb->user['username']] = array( - "uid" => $mybb->user['uid'], - "username" => $mybb->user['username'], - "ip" => $user["ip"], - "type" => $user_type - ); - } - else - { - $uid_in = array(); - while($user = $db->fetch_array($query)) - { - $uid_in[] = $user['uid']; - - $user_type = "desktop"; - if(is_mobile($user['useragent'])) - { - $user_type = "mobile"; - } - - $online_admins[$user['uid']] = array( - "ip" => $user['ip'], - "type" => $user_type - ); - } - - $query = $db->simple_select("users", "uid, username", "uid IN(".implode(',', $uid_in).")", array('order_by' => 'username')); - while($user = $db->fetch_array($query)) - { - $online_admins[$user['username']] = array( - "uid" => $user['uid'], - "username" => $user['username'], - "ip" => $online_admins[$user['uid']]['ip'], - "type" => $online_admins[$user['uid']]['type'] - ); - unset($online_admins[$user['uid']]); - } - } - - $done_users = array(); - - asort($online_admins); - - foreach($online_admins as $user) - { - if(!isset($done_users["{$user['uid']}.{$user['ip']}"])) - { - if($user['type'] == "mobile") - { - $class = " class=\"mobile_user\""; - } - else - { - $class = ""; - } - $ip_address = my_inet_ntop($db->unescape_binary($user['ip'])); - $online_users .= "
  • ipaddress} {$ip_address}\"{$class}>".build_profile_link(htmlspecialchars_uni($user['username']).' ('.$ip_address.')', $user['uid'], "_blank")."
  • "; - $done_users["{$user['uid']}.{$user['ip']}"] = 1; - } - } - $online_users .= "
"; - $sidebar = new SidebarItem($lang->online_admins); - $sidebar->set_contents($online_users); - - $page->sidebar .= $sidebar->get_markup(); - } - - if(isset($actions[$action])) - { - $page->active_action = $actions[$action]['active']; - return $actions[$action]['file']; - } - else - { - $page->active_action = "dashboard"; - return "index.php"; - } -} - diff --git a/html/forums/admin/modules/home/preferences.php b/html/forums/admin/modules/home/preferences.php deleted file mode 100644 index 651fed4..0000000 --- a/html/forums/admin/modules/home/preferences.php +++ /dev/null @@ -1,192 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->preferences_and_personal_notes, "index.php?module=home-preferences"); - -$plugins->run_hooks("admin_home_preferences_begin"); - -if($mybb->input['action'] == "recovery_codes") -{ - $page->add_breadcrumb_item($lang->recovery_codes, "index.php?module=home-preferences&action=recovery_codes"); - - // First: regenerate the codes - $codes = generate_recovery_codes(); - $db->update_query("adminoptions", array("recovery_codes" => $db->escape_string(my_serialize($codes))), "uid='{$mybb->user['uid']}'"); - - // And now display them - $page->output_header($lang->recovery_codes); - - $table = new Table; - $table->construct_header($lang->recovery_codes); - - $table->construct_cell("{$lang->recovery_codes_warning} {$lang->print_recovery_codes}"); - $table->construct_row(); - - $table->construct_cell(implode("
", $codes)); - $table->construct_row(); - - $table->output($lang->recovery_codes); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - require_once MYBB_ROOT."inc/3rdparty/2fa/GoogleAuthenticator.php"; - $auth = new PHPGangsta_GoogleAuthenticator; - - $plugins->run_hooks("admin_home_preferences_start"); - - if($mybb->request_method == "post") - { - $query = $db->simple_select("adminoptions", "permissions, defaultviews, authsecret, recovery_codes", "uid='{$mybb->user['uid']}'"); - $adminopts = $db->fetch_array($query); - - $secret = $adminopts['authsecret']; - // Was the option changed? empty = disabled so == - if($mybb->input['2fa'] == empty($secret)) - { - // 2FA was enabled -> create secret and log - if($mybb->input['2fa']) - { - $secret = $auth->createSecret(); - // We don't want to close this session now - $db->update_query("adminsessions", array("authenticated" => 1), "sid='".$db->escape_string($mybb->cookies['adminsid'])."'"); - log_admin_action("enabled"); - } - // 2FA was disabled -> clear secret - else - { - $secret = ""; - $adminopts['recovery_codes'] = ""; - log_admin_action("disabled"); - } - } - - $sqlarray = array( - "notes" => $db->escape_string($mybb->input['notes']), - "cpstyle" => $db->escape_string($mybb->input['cpstyle']), - "cplanguage" => $db->escape_string($mybb->input['cplanguage']), - "permissions" => $db->escape_string($adminopts['permissions']), - "defaultviews" => $db->escape_string($adminopts['defaultviews']), - "uid" => $mybb->user['uid'], - "codepress" => $mybb->get_input('codepress', MyBB::INPUT_INT), // It's actually CodeMirror but for compatibility purposes lets leave it codepress - "authsecret" => $db->escape_string($secret), - "recovery_codes" => $db->escape_string($adminopts['recovery_codes']), - ); - - $db->replace_query("adminoptions", $sqlarray, "uid"); - - $plugins->run_hooks("admin_home_preferences_start_commit"); - - flash_message($lang->success_preferences_updated, 'success'); - admin_redirect("index.php?module=home-preferences"); - } - - $page->output_header($lang->preferences_and_personal_notes); - - $sub_tabs['preferences'] = array( - 'title' => $lang->preferences_and_personal_notes, - 'link' => "index.php?module=home-preferences", - 'description' => $lang->prefs_and_personal_notes_description - ); - - $page->output_nav_tabs($sub_tabs, 'preferences'); - - $query = $db->simple_select("adminoptions", "notes, cpstyle, cplanguage, codepress, authsecret", "uid='".$mybb->user['uid']."'", array('limit' => 1)); - $admin_options = $db->fetch_array($query); - - $form = new Form("index.php?module=home-preferences", "post"); - $dir = @opendir(MYBB_ADMIN_DIR."/styles"); - - $folders = array(); - while($folder = readdir($dir)) - { - if($folder != "." && $folder != ".." && @file_exists(MYBB_ADMIN_DIR."/styles/$folder/main.css")) - { - $folders[$folder] = ucfirst($folder); - } - } - closedir($dir); - ksort($folders); - $setting_code = $form->generate_select_box("cpstyle", $folders, $admin_options['cpstyle']); - - $languages = array_merge(array('' => $lang->use_default), $lang->get_languages(1)); - $language_code = $form->generate_select_box("cplanguage", $languages, $admin_options['cplanguage']); - - $table = new Table; - $table->construct_header($lang->global_preferences); - - $table->construct_cell("{$lang->acp_theme}
{$lang->select_acp_theme}

{$setting_code}"); - $table->construct_row(); - - $table->construct_cell("{$lang->acp_language}
{$lang->select_acp_language}

{$language_code}"); - $table->construct_row(); - - $table->construct_cell("{$lang->codemirror}
{$lang->use_codemirror_desc}

".$form->generate_on_off_radio('codepress', $admin_options['codepress'])); - $table->construct_row(); - - // If 2FA is enabled we need to display a link to the recovery codes page - if(!empty($admin_options['authsecret'])) - { - $lang->use_2fa_desc .= "
".$lang->recovery_codes_desc." ".$lang->recovery_codes_warning; - } - - $table->construct_cell("{$lang->my2fa}
{$lang->use_2fa_desc}

".$form->generate_on_off_radio('2fa', (int)!empty($admin_options['authsecret']))); - $table->construct_row(); - - if(!empty($admin_options['authsecret'])) - { - $qr = $auth->getQRCodeGoogleUrl($mybb->user['username']."@".str_replace(" ", "", $mybb->settings['bbname']), $admin_options['authsecret']); - $table->construct_cell("{$lang->my2fa_qr}
construct_row(); - } - - $table->output($lang->preferences); - - $table->construct_header($lang->notes_not_shared); - - $table->construct_cell($form->generate_text_area("notes", $admin_options['notes'], array('style' => 'width: 99%; height: 300px;'))); - $table->construct_row(); - - $table->output($lang->personal_notes); - - $buttons[] = $form->generate_submit_button($lang->save_notes_and_prefs); - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -/** - * Generate 10 random recovery codes, each with a length of 6 and without duplicates - * - * @return array - */ -function generate_recovery_codes() -{ - $t = array(); - while(count($t) < 10) - { - $g = random_str(6); - if(!in_array($g, $t)) - { - $t[] = $g; - } - } - return $t; -} diff --git a/html/forums/admin/modules/index.html b/html/forums/admin/modules/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/modules/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/modules/style/index.html b/html/forums/admin/modules/style/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/modules/style/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/modules/style/module_meta.php b/html/forums/admin/modules/style/module_meta.php deleted file mode 100644 index 2cefa8a..0000000 --- a/html/forums/admin/modules/style/module_meta.php +++ /dev/null @@ -1,79 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -/** - * @return bool true - */ -function style_meta() -{ - global $page, $lang, $plugins; - - $sub_menu = array(); - $sub_menu['10'] = array("id" => "themes", "title" => $lang->themes, "link" => "index.php?module=style-themes"); - $sub_menu['20'] = array("id" => "templates", "title" => $lang->templates, "link" => "index.php?module=style-templates"); - - $sub_menu = $plugins->run_hooks("admin_style_menu", $sub_menu); - - $page->add_menu_item($lang->templates_and_style, "style", "index.php?module=style", 40, $sub_menu); - return true; -} - -/** - * @param string $action - * - * @return string - */ -function style_action_handler($action) -{ - global $page, $plugins; - - $page->active_module = "style"; - - $actions = array( - 'templates' => array('active' => 'templates', 'file' => 'templates.php'), - 'themes' => array('active' => 'themes', 'file' => 'themes.php') - ); - - $actions = $plugins->run_hooks("admin_style_action_handler", $actions); - - if(isset($actions[$action])) - { - $page->active_action = $actions[$action]['active']; - return $actions[$action]['file']; - } - else - { - $page->active_action = "themes"; - return "themes.php"; - } -} - -/** - * @return array - */ -function style_admin_permissions() -{ - global $lang, $plugins; - - $admin_permissions = array( - "themes" => $lang->can_manage_themes, - "templates" => $lang->can_manage_templates, - ); - - $admin_permissions = $plugins->run_hooks("admin_style_permissions", $admin_permissions); - - return array("name" => $lang->templates_and_style, "permissions" => $admin_permissions, "disporder" => 40); -} diff --git a/html/forums/admin/modules/style/templates.php b/html/forums/admin/modules/style/templates.php deleted file mode 100644 index 8136e0f..0000000 --- a/html/forums/admin/modules/style/templates.php +++ /dev/null @@ -1,2015 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->template_sets, "index.php?module=style-templates"); - -$sid = $mybb->get_input('sid', MyBB::INPUT_INT); - -$expand_str = ""; -$expand_str2 = ""; -$expand_array = array(); -if(isset($mybb->input['expand'])) -{ - $expand_array = explode("|", $mybb->input['expand']); - $expand_array = array_map("intval", $expand_array); - $expand_str = "&expand=".implode("|", $expand_array); - $expand_str2 = "&expand=".implode("|", $expand_array); -} - -if($mybb->input['action'] == "add_set" || $mybb->input['action'] == "add_template" || ($mybb->input['action'] == "add_template_group" && !$sid) || $mybb->input['action'] == "search_replace" || $mybb->input['action'] == "find_updated" || (!$mybb->input['action'] && !$sid)) -{ - $sub_tabs['templates'] = array( - 'title' => $lang->manage_template_sets, - 'link' => "index.php?module=style-templates", - 'description' => $lang->manage_template_sets_desc - ); - - $sub_tabs['add_set'] = array( - 'title' => $lang->add_set, - 'link' => "index.php?module=style-templates&action=add_set".$expand_str - ); - - if($mybb->get_input('sid', MyBB::INPUT_INT) != -1) - { - $sub_tabs['add_template_group'] = array( - 'title' => $lang->add_template_group, - 'link' => "index.php?module=style-templates&action=add_template_group".$expand_str, - 'description' => $lang->add_template_group_desc - ); - } - - $sub_tabs['search_replace'] = array( - 'title' => $lang->search_replace, - 'link' => "index.php?module=style-templates&action=search_replace", - 'description' => $lang->search_replace_desc - ); - - $sub_tabs['find_updated'] = array( - 'title' => $lang->find_updated, - 'link' => "index.php?module=style-templates&action=find_updated", - 'description' => $lang->find_updated_desc - ); -} -else if(($sid && !$mybb->input['action']) || $mybb->input['action'] == "edit_set" || $mybb->input['action'] == "check_set" || $mybb->input['action'] == "edit_template" || $mybb->input['action'] == "add_template_group") -{ - $sub_tabs['manage_templates'] = array( - 'title' => $lang->manage_templates, - 'link' => "index.php?module=style-templates&sid=".$sid.$expand_str, - 'description' => $lang->manage_templates_desc - ); - - if($sid > 0) - { - $sub_tabs['edit_set'] = array( - 'title' => $lang->edit_set, - 'link' => "index.php?module=style-templates&action=edit_set&sid=".$sid.$expand_str, - 'description' => $lang->edit_set_desc - ); - } - - $sub_tabs['add_template'] = array( - 'title' => $lang->add_template, - 'link' => "index.php?module=style-templates&action=add_template&sid=".$sid.$expand_str, - 'description' => $lang->add_template_desc - ); - - if($mybb->get_input('sid', MyBB::INPUT_INT) != -1) - { - $sub_tabs['add_template_group'] = array( - 'title' => $lang->add_template_group, - 'link' => "index.php?module=style-templates&action=add_template_group&sid=".$sid.$expand_str, - 'description' => $lang->add_template_group_desc - ); - } -} - -$template_sets = array(); -$template_sets[-1] = $lang->global_templates; - -$query = $db->simple_select("templatesets", "*", "", array('order_by' => 'title', 'order_dir' => 'ASC')); -while($template_set = $db->fetch_array($query)) -{ - $template_sets[$template_set['sid']] = $template_set['title']; -} - -$plugins->run_hooks("admin_style_templates"); - -if($mybb->input['action'] == "add_set") -{ - $plugins->run_hooks("admin_style_templates_add_set"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_set_title; - } - - if(!$errors) - { - $sid = $db->insert_query("templatesets", array('title' => $db->escape_string($mybb->input['title']))); - - $plugins->run_hooks("admin_style_templates_add_set_commit"); - - // Log admin action - log_admin_action($sid, $mybb->input['title']); - - flash_message($lang->success_template_set_saved, 'success'); - admin_redirect("index.php?module=style-templates&sid=".$sid); - } - } - - $page->add_breadcrumb_item($lang->add_set); - - $page->output_header($lang->add_set); - - $sub_tabs = array(); - $sub_tabs['add_set'] = array( - 'title' => $lang->add_set, - 'link' => "index.php?module=style-templates&action=add_set", - 'description' => $lang->add_set_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_set'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['title'] = ""; - } - - $form = new Form("index.php?module=style-templates&action=add_set", "post", "add_set"); - - $form_container = new FormContainer($lang->add_set); - $form_container->output_row($lang->title, "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->end(); - - $buttons = array(); - $buttons[] = $form->generate_submit_button($lang->save); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "add_template") -{ - $plugins->run_hooks("admin_style_templates_add_template"); - - if($mybb->request_method == "post") - { - if(empty($mybb->input['title'])) - { - $errors[] = $lang->error_missing_set_title; - } - else - { - $query = $db->simple_select("templates", "COUNT(tid) as count", "title='".$db->escape_string($mybb->input['title'])."' AND (sid = '-2' OR sid = '{$sid}')"); - if($db->fetch_field($query, "count") > 0) - { - $errors[] = $lang->error_already_exists; - } - } - - if(!isset($template_sets[$sid])) - { - $errors[] = $lang->error_invalid_set; - } - - // Are we trying to do malicious things in our template? - if(check_template($mybb->input['template'])) - { - $errors[] = $lang->error_security_problem; - } - - if(!$errors) - { - $template_array = array( - 'title' => $db->escape_string($mybb->input['title']), - 'sid' => $sid, - 'template' => $db->escape_string(rtrim($mybb->input['template'])), - 'version' => $db->escape_string($mybb->version_code), - 'status' => '', - 'dateline' => TIME_NOW - ); - - $tid = $db->insert_query("templates", $template_array); - - $plugins->run_hooks("admin_style_templates_add_template_commit"); - - // Log admin action - log_admin_action($tid, $mybb->input['title'], $sid, $template_sets[$sid]); - - flash_message($lang->success_template_saved, 'success'); - - if($mybb->input['continue']) - { - admin_redirect("index.php?module=style-templates&action=edit_template&title=".urlencode($mybb->input['title'])."&sid=".$sid.$expand_str2); - } - else - { - admin_redirect("index.php?module=style-templates&sid=".$sid.$expand_str2); - } - } - } - - if($errors) - { - $template = $mybb->input; - } - else - { - if(!$sid) - { - $sid = -1; - } - - $template['template'] = ""; - $template['sid'] = $sid; - } - - if($mybb->input['sid']) - { - $page->add_breadcrumb_item($template_sets[$sid], "index.php?module=style-templates&sid={$sid}{$expand_str}"); - } - - if($admin_options['codepress'] != 0) - { - $page->extra_header .= ' - - - - - - - - - - - - - - - -'; - } - - $page->add_breadcrumb_item($lang->add_template); - - $page->output_header($lang->add_template); - - $sub_tabs = array(); - $sub_tabs['add_template'] = array( - 'title' => $lang->add_template, - 'link' => "index.php?module=style-templates&action=add_template&sid=".$template['sid'].$expand_str, - 'description' => $lang->add_template_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_template'); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=style-templates&action=add_template{$expand_str}", "post", "add_template"); - - $form_container = new FormContainer($lang->add_template, 'tfixed'); - $form_container->output_row($lang->template_name, $lang->template_name_desc, $form->generate_text_box('title', $template['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->template_set, $lang->template_set_desc, $form->generate_select_box('sid', $template_sets, $sid), 'sid'); - $form_container->output_row("", "", $form->generate_text_area('template', $template['template'], array('id' => 'template', 'class' => '', 'style' => 'width: 100%; height: 500px;')), 'template'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_continue, array('name' => 'continue')); - $buttons[] = $form->generate_submit_button($lang->save_close, array('name' => 'close')); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - if($admin_options['codepress'] != 0) - { - echo ''; - } - - $page->output_footer(); -} - -if($mybb->input['action'] == "add_template_group") -{ - $plugins->run_hooks("admin_style_templates_add_template_group"); - - if($mybb->get_input('sid', MyBB::INPUT_INT) == -1) - { - admin_redirect("index.php?module=style-templates&sid={$sid}".$expand_str2); - } - - $errors = array(); - if($mybb->request_method == "post") - { - $prefix = trim($mybb->input['prefix']); - if(!$prefix) - { - $errors[] = $lang->error_missing_group_prefix; - } - - if(strpos($prefix, "_") !== false) - { - $errors[] = $lang->error_invalid_group_title; - } - - $title = trim($mybb->input['title']); - if(!$title) - { - $errors[] = $lang->error_missing_group_title; - } - - if(!$errors) - { - $query = $db->simple_select("templategroups", "COUNT(gid) AS gid", "prefix = '".$db->escape_string($mybb->input['prefix'])."'"); - $prefix_count = $db->fetch_field($query, 'gid'); - - if($prefix_count >= 1) - { - $errors[] = $lang->error_duplicate_group_prefix; - } - else - { - // Add template group - $insert_array = array( - 'prefix' => $db->escape_string($prefix), - 'title' => $db->escape_string($title), - 'isdefault' => 0 - ); - - $gid = $db->insert_query('templategroups', $insert_array); - - $plugins->run_hooks('admin_style_templates_add_template_group_commit'); - - log_admin_action($gid, $title); - flash_message($lang->success_template_group_saved, 'success'); - - if($sid) - { - admin_redirect("index.php?module=style-templates&sid={$sid}".$expand_str2); - } - - admin_redirect('index.php?module=style-templates'); - } - } - } - - if($mybb->input['sid']) - { - $page->add_breadcrumb_item($template_sets[$sid], "index.php?module=style-templates&sid={$sid}{$expand_str}"); - } - - $page->add_breadcrumb_item($lang->add_template_group); - $page->output_header($lang->add_template_group); - $page->output_nav_tabs($sub_tabs, 'add_template_group'); - - if($errors) - { - $template_group = array( - 'prefix' => $prefix, - 'title' => $title - ); - - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=style-templates&action=add_template_group{$expand_str}", "post", "add_template_group"); - echo $form->generate_hidden_field('sid', $sid); - - $form_container = new FormContainer($lang->add_template_group); - $form_container->output_row($lang->template_group_prefix, $lang->template_group_prefix_desc, $form->generate_text_box('prefix', $template_group['prefix'], array('id' => 'prefix')), 'prefix'); - $form_container->output_row($lang->template_group_title, $lang->template_group_title_desc, $form->generate_text_box('title', $template_group['title'], array('id' => 'title')), 'title'); - $form_container->end(); - - $buttons = array( - $form->generate_submit_button($lang->add_template_group) - ); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit_set") -{ - $query = $db->simple_select("templatesets", "*", "sid='{$sid}'"); - $set = $db->fetch_array($query); - if(!$set) - { - flash_message($lang->error_invalid_input, 'error'); - admin_redirect("index.php?module=style-templates"); - } - - $plugins->run_hooks("admin_style_templates_edit_set"); - - $sid = $set['sid']; - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_set_title; - } - - if(!$errors) - { - $query = $db->update_query("templatesets", array('title' => $db->escape_string($mybb->input['title'])), "sid='{$sid}'"); - - $plugins->run_hooks("admin_style_templates_edit_set_commit"); - - // Log admin action - log_admin_action($sid, $set['title']); - - flash_message($lang->success_template_set_saved, 'success'); - admin_redirect("index.php?module=style-templates&sid=".$sid.$expand_str2); - } - } - - if($sid) - { - $page->add_breadcrumb_item($template_sets[$sid], "index.php?module=style-templates&sid={$sid}{$expand_str}"); - } - - $page->add_breadcrumb_item($lang->edit_set); - - $page->output_header($lang->edit_set); - - $sub_tabs = array(); - $sub_tabs['edit_set'] = array( - 'title' => $lang->edit_set, - 'link' => "index.php?module=style-templates&action=edit_set&sid=".$sid, - 'description' => $lang->edit_set_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_set'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $query = $db->simple_select("templatesets", "title", "sid='{$sid}'"); - $mybb->input['title'] = $db->fetch_field($query, "title"); - } - - $form = new Form("index.php?module=style-templates&action=edit_set{$expand_str}", "post", "edit_set"); - echo $form->generate_hidden_field("sid", $sid); - - $form_container = new FormContainer($lang->edit_set); - $form_container->output_row($lang->title, "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->end(); - - $buttons = array(); - $buttons[] = $form->generate_submit_button($lang->save); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit_template") -{ - if(!$mybb->input['title'] || !$sid || !isset($template_sets[$sid])) - { - flash_message($lang->error_missing_input, 'error'); - admin_redirect("index.php?module=style-templates"); - } - - $plugins->run_hooks("admin_style_templates_edit_template"); - - if($mybb->request_method == "post") - { - if(empty($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - // Are we trying to do malicious things in our template? - if(check_template($mybb->input['template'])) - { - $errors[] = $lang->error_security_problem; - } - - if(!$errors) - { - $query = $db->simple_select("templates", "*", "tid='{$mybb->input['tid']}'"); - $template = $db->fetch_array($query); - - $template_array = array( - 'title' => $db->escape_string($mybb->input['title']), - 'sid' => $sid, - 'template' => $db->escape_string(rtrim($mybb->input['template'])), - 'version' => $mybb->version_code, - 'status' => '', - 'dateline' => TIME_NOW - ); - - // Make sure we have the correct tid associated with this template. If the user double submits then the tid could originally be the master template tid, but because the form is sumbitted again, the tid doesn't get updated to the new modified template one. This then causes the master template to be overwritten - $query = $db->simple_select("templates", "tid", "title='".$db->escape_string($template['title'])."' AND (sid = '-2' OR sid = '{$template['sid']}')", array('order_by' => 'sid', 'order_dir' => 'desc', 'limit' => 1)); - $template['tid'] = $db->fetch_field($query, "tid"); - - $plugins->run_hooks("admin_style_templates_edit_template_commit_start"); - - if($sid > 0) - { - // Check to see if it's never been edited before (i.e. master) or if this a new template (i.e. we've renamed it) or if it's a custom template - $query = $db->simple_select("templates", "sid", "title='".$db->escape_string($mybb->input['title'])."' AND (sid = '-2' OR sid = '{$sid}' OR sid='{$template['sid']}')", array('order_by' => 'sid', 'order_dir' => 'desc')); - $existing_sid = $db->fetch_field($query, "sid"); - $existing_rows = $db->num_rows($query); - - if(($existing_sid == -2 && $existing_rows == 1) || $existing_rows == 0) - { - $template['tid'] = $db->insert_query("templates", $template_array); - } - else - { - $db->update_query("templates", $template_array, "tid='{$template['tid']}' AND sid != '-2'"); - } - } - else - { - // Global template set - $db->update_query("templates", $template_array, "tid='{$template['tid']}' AND sid != '-2'"); - } - - $plugins->run_hooks("admin_style_templates_edit_template_commit"); - - $query = $db->simple_select("templatesets", "title", "sid='{$sid}'"); - $set = $db->fetch_array($query); - - $exploded = explode("_", $template_array['title'], 2); - $prefix = $exploded[0]; - - $query = $db->simple_select("templategroups", "gid", "prefix = '".$db->escape_string($prefix)."'"); - $group = $db->fetch_field($query, "gid"); - - if(!$group) - { - $group = "-1"; - } - - // Log admin action - log_admin_action($template['tid'], $mybb->input['title'], $mybb->input['sid'], $set['title']); - - flash_message($lang->success_template_saved, 'success'); - - if($mybb->input['continue']) - { - if($mybb->input['from'] == "diff_report") - { - admin_redirect("index.php?module=style-templates&action=edit_template&title=".urlencode($mybb->input['title'])."&sid=".$mybb->get_input('sid', MyBB::INPUT_INT).$expand_str2."&from=diff_report"); - } - else - { - admin_redirect("index.php?module=style-templates&action=edit_template&title=".urlencode($mybb->input['title'])."&sid=".$mybb->get_input('sid', MyBB::INPUT_INT).$expand_str2); - } - } - else - { - if($mybb->input['from'] == "diff_report") - { - admin_redirect("index.php?module=style-templates&action=find_updated"); - } - else - { - admin_redirect("index.php?module=style-templates&sid=".$mybb->get_input('sid', MyBB::INPUT_INT).$expand_str2."#group_{$group}"); - } - } - } - } - - if($errors) - { - $template = $mybb->input; - } - else - { - $query = $db->simple_select("templates", "*", "title='".$db->escape_string($mybb->input['title'])."' AND (sid='-2' OR sid='{$sid}')", array('order_by' => 'sid', 'order_dir' => 'DESC', 'limit' => 1)); - $template = $db->fetch_array($query); - } - $template['title'] = htmlspecialchars_uni($template['title']); - - if($admin_options['codepress'] != 0) - { - $page->extra_header .= ' - - - - - - - - - - - - - - - -'; - } - - $page->add_breadcrumb_item($template_sets[$sid], "index.php?module=style-templates&sid={$sid}{$expand_str}"); - - if(!isset($mybb->input['from'])) - { - $mybb->input['from'] = ''; - } - - if($mybb->input['from'] == "diff_report") - { - $page->add_breadcrumb_item($lang->find_updated, "index.php?module=style-templates&action=find_updated"); - } - - $page->add_breadcrumb_item($lang->edit_template_breadcrumb.$template['title'], "index.php?module=style-templates&sid={$sid}"); - - $page->output_header($lang->sprintf($lang->editing_template, $template['title'])); - - - $sub_tabs = array(); - - if($mybb->input['from'] == "diff_report") - { - $sub_tabs['find_updated'] = array( - 'title' => $lang->find_updated, - 'link' => "index.php?module=style-templates&action=find_updated" - ); - - $sub_tabs['diff_report'] = array( - 'title' => $lang->diff_report, - 'link' => "index.php?module=style-templates&action=diff_report&title=".$db->escape_string($template['title'])."&sid1=".(int)$template['sid']."&sid2=-2", - ); - } - - $sub_tabs['edit_template'] = array( - 'title' => $lang->edit_template, - 'link' => "index.php?module=style-templates&action=edit_template&title=".htmlspecialchars_uni($template['title']).$expand_str, - 'description' => $lang->edit_template_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_template'); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=style-templates&action=edit_template{$expand_str}", "post", "edit_template"); - echo $form->generate_hidden_field('tid', $template['tid'])."\n"; - - if($mybb->input['from'] == "diff_report") - { - echo $form->generate_hidden_field('from', "diff_report"); - } - - $form_container = new FormContainer($lang->edit_template_breadcrumb.$template['title'], 'tfixed'); - $form_container->output_row($lang->template_name, $lang->template_name_desc, $form->generate_text_box('title', $template['title'], array('id' => 'title')), 'title'); - - // Force users to save the default template to a specific set, rather than the "global" templates - where they can delete it - if($template['sid'] == "-2") - { - unset($template_sets[-1]); - } - - $form_container->output_row($lang->template_set, $lang->template_set_desc, $form->generate_select_box('sid', $template_sets, $sid)); - - $form_container->output_row("", "", $form->generate_text_area('template', $template['template'], array('id' => 'template', 'class' => '', 'style' => 'width: 100%; height: 500px;'))); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_continue, array('name' => 'continue')); - $buttons[] = $form->generate_submit_button($lang->save_close, array('name' => 'close')); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - if($admin_options['codepress'] != 0) - { - echo ''; - } - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit_template_group") -{ - $query = $db->simple_select("templategroups", "*", "gid = '".$mybb->get_input('gid', MyBB::INPUT_INT)."'"); - - if(!$db->num_rows($query)) - { - flash_message($lang->error_missing_template_group, 'error'); - admin_redirect("index.php?module=style-templates&sid={$sid}{$expand_str}"); - } - - $template_group = $db->fetch_array($query); - if(isset($template_group['isdefault']) && $template_group['isdefault'] == 1) - { - flash_message($lang->error_default_template_group, 'error'); - admin_redirect("index.php?module=style-templates&sid={$sid}{$expand_str}"); - } - - $plugins->run_hooks("admin_style_templates_edit_template_group"); - - $errors = array(); - if($mybb->request_method == "post") - { - $prefix = trim($mybb->input['prefix']); - if(!$prefix) - { - $errors[] = $lang->error_missing_group_prefix; - } - - if(strpos($prefix, "_") !== false) - { - $errors[] = $lang->error_invalid_group_title; - } - - $title = trim($mybb->input['title']); - if(!$title) - { - $errors[] = $lang->error_missing_group_title; - } - - if(!$errors) - { - if($prefix != $template_group['prefix']) - { - $query = $db->simple_select("templategroups", "COUNT(gid) AS gid", "prefix = '".$db->escape_string($mybb->input['prefix'])."'"); - $prefix_count = $db->fetch_field($query, 'gid'); - - if($prefix_count >= 1) - { - $errors[] = $lang->error_duplicate_group_prefix; - } - } - - if(!$errors) - { - // Add template group - $update_array = array( - 'prefix' => $db->escape_string($prefix), - 'title' => $db->escape_string($title), - 'isdefault' => 0 - ); - - $plugins->run_hooks('admin_style_templates_edit_template_group_commit'); - - $db->update_query('templategroups', $update_array, "gid = '{$template_group['gid']}'"); - - log_admin_action($template_group['gid'], htmlspecialchars_uni($title)); - flash_message($lang->success_template_group_saved, 'success'); - admin_redirect("index.php?module=style-templates&sid={$sid}"); - } - } - } - - $lang->editing_template_group = $lang->sprintf($lang->editing_template_group, htmlspecialchars_uni($template_group['title'])); - - $page->add_breadcrumb_item($template_sets[$sid], "index.php?module=style-templates&sid={$sid}{$expand_str}"); - $page->add_breadcrumb_item($lang->editing_template_group, "index.php?module=style-templates&sid={$sid}"); - - $page->output_header($lang->editing_template_group); - - if($errors) - { - $template_group['prefix'] = $prefix; - $template_group['title'] = $title; - - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=style-templates&action=edit_template_group", "post"); - echo $form->generate_hidden_field('sid', $sid); - echo $form->generate_hidden_field('gid', $template_group['gid']); - - $form_container = new FormContainer($lang->edit_template_group); - $form_container->output_row($lang->template_group_prefix, $lang->template_group_prefix_desc, $form->generate_text_box('prefix', $template_group['prefix'], array('id' => 'prefix')), 'prefix'); - $form_container->output_row($lang->template_group_title, $lang->template_group_title_desc, $form->generate_text_box('title', $template_group['title'], array('id' => 'title')), 'title'); - $form_container->end(); - - $buttons = array( - $form->generate_submit_button($lang->save_template_group) - ); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "search_replace") -{ - $plugins->run_hooks("admin_style_templates_search_replace"); - - if($mybb->request_method == "post") - { - if($mybb->input['type'] == "templates") - { - // Search and replace in templates - - if(!$mybb->input['find']) - { - flash_message($lang->search_noneset, "error"); - admin_redirect("index.php?module=style-templates&action=search_replace"); - } - else - { - $page->add_breadcrumb_item($lang->search_replace); - - $page->output_header($lang->search_replace); - - $plugins->run_hooks("admin_style_templates_search_replace_find"); - - $page->output_nav_tabs($sub_tabs, 'search_replace'); - - $templates_list = array(); - $table = new Table; - - $template_sets = array(); - - // Get the names of all template sets - $template_sets[-2] = $lang->master_templates; - $template_sets[-1] = $lang->global_templates; - - $query = $db->simple_select("templatesets", "sid, title"); - while($set = $db->fetch_array($query)) - { - $template_sets[$set['sid']] = $set['title']; - } - - $search_string = str_replace(array("\r\n", "\r"), "\n", $mybb->input['find']); - $search_string = str_replace(array(" ", "\t"), "", $search_string); - - // Select all templates with that search term - $query = $db->query(" - SELECT t.tid, t.title, t.sid, t.template - FROM ".TABLE_PREFIX."templates t - LEFT JOIN ".TABLE_PREFIX."templatesets s ON (t.sid=s.sid) - LEFT JOIN ".TABLE_PREFIX."templates t2 ON (t.title=t2.title AND t2.sid='1') - WHERE REPLACE(REPLACE(REPLACE(REPLACE(t.template, '\r\n', '\n'), '\r', '\n'), ' ', ''), '\t', '') LIKE '%".$db->escape_string_like($search_string)."%' AND NOT (t.sid = -2 AND (t2.tid) IS NOT NULL) - ORDER BY t.title ASC - "); - if($db->num_rows($query) == 0) - { - $table->construct_cell($lang->sprintf($lang->search_noresults, htmlspecialchars_uni($mybb->input['find'])), array("class" => "align_center")); - - $table->construct_row(); - - $table->output($lang->search_results); - } - else - { - $template_list = array(); - while($template = $db->fetch_array($query)) - { - $template_list[$template['sid']][$template['title']] = $template; - } - - $count = 0; - - foreach($template_list as $sid => $templates) - { - ++$count; - - $search_header = $lang->sprintf($lang->search_header, htmlspecialchars_uni($mybb->input['find']), $template_sets[$sid]); - $table->construct_header($search_header, array("colspan" => 2)); - - foreach($templates as $title => $template) - { - // Do replacement - $newtemplate = str_ireplace($mybb->input['find'], $mybb->input['replace'], $template['template']); - if($newtemplate != $template['template'] && check_template($newtemplate) === false) - { - // If the template is different, that means the search term has been found. - if(trim($mybb->input['replace']) != "") - { - if($template['sid'] == -2) - { - // The template is a master template. We have to make a new custom template. - $new_template = array( - "title" => $db->escape_string($title), - "template" => $db->escape_string($newtemplate), - "sid" => 1, - "version" => $mybb->version_code, - "status" => '', - "dateline" => TIME_NOW - ); - $new_tid = $db->insert_query("templates", $new_template); - $label = $lang->sprintf($lang->search_created_custom, $template['title']); - $url = "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid=1"; - } - else - { - // The template is a custom template. Replace as normal. - // Update the template if there is a replacement term - $updatedtemplate = array( - "template" => $db->escape_string($newtemplate) - ); - $db->update_query("templates", $updatedtemplate, "tid='".$template['tid']."'"); - $label = $lang->sprintf($lang->search_updated, $template['title']); - $url = "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid={$template['sid']}"; - } - } - else - { - // Just show that the term was found - if($template['sid'] == -2) - { - $label = $lang->sprintf($lang->search_found, $template['title']); - } - else - { - $label = $lang->sprintf($lang->search_found, $template['title']); - $url = "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid={$template['sid']}"; - } - } - } - else - { - // Just show that the term was found - if($template['sid'] == -2) - { - $label = $lang->sprintf($lang->search_found, $template['title']); - } - else - { - $label = $lang->sprintf($lang->search_found, $template['title']); - $url = "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid={$template['sid']}"; - } - } - - $table->construct_cell($label, array("width" => "85%")); - - if($sid == -2) - { - $popup = new PopupMenu("template_{$template['tid']}", $lang->options); - - foreach($template_sets as $set_sid => $title) - { - if($set_sid > 0) - { - $popup->add_item($lang->edit_in." ".htmlspecialchars_uni($title), "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid={$set_sid}"); - } - } - - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - } - else - { - $table->construct_cell("{$lang->edit}", array("class" => "align_center")); - } - - $table->construct_row(); - } - - if($count == 1) - { - $table->output($lang->search_results); - } - else - { - $table->output(); - } - } - } - - if(trim($mybb->input['replace']) != "") - { - // Log admin action - only if replace - log_admin_action($mybb->input['find'], $mybb->input['replace']); - } - - $page->output_footer(); - exit; - } - } - else - { - if(!$mybb->input['title']) - { - flash_message($lang->search_noneset, "error"); - admin_redirect("index.php?module=style-templates&action=search_replace"); - } - else - { - // Search Template Titles - - $templatessets = array(); - - $templates_sets = array(); - // Get the names of all template sets - $template_sets[-2] = $lang->master_templates; - $template_sets[-1] = $lang->global_templates; - - $plugins->run_hooks("admin_style_templates_search_replace_title"); - - $query = $db->simple_select("templatesets", "sid, title"); - while($set = $db->fetch_array($query)) - { - $template_sets[$set['sid']] = $set['title']; - } - - $table = new Table; - - $query = $db->query(" - SELECT t.tid, t.title, t.sid, s.title as settitle, t2.tid as customtid - FROM ".TABLE_PREFIX."templates t - LEFT JOIN ".TABLE_PREFIX."templatesets s ON (t.sid=s.sid) - LEFT JOIN ".TABLE_PREFIX."templates t2 ON (t.title=t2.title AND t2.sid='1') - WHERE t.title LIKE '%".$db->escape_string_like($mybb->input['title'])."%' - ORDER BY t.title ASC - "); - while($template = $db->fetch_array($query)) - { - if($template['sid'] == -2) - { - if(!$template['customtid']) - { - $template['original'] = true; - } - else - { - $template['modified'] = true; - } - } - else - { - $template['original'] = false; - $template['modified'] = false; - } - $templatessets[$template['sid']][$template['title']] = $template; - } - - $page->add_breadcrumb_item($lang->search_replace); - - $page->output_header($lang->search_replace); - - $page->output_nav_tabs($sub_tabs, 'search_replace'); - - if(empty($templatessets)) - { - $table->construct_cell($lang->sprintf($lang->search_noresults_title, htmlspecialchars_uni($mybb->input['title'])), array("class" => "align_center")); - - $table->construct_row(); - - $table->output($lang->search_results); - } - - $count = 0; - - foreach($templatessets as $sid => $templates) - { - ++$count; - - $table->construct_header($template_sets[$sid], array("colspan" => 2)); - - foreach($templates as $template) - { - $template['pretty_title'] = $template['title']; - - $popup = new PopupMenu("template_{$template['tid']}", $lang->options); - - if($sid == -2) - { - foreach($template_sets as $set_sid => $title) - { - if($set_sid < 0) continue; - - $popup->add_item($lang->edit_in." ".htmlspecialchars_uni($title), "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid={$set_sid}"); - } - } - else - { - $popup->add_item($lang->full_edit, "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid={$sid}"); - } - - if(isset($template['modified']) && $template['modified'] == true) - { - if($sid > 0) - { - $popup->add_item($lang->diff_report, "index.php?module=style-templates&action=diff_report&title=".urlencode($template['title'])."&sid2={$sid}"); - - $popup->add_item($lang->revert_to_orig, "index.php?module=style-templates&action=revert&title=".urlencode($template['title'])."&sid={$sid}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_template_revertion}')"); - } - - $template['pretty_title'] = "{$template['title']}"; - } - // This template does not exist in the master list - else if(!isset($template['original']) || $template['original'] == false) - { - $popup->add_item($lang->delete_template, "index.php?module=style-templates&action=delete_template&title=".urlencode($template['title'])."&sid={$sid}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_template_deletion}')"); - - $template['pretty_title'] = "{$template['title']}"; - } - - $table->construct_cell("{$template['pretty_title']}", array("width" => "85%")); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - - $table->construct_row(); - } - - if($count == 1) - { - $table->output($lang->sprintf($lang->search_names_header, htmlspecialchars_uni($mybb->input['title']))); - } - else if($count > 0) - { - $table->output(); - } - } - - $page->output_footer(); - exit; - } - } - } - - if($admin_options['codepress'] != 0) - { - $page->extra_header .= ' - - - - - - - - - - - - - - - -'; - } - - $page->add_breadcrumb_item($lang->search_replace); - - $page->output_header($lang->search_replace); - - $page->output_nav_tabs($sub_tabs, 'search_replace'); - - $form = new Form("index.php?module=style-templates&action=search_replace", "post", "do_template"); - echo $form->generate_hidden_field('type', "templates"); - - $form_container = new FormContainer($lang->search_replace, 'tfixed'); - $form_container->output_row($lang->search_for, "", $form->generate_text_area('find', $mybb->input['find'], array('id' => 'find', 'class' => '', 'style' => 'width: 100%; height: 200px;'))); - - $form_container->output_row($lang->replace_with, "", $form->generate_text_area('replace', $mybb->input['replace'], array('id' => 'replace', 'class' => '', 'style' => 'width: 100%; height: 200px;'))); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->find_and_replace); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - echo "
"; - - - $form = new Form("index.php?module=style-templates&action=search_replace", "post", "do_title"); - echo $form->generate_hidden_field('type', "titles"); - - $form_container = new FormContainer($lang->search_template_names); - - $form_container->output_row($lang->search_for, "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - - $form_container->end(); - - $buttons = array(); - $buttons[] = $form->generate_submit_button($lang->find_templates); - $buttons[] = $form->generate_reset_button($lang->reset); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - if($admin_options['codepress'] != 0) - { - echo ''; - } - - $page->output_footer(); -} - -if($mybb->input['action'] == "find_updated") -{ - // Finds templates that are old and have been updated by MyBB - $compare_version = $mybb->version_code; - $query = $db->query(" - SELECT COUNT(*) AS updated_count - FROM ".TABLE_PREFIX."templates t - LEFT JOIN ".TABLE_PREFIX."templates m ON (m.title=t.title AND m.sid=-2 AND m.version > t.version) - WHERE t.sid > 0 AND m.template != t.template - "); - $count = $db->fetch_array($query); - - if($count['updated_count'] < 1) - { - flash_message($lang->no_updated_templates, 'success'); - admin_redirect("index.php?module=style-templates"); - } - - $plugins->run_hooks("admin_style_templates_find_updated"); - - $page->add_breadcrumb_item($lang->find_updated, "index.php?module=style-templates&action=find_updated"); - - $page->output_header($lang->find_updated); - - $page->output_nav_tabs($sub_tabs, 'find_updated'); - - $query = $db->simple_select("templatesets", "*", "", array('order_by' => 'title')); - while($templateset = $db->fetch_array($query)) - { - $templatesets[$templateset['sid']] = $templateset; - } - - echo << -{$lang->legend} -
    -
  • {$lang->updated_template_welcome1}
  • -
  • {$lang->updated_template_welcome2}
  • -
  • {$lang->updated_template_welcome3}
  • -
- -LEGEND; - - $count = 0; - $done_set = array(); - $done_output = array(); - $templates = array(); - $table = new Table; - - $query = $db->query(" - SELECT t.tid, t.title, t.sid, t.version - FROM ".TABLE_PREFIX."templates t - LEFT JOIN ".TABLE_PREFIX."templates m ON (m.title=t.title AND m.sid=-2 AND m.version > t.version) - WHERE t.sid > 0 AND m.template != t.template - ORDER BY t.sid ASC, title ASC - "); - while($template = $db->fetch_array($query)) - { - $templates[$template['sid']][] = $template; - } - - foreach($templates as $sid => $templates) - { - if(!$done_set[$sid]) - { - $table->construct_header($templatesets[$sid]['title'], array("colspan" => 2)); - - $done_set[$sid] = 1; - ++$count; - } - - foreach($templates as $template) - { - $popup = new PopupMenu("template_{$template['tid']}", $lang->options); - $popup->add_item($lang->full_edit, "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid={$sid}&from=diff_report"); - $popup->add_item($lang->diff_report, "index.php?module=style-templates&action=diff_report&title=".urlencode($template['title'])."&sid1=".$template['sid']."&sid2=-2&from=diff_report"); - $popup->add_item($lang->revert_to_orig, "index.php?module=style-templates&action=revert&title=".urlencode($template['title'])."&sid={$sid}&from=diff_report&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_template_revertion}')"); - - $table->construct_cell("{$template['title']}", array('width' => '80%')); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - - $table->construct_row(); - } - - if($done_set[$sid] && !$done_output[$sid]) - { - $done_output[$sid] = 1; - if($count == 1) - { - $table->output($lang->find_updated); - } - else - { - $table->output(); - } - } - } - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete_template_group") -{ - $gid = $mybb->get_input('gid', MyBB::INPUT_INT); - $query = $db->simple_select("templategroups", "*", "gid='{$gid}'"); - - if(!$db->num_rows($query)) - { - flash_message($lang->error_missing_template_group, 'error'); - admin_redirect("index.php?module=style-templates&sid={$sid}"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=style-templates&sid={$sid}"); - } - - $plugins->run_hooks("admin_style_template_group_delete"); - - $template_group = $db->fetch_array($query); - - if($mybb->request_method == "post") - { - // Delete the group - $db->delete_query("templategroups", "gid = '{$template_group['gid']}'"); - - $plugins->run_hooks("admin_style_template_group_delete_commit"); - - // Log admin action - log_admin_action($template_group['gid'], htmlspecialchars_uni($template_group['title'])); - - flash_message($lang->success_template_group_deleted, 'success'); - admin_redirect("index.php?module=style-templates&sid={$sid}"); - } - else - { - $page->output_confirm_action("index.php?module=style-templates&action=delete_template_group&gid={$template_group['gid']}&sid={$sid}", $lang->confirm_template_group_delete); - } -} - -if($mybb->input['action'] == "delete_set") -{ - $query = $db->simple_select("templatesets", "*", "sid='{$sid}' AND sid > 0"); - $set = $db->fetch_array($query); - - // Does the template not exist? - if(!$set['sid']) - { - flash_message($lang->error_invalid_template_set, 'error'); - admin_redirect("index.php?module=style-templates"); - } - - $plugins->run_hooks("admin_style_templates_delete_set"); - - // Is there a theme attached to this set? - $query = $db->simple_select("themes", "properties"); - while($theme = $db->fetch_array($query)) - { - $properties = my_unserialize($theme['properties']); - if($properties['templateset'] == $sid) - { - flash_message($lang->error_themes_attached_template_set, 'error'); - admin_redirect("index.php?module=style-templates"); - break; - } - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=style-templates"); - } - - if($mybb->request_method == "post") - { - // Delete the templateset - $db->delete_query("templatesets", "sid='{$set['sid']}'"); - // Delete all custom templates in this templateset - $db->delete_query("templates", "sid='{$set['sid']}'"); - - $plugins->run_hooks("admin_style_templates_delete_set_commit"); - - // Log admin action - log_admin_action($set['sid'], $set['title']); - - flash_message($lang->success_template_set_deleted, 'success'); - admin_redirect("index.php?module=style-templates"); - } - else - { - $page->output_confirm_action("index.php?module=style-templates&action=delete_set&sid={$set['sid']}", $lang->confirm_template_set_deletion); - } - -} - -if($mybb->input['action'] == "delete_template") -{ - $query = $db->query(" - SELECT t.*, s.title as set_title - FROM ".TABLE_PREFIX."templates t - LEFT JOIN ".TABLE_PREFIX."templatesets s ON(t.sid=s.sid) - WHERE t.title='".$db->escape_string($mybb->input['title'])."' AND t.sid > '-2' AND t.sid = '{$sid}' - "); - $template = $db->fetch_array($query); - - // Does the template not exist? - if(!$template) - { - flash_message($lang->error_invalid_template, 'error'); - admin_redirect("index.php?module=style-templates"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=style-templates&sid={$template['sid']}{$expand_str2}"); - } - - $plugins->run_hooks("admin_style_templates_delete_template"); - - if($mybb->request_method == "post") - { - // Delete the template - $db->delete_query("templates", "tid='{$template['tid']}'"); - - $plugins->run_hooks("admin_style_templates_delete_template_commit"); - - // Log admin action - log_admin_action($template['tid'], $template['title'], $template['sid'], $template['set_title']); - - flash_message($lang->success_template_deleted, 'success'); - admin_redirect("index.php?module=style-templates&sid={$template['sid']}{$expand_str2}"); - } - else - { - $page->output_confirm_action("index.php?module=style-templates&action=delete_template&sid={$template['sid']}{$expand_str}", $lang->confirm_template_deletion); - } -} - -if($mybb->input['action'] == "diff_report") -{ - // Compares a template of sid1 with that of sid2, if no sid1, it is assumed -2 - if(!$mybb->input['sid1'] || !isset($template_sets[$mybb->input['sid1']])) - { - $mybb->input['sid1'] = -2; - } - - if($mybb->input['sid2'] == -2) - { - $sub_tabs['find_updated'] = array( - 'title' => $lang->find_updated, - 'link' => "index.php?module=style-templates&action=find_updated" - ); - } - - if($mybb->input['sid2'] != -2 && !isset($template_sets[$mybb->input['sid2']])) - { - flash_message($lang->error_invalid_input, 'error'); - admin_redirect("index.php?module=style-templates"); - } - - if(!$mybb->input['from']) - { - $mybb->input['from'] = 0; - } - - $sub_tabs['diff_report'] = array( - 'title' => $lang->diff_report, - 'link' => "index.php?module=style-templates&action=diff_report&title=".$db->escape_string($mybb->input['title'])."&from=".htmlspecialchars_uni($mybb->input['from'])."sid1=".$mybb->get_input('sid1', MyBB::INPUT_INT)."&sid2=".$mybb->get_input('sid2', MyBB::INPUT_INT), - 'description' => $lang->diff_report_desc - ); - - $plugins->run_hooks("admin_style_templates_diff_report"); - - $query = $db->simple_select("templates", "*", "title='".$db->escape_string($mybb->input['title'])."' AND sid='".$mybb->get_input('sid1', MyBB::INPUT_INT)."'"); - $template1 = $db->fetch_array($query); - - $query = $db->simple_select("templates", "*", "title='".$db->escape_string($mybb->input['title'])."' AND sid='".$mybb->get_input('sid2', MyBB::INPUT_INT)."'"); - $template2 = $db->fetch_array($query); - - if($mybb->input['sid2'] == -2) - { - $sub_tabs['full_edit'] = array( - 'title' => $lang->full_edit, - 'link' => "index.php?module=style-templates&action=edit_template&title=".urlencode($template1['title'])."&sid=".$mybb->get_input('sid1', MyBB::INPUT_INT)."&from=diff_report", - ); - } - - if($template1['template'] == $template2['template']) - { - flash_message($lang->templates_the_same, 'error'); - admin_redirect("index.php?module=style-templates&sid=".$mybb->get_input('sid2', MyBB::INPUT_INT).$expand_str); - } - - $template1['template'] = explode("\n", $template1['template']); - $template2['template'] = explode("\n", $template2['template']); - - $plugins->run_hooks("admin_style_templates_diff_report_run"); - - require_once MYBB_ROOT."inc/3rdparty/diff/Diff.php"; - require_once MYBB_ROOT."inc/3rdparty/diff/Diff/Renderer.php"; - require_once MYBB_ROOT."inc/3rdparty/diff/Diff/Renderer/Inline.php"; - - $diff = new Horde_Text_Diff('auto', array($template1['template'], $template2['template'])); - $renderer = new Horde_Text_Diff_Renderer_Inline(); - - if($sid) - { - $page->add_breadcrumb_item($template_sets[$sid], "index.php?module=style-templates&sid={$sid}{$expand_str}"); - } - - if($mybb->input['sid2'] == -2) - { - $page->add_breadcrumb_item($lang->find_updated, "index.php?module=style-templates&action=find_updated"); - } - - $page->add_breadcrumb_item($lang->diff_report.": ".htmlspecialchars_uni($template1['title']), "index.php?module=style-templates&action=diff_report&title=".$db->escape_string($mybb->input['title'])."&from=".htmlspecialchars_uni($mybb->input['from'])."&sid1=".$mybb->get_input('sid1', MyBB::INPUT_INT)."&sid2=".$mybb->get_input('sid2', MyBB::INPUT_INT)); - - $page->output_header($lang->template_sets); - - $page->output_nav_tabs($sub_tabs, 'diff_report'); - - $table = new Table; - - if($mybb->input['from']) - { - $table->construct_header("".$lang->master_updated_ins."
".$lang->master_updated_del.""); - } - else - { - $table->construct_header("".$lang->master_updated_del."
".$lang->master_updated_ins.""); - } - - $table->construct_cell("
".$renderer->render($diff)."
"); - $table->construct_row(); - - $table->output($lang->template_diff_analysis.": ".$template1['title']); - - $page->output_footer(); -} - -if($mybb->input['action'] == "revert") -{ - $query = $db->query(" - SELECT t.*, s.title as set_title - FROM ".TABLE_PREFIX."templates t - LEFT JOIN ".TABLE_PREFIX."templatesets s ON(s.sid=t.sid) - WHERE t.title='".$db->escape_string($mybb->input['title'])."' AND t.sid > 0 AND t.sid = '".$mybb->get_input('sid', MyBB::INPUT_INT)."' - "); - $template = $db->fetch_array($query); - - // Does the template not exist? - if(!$template) - { - flash_message($lang->error_invalid_template, 'error'); - admin_redirect("index.php?module=style-templates"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=style-templates&sid={$template['sid']}{$expand_str2}"); - } - - $plugins->run_hooks("admin_style_templates_revert"); - - if($mybb->request_method == "post") - { - // Revert the template - $db->delete_query("templates", "tid='{$template['tid']}'"); - - $plugins->run_hooks("admin_style_templates_revert_commit"); - - // Log admin action - log_admin_action($template['tid'], $template['title'], $template['sid'], $template['set_title']); - - flash_message($lang->success_template_reverted, 'success'); - - if($mybb->input['from'] == "diff_report") - { - admin_redirect("index.php?module=style-templates&action=find_updated"); - } - else - { - admin_redirect("index.php?module=style-templates&sid={$template['sid']}{$expand_str2}"); - } - } - else - { - $page->output_confirm_action("index.php?module=style-templates&sid={$template['sid']}{$expand_str}", $lang->confirm_template_revertion); - } -} - -if($mybb->input['sid'] && !$mybb->input['action']) -{ - if(!isset($template_sets[$mybb->input['sid']])) - { - flash_message($lang->error_invalid_input, 'error'); - admin_redirect("index.php?module=style-templates"); - } - - $plugins->run_hooks("admin_style_templates_set"); - - $table = new Table; - - $page->add_breadcrumb_item($template_sets[$sid], "index.php?module=style-templates&sid={$sid}"); - - $page->output_header($lang->template_sets); - - $page->output_nav_tabs($sub_tabs, 'manage_templates'); - - $table->construct_header($lang->template_set); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - // Global Templates - if($sid == -1) - { - $query = $db->simple_select("templates", "tid,title", "sid='-1'", array('order_by' => 'title', 'order_dir' => 'ASC')); - while($template = $db->fetch_array($query)) - { - $popup = new PopupMenu("template_{$template['tid']}", $lang->options); - $popup->add_item($lang->full_edit, "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid=-1"); - $popup->add_item($lang->delete_template, "index.php?module=style-templates&action=delete_template&title=".urlencode($template['title'])."&sid=-1&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_template_deletion}')"); - - $table->construct_cell("{$template['title']}"); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_global_templates, array('colspan' => 2)); - $table->construct_row(); - } - - $table->output($template_sets[$sid]); - - $page->output_footer(); - } - - if(!isset($mybb->input['expand'])) - { - $mybb->input['expand'] = ''; - } - if($mybb->input['expand'] == 'all') - { - // If we're expanding everything, stick in the ungrouped templates in the list as well - $expand_array = array(-1); - } - // Fetch Groups - $query = $db->simple_select("templategroups", "*"); - - $template_groups = array(); - while($templategroup = $db->fetch_array($query)) - { - $templategroup['title'] = $lang->sprintf($lang->templates, htmlspecialchars_uni($lang->parse($templategroup['title']))); - if($mybb->input['expand'] == 'all') - { - $expand_array[] = $templategroup['gid']; - } - if(in_array($templategroup['gid'], $expand_array)) - { - $templategroup['expanded'] = 1; - } - $template_groups[$templategroup['prefix']] = $templategroup; - } - - /** - * @param array $a - * @param array $b - * - * @return int - */ - function sort_template_groups($a, $b) - { - return strcasecmp($a['title'], $b['title']); - } - uasort($template_groups, "sort_template_groups"); - - // Add the ungrouped templates group at the bottom - $template_groups['-1'] = array( - "prefix" => "", - "title" => $lang->ungrouped_templates, - "gid" => -1 - ); - - // Set the template group keys to lowercase for case insensitive comparison. - $template_groups = array_change_key_case($template_groups, CASE_LOWER); - - // Load the list of templates - $query = $db->simple_select("templates", "*", "sid='".$mybb->get_input('sid', MyBB::INPUT_INT)."' OR sid='-2'", array('order_by' => 'sid DESC, title', 'order_dir' => 'ASC')); - while($template = $db->fetch_array($query)) - { - $exploded = explode("_", $template['title'], 2); - - // Set the prefix to lowercase for case insensitive comparison. - $exploded[0] = strtolower($exploded[0]); - - if(isset($template_groups[$exploded[0]])) - { - $group = $exploded[0]; - } - else - { - $group = -1; - } - - $template['gid'] = -1; - if(isset($template_groups[$exploded[0]]['gid'])) - { - $template['gid'] = $template_groups[$exploded[0]]['gid']; - } - - // If this template is not a master template, we simple add it to the list - if($template['sid'] != -2) - { - $template['original'] = false; - $template['modified'] = false; - $template_groups[$group]['templates'][$template['title']] = $template; - } - else if(!in_array($template['gid'], $expand_array) && !isset($expand_array[-1])) - { - $template['original'] = true; - $template['modified'] = false; - $template_groups[$group]['templates'][$template['title']] = $template; - - // Save some memory! - unset($template_groups[$group]['templates'][$template['title']]['template']); - } - // Otherwise, if we are down to master templates we need to do a few extra things - else - { - // Master template that hasn't been customised in the set we have expanded - if(!isset($template_groups[$group]['templates'][$template['title']]) || $template_groups[$group]['templates'][$template['title']]['template'] == $template['template']) - { - $template['original'] = true; - $template_groups[$group]['templates'][$template['title']] = $template; - } - // Template has been modified in the set we have expanded (it doesn't match the master) - else if($template_groups[$group]['templates'][$template['title']]['template'] != $template['template'] && $template_groups[$group]['templates'][$template['title']]['sid'] != -2) - { - $template_groups[$group]['templates'][$template['title']]['modified'] = true; - } - - // Save some memory! - unset($template_groups[$group]['templates'][$template['title']]['template']); - } - } - - foreach($template_groups as $prefix => $group) - { - $tmp_expand = ""; - if(in_array($group['gid'], $expand_array)) - { - $expand = $lang->collapse; - $expanded = true; - - $tmp_expand = $expand_array; - $unsetgid = array_search($group['gid'], $tmp_expand); - unset($tmp_expand[$unsetgid]); - $group['expand_str'] = implode("|", $tmp_expand); - } - else - { - $expand = $lang->expand; - $expanded = false; - - $group['expand_str'] = implode("|", $expand_array); - if($group['expand_str']) - { - $group['expand_str'] .= "|"; - } - $group['expand_str'] .= $group['gid']; - } - - if($group['expand_str']) - { - $group['expand_str'] = "&expand={$group['expand_str']}"; - } - - $set_popup = ''; - if(isset($group['isdefault']) && !$group['isdefault']) - { - $popup = new PopupMenu("template_set_{$group['gid']}", $lang->options); - $popup->add_item($lang->edit_template_group, "index.php?module=style-templates&sid={$sid}&action=edit_template_group&gid={$group['gid']}{$group['expand_str']}"); - $popup->add_item($lang->delete_template_group, "index.php?module=style-templates&sid={$sid}&action=delete_template_group&gid={$group['gid']}&my_post_key={$mybb->post_code}{$group['expand_str']}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_template_group_delete}')"); - - $set_popup = "
{$popup->fetch()}
"; - } - - if($expanded == true) - { - // Show templates in this group - $table->construct_cell("{$set_popup}{$group['title']}"); - $table->construct_cell("{$expand}", array("class" => "align_center")); - $table->construct_row(array("class" => "alt_row", "id" => "group_".$group['gid'], "name" => "group_".$group['gid'])); - - if(isset($group['templates']) && count($group['templates']) > 0) - { - $templates = $group['templates']; - ksort($templates); - - foreach($templates as $template) - { - $template['pretty_title'] = $template['title']; - - $popup = new PopupMenu("template_{$template['tid']}", $lang->options); - $popup->add_item($lang->full_edit, "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid={$sid}{$expand_str}"); - - if(isset($template['modified']) && $template['modified'] == true) - { - if($sid > 0) - { - $popup->add_item($lang->diff_report, "index.php?module=style-templates&action=diff_report&title=".urlencode($template['title'])."&sid2={$sid}"); - - $popup->add_item($lang->revert_to_orig, "index.php?module=style-templates&action=revert&title=".urlencode($template['title'])."&sid={$sid}&my_post_key={$mybb->post_code}{$expand_str}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_template_revertion}')"); - } - - $template['pretty_title'] = "{$template['title']}"; - } - // This template does not exist in the master list - else if(isset($template['original']) && $template['original'] == false) - { - $popup->add_item($lang->delete_template, "index.php?module=style-templates&action=delete_template&title=".urlencode($template['title'])."&sid={$sid}&my_post_key={$mybb->post_code}{$expand_str}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_template_deletion}')"); - - $template['pretty_title'] = "{$template['title']}"; - } - - $table->construct_cell("{$template['pretty_title']}"); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - - $table->construct_row(); - } - } - else - { - // No templates in this group - $table->construct_cell($lang->empty_template_set, array('colspan' => 2)); - $table->construct_row(); - } - } - else - { - // Collapse template set - $table->construct_cell("{$set_popup}{$group['title']}"); - $table->construct_cell("{$expand}", array("class" => "align_center")); - $table->construct_row(array("class" => "alt_row", "id" => "group_".$group['gid'], "name" => "group_".$group['gid'])); - } - } - - $table->output($template_sets[$sid]); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_style_templates_start"); - - $page->output_header($lang->template_sets); - - $page->output_nav_tabs($sub_tabs, 'templates'); - - $themes = array(); - $query = $db->simple_select("themes", "name,tid,properties", "tid != '1'"); - while($theme = $db->fetch_array($query)) - { - $tbits = my_unserialize($theme['properties']); - $themes[$tbits['templateset']][$theme['tid']] = htmlspecialchars_uni($theme['name']); - } - - $template_sets = array(); - $template_sets[-1]['title'] = $lang->global_templates; - $template_sets[-1]['sid'] = -1; - - $query = $db->simple_select("templatesets", "*", "", array('order_by' => 'title', 'order_dir' => 'ASC')); - while($template_set = $db->fetch_array($query)) - { - $template_sets[$template_set['sid']] = $template_set; - } - - $table = new Table; - $table->construct_header($lang->template_set); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - foreach($template_sets as $set) - { - if($set['sid'] == -1) - { - $table->construct_cell("{$lang->global_templates}
{$lang->used_by_all_themes}"); - $table->construct_cell("{$lang->expand_templates}", array("class" => "align_center")); - $table->construct_row(); - continue; - } - - if($themes[$set['sid']]) - { - $used_by_note = $lang->used_by; - $comma = ""; - foreach($themes[$set['sid']] as $theme_name) - { - $used_by_note .= $comma.$theme_name; - $comma = $lang->comma; - } - } - else - { - $used_by_note = $lang->not_used_by_any_themes; - } - - if($set['sid'] == 1) - { - $actions = "{$lang->expand_templates}"; - } - else - { - $popup = new PopupMenu("templateset_{$set['sid']}", $lang->options); - $popup->add_item($lang->expand_templates, "index.php?module=style-templates&sid={$set['sid']}"); - - if($set['sid'] != 1) - { - $popup->add_item($lang->edit_template_set, "index.php?module=style-templates&action=edit_set&sid={$set['sid']}"); - - if(!$themes[$set['sid']]) - { - $popup->add_item($lang->delete_template_set, "index.php?module=style-templates&action=delete_set&sid={$set['sid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_template_set_deletion}')"); - } - } - - $actions = $popup->fetch(); - } - - $table->construct_cell("{$set['title']}
{$used_by_note}"); - $table->construct_cell($actions, array("class" => "align_center")); - $table->construct_row(); - } - - $table->output($lang->template_sets); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/style/themes.php b/html/forums/admin/modules/style/themes.php deleted file mode 100644 index 4064c5d..0000000 --- a/html/forums/admin/modules/style/themes.php +++ /dev/null @@ -1,3011 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -require_once MYBB_ADMIN_DIR."inc/functions_themes.php"; - -$page->extra_header .= " -"; - -if($mybb->input['action'] == "xmlhttp_stylesheet" && $mybb->request_method == "post") -{ - // Fetch the theme we want to edit this stylesheet in - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - if(!$theme['tid'] || $theme['tid'] == 1) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $parent_list = make_parent_theme_list($theme['tid']); - $parent_list = implode(',', $parent_list); - if(!$parent_list) - { - $parent_list = 1; - } - - $query = $db->simple_select("themestylesheets", "*", "name='".$db->escape_string($mybb->input['file'])."' AND tid IN ({$parent_list})", array('order_by' => 'tid', 'order_dir' => 'desc', 'limit' => 1)); - $stylesheet = $db->fetch_array($query); - - // Does the theme not exist? - if(!$stylesheet['sid']) - { - flash_message($lang->error_invalid_stylesheet, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $css_array = css_to_array($stylesheet['stylesheet']); - $selector_list = get_selectors_as_options($css_array, $mybb->input['selector']); - $editable_selector = $css_array[$mybb->input['selector']]; - $properties = parse_css_properties($editable_selector['values']); - - $form = new Form("index.php?module=style-themes&action=stylesheet_properties", "post", "selector_form", 0, "", true); - echo $form->generate_hidden_field("tid", $mybb->input['tid'], array('id' => "tid"))."\n"; - echo $form->generate_hidden_field("file", htmlspecialchars_uni($mybb->input['file']), array('id' => "file"))."\n"; - echo $form->generate_hidden_field("selector", htmlspecialchars_uni($mybb->input['selector']), array('id' => 'hidden_selector'))."\n"; - - $table = new Table; - if($lang->settings['rtl'] === true) - { - $div_align = "left"; - } - else - { - $div_align = "right"; - } - - $table->construct_cell("
".$form->generate_text_box('css_bits[background]', $properties['background'], array('id' => 'css_bits[background]', 'style' => 'width: 260px;'))."
{$lang->background}
", array('style' => 'width: 20%;')); - $table->construct_cell("{$lang->extra_css_atribs}
".$form->generate_text_area('css_bits[extra]', $properties['extra'], array('id' => 'css_bits[extra]', 'style' => 'width: 98%;', 'rows' => '19'))."
", array('rowspan' => 8)); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[color]', $properties['color'], array('id' => 'css_bits[color]', 'style' => 'width: 260px;'))."
{$lang->color}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[width]', $properties['width'], array('id' => 'css_bits[width]', 'style' => 'width: 260px;'))."
{$lang->width}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[font_family]', $properties['font-family'], array('id' => 'css_bits[font_family]', 'style' => 'width: 260px;'))."
{$lang->font_family}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[font_size]', $properties['font-size'], array('id' => 'css_bits[font_size]', 'style' => 'width: 260px;'))."
{$lang->font_size}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[font_style]', $properties['font-style'], array('id' => 'css_bits[font_style]', 'style' => 'width: 260px;'))."
{$lang->font_style}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[font_weight]', $properties['font-weight'], array('id' => 'css_bits[font_weight]', 'style' => 'width: 260px;'))."
{$lang->font_weight}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[text_decoration]', $properties['text-decoration'], array('id' => 'css_bits[text_decoration]', 'style' => 'width: 260px;'))."
{$lang->text_decoration}
", array('style' => 'width: 40%;')); - $table->construct_row(); - - $table->output(htmlspecialchars_uni($editable_selector['class_name']).""); - exit; -} - -$page->add_breadcrumb_item($lang->themes, "index.php?module=style-themes"); - -if($mybb->input['action'] == "add" || $mybb->input['action'] == "import" || $mybb->input['action'] == "browse" || !$mybb->input['action']) -{ - $sub_tabs['themes'] = array( - 'title' => $lang->themes, - 'link' => "index.php?module=style-themes", - 'description' => $lang->themes_desc - ); - - $sub_tabs['create_theme'] = array( - 'title' => $lang->create_new_theme, - 'link' => "index.php?module=style-themes&action=add", - 'description' => $lang->create_new_theme_desc - ); - - $sub_tabs['import_theme'] = array( - 'title' => $lang->import_a_theme, - 'link' => "index.php?module=style-themes&action=import", - 'description' => $lang->import_a_theme_desc - ); - - $sub_tabs['browse_themes'] = array( - 'title' => $lang->browse_themes, - 'link' => "index.php?module=style-themes&action=browse", - 'description' => $lang->browse_themes_desc - ); -} - -$plugins->run_hooks("admin_style_themes_begin"); - -if($mybb->input['action'] == "browse") -{ - $plugins->run_hooks("admin_style_themes_browse"); - - $page->add_breadcrumb_item($lang->browse_themes); - - $page->output_header($lang->browse_themes); - - $page->output_nav_tabs($sub_tabs, 'browse_themes'); - - // Process search requests - require_once MYBB_ROOT."inc/class_xml.php"; - - $keywords = ""; - if($mybb->input['keywords']) - { - $keywords = "&keywords=".urlencode($mybb->input['keywords']); - } - - if($mybb->input['page']) - { - $url_page = "&page=".$mybb->get_input('page', MyBB::INPUT_INT); - } - else - { - $mybb->input['page'] = 1; - $url_page = ""; - } - - // Gets the major version code. i.e. 1410 -> 1400 or 121 -> 1200 - $major_version_code = round($mybb->version_code/100, 0)*100; - // Convert to mods site version codes - $search_version = ($major_version_code/100).'x'; - - $contents = fetch_remote_file("https://community.mybb.com/xmlbrowse.php?type=themes&version={$search_version}{$keywords}{$url_page}", $post_data); - - if(!$contents) - { - $page->output_inline_error($lang->error_communication_problem); - $page->output_footer(); - exit; - } - - $table = new Table; - $table->construct_header($lang->themes, array('colspan' => 2)); - $table->construct_header($lang->controls, array("class" => "align_center", 'width' => 125)); - - $parser = new XMLParser($contents); - $tree = $parser->get_tree(); - - if(!is_array($tree) || !isset($tree['results'])) - { - $page->output_inline_error($lang->error_communication_problem); - $page->output_footer(); - exit; - } - - if(!empty($tree['results']['result'])) - { - if(array_key_exists("tag", $tree['results']['result'])) - { - $only_theme = $tree['results']['result']; - unset($tree['results']['result']); - $tree['results']['result'][0] = $only_theme; - } - - require_once MYBB_ROOT . '/inc/class_parser.php'; - $post_parser = new postParser(); - - foreach($tree['results']['result'] as $result) - { - $result['thumbnail']['value'] = htmlspecialchars_uni($result['thumbnail']['value']); - $result['name']['value'] = htmlspecialchars_uni($result['name']['value']); - $result['description']['value'] = htmlspecialchars_uni($result['description']['value']); - $result['author']['value'] = $post_parser->parse_message($result['author']['value'], array( - 'allow_html' => true - ) - ); - $result['download_url']['value'] = htmlspecialchars_uni(html_entity_decode($result['download_url']['value'])); - - $table->construct_cell("\"{$lang-theme_thumbnail}\" title=\"{$lang->theme_thumbnail}\"/>", array("class" => "align_center", "width" => 100)); - $table->construct_cell("{$result['name']['value']}
{$result['description']['value']}
{$lang->created_by} {$result['author']['value']}"); - $table->construct_cell("{$lang->download}", array("class" => "align_center")); - $table->construct_row(); - } - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->error_no_results_found, array("colspan" => 3)); - $table->construct_row(); - } - - $search = new Form("index.php?module=style-themes&action=browse", 'post', 'search_form'); - echo "
"; - if($mybb->input['keywords']) - { - $default_class = ''; - $value = htmlspecialchars_uni($mybb->input['keywords']); - } - else - { - $default_class = "search_default"; - $value = $lang->search_for_themes; - } - echo $search->generate_text_box('keywords', $value, array('id' => 'search_keywords', 'class' => "{$default_class} field150 field_small"))."\n"; - echo "search}\" />\n"; - echo "\n"; - echo "
\n"; - echo $search->end(); - - // Recommended themes = Default; Otherwise search results & pagination - if($mybb->request_method == "post") - { - $table->output("{$lang->browse_all_themes}".$lang->sprintf($lang->browse_results_for_mybb, $mybb->version)); - } - else - { - $table->output("{$lang->browse_all_themes}".$lang->sprintf($lang->recommended_themes_for_mybb, $mybb->version)); - } - - echo "
".draw_admin_pagination($mybb->input['page'], 15, $tree['results']['attributes']['total'], "index.php?module=style-themes&action=browse{$keywords}&page={page}"); - - $page->output_footer(); -} - -if($mybb->input['action'] == "import") -{ - $plugins->run_hooks("admin_style_themes_import"); - - if($mybb->request_method == "post") - { - if(!$_FILES['local_file'] && !$mybb->input['url']) - { - $errors[] = $lang->error_missing_url; - } - - if(!$errors) - { - // Find out if there was an uploaded file - if($_FILES['local_file']['error'] != 4) - { - // Find out if there was an error with the uploaded file - if($_FILES['local_file']['error'] != 0) - { - $errors[] = $lang->error_uploadfailed.$lang->error_uploadfailed_detail; - switch($_FILES['local_file']['error']) - { - case 1: // UPLOAD_ERR_INI_SIZE - $errors[] = $lang->error_uploadfailed_php1; - break; - case 2: // UPLOAD_ERR_FORM_SIZE - $errors[] = $lang->error_uploadfailed_php2; - break; - case 3: // UPLOAD_ERR_PARTIAL - $errors[] = $lang->error_uploadfailed_php3; - break; - case 6: // UPLOAD_ERR_NO_TMP_DIR - $errors[] = $lang->error_uploadfailed_php6; - break; - case 7: // UPLOAD_ERR_CANT_WRITE - $errors[] = $lang->error_uploadfailed_php7; - break; - default: - $errors[] = $lang->sprintf($lang->error_uploadfailed_phpx, $_FILES['local_file']['error']); - break; - } - } - - if(!$errors) - { - // Was the temporary file found? - if(!is_uploaded_file($_FILES['local_file']['tmp_name'])) - { - $errors[] = $lang->error_uploadfailed_lost; - } - // Get the contents - $contents = @file_get_contents($_FILES['local_file']['tmp_name']); - // Delete the temporary file if possible - @unlink($_FILES['local_file']['tmp_name']); - // Are there contents? - if(!trim($contents)) - { - $errors[] = $lang->error_uploadfailed_nocontents; - } - } - } - else if(!empty($mybb->input['url'])) - { - // Get the contents - $contents = @fetch_remote_file($mybb->input['url']); - if(!$contents) - { - $errors[] = $lang->error_local_file; - } - } - else - { - // UPLOAD_ERR_NO_FILE - $errors[] = $lang->error_uploadfailed_php4; - } - - if(!$errors) - { - $options = array( - 'no_stylesheets' => ($mybb->input['import_stylesheets'] ? 0 : 1), - 'no_templates' => ($mybb->input['import_templates'] ? 0 : 1), - 'version_compat' => $mybb->get_input('version_compat', MyBB::INPUT_INT), - 'parent' => $mybb->get_input('tid', MyBB::INPUT_INT), - 'force_name_check' => true, - ); - $theme_id = import_theme_xml($contents, $options); - - if($theme_id > -1) - { - $plugins->run_hooks("admin_style_themes_import_commit"); - - // Log admin action - log_admin_action($theme_id); - - flash_message($lang->success_imported_theme, 'success'); - admin_redirect("index.php?module=style-themes&action=edit&tid=".$theme_id); - } - else - { - switch($theme_id) - { - case -1: - $errors[] = $lang->error_uploadfailed_nocontents; - break; - case -2: - $errors[] = $lang->error_invalid_version; - break; - case -3: - $errors[] = $lang->error_theme_already_exists; - break; - case -4: - $errors[] = $lang->error_theme_security_problem; - } - } - } - } - } - - $query = $db->simple_select("themes", "tid, name"); - while($theme = $db->fetch_array($query)) - { - $themes[$theme['tid']] = $theme['name']; - } - - $page->add_breadcrumb_item($lang->import_a_theme, "index.php?module=style-themes&action=import"); - - $page->output_header("{$lang->themes} - {$lang->import_a_theme}"); - - $page->output_nav_tabs($sub_tabs, 'import_theme'); - - if($errors) - { - $page->output_inline_error($errors); - - if($mybb->input['import'] == 1) - { - $import_checked[1] = ""; - $import_checked[2] = "checked=\"checked\""; - } - else - { - $import_checked[1] = "checked=\"checked\""; - $import_checked[2] = ""; - } - } - else - { - $import_checked[1] = "checked=\"checked\""; - $import_checked[2] = ""; - - $mybb->input['import_stylesheets'] = true; - $mybb->input['import_templates'] = true; - } - - $form = new Form("index.php?module=style-themes&action=import", "post", "", 1); - - $actions = ' -
-
-
- - - - -
'.$form->generate_file_upload_box("local_file", array('style' => 'width: 230px;')).'
-
-
-
- - - - -
'.$form->generate_text_box("url", $mybb->input['file']).'
-
- '; - - $form_container = new FormContainer($lang->import_a_theme); - $form_container->output_row($lang->import_from, $lang->import_from_desc, $actions, 'file'); - $form_container->output_row($lang->parent_theme, $lang->parent_theme_desc, $form->generate_select_box('tid', $themes, $mybb->input['tid'], array('id' => 'tid')), 'tid'); - $form_container->output_row($lang->new_name, $lang->new_name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->advanced_options, "", $form->generate_check_box('version_compat', '1', $lang->ignore_version_compatibility, array('checked' => $mybb->input['version_compat'], 'id' => 'version_compat'))."
{$lang->ignore_version_compat_desc}
".$form->generate_check_box('import_stylesheets', '1', $lang->import_stylesheets, array('checked' => $mybb->input['import_stylesheets'], 'id' => 'import_stylesheets'))."
{$lang->import_stylesheets_desc}
".$form->generate_check_box('import_templates', '1', $lang->import_templates, array('checked' => $mybb->input['import_templates'], 'id' => 'import_templates'))."
{$lang->import_templates_desc}"); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->import_theme); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "export") -{ - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - // Does the theme not exist? - if(!$theme['tid']) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_export"); - - if($mybb->request_method == "post") - { - $properties = my_unserialize($theme['properties']); - - $xml = "settings['charset']}\"?".">\r\n"; - $xml .= "version_code."\">\r\n"; - $xml .= "\t\r\n"; - foreach($properties as $property => $value) - { - if($property == "inherited") continue; - - if(is_array($value)) - { - $value = my_serialize($value); - } - - $value = str_replace(']]>', ']]]]>', $value); - - $xml .= "\t\t<{$property}>\r\n"; - } - $xml .= "\t\r\n"; - - // Fetch list of all of the stylesheets for this theme - $file_stylesheets = my_unserialize($theme['stylesheets']); - - $stylesheets = array(); - $inherited_load = array(); - - // Now we loop through the list of stylesheets for each file - foreach($file_stylesheets as $file => $action_stylesheet) - { - if($file == 'inherited' || !is_array($action_stylesheet)) - { - continue; - } - - foreach($action_stylesheet as $action => $style) - { - foreach($style as $stylesheet) - { - $stylesheets[$stylesheet]['applied_to'][$file][] = $action; - if(is_array($file_stylesheets['inherited'][$file."_".$action]) && in_array($stylesheet, array_keys($file_stylesheets['inherited'][$file."_".$action]))) - { - $stylesheets[$stylesheet]['inherited'] = $file_stylesheets['inherited'][$file."_".$action]; - foreach($file_stylesheets['inherited'][$file."_".$action] as $value) - { - $inherited_load[] = $value; - } - } - } - } - } - - $inherited_load[] = $mybb->input['tid']; - $inherited_load = array_unique($inherited_load); - - $inherited_themes = array(); - if(count($inherited_load) > 0) - { - $query = $db->simple_select("themes", "tid, name", "tid IN (".implode(",", $inherited_load).")"); - while($inherited_theme = $db->fetch_array($query)) - { - $inherited_themes[$inherited_theme['tid']] = $inherited_theme['name']; - } - } - - $theme_stylesheets = array(); - - if(count($inherited_load) > 0) - { - $query = $db->simple_select("themestylesheets", "*", "tid IN (".implode(",", $inherited_load).")", array('order_by' => 'tid', 'order_dir' => 'desc')); - while($theme_stylesheet = $db->fetch_array($query)) - { - if(!$theme_stylesheets[$theme_stylesheet['cachefile']]) - { - $theme_stylesheets[$theme_stylesheet['cachefile']] = $theme_stylesheet; - $theme_stylesheets[$theme_stylesheet['sid']] = $theme_stylesheet['cachefile']; - } - } - } - - $xml .= "\t\r\n"; - foreach($stylesheets as $filename => $style) - { - if(strpos($filename, 'css.php?stylesheet=') !== false) - { - $style['sid'] = (int)str_replace('css.php?stylesheet=', '', $filename); - $filename = $theme_stylesheets[$style['sid']]; - } - else - { - $filename = basename($filename); - $style['sid'] = $theme_stylesheets[$filename]['sid']; - } - - $style['tid'] = $theme_stylesheets[$filename]['tid']; - - if($mybb->input['custom_theme'] == 1 && $style['tid'] != $mybb->input['tid']) - { - continue; - } - - // Has the file on the file system been modified? - resync_stylesheet($theme_stylesheets[$filename]); - - $style['sid'] = $theme_stylesheets[$filename]['sid']; - - $attachedto = $theme_stylesheets[$filename]['attachedto']; - $stylesheet = $theme_stylesheets[$filename]['stylesheet']; - $stylesheet = str_replace(']]>', ']]]]>', $stylesheet); - - if($attachedto) - { - $attachedto = "attachedto=\"{$attachedto}\" "; - } - - $filename = $theme_stylesheets[$filename]['name']; - - $xml .= "\t\tversion_code}\">\r\n\t\t\r\n"; - - } - $xml .= "\t\r\n"; - - if($mybb->input['include_templates'] != 0) - { - $xml .= "\t\r\n"; - $query = $db->simple_select("templates", "*", "sid='".$properties['templateset']."'"); - while($template = $db->fetch_array($query)) - { - $template['template'] = str_replace(']]>', ']]]]>', $template['template']); - $xml .= "\t\t\r\n"; - } - $xml .= "\t\r\n"; - } - $xml .= ""; - - $plugins->run_hooks("admin_style_themes_export_commit"); - - // Log admin action - log_admin_action($theme['tid'], htmlspecialchars_uni($theme['name'])); - - $theme['name'] = rawurlencode($theme['name']); - header("Content-disposition: attachment; filename=".$theme['name']."-theme.xml"); - header("Content-type: application/octet-stream"); - header("Content-Length: ".strlen($xml)); - header("Pragma: no-cache"); - header("Expires: 0"); - echo $xml; - exit; - } - - $page->add_breadcrumb_item(htmlspecialchars_uni($theme['name']), "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}"); - - $page->add_breadcrumb_item($lang->export_theme, "index.php?module=style-themes&action=export"); - - $page->output_header("{$lang->themes} - {$lang->export_theme}"); - - $sub_tabs['edit_stylesheets'] = array( - 'title' => $lang->edit_stylesheets, - 'link' => "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}", - ); - - $sub_tabs['add_stylesheet'] = array( - 'title' => $lang->add_stylesheet, - 'link' => "index.php?module=style-themes&action=add_stylesheet&tid={$mybb->input['tid']}", - ); - - $sub_tabs['export_theme'] = array( - 'title' => $lang->export_theme, - 'link' => "index.php?module=style-themes&action=export&tid={$mybb->input['tid']}", - 'description' => $lang->export_theme_desc - ); - - $sub_tabs['duplicate_theme'] = array( - 'title' => $lang->duplicate_theme, - 'link' => "index.php?module=style-themes&action=duplicate&tid={$mybb->input['tid']}", - 'description' => $lang->duplicate_theme_desc - ); - - $page->output_nav_tabs($sub_tabs, 'export_theme'); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=style-themes&action=export", "post"); - echo $form->generate_hidden_field("tid", $theme['tid']); - - $form_container = new FormContainer($lang->export_theme.": ".htmlspecialchars_uni($theme['name'])); - $form_container->output_row($lang->include_custom_only, $lang->include_custom_only_desc, $form->generate_yes_no_radio('custom_theme', $mybb->input['custom_theme']), 'custom_theme'); - $form_container->output_row($lang->include_templates, $lang->include_templates_desc, $form->generate_yes_no_radio('include_templates', $mybb->input['include_templates']), 'include_templates'); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->export_theme); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "duplicate") -{ - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - // Does the theme not exist? - if(!$theme['tid']) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_duplicate"); - - if($mybb->request_method == "post") - { - if($mybb->input['name'] == "") - { - $errors[] = $lang->error_missing_name; - } - else - { - $query = $db->simple_select("themes", "COUNT(tid) as numthemes", "name = '".$db->escape_string($mybb->get_input('name'))."'"); - $numthemes = $db->fetch_field($query, 'numthemes'); - - if($numthemes) - { - $errors[] = $lang->error_theme_already_exists; - } - } - - if(!$errors) - { - $properties = my_unserialize($theme['properties']); - $sid = $properties['templateset']; - $nprops = null; - if($mybb->input['duplicate_templates']) - { - $nsid = $db->insert_query("templatesets", array('title' => $db->escape_string($mybb->input['name'])." Templates")); - - // Copy all old Templates to our new templateset - $query = $db->simple_select("templates", "*", "sid='{$sid}'"); - while($template = $db->fetch_array($query)) - { - $insert = array( - "title" => $db->escape_string($template['title']), - "template" => $db->escape_string($template['template']), - "sid" => $nsid, - "version" => $db->escape_string($template['version']), - "dateline" => TIME_NOW - ); - - if($db->engine == "pgsql") - { - echo " "; - flush(); - } - - $db->insert_query("templates", $insert); - } - - // We need to change the templateset so we need to work out the others properties too - foreach($properties as $property => $value) - { - if($property == "inherited") - { - continue; - } - - $nprops[$property] = $value; - if($properties['inherited'][$property]) - { - $nprops['inherited'][$property] = $properties['inherited'][$property]; - } - else - { - $nprops['inherited'][$property] = $theme['tid']; - } - } - $nprops['templateset'] = $nsid; - } - $tid = build_new_theme($mybb->input['name'], $nprops, $theme['tid']); - - update_theme_stylesheet_list($tid); - - $plugins->run_hooks("admin_style_themes_duplicate_commit"); - - // Log admin action - log_admin_action($tid, $theme['tid']); - - flash_message($lang->success_duplicated_theme, 'success'); - admin_redirect("index.php?module=style-themes&action=edit&tid=".$tid); - } - } - - $page->add_breadcrumb_item(htmlspecialchars_uni($theme['name']), "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}"); - - $page->add_breadcrumb_item($lang->duplicate_theme, "index.php?module=style-themes&action=duplicate&tid={$theme['tid']}"); - - $page->output_header("{$lang->themes} - {$lang->duplicate_theme}"); - - $sub_tabs['edit_stylesheets'] = array( - 'title' => $lang->edit_stylesheets, - 'link' => "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}", - ); - - $sub_tabs['add_stylesheet'] = array( - 'title' => $lang->add_stylesheet, - 'link' => "index.php?module=style-themes&action=add_stylesheet&tid={$mybb->input['tid']}", - ); - - $sub_tabs['export_theme'] = array( - 'title' => $lang->export_theme, - 'link' => "index.php?module=style-themes&action=export&tid={$mybb->input['tid']}", - 'description' => $lang->export_theme_desc - ); - - $sub_tabs['duplicate_theme'] = array( - 'title' => $lang->duplicate_theme, - 'link' => "index.php?module=style-themes&action=duplicate&tid={$mybb->input['tid']}", - 'description' => $lang->duplicate_theme_desc - ); - - $page->output_nav_tabs($sub_tabs, 'duplicate_theme'); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['duplicate_templates'] = true; - } - - $form = new Form("index.php?module=style-themes&action=duplicate&tid={$theme['tid']}", "post"); - - $form_container = new FormContainer($lang->duplicate_theme); - $form_container->output_row($lang->new_name, $lang->new_name_duplicate_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->advanced_options, "", $form->generate_check_box('duplicate_templates', '1', $lang->duplicate_templates, array('checked' => $mybb->input['duplicate_templates'], 'id' => 'duplicate_templates'))."
{$lang->duplicate_templates_desc}"); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->duplicate_theme); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_style_themes_add"); - - $query = $db->simple_select("themes", "tid, name"); - while($theme = $db->fetch_array($query)) - { - $themes[$theme['tid']] = $theme['name']; - } - - if($mybb->request_method == "post") - { - if(!$mybb->input['name']) - { - $errors[] = $lang->error_missing_name; - } - else if(in_array($mybb->input['name'], $themes)) - { - $errors[] = $lang->error_theme_already_exists; - } - - if(!$errors) - { - $tid = build_new_theme($mybb->input['name'], null, $mybb->input['tid']); - - $plugins->run_hooks("admin_style_themes_add_commit"); - - // Log admin action - log_admin_action(htmlspecialchars_uni($mybb->input['name']), $tid); - - flash_message($lang->success_theme_created, 'success'); - admin_redirect("index.php?module=style-themes&action=edit&tid=".$tid); - } - } - - $page->add_breadcrumb_item($lang->create_new_theme, "index.php?module=style-themes&action=add"); - - $page->output_header("{$lang->themes} - {$lang->create_new_theme}"); - - $page->output_nav_tabs($sub_tabs, 'create_theme'); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=style-themes&action=add", "post"); - - $form_container = new FormContainer($lang->create_a_theme); - $form_container->output_row($lang->name, $lang->name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); - $form_container->output_row($lang->parent_theme, $lang->parent_theme_desc, $form->generate_select_box('tid', $themes, $mybb->input['tid'], array('id' => 'tid')), 'tid'); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->create_new_theme); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - // Does the theme not exist? or are we trying to delete the master? - if(!$theme['tid'] || $theme['tid'] == 1) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_delete"); - - if($mybb->request_method == "post") - { - $inherited_theme_cache = array(); - - $query = $db->simple_select("themes", "tid,stylesheets", "tid != '{$theme['tid']}'", array('order_by' => "pid, name")); - while($theme2 = $db->fetch_array($query)) - { - $theme2['stylesheets'] = my_unserialize($theme2['stylesheets']); - - if(!$theme2['stylesheets']['inherited']) - { - continue; - } - - $inherited_theme_cache[$theme2['tid']] = $theme2['stylesheets']['inherited']; - } - - $inherited_stylesheets = false; - - // Are any other themes relying on stylesheets from this theme? Get a list and show an error - foreach($inherited_theme_cache as $tid => $inherited) - { - foreach($inherited as $file => $value) - { - foreach($value as $filepath => $val) - { - if(strpos($filepath, "cache/themes/theme{$theme['tid']}") !== false) - { - $inherited_stylesheets = true; - } - } - } - } - - if($inherited_stylesheets == true) - { - flash_message($lang->error_inheriting_stylesheets, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $query = $db->simple_select("themestylesheets", "cachefile", "tid='{$theme['tid']}'"); - while($cachefile = $db->fetch_array($query)) - { - @unlink(MYBB_ROOT."cache/themes/theme{$theme['tid']}/{$cachefile['cachefile']}"); - - $filename_min = str_replace('.css', '.min.css', $cachefile['cachefile']); - @unlink(MYBB_ROOT."cache/themes/theme{$theme['tid']}/{$filename_min}"); - } - @unlink(MYBB_ROOT."cache/themes/theme{$theme['tid']}/index.html"); - - $db->delete_query("themestylesheets", "tid='{$theme['tid']}'"); - - // Update the CSS file list for this theme - update_theme_stylesheet_list($theme['tid'], $theme, true); - - $db->update_query("users", array('style' => 0), "style='{$theme['tid']}'"); - - @rmdir(MYBB_ROOT."cache/themes/theme{$theme['tid']}/"); - - $children = (array)make_child_theme_list($theme['tid']); - $child_tids = array(); - - foreach($children as $child_tid) - { - if($child_tid != 0) - { - $child_tids[] = $child_tid; - } - } - - if(!empty($child_tids)) - { - $db->update_query("themes", array('pid' => $theme['pid']), "tid IN (".implode(',', $child_tids).")"); - } - - $db->delete_query("themes", "tid='{$theme['tid']}'", 1); - - $plugins->run_hooks("admin_style_themes_delete_commit"); - - // Log admin action - log_admin_action($theme['tid'], htmlspecialchars_uni($theme['name'])); - - flash_message($lang->success_theme_deleted, 'success'); - admin_redirect("index.php?module=style-themes"); - } - else - { - $page->output_confirm_action("index.php?module=style-themes&action=delete&tid={$theme['tid']}", $lang->confirm_theme_deletion); - } -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - // Does the theme not exist? - if(!$theme['tid'] || $theme['tid'] == 1) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_edit"); - - if($mybb->request_method == "post" && !$mybb->input['do']) - { - $properties = array( - 'templateset' => $mybb->get_input('templateset', MyBB::INPUT_INT), - 'editortheme' => $mybb->input['editortheme'], - 'imgdir' => $mybb->input['imgdir'], - 'logo' => $mybb->input['logo'], - 'tablespace' => $mybb->get_input('tablespace', MyBB::INPUT_INT), - 'borderwidth' => $mybb->get_input('borderwidth', MyBB::INPUT_INT), - 'color' => $mybb->input['color'] - ); - - if($properties['color'] == 'none') - { - unset($properties['color']); - } - - if($mybb->input['colors']) - { - $colors = explode("\n", $mybb->input['colors']); - - foreach($colors as $color) - { - $color = explode("=", $color); - - $properties['colors'][$color[0]] = $color[1]; - } - } - - if($properties['templateset'] <= 0) - { - $errors[] = $lang->error_invalid_templateset; - } - - $theme_properties = my_unserialize($theme['properties']); - if(is_array($theme_properties['disporder'])) - { - $properties['disporder'] = $theme_properties['disporder']; - } - else - { - $errors[] = $lang->error_no_display_order; - } - - $allowedgroups = array(); - if(is_array($mybb->input['allowedgroups'])) - { - foreach($mybb->input['allowedgroups'] as $gid) - { - if($gid == "all") - { - $allowedgroups = "all"; - break; - } - $gid = (int)$gid; - $allowedgroups[$gid] = $gid; - } - } - if(is_array($allowedgroups)) - { - $allowedgroups = implode(",", $allowedgroups); - } - - $update_array = array( - 'name' => $db->escape_string($mybb->input['name']), - 'pid' => $mybb->get_input('pid', MyBB::INPUT_INT), - 'allowedgroups' => $allowedgroups, - 'properties' => $db->escape_string(my_serialize($properties)) - ); - - // perform validation - if(!$update_array['name']) - { - $errors[] = $lang->error_missing_name; - } - else - { - $query = $db->simple_select("themes", "COUNT(tid) as numthemes", "name = '".$db->escape_string($update_array['name'])."' AND tid != '{$theme['tid']}'"); - $numthemes = $db->fetch_field($query, 'numthemes'); - - if($numthemes) - { - $errors[] = $lang->error_theme_already_exists; - } - } - - if($update_array['pid']) - { - $query = $db->simple_select("themes", "tid", "tid='".$update_array['pid']."'"); - $parent_check = $db->fetch_field($query, "tid"); - if(!$parent_check) - { - $errors[] = $lang->error_invalid_parent_theme; - } - } - if($properties['templateset']) - { - $query = $db->simple_select("templatesets", "sid", "sid='".$properties['templateset']."'"); - $ts_check = $db->fetch_field($query, "sid"); - if(!$ts_check) - { - unset($properties['templateset']); - } - } - if(!$properties['templateset']) - { - $errors[] = $lang->error_invalid_templateset; - } - if(!$properties['editortheme'] || !file_exists(MYBB_ROOT."jscripts/sceditor/editor_themes/".$properties['editortheme']) || is_dir(MYBB_ROOT."jscripts/sceditor/editor_themes/".$properties['editortheme'])) - { - $errors[] = $lang->error_invalid_editortheme; - } - - if(empty($errors)) - { - $plugins->run_hooks("admin_style_themes_edit_commit"); - - $db->update_query("themes", $update_array, "tid='{$theme['tid']}'"); - update_theme_stylesheet_list($theme['tid']); - - if($theme['def'] == 1) - { - $cache->update_default_theme(); - } - - // Log admin action - log_admin_action($theme['tid'], htmlspecialchars_uni($theme['name'])); - - flash_message($lang->success_theme_properties_updated, 'success'); - admin_redirect("index.php?module=style-themes&action=edit&tid={$theme['tid']}"); - } - } - - // Fetch list of all of the stylesheets for this theme - $file_stylesheets = my_unserialize($theme['stylesheets']); - - $stylesheets = array(); - $inherited_load = array(); - - // Now we loop through the list of stylesheets for each file - foreach($file_stylesheets as $file => $action_stylesheet) - { - if($file == 'inherited' || !is_array($action_stylesheet)) - { - continue; - } - - foreach($action_stylesheet as $action => $style) - { - foreach($style as $stylesheet) - { - $stylesheets[$stylesheet]['applied_to'][$file][] = $action; - if(is_array($file_stylesheets['inherited'][$file."_".$action]) && in_array($stylesheet, array_keys($file_stylesheets['inherited'][$file."_".$action]))) - { - $stylesheets[$stylesheet]['inherited'] = $file_stylesheets['inherited'][$file."_".$action]; - foreach($file_stylesheets['inherited'][$file."_".$action] as $value) - { - $inherited_load[] = $value; - } - } - } - } - } - - $inherited_load[] = $mybb->input['tid']; - $inherited_load = array_unique($inherited_load); - - $inherited_themes = array(); - if(count($inherited_load) > 0) - { - $query = $db->simple_select("themes", "tid, name", "tid IN (".implode(",", $inherited_load).")"); - while($inherited_theme = $db->fetch_array($query)) - { - $inherited_themes[$inherited_theme['tid']] = $inherited_theme['name']; - } - } - - $theme_stylesheets = array(); - - if(count($inherited_load) > 0) - { - $query = $db->simple_select("themestylesheets", "*", "", array('order_by' => 'sid DESC, tid', 'order_dir' => 'desc')); - while($theme_stylesheet = $db->fetch_array($query)) - { - if(!isset($theme_stylesheets[$theme_stylesheet['name']]) && in_array($theme_stylesheet['tid'], $inherited_load)) - { - $theme_stylesheets[$theme_stylesheet['name']] = $theme_stylesheet; - } - - $theme_stylesheets[$theme_stylesheet['sid']] = $theme_stylesheet['name']; - } - } - - // Save any stylesheet orders - if($mybb->request_method == "post" && $mybb->input['do'] == "save_orders") - { - if(!is_array($mybb->input['disporder'])) - { - // Error out - flash_message($lang->error_no_display_order, 'error'); - admin_redirect("index.php?module=style-themes&action=edit&tid={$theme['tid']}"); - } - - $orders = array(); - foreach($theme_stylesheets as $stylesheet => $properties) - { - if(is_array($properties)) - { - $order = (int)$mybb->input['disporder'][$properties['sid']]; - - $orders[$properties['name']] = $order; - } - } - - asort($orders, SORT_NUMERIC); - - // Save the orders in the theme properties - $properties = my_unserialize($theme['properties']); - $properties['disporder'] = $orders; - - $update_array = array( - "properties" => $db->escape_string(my_serialize($properties)) - ); - - $db->update_query("themes", $update_array, "tid = '{$theme['tid']}'"); - - if($theme['def'] == 1) - { - $cache->update_default_theme(); - } - - // normalize for consistency - update_theme_stylesheet_list($theme['tid'], false, true); - - flash_message($lang->success_stylesheet_order_updated, 'success'); - admin_redirect("index.php?module=style-themes&action=edit&tid={$theme['tid']}"); - } - - $page->add_breadcrumb_item(htmlspecialchars_uni($theme['name']), "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}"); - - $page->output_header("{$lang->themes} - {$lang->stylesheets}"); - - $sub_tabs['edit_stylesheets'] = array( - 'title' => $lang->edit_stylesheets, - 'link' => "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}", - 'description' => $lang->edit_stylesheets_desc - ); - - $sub_tabs['add_stylesheet'] = array( - 'title' => $lang->add_stylesheet, - 'link' => "index.php?module=style-themes&action=add_stylesheet&tid={$mybb->input['tid']}", - ); - - $sub_tabs['export_theme'] = array( - 'title' => $lang->export_theme, - 'link' => "index.php?module=style-themes&action=export&tid={$mybb->input['tid']}" - ); - - $sub_tabs['duplicate_theme'] = array( - 'title' => $lang->duplicate_theme, - 'link' => "index.php?module=style-themes&action=duplicate&tid={$mybb->input['tid']}", - 'description' => $lang->duplicate_theme_desc - ); - - $properties = my_unserialize($theme['properties']); - $page->output_nav_tabs($sub_tabs, 'edit_stylesheets'); - - $table = new Table; - $table->construct_header($lang->stylesheets); - $table->construct_header($lang->display_order, array("class" => "align_center", "width" => 50)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - // Display Order form - $form = new Form("index.php?module=style-themes&action=edit", "post", "edit"); - echo $form->generate_hidden_field("tid", $theme['tid']); - echo $form->generate_hidden_field("do", 'save_orders'); - - // Order the stylesheets - $ordered_stylesheets = array(); - - foreach($properties['disporder'] as $style_name => $order) - { - foreach($stylesheets as $filename => $style) - { - if(strpos($filename, 'css.php?stylesheet=') !== false) - { - $style['sid'] = (int)str_replace('css.php?stylesheet=', '', $filename); - $filename = $theme_stylesheets[$style['sid']]; - } - - if(basename($filename) != $style_name) - { - continue; - } - - $ordered_stylesheets[$filename] = $style; - } - } - - foreach($ordered_stylesheets as $filename => $style) - { - if(strpos($filename, 'css.php?stylesheet=') !== false) - { - $style['sid'] = (int)str_replace('css.php?stylesheet=', '', $filename); - $filename = $theme_stylesheets[$style['sid']]; - } - else - { - $filename = basename($filename); - $style['sid'] = $theme_stylesheets[$filename]['sid']; - } - - // Has the file on the file system been modified? - resync_stylesheet($theme_stylesheets[$filename]); - - $filename = $theme_stylesheets[$filename]['name']; - - $inherited = ""; - $inherited_ary = array(); - if(is_array($style['inherited'])) - { - foreach($style['inherited'] as $tid) - { - if($inherited_themes[$tid]) - { - $inherited_ary[$tid] = $inherited_themes[$tid]; - } - } - } - - if(!empty($inherited_ary)) - { - $inherited = " ({$lang->inherited_from}"; - $sep = " "; - $inherited_count = count($inherited_ary); - $count = 0; - - foreach($inherited_ary as $tid => $file) - { - if(isset($applied_to_count) && $count == $applied_to_count && $count != 0) - { - $sep = " {$lang->and} "; - } - - $inherited .= $sep.$file; - $sep = $lang->comma; - - ++$count; - } - $inherited .= ")"; - } - - if(is_array($style['applied_to']) && (!isset($style['applied_to']['global']) || $style['applied_to']['global'][0] != "global")) - { - $attached_to = ''; - - $applied_to_count = count($style['applied_to']); - $count = 0; - $sep = " "; - $name = ""; - - $colors = array(); - - if(!is_array($properties['colors'])) - { - $properties['colors'] = array(); - } - - foreach($style['applied_to'] as $name => $actions) - { - if(!$name) - { - continue; - } - - if(array_key_exists($name, $properties['colors'])) - { - $colors[] = $properties['colors'][$name]; - } - - if(count($colors)) - { - // Colors override files and are handled below. - continue; - } - - // It's a file: - ++$count; - - if($actions[0] != "global") - { - $name = "{$name} ({$lang->actions}: ".implode(',', $actions).")"; - } - - if($count == $applied_to_count && $count > 1) - { - $sep = " {$lang->and} "; - } - $attached_to .= $sep.$name; - - $sep = $lang->comma; - } - - if($attached_to) - { - $attached_to = "{$lang->attached_to} {$attached_to}"; - } - - if(count($colors)) - { - // Attached to color instead of files. - $count = 1; - $color_list = $sep = ''; - - foreach($colors as $color) - { - if($count == count($colors) && $count > 1) - { - $sep = " {$lang->and} "; - } - - $color_list .= $sep.trim($color); - ++$count; - - $sep = ', '; - } - - $attached_to = "{$lang->attached_to} ".$lang->sprintf($lang->colors_attached_to)." {$color_list}"; - } - - if($attached_to == '') - { - // Orphaned! :( - $attached_to = "{$lang->attached_to_nothing}"; - } - } - else - { - $attached_to = "{$lang->attached_to_all_pages}"; - } - - $popup = new PopupMenu("style_{$style['sid']}", $lang->options); - - $popup->add_item($lang->edit_style, "index.php?module=style-themes&action=edit_stylesheet&file=".htmlspecialchars_uni($filename)."&tid={$theme['tid']}"); - $popup->add_item($lang->properties, "index.php?module=style-themes&action=stylesheet_properties&file=".htmlspecialchars_uni($filename)."&tid={$theme['tid']}"); - - if($inherited == "") - { - $popup->add_item($lang->delete_revert, "index.php?module=style-themes&action=delete_stylesheet&file=".htmlspecialchars_uni($filename)."&tid={$theme['tid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_stylesheet_deletion}')"); - } - - $table->construct_cell("{$filename}{$inherited}
{$attached_to}"); - $table->construct_cell($form->generate_numeric_field("disporder[{$theme_stylesheets[$filename]['sid']}]", $properties['disporder'][$filename], array('style' => 'width: 80%; text-align: center;', 'min' => 0)), array("class" => "align_center")); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - $table->construct_row(); - } - - $table->output("{$lang->stylesheets_in} ".htmlspecialchars_uni($theme['name'])); - - $buttons = array($form->generate_submit_button($lang->save_stylesheet_order)); - $form->output_submit_wrapper($buttons); - $form->end(); - - echo '
'; - - // Theme Properties table - if($errors) - { - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=style-themes&action=edit", "post", "edit"); - echo $form->generate_hidden_field("tid", $theme['tid']); - $form_container = new FormContainer($lang->edit_theme_properties); - $form_container->output_row($lang->name." *", $lang->name_desc_edit, $form->generate_text_box('name', $theme['name'], array('id' => 'name')), 'name'); - - $options = build_theme_array($theme['tid']); - $form_container->output_row($lang->parent_theme." *", $lang->parent_theme_desc, $form->generate_select_box('pid', $options, $theme['pid'], array('id' => 'pid')), 'pid'); - - $options = array(); - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - $options['all'] = $lang->all_user_groups; - while($usergroup = $db->fetch_array($query)) - { - $options[(int)$usergroup['gid']] = $usergroup['title']; - } - $form_container->output_row($lang->allowed_user_groups, $lang->allowed_user_groups_desc, $form->generate_select_box('allowedgroups[]', $options, explode(",", $theme['allowedgroups']), array('id' => 'allowedgroups', 'multiple' => true, 'size' => 5)), 'allowedgroups'); - - $options = array(); - $query = $db->simple_select("templatesets", "*", "", array('order_by' => 'title')); - while($templateset = $db->fetch_array($query)) - { - $options[(int)$templateset['sid']] = $templateset['title']; - } - $form_container->output_row($lang->template_set." *", $lang->template_set_desc, $form->generate_select_box('templateset', $options, $properties['templateset'], array('id' => 'templateset')), 'templateset'); - - $options = array(); - $editor_theme_root = MYBB_ROOT."jscripts/sceditor/editor_themes/"; - if($dh = @opendir($editor_theme_root)) - { - while($dir = readdir($dh)) - { - if($dir == ".svn" || $dir == "." || $dir == ".." || is_dir($editor_theme_root.$dir) || get_extension($editor_theme_root.$dir) != 'css') - { - continue; - } - $options[$dir] = ucfirst(str_replace(array('_', '.css'), array(' ', ''), $dir)); - } - } - - $form_container->output_row($lang->editor_theme." *", $lang->editor_theme_desc, $form->generate_select_box('editortheme', $options, $properties['editortheme'], array('id' => 'editortheme')), 'editortheme'); - - $form_container->output_row($lang->img_directory, $lang->img_directory_desc, $form->generate_text_box('imgdir', $properties['imgdir'], array('id' => 'imgdir')), 'imgdir'); - $form_container->output_row($lang->logo, $lang->logo_desc, $form->generate_text_box('logo', $properties['logo'], array('id' => 'boardlogo')), 'logo'); - $form_container->output_row($lang->table_spacing, $lang->table_spacing_desc, $form->generate_numeric_field('tablespace', $properties['tablespace'], array('id' => 'tablespace', 'min' => 0)), 'tablespace'); - $form_container->output_row($lang->inner_border, $lang->inner_border_desc, $form->generate_numeric_field('borderwidth', $properties['borderwidth'], array('id' => 'borderwidth', 'min' => 0)), 'borderwidth'); - - $form_container->end(); - - $form_container = new FormContainer($lang->colors_manage); - - if(!$properties['colors'] || !is_array($properties['colors'])) - { - $color_setting = $lang->colors_no_color_setting; - } - else - { - $colors = array('none' => $lang->colors_please_select); - $colors = array_merge($colors, $properties['colors']); - - $color_setting = $form->generate_select_box('color', $colors, $properties['color'], array('class' => "select\" style=\"width: 200px;")); - - $mybb->input['colors'] = ''; - foreach($properties['colors'] as $key => $color) - { - if($mybb->input['colors']) - { - $mybb->input['colors'] .= "\n"; - } - - $mybb->input['colors'] .= "{$key}={$color}"; - } - } - - $form_container->output_row($lang->colors_setting, $lang->colors_setting_desc, $color_setting, 'color'); - $form_container->output_row($lang->colors_add, $lang->colors_add_desc, $form->generate_text_area('colors', $mybb->input['colors'], array('style' => 'width: 200px;', 'rows' => '5'))); - - $form_container->end(); - - $buttons = array(); - $buttons[] = $form->generate_submit_button($lang->save_theme_properties); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "stylesheet_properties") -{ - // Fetch the theme we want to edit this stylesheet in - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - if(!$theme['tid'] || $theme['tid'] == 1) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_stylesheet_properties"); - - $parent_list = make_parent_theme_list($theme['tid']); - $parent_list = implode(',', $parent_list); - if(!$parent_list) - { - $parent_list = 1; - } - - $query = $db->simple_select("themestylesheets", "*", "name='".$db->escape_string($mybb->input['file'])."' AND tid IN ({$parent_list})", array('order_by' => 'tid', 'order_dir' => 'desc', 'limit' => 1)); - $stylesheet = $db->fetch_array($query); - - // Does the theme not exist? - if(!$stylesheet['sid']) - { - flash_message($lang->error_invalid_stylesheet, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - // Fetch list of all of the stylesheets for this theme - $stylesheets = fetch_theme_stylesheets($theme); - - if(!array_key_exists($stylesheet['cachefile'], $stylesheets) && array_key_exists("css.php?stylesheet=".$stylesheet['tid'], $stylesheets)) - { - $stylesheet['cachefile'] = "css.php?stylesheet=".$stylesheet['tid']; - } - - $this_stylesheet = $stylesheets[$stylesheet['cachefile']]; - unset($stylesheets); - - if($mybb->request_method == "post") - { - // Do we not have a name, or is it just an extension? - if(!$mybb->input['name'] || $mybb->input['name'] == ".css") - { - $errors[] = $lang->error_missing_stylesheet_name; - } - - // Get 30 chars only because we don't want more than that - $mybb->input['name'] = my_substr($mybb->input['name'], 0, 30); - if(get_extension($mybb->input['name']) != "css") - { - // Does not end with '.css' - $errors[] = $lang->sprintf($lang->error_missing_stylesheet_extension, $mybb->input['name']); - } - - if(!$errors) - { - // Theme & stylesheet theme ID do not match, editing inherited - we copy to local theme - if($theme['tid'] != $stylesheet['tid']) - { - $stylesheet['sid'] = copy_stylesheet_to_theme($stylesheet, $theme['tid']); - } - - $attached = array(); - if($mybb->input['attach'] == 1) - { - // Our stylesheet is attached to custom pages in MyBB - foreach($mybb->input as $id => $value) - { - $actions_list = ""; - $attached_to = $value; - - if(strpos($id, 'attached_') !== false) - { - // We have a custom attached file - $attached_id = (int)str_replace('attached_', '', $id); - - if($mybb->input['action_'.$attached_id] == 1) - { - // We have custom actions for attached files - $actions_list = $mybb->input['action_list_'.$attached_id]; - } - - if($actions_list) - { - $attached_to .= "?".$actions_list; - } - - $attached[] = $attached_to; - } - } - } - else if($mybb->input['attach'] == 2) - { - if(!is_array($mybb->input['color'])) - { - $errors[] = $lang->error_no_color_picked; - } - else - { - $attached = $mybb->input['color']; - } - } - - // Update Stylesheet - $update_array = array( - 'name' => $db->escape_string($mybb->input['name']), - 'attachedto' => $db->escape_string(implode('|', $attached)) - ); - - if($stylesheet['name'] != $mybb->input['name']) - { - $update_array['cachefile'] = $db->escape_string(str_replace('/', '', $mybb->input['name'])); - } - - $db->update_query("themestylesheets", $update_array, "sid='{$stylesheet['sid']}'", 1); - - // If the name changed, re-cache our stylesheet - $theme_c = $update_d = false; - if($stylesheet['name'] != $mybb->input['name']) - { - // Update the theme stylesheet list if the name is changed - $theme_c = $theme; - $update_d = true; - - $db->update_query("themestylesheets", array('lastmodified' => TIME_NOW), "sid='{$stylesheet['sid']}'", 1); - if(!cache_stylesheet($theme['tid'], str_replace('/', '', $mybb->input['name']), $stylesheet['stylesheet'])) - { - $db->update_query("themestylesheets", array('cachefile' => "css.php?stylesheet={$stylesheet['sid']}"), "sid='{$stylesheet['sid']}'", 1); - } - @unlink(MYBB_ROOT."cache/themes/theme{$theme['tid']}/{$stylesheet['cachefile']}"); - - $filename_min = str_replace('.css', '.min.css', $stylesheet['cachefile']); - @unlink(MYBB_ROOT."cache/themes/theme{$theme['tid']}/{$filename_min}"); - } - - // Update the CSS file list for this theme - update_theme_stylesheet_list($theme['tid'], $theme_c, $update_d); - - $plugins->run_hooks("admin_style_themes_stylesheet_properties_commit"); - - // Log admin action - log_admin_action($stylesheet['sid'], $mybb->input['name'], $theme['tid'], htmlspecialchars_uni($theme['name'])); - - flash_message($lang->success_stylesheet_properties_updated, 'success'); - admin_redirect("index.php?module=style-themes&action=edit&tid={$theme['tid']}"); - } - } - - $properties = my_unserialize($theme['properties']); - $page->add_breadcrumb_item(htmlspecialchars_uni($theme['name']), "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}"); - $page->add_breadcrumb_item(htmlspecialchars_uni($stylesheet['name'])." {$lang->properties}", "index.php?module=style-themes&action=edit_properties&tid={$mybb->input['tid']}"); - - $page->output_header("{$lang->themes} - {$lang->stylesheet_properties}"); - - // If the stylesheet and theme do not match, we must be editing something that is inherited - if($this_stylesheet['inherited'][$stylesheet['name']]) - { - $query = $db->simple_select("themes", "name", "tid='{$stylesheet['tid']}'"); - $stylesheet_parent = htmlspecialchars_uni($db->fetch_field($query, 'name')); - - // Show inherited warning - if($stylesheet['tid'] == 1) - { - $page->output_alert($lang->sprintf($lang->stylesheet_inherited_default, $stylesheet_parent)); - } - else - { - $page->output_alert($lang->sprintf($lang->stylesheet_inherited, $stylesheet_parent)); - } - } - - $applied_to = $this_stylesheet['applied_to']; - unset($this_stylesheet); - - if($errors) - { - $page->output_inline_error($errors); - - foreach($mybb->input as $name => $value) - { - if(strpos($name, "attached") !== false) - { - list(, $id) = explode('_', $name); - $id = (int)$id; - - $applied_to[$value] = array(0 => 'global'); - - if($mybb->input['action_'.$id] == 1) - { - $applied_to[$value] = explode(',', $mybb->input['action_list_'.$id]); - } - } - } - } - else - { - $mybb->input['name'] = $stylesheet['name']; - } - - $global_checked[1] = "checked=\"checked\""; - $global_checked[2] = ""; - $global_checked[3] = ""; - - $form = new Form("index.php?module=style-themes&action=stylesheet_properties", "post"); - - $specific_files = "
"; - $count = 0; - if(is_array($applied_to) && $applied_to['global'][0] != "global") - { - $check_actions = ""; - $stylesheet['colors'] = array(); - - if(!is_array($properties['colors'])) - { - $properties['colors'] = array(); - } - - foreach($applied_to as $name => $actions) - { - // Verify this is a color for this theme - if(array_key_exists($name, $properties['colors'])) - { - $stylesheet['colors'][] = $name; - } - - if(count($stylesheet['colors'])) - { - // Colors override files and are handled below. - continue; - } - - // It's a file: - $action_list = ""; - if($actions[0] != "global") - { - $action_list = implode(',', $actions); - } - - if($actions[0] == "global") - { - $global_action_checked[1] = "checked=\"checked\""; - $global_action_checked[2] = ""; - } - else - { - $global_action_checked[2] = "checked=\"checked\""; - $global_action_checked[1] = ""; - } - - $specific_file = "
-
-
-
- {$lang->specific_actions_desc} - - - - -
".$form->generate_text_box('action_list_'.$count, $action_list, array('id' => 'action_list_'.$count, 'style' => 'width: 190px;'))."
-
-
"; - - $form_container = new FormContainer(); - $form_container->output_row("", "", "style}/images/icons/cross.png\" alt=\"{$lang->delete}\" title=\"{$lang->delete}\" />{$lang->file}  ".$form->generate_text_box("attached_{$count}", $name, array('id' => "attached_{$count}", 'style' => 'width: 200px;')), "attached_{$count}"); - - $form_container->output_row("", "", $specific_file); - - $specific_files .= "
".$form_container->end(true)."
"; - - $check_actions .= "\n\tcheckAction('action_{$count}');"; - - ++$count; - } - - if($check_actions) - { - $global_checked[3] = ""; - $global_checked[2] = "checked=\"checked\""; - $global_checked[1] = ""; - } - - if(!empty($stylesheet['colors'])) - { - $global_checked[3] = "checked=\"checked\""; - $global_checked[2] = ""; - $global_checked[1] = ""; - } - } - - $specific_files .= "
"; - - // Colors - $specific_colors = $specific_colors_option = ''; - - if(is_array($properties['colors'])) - { - $specific_colors = "
"; - $specific_colors_option = '

'; - - $specific_color = " - {$lang->colors_add_edit_desc} -

- ".$form->generate_select_box('color[]', $properties['colors'], $stylesheet['colors'], array('multiple' => true, 'size' => "5\" style=\"width: 200px;"))." - "; - - $form_container = new FormContainer(); - $form_container->output_row("", "", $specific_color); - $specific_colors .= $form_container->end(true)."
"; - } - - $actions = ' -
-

-

- '.$specific_files.' - '.$specific_colors_option.' - '.$specific_colors.' -
- '; - - echo $form->generate_hidden_field("file", htmlspecialchars_uni($stylesheet['name']))."
\n"; - echo $form->generate_hidden_field("tid", $theme['tid'])."
\n"; - - $form_container = new FormContainer("{$lang->edit_stylesheet_properties_for} ".htmlspecialchars_uni($stylesheet['name'])); - $form_container->output_row($lang->file_name, $lang->file_name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name', 'style' => 'width: 200px;')), 'name'); - - $form_container->output_row($lang->attached_to, $lang->attached_to_desc, $actions); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_stylesheet_properties); - - $form->output_submit_wrapper($buttons); - - echo << - -EOF; - - $form->end(); - - $page->output_footer(); -} - -// Shows the page where you can actually edit a particular selector or the whole stylesheet -if($mybb->input['action'] == "edit_stylesheet" && (!isset($mybb->input['mode']) || $mybb->input['mode'] == "simple")) -{ - // Fetch the theme we want to edit this stylesheet in - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - if(!$theme['tid'] || $theme['tid'] == 1) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_edit_stylesheet_simple"); - - $parent_list = make_parent_theme_list($theme['tid']); - $parent_list = implode(',', $parent_list); - if(!$parent_list) - { - $parent_list = 1; - } - - $query = $db->simple_select("themestylesheets", "*", "name='".$db->escape_string($mybb->input['file'])."' AND tid IN ({$parent_list})", array('order_by' => 'tid', 'order_dir' => 'desc', 'limit' => 1)); - $stylesheet = $db->fetch_array($query); - - // Does the theme not exist? - if(!$stylesheet['sid']) - { - flash_message($lang->error_invalid_stylesheet, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - if($mybb->request_method == "post") - { - $sid = $stylesheet['sid']; - - // Theme & stylesheet theme ID do not match, editing inherited - we copy to local theme - if($theme['tid'] != $stylesheet['tid']) - { - $sid = copy_stylesheet_to_theme($stylesheet, $theme['tid']); - } - - // Insert the modified CSS - $new_stylesheet = $stylesheet['stylesheet']; - - if($mybb->input['serialized'] == 1) - { - $mybb->input['css_bits'] = my_unserialize($mybb->input['css_bits']); - } - - $css_to_insert = ''; - foreach($mybb->input['css_bits'] as $field => $value) - { - if(!trim($value) || !trim($field)) - { - continue; - } - - if($field == "extra") - { - $css_to_insert .= $value."\n"; - } - else - { - $field = str_replace("_", "-", $field); - $css_to_insert .= "{$field}: {$value};\n"; - } - } - - $new_stylesheet = insert_into_css($css_to_insert, $mybb->input['selector'], $new_stylesheet); - - // Now we have the new stylesheet, save it - $updated_stylesheet = array( - "cachefile" => $db->escape_string($stylesheet['name']), - "stylesheet" => $db->escape_string(unfix_css_urls($new_stylesheet)), - "lastmodified" => TIME_NOW - ); - $db->update_query("themestylesheets", $updated_stylesheet, "sid='{$sid}'"); - - // Cache the stylesheet to the file - if(!cache_stylesheet($theme['tid'], $stylesheet['name'], $new_stylesheet)) - { - $db->update_query("themestylesheets", array('cachefile' => "css.php?stylesheet={$sid}"), "sid='{$sid}'", 1); - } - - // Update the CSS file list for this theme - update_theme_stylesheet_list($theme['tid']); - - $plugins->run_hooks("admin_style_themes_edit_stylesheet_simple_commit"); - - // Log admin action - log_admin_action(htmlspecialchars_uni($theme['name']), $stylesheet['name']); - - if(!$mybb->input['ajax']) - { - flash_message($lang->success_stylesheet_updated, 'success'); - - if($mybb->input['save_close']) - { - admin_redirect("index.php?module=style-themes&action=edit&tid={$theme['tid']}"); - } - else - { - admin_redirect("index.php?module=style-themes&action=edit_stylesheet&tid={$theme['tid']}&file={$stylesheet['name']}"); - } - } - else - { - echo "1"; - exit; - } - } - - // Has the file on the file system been modified? - if(resync_stylesheet($stylesheet)) - { - // Need to refetch new stylesheet as it was modified - $query = $db->simple_select("themestylesheets", "stylesheet", "sid='{$stylesheet['sid']}'"); - $stylesheet['stylesheet'] = $db->fetch_field($query, 'stylesheet'); - } - - $css_array = css_to_array($stylesheet['stylesheet']); - $selector_list = get_selectors_as_options($css_array, $mybb->input['selector']); - - // Do we not have any selectors? Send em to the full edit page - if(!$selector_list) - { - flash_message($lang->error_cannot_parse, 'error'); - admin_redirect("index.php?module=style-themes&action=edit_stylesheet&tid={$theme['tid']}&file=".htmlspecialchars_uni($stylesheet['name'])."&mode=advanced"); - exit; - } - - // Fetch list of all of the stylesheets for this theme - $stylesheets = fetch_theme_stylesheets($theme); - $this_stylesheet = $stylesheets[$stylesheet['name']]; - unset($stylesheets); - - $page->extra_header .= " - "; - - $page->add_breadcrumb_item(htmlspecialchars_uni($theme['name']), "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}"); - $page->add_breadcrumb_item("{$lang->editing} ".htmlspecialchars_uni($stylesheet['name']), "index.php?module=style-themes&action=edit_stylesheet&tid={$mybb->input['tid']}&file=".htmlspecialchars_uni($mybb->input['file'])."&mode=simple"); - - $page->output_header("{$lang->themes} - {$lang->edit_stylesheets}"); - - // If the stylesheet and theme do not match, we must be editing something that is inherited - if($this_stylesheet['inherited'][$stylesheet['name']]) - { - $query = $db->simple_select("themes", "name", "tid='{$stylesheet['tid']}'"); - $stylesheet_parent = htmlspecialchars_uni($db->fetch_field($query, 'name')); - - // Show inherited warning - if($stylesheet['tid'] == 1) - { - $page->output_alert($lang->sprintf($lang->stylesheet_inherited_default, $stylesheet_parent), "ajax_alert"); - } - else - { - $page->output_alert($lang->sprintf($lang->stylesheet_inherited, $stylesheet_parent), "ajax_alert"); - } - } - - $sub_tabs['edit_stylesheet'] = array( - 'title' => $lang->edit_stylesheet_simple_mode, - 'link' => "index.php?module=style-themes&action=edit_stylesheet&tid={$mybb->input['tid']}&file=".htmlspecialchars_uni($mybb->input['file'])."&mode=simple", - 'description' => $lang->edit_stylesheet_simple_mode_desc - ); - - $sub_tabs['edit_stylesheet_advanced'] = array( - 'title' => $lang->edit_stylesheet_advanced_mode, - 'link' => "index.php?module=style-themes&action=edit_stylesheet&tid={$mybb->input['tid']}&file=".htmlspecialchars_uni($mybb->input['file'])."&mode=advanced", - ); - - $page->output_nav_tabs($sub_tabs, 'edit_stylesheet'); - - // Output the selection box - $form = new Form("index.php", "get", "selector_form"); - echo $form->generate_hidden_field("module", "style/themes")."\n"; - echo $form->generate_hidden_field("action", "edit_stylesheet")."\n"; - echo $form->generate_hidden_field("tid", $mybb->input['tid'])."\n"; - echo $form->generate_hidden_field("file", htmlspecialchars_uni($mybb->input['file']))."\n"; - - echo "{$lang->selector}: ".$form->generate_submit_button($lang->go)."

\n"; - - $form->end(); - - // Haven't chosen a selector to edit, show the first one from the stylesheet - if(!$mybb->input['selector']) - { - reset($css_array); - uasort($css_array, "css_selectors_sort_cmp"); - $selector = key($css_array); - $editable_selector = $css_array[$selector]; - } - // Show a specific selector - else - { - $editable_selector = $css_array[$mybb->input['selector']]; - $selector = $mybb->input['selector']; - } - - // Get the properties from this item - $properties = parse_css_properties($editable_selector['values']); - - foreach(array('background', 'color', 'width', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-decoration') as $_p) - { - if(!isset($properties[$_p])) - { - $properties[$_p] = ''; - } - } - - $form = new Form("index.php?module=style-themes&action=edit_stylesheet", "post"); - echo $form->generate_hidden_field("tid", $mybb->input['tid'], array('id' => "tid"))."\n"; - echo $form->generate_hidden_field("file", htmlspecialchars_uni($mybb->input['file']), array('id' => "file"))."\n"; - echo $form->generate_hidden_field("selector", htmlspecialchars_uni($selector), array('id' => 'hidden_selector'))."\n"; - - echo "
"; - $table = new Table; - $table->construct_cell("
".$form->generate_text_box('css_bits[background]', $properties['background'], array('id' => 'css_bits[background]', 'style' => 'width: 260px;'))."
{$lang->background}
", array('style' => 'width: 20%;')); - $table->construct_cell("{$lang->extra_css_atribs}
".$form->generate_text_area('css_bits[extra]', $properties['extra'], array('id' => 'css_bits[extra]', 'style' => 'width: 98%;', 'rows' => '19'))."
", array('rowspan' => 8)); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[color]', $properties['color'], array('id' => 'css_bits[color]', 'style' => 'width: 260px;'))."
{$lang->color}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[width]', $properties['width'], array('id' => 'css_bits[width]', 'style' => 'width: 260px;'))."
{$lang->width}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[font_family]', $properties['font-family'], array('id' => 'css_bits[font_family]', 'style' => 'width: 260px;'))."
{$lang->font_family}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[font_size]', $properties['font-size'], array('id' => 'css_bits[font_size]', 'style' => 'width: 260px;'))."
{$lang->font_size}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[font_style]', $properties['font-style'], array('id' => 'css_bits[font_style]', 'style' => 'width: 260px;'))."
{$lang->font_style}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[font_weight]', $properties['font-weight'], array('id' => 'css_bits[font_weight]', 'style' => 'width: 260px;'))."
{$lang->font_weight}
", array('style' => 'width: 40%;')); - $table->construct_row(); - $table->construct_cell("
".$form->generate_text_box('css_bits[text_decoration]', $properties['text-decoration'], array('id' => 'css_bits[text_decoration]', 'style' => 'width: 260px;'))."
{$lang->text_decoration}
", array('style' => 'width: 40%;')); - $table->construct_row(); - - $table->output(htmlspecialchars_uni($editable_selector['class_name']).""); - - echo "
"; - - $buttons[] = $form->generate_reset_button($lang->reset); - $buttons[] = $form->generate_submit_button($lang->save_changes, array('id' => 'save', 'name' => 'save')); - $buttons[] = $form->generate_submit_button($lang->save_changes_and_close, array('id' => 'save_close', 'name' => 'save_close')); - - $form->output_submit_wrapper($buttons); - - echo ''; - echo ''; - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit_stylesheet" && $mybb->input['mode'] == "advanced") -{ - // Fetch the theme we want to edit this stylesheet in - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - if(!$theme['tid'] || $theme['tid'] == 1) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_edit_stylesheet_advanced"); - - $parent_list = make_parent_theme_list($theme['tid']); - $parent_list = implode(',', $parent_list); - if(!$parent_list) - { - $parent_list = 1; - } - - $query = $db->simple_select("themestylesheets", "*", "name='".$db->escape_string($mybb->input['file'])."' AND tid IN ({$parent_list})", array('order_by' => 'tid', 'order_dir' => 'desc', 'limit' => 1)); - $stylesheet = $db->fetch_array($query); - - // Does the theme not exist? - if(!$stylesheet['sid']) - { - flash_message($lang->error_invalid_stylesheet, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - if($mybb->request_method == "post") - { - $sid = $stylesheet['sid']; - - // Theme & stylesheet theme ID do not match, editing inherited - we copy to local theme - if($theme['tid'] != $stylesheet['tid']) - { - $sid = copy_stylesheet_to_theme($stylesheet, $theme['tid']); - } - - // Now we have the new stylesheet, save it - $updated_stylesheet = array( - "cachefile" => $db->escape_string($stylesheet['name']), - "stylesheet" => $db->escape_string(unfix_css_urls($mybb->input['stylesheet'])), - "lastmodified" => TIME_NOW - ); - $db->update_query("themestylesheets", $updated_stylesheet, "sid='{$sid}'"); - - // Cache the stylesheet to the file - if(!cache_stylesheet($theme['tid'], $stylesheet['name'], $mybb->input['stylesheet'])) - { - $db->update_query("themestylesheets", array('cachefile' => "css.php?stylesheet={$sid}"), "sid='{$sid}'", 1); - } - - // Update the CSS file list for this theme - update_theme_stylesheet_list($theme['tid']); - - $plugins->run_hooks("admin_style_themes_edit_stylesheet_advanced_commit"); - - // Log admin action - log_admin_action(htmlspecialchars_uni($theme['name']), $stylesheet['name']); - - flash_message($lang->success_stylesheet_updated, 'success'); - - if(!$mybb->input['save_close']) - { - admin_redirect("index.php?module=style-themes&action=edit_stylesheet&file=".htmlspecialchars_uni($stylesheet['name'])."&tid={$theme['tid']}&mode=advanced"); - } - else - { - admin_redirect("index.php?module=style-themes&action=edit&tid={$theme['tid']}"); - } - } - - // Fetch list of all of the stylesheets for this theme - $stylesheets = fetch_theme_stylesheets($theme); - $this_stylesheet = $stylesheets[$stylesheet['name']]; - unset($stylesheets); - - if($admin_options['codepress'] != 0) - { - $page->extra_header .= ' - - - - - - - - -'; - } - - $page->add_breadcrumb_item(htmlspecialchars_uni($theme['name']), "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}"); - $page->add_breadcrumb_item("{$lang->editing} ".htmlspecialchars_uni($stylesheet['name']), "index.php?module=style-themes&action=edit_stylesheet&tid={$mybb->input['tid']}&file=".htmlspecialchars_uni($mybb->input['file'])."&mode=advanced"); - - $page->output_header("{$lang->themes} - {$lang->edit_stylesheet_advanced_mode}"); - - // If the stylesheet and theme do not match, we must be editing something that is inherited - if($this_stylesheet['inherited'][$stylesheet['name']]) - { - $query = $db->simple_select("themes", "name", "tid='{$stylesheet['tid']}'"); - $stylesheet_parent = htmlspecialchars_uni($db->fetch_field($query, 'name')); - - // Show inherited warning - if($stylesheet['tid'] == 1) - { - $page->output_alert($lang->sprintf($lang->stylesheet_inherited_default, $stylesheet_parent)); - } - else - { - $page->output_alert($lang->sprintf($lang->stylesheet_inherited, $stylesheet_parent)); - } - } - - $sub_tabs['edit_stylesheet'] = array( - 'title' => $lang->edit_stylesheet_simple_mode, - 'link' => "index.php?module=style-themes&action=edit_stylesheet&tid={$mybb->input['tid']}&file=".htmlspecialchars_uni($mybb->input['file'])."&mode=simple" - ); - - $sub_tabs['edit_stylesheet_advanced'] = array( - 'title' => $lang->edit_stylesheet_advanced_mode, - 'link' => "index.php?module=style-themes&action=edit_stylesheet&tid={$mybb->input['tid']}&file=".htmlspecialchars_uni($mybb->input['file'])."&mode=advanced", - 'description' => $lang->edit_stylesheet_advanced_mode_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_stylesheet_advanced'); - - // Has the file on the file system been modified? - if(resync_stylesheet($stylesheet)) - { - // Need to refetch new stylesheet as it was modified - $query = $db->simple_select("themestylesheets", "stylesheet", "sid='{$stylesheet['sid']}'"); - $stylesheet['stylesheet'] = $db->fetch_field($query, 'stylesheet'); - } - - $form = new Form("index.php?module=style-themes&action=edit_stylesheet&mode=advanced", "post", "edit_stylesheet"); - echo $form->generate_hidden_field("tid", $mybb->input['tid'])."\n"; - echo $form->generate_hidden_field("file", htmlspecialchars_uni($mybb->input['file']))."\n"; - - $table = new Table; - $table->construct_cell($form->generate_text_area('stylesheet', $stylesheet['stylesheet'], array('id' => 'stylesheet', 'style' => 'width: 99%;', 'class' => '', 'rows' => '30'))); - $table->construct_row(); - $table->output($lang->full_stylesheet_for.' '.htmlspecialchars_uni($stylesheet['name']), 1, 'tfixed'); - - $buttons[] = $form->generate_submit_button($lang->save_changes, array('id' => 'save', 'name' => 'save')); - $buttons[] = $form->generate_submit_button($lang->save_changes_and_close, array('id' => 'save_close', 'name' => 'save_close')); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - if($admin_options['codepress'] != 0) - { - echo ''; - } - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete_stylesheet") -{ - // Fetch the theme we want to edit this stylesheet in - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - if(!$theme['tid'] || $theme['tid'] == 1) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_delete_stylesheet"); - - $parent_list = make_parent_theme_list($theme['tid']); - $parent_list = implode(',', $parent_list); - if(!$parent_list) - { - $parent_list = 1; - } - - $query = $db->simple_select("themestylesheets", "*", "name='".$db->escape_string($mybb->input['file'])."' AND tid IN ({$parent_list})", array('order_by' => 'tid', 'order_dir' => 'desc', 'limit' => 1)); - $stylesheet = $db->fetch_array($query); - - // Does the theme not exist? or are we trying to delete the master? - if(!$stylesheet['sid'] || $stylesheet['tid'] == 1) - { - flash_message($lang->error_invalid_stylesheet, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=style-themes"); - } - - if($mybb->request_method == "post") - { - $db->delete_query("themestylesheets", "sid='{$stylesheet['sid']}'", 1); - @unlink(MYBB_ROOT."cache/themes/theme{$theme['tid']}/{$stylesheet['cachefile']}"); - - $filename_min = str_replace('.css', '.min.css', $stylesheet['cachefile']); - @unlink(MYBB_ROOT."cache/themes/theme{$theme['tid']}/{$filename_min}"); - - // Update the CSS file list for this theme - update_theme_stylesheet_list($theme['tid'], $theme, true); - - $plugins->run_hooks("admin_style_themes_delete_stylesheet_commit"); - - // Log admin action - log_admin_action($stylesheet['sid'], $stylesheet['name'], $theme['tid'], htmlspecialchars_uni($theme['name'])); - - flash_message($lang->success_stylesheet_deleted, 'success'); - admin_redirect("index.php?module=style-themes&action=edit&tid={$theme['tid']}"); - } - else - { - $page->output_confirm_action("index.php?module=style-themes&action=force&tid={$theme['tid']}", $lang->confirm_stylesheet_deletion); - } -} - -if($mybb->input['action'] == "add_stylesheet") -{ - // Fetch the theme we want to edit this stylesheet in - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - if(!$theme['tid'] || $theme['tid'] == 1) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_add_stylesheet"); - - // Fetch list of all of the stylesheets for this theme - $stylesheets = fetch_theme_stylesheets($theme); - - if($mybb->request_method == "post") - { - // Remove special characters - $mybb->input['name'] = preg_replace('#([^a-z0-9-_\.]+)#i', '', $mybb->input['name']); - if(!$mybb->input['name'] || $mybb->input['name'] == ".css") - { - $errors[] = $lang->error_missing_stylesheet_name; - } - - // Get 30 chars only because we don't want more than that - $mybb->input['name'] = my_substr($mybb->input['name'], 0, 30); - if(get_extension($mybb->input['name']) != "css") - { - // Does not end with '.css' - $errors[] = $lang->sprintf($lang->error_missing_stylesheet_extension, $mybb->input['name']); - } - - if(!$errors) - { - if($mybb->input['add_type'] == 1) - { - // Import from a current stylesheet - $parent_list = make_parent_theme_list($theme['tid']); - $parent_list = implode(',', $parent_list); - - $query = $db->simple_select("themestylesheets", "stylesheet", "name='".$db->escape_string($mybb->input['import'])."' AND tid IN ({$parent_list})", array('limit' => 1, 'order_by' => 'tid', 'order_dir' => 'desc')); - $stylesheet = $db->fetch_field($query, "stylesheet"); - } - else - { - // Custom stylesheet - $stylesheet = $mybb->input['stylesheet']; - } - - $attached = array(); - - if($mybb->input['attach'] == 1) - { - // Our stylesheet is attached to custom pages in MyBB - foreach($mybb->input as $id => $value) - { - $actions_list = ""; - $attached_to = ""; - - if(strpos($id, 'attached_') !== false) - { - // We have a custom attached file - $attached_id = (int)str_replace('attached_', '', $id); - $attached_to = $value; - - if($mybb->input['action_'.$attached_id] == 1) - { - // We have custom actions for attached files - $actions_list = $mybb->input['action_list_'.$attached_id]; - } - - if($actions_list) - { - $attached_to = $attached_to."?".$actions_list; - } - - $attached[] = $attached_to; - } - } - } - else if($mybb->input['attach'] == 2) - { - if(!is_array($mybb->input['color'])) - { - $errors[] = $lang->error_no_color_picked; - } - else - { - $attached = $mybb->input['color']; - } - } - - // Add Stylesheet - $insert_array = array( - 'name' => $db->escape_string($mybb->input['name']), - 'tid' => $mybb->get_input('tid', MyBB::INPUT_INT), - 'attachedto' => implode('|', array_map(array($db, "escape_string"), $attached)), - 'stylesheet' => $db->escape_string($stylesheet), - 'cachefile' => $db->escape_string(str_replace('/', '', $mybb->input['name'])), - 'lastmodified' => TIME_NOW - ); - - $sid = $db->insert_query("themestylesheets", $insert_array); - - if(!cache_stylesheet($theme['tid'], str_replace('/', '', $mybb->input['name']), $stylesheet)) - { - $db->update_query("themestylesheets", array('cachefile' => "css.php?stylesheet={$sid}"), "sid='{$sid}'", 1); - } - - // Update the CSS file list for this theme - update_theme_stylesheet_list($theme['tid'], $theme, true); - - $plugins->run_hooks("admin_style_themes_add_stylesheet_commit"); - - // Log admin action - log_admin_action($sid, $mybb->input['name'], $theme['tid'], htmlspecialchars_uni($theme['name'])); - - flash_message($lang->success_stylesheet_added, 'success'); - admin_redirect("index.php?module=style-themes&action=edit_stylesheet&tid={$mybb->input['tid']}&sid={$sid}&file=".urlencode($mybb->input['name'])); - } - } - - if($admin_options['codepress'] != 0) - { - $page->extra_header .= ' - - - - - - - - -'; - } - - $page->add_breadcrumb_item(htmlspecialchars_uni($theme['name']), "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}"); - $page->add_breadcrumb_item($lang->add_stylesheet); - $properties = my_unserialize($theme['properties']); - - $page->output_header("{$lang->themes} - {$lang->add_stylesheet}"); - - $sub_tabs['edit_stylesheets'] = array( - 'title' => $lang->edit_stylesheets, - 'link' => "index.php?module=style-themes&action=edit&tid={$mybb->input['tid']}" - ); - - $sub_tabs['add_stylesheet'] = array( - 'title' => $lang->add_stylesheet, - 'link' => "index.php?module=style-themes&action=add_stylesheet&tid={$mybb->input['tid']}", - 'description' => $lang->add_stylesheet_desc - ); - - $sub_tabs['export_theme'] = array( - 'title' => $lang->export_theme, - 'link' => "index.php?module=style-themes&action=export&tid={$mybb->input['tid']}" - ); - - $sub_tabs['duplicate_theme'] = array( - 'title' => $lang->duplicate_theme, - 'link' => "index.php?module=style-themes&action=duplicate&tid={$mybb->input['tid']}", - 'description' => $lang->duplicate_theme_desc - ); - - $page->output_nav_tabs($sub_tabs, 'add_stylesheet'); - - if($errors) - { - $page->output_inline_error($errors); - - foreach($mybb->input as $name => $value) - { - if(strpos($name, "attached") !== false) - { - list(, $id) = explode('_', $name); - $id = (int)$id; - - $mybb->input['applied_to'][$value] = array(0 => 'global'); - - if($mybb->input['action_'.$id] == 1) - { - $mybb->input['applied_to'][$value] = explode(',', $mybb->input['action_list_'.$id]); - } - } - } - - if($mybb->input['add_type'] == 1) - { - $add_checked[1] = "checked=\"checked\""; - $add_checked[2] = ""; - } - else - { - $add_checked[2] = "checked=\"checked\""; - $add_checked[1] = ""; - } - } - else - { - $mybb->input['name'] = $stylesheet['name']; - } - - $global_checked[1] = "checked=\"checked\""; - $global_checked[2] = ""; - $global_checked[3] = ""; - - $form = new Form("index.php?module=style-themes&action=add_stylesheet", "post", "add_stylesheet"); - - echo $form->generate_hidden_field("tid", $mybb->input['tid'])."\n"; - - $specific_files = "
"; - $count = 0; - - if($mybb->input['attach'] == 1 && is_array($mybb->input['applied_to']) && (!isset($mybb->input['applied_to']['global']) || $mybb->input['applied_to']['global'][0] != "global")) - { - $check_actions = ""; - - foreach($mybb->input['applied_to'] as $name => $actions) - { - $action_list = ""; - if($actions[0] != "global") - { - $action_list = implode(',', $actions); - } - - if($actions[0] == "global") - { - $global_action_checked[1] = "checked=\"checked\""; - $global_action_checked[2] = ""; - } - else - { - $global_action_checked[2] = "checked=\"checked\""; - $global_action_checked[1] = ""; - } - - $specific_file = "
-
-
-
- {$lang->specific_actions_desc} - - - - -
".$form->generate_text_box('action_list_'.$count, $action_list, array('id' => 'action_list_'.$count, 'style' => 'width: 190px;'))."
-
-
"; - - $form_container = new FormContainer(); - $form_container->output_row("", "", "style}/images/icons/cross.png\" alt=\"{$lang->delete}\" title=\"{$lang->delete}\" />{$lang->file}  ".$form->generate_text_box("attached_{$count}", $name, array('id' => "attached_{$count}", 'style' => 'width: 200px;')), "attached_{$count}"); - - $form_container->output_row("", "", $specific_file); - - $specific_files .= "
".$form_container->end(true)."
"; - - $check_actions .= "\n\tcheckAction('action_{$count}');"; - - ++$count; - } - - if($check_actions) - { - $global_checked[3] = ""; - $global_checked[2] = "checked=\"checked\""; - $global_checked[1] = ""; - } - } - else if($mybb->input['attach'] == 2) - { - // Colors - $stylesheet['colors'] = array(); - if(is_array($properties['colors'])) - { - // We might have colors here... - foreach($mybb->input['color'] as $color) - { - // Verify this is a color for this theme - if(array_key_exists($color, $properties['colors'])) - { - $stylesheet['colors'][] = $color; - } - } - - if(!empty($stylesheet['colors'])) - { - $global_checked[3] = "checked=\"checked\""; - $global_checked[2] = ""; - $global_checked[1] = ""; - } - } - } - - $specific_files .= "
"; - - // Colors - $specific_colors = $specific_colors_option = ''; - - if(is_array($properties['colors'])) - { - $specific_colors = "
"; - $specific_colors_option = '
'; - - $specific_color = " - {$lang->colors_add_edit_desc} -

- ".$form->generate_select_box('color[]', $properties['colors'], $stylesheet['colors'], array('multiple' => true, 'size' => "5\" style=\"width: 200px;"))." - "; - - $form_container = new FormContainer(); - $form_container->output_row("", "", $specific_color); - $specific_colors .= $form_container->end(true)."
"; - } - - $actions = ' -
-

-

- '.$specific_files.' - '.$specific_colors_option.' - '.$specific_colors.' -
- '; - - echo $form->generate_hidden_field("sid", $stylesheet['sid'])."
\n"; - - $form_container = new FormContainer($lang->add_stylesheet_to.' '.htmlspecialchars_uni($theme['name']), 'tfixed'); - $form_container->output_row($lang->file_name, $lang->file_name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name', 'style' => 'width: 200px;')), 'name'); - - $form_container->output_row($lang->attached_to, $lang->attached_to_desc, $actions); - - $sheetnames = array(); - foreach($stylesheets as $filename => $style) - { - $sheetnames[basename($filename)] = basename($filename); - } - - $actions = "
-
-
- - - - -
".$form->generate_select_box('import', $sheetnames, $mybb->input['import'], array('id' => 'import'))."
-
-
-
".$form->generate_text_area('stylesheet', $mybb->input['stylesheet'], array('id' => 'stylesheet', 'style' => 'width: 99%;', 'class' => '', 'rows' => '30'))."
-
"; - - $form_container->output_row("", "", $actions); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_stylesheet); - - $form->output_submit_wrapper($buttons); - - if($admin_options['codepress'] != 0) - { - echo ''; - } - - echo ''; - echo ''; - echo ''; - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "set_default") -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - // Does the theme not exist? - if(!$theme['tid'] || $theme['tid'] == 1) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_set_default"); - - $cache->update('default_theme', $theme); - - $db->update_query("themes", array('def' => 0)); - $db->update_query("themes", array('def' => 1), "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - - $plugins->run_hooks("admin_style_themes_set_default_commit"); - - // Log admin action - log_admin_action($theme['tid'], htmlspecialchars_uni($theme['name'])); - - flash_message($lang->success_theme_set_default, 'success'); - admin_redirect("index.php?module=style-themes"); -} - -if($mybb->input['action'] == "force") -{ - $query = $db->simple_select("themes", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $theme = $db->fetch_array($query); - - // Does the theme not exist? - if(!$theme['tid'] || $theme['tid'] == 1) - { - flash_message($lang->error_invalid_theme, 'error'); - admin_redirect("index.php?module=style-themes"); - } - - $plugins->run_hooks("admin_style_themes_force"); - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=style-themes"); - } - - if($mybb->request_method == "post") - { - $updated_users = array( - "style" => $theme['tid'] - ); - - $plugins->run_hooks("admin_style_themes_force_commit"); - - $db->update_query("users", $updated_users); - - // Log admin action - log_admin_action($theme['tid'], htmlspecialchars_uni($theme['name'])); - - flash_message($lang->success_theme_forced, 'success'); - admin_redirect("index.php?module=style-themes"); - } - else - { - $page->output_confirm_action("index.php?module=style-themes&action=force&tid={$theme['tid']}", $lang->confirm_theme_forced); - } -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->themes); - - $plugins->run_hooks("admin_style_themes_start"); - - $page->output_nav_tabs($sub_tabs, 'themes'); - - $table = new Table; - $table->construct_header($lang->theme); - $table->construct_header($lang->num_users, array("class" => "align_center", "width" => 100)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - build_theme_list(); - - $table->output($lang->themes); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/tools/adminlog.php b/html/forums/admin/modules/tools/adminlog.php deleted file mode 100644 index ffd9374..0000000 --- a/html/forums/admin/modules/tools/adminlog.php +++ /dev/null @@ -1,609 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->admin_logs, "index.php?module=tools-adminlog"); - -$sub_tabs['admin_logs'] = array( - 'title' => $lang->admin_logs, - 'link' => "index.php?module=tools-adminlog", - 'description' => $lang->admin_logs_desc -); -$sub_tabs['prune_admin_logs'] = array( - 'title' => $lang->prune_admin_logs, - 'link' => "index.php?module=tools-adminlog&action=prune", - 'description' => $lang->prune_admin_logs_desc -); - -$plugins->run_hooks("admin_tools_adminlog_begin"); - -if($mybb->input['action'] == 'prune') -{ - if(!is_super_admin($mybb->user['uid'])) - { - flash_message($lang->cannot_perform_action_super_admin_general, 'error'); - admin_redirect("index.php?module=tools-adminlog"); - } - - $plugins->run_hooks("admin_tools_adminlog_prune"); - - if($mybb->request_method == 'post') - { - $is_today = false; - $mybb->input['older_than'] = $mybb->get_input('older_than', MyBB::INPUT_INT); - if($mybb->input['older_than'] <= 0) - { - $is_today = true; - $mybb->input['older_than'] = 1; - } - $where = 'dateline < '.(TIME_NOW-($mybb->input['older_than']*86400)); - - // Searching for entries by a particular user - if($mybb->input['uid']) - { - $where .= " AND uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"; - } - - // Searching for entries in a specific module - if($mybb->input['filter_module']) - { - $where .= " AND module='".$db->escape_string($mybb->input['filter_module'])."'"; - } - - $query = $db->delete_query("adminlog", $where); - $num_deleted = $db->affected_rows(); - - $plugins->run_hooks("admin_tools_adminlog_prune_commit"); - - // Log admin action - log_admin_action($mybb->input['older_than'], $mybb->input['uid'], $mybb->input['filter_module'], $num_deleted); - - $success = $lang->success_pruned_admin_logs; - if($is_today == true && $num_deleted > 0) - { - $success .= ' '.$lang->note_logs_locked; - } - elseif($is_today == true && $num_deleted == 0) - { - flash_message($lang->note_logs_locked, 'error'); - admin_redirect("index.php?module=tools-adminlog"); - } - flash_message($success, 'success'); - admin_redirect("index.php?module=tools-adminlog"); - } - $page->add_breadcrumb_item($lang->prune_admin_logs, "index.php?module=tools-adminlog&action=prune"); - $page->output_header($lang->prune_admin_logs); - $page->output_nav_tabs($sub_tabs, 'prune_admin_logs'); - - // Fetch filter options - $sortbysel[$mybb->input['sortby']] = 'selected="selected"'; - $ordersel[$mybb->input['order']] = 'selected="selected"'; - - $user_options[''] = $lang->all_administrators; - $user_options['0'] = '----------'; - - $query = $db->query(" - SELECT DISTINCT l.uid, u.username - FROM ".TABLE_PREFIX."adminlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (l.uid=u.uid) - ORDER BY u.username ASC - "); - while($user = $db->fetch_array($query)) - { - $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); - } - - $module_options = array(); - $module_options[''] = $lang->all_modules; - $module_options['0'] = '----------'; - $query = $db->query(" - SELECT DISTINCT l.module - FROM ".TABLE_PREFIX."adminlog l - ORDER BY l.module ASC - "); - while($module = $db->fetch_array($query)) - { - $module_options[$module['module']] = str_replace(' ', ' -> ', ucwords(str_replace('/', ' ', $module['module']))); - } - - $form = new Form("index.php?module=tools-adminlog&action=prune", "post"); - $form_container = new FormContainer($lang->prune_administrator_logs); - $form_container->output_row($lang->module, "", $form->generate_select_box('filter_module', $module_options, $mybb->input['filter_module'], array('id' => 'filter_module')), 'filter_module'); - $form_container->output_row($lang->administrator, "", $form->generate_select_box('uid', $user_options, $mybb->input['uid'], array('id' => 'uid')), 'uid'); - if(!$mybb->input['older_than']) - { - $mybb->input['older_than'] = '30'; - } - $form_container->output_row($lang->date_range, "", $lang->older_than.$form->generate_numeric_field('older_than', $mybb->input['older_than'], array('id' => 'older_than', 'style' => 'width: 50px', 'min' => 0))." {$lang->days}", 'older_than'); - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->prune_administrator_logs); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->admin_logs); - $page->output_nav_tabs($sub_tabs, 'admin_logs'); - - $perpage = $mybb->get_input('perpage', MyBB::INPUT_INT); - if(!$perpage) - { - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - $perpage = $mybb->settings['threadsperpage']; - } - - $where = ''; - - $plugins->run_hooks("admin_tools_adminlog_start"); - - // Searching for entries by a particular user - if($mybb->input['uid']) - { - $where .= " AND l.uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"; - } - - // Searching for entries in a specific module - if($mybb->input['filter_module']) - { - $where .= " AND module='".$db->escape_string($mybb->input['filter_module'])."'"; - } - - // Order? - switch($mybb->input['sortby']) - { - case "username": - $sortby = "u.username"; - break; - default: - $sortby = "l.dateline"; - } - $order = $mybb->input['order']; - if($order != 'asc') - { - $order = 'desc'; - } - - $query = $db->query(" - SELECT COUNT(l.dateline) AS count - FROM ".TABLE_PREFIX."adminlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=l.uid) - WHERE 1=1 {$where} - "); - $rescount = $db->fetch_field($query, "count"); - - // Figure out if we need to display multiple pages. - if($mybb->input['page'] != "last") - { - $pagecnt = $mybb->get_input('page', MyBB::INPUT_INT); - } - - $postcount = (int)$rescount; - $pages = $postcount / $perpage; - $pages = ceil($pages); - - if($mybb->input['page'] == "last") - { - $pagecnt = $pages; - } - - if($pagecnt > $pages) - { - $pagecnt = 1; - } - - if($pagecnt) - { - $start = ($pagecnt-1) * $perpage; - } - else - { - $start = 0; - $pagecnt = 1; - } - - $table = new Table; - $table->construct_header($lang->username, array('width' => '10%')); - $table->construct_header($lang->date, array('class' => 'align_center', 'width' => '15%')); - $table->construct_header($lang->information, array('class' => 'align_center', 'width' => '65%')); - $table->construct_header($lang->ipaddress, array('class' => 'align_center', 'width' => '10%')); - - $query = $db->query(" - SELECT l.*, u.username, u.usergroup, u.displaygroup - FROM ".TABLE_PREFIX."adminlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=l.uid) - WHERE 1=1 {$where} - ORDER BY {$sortby} {$order} - LIMIT {$start}, {$perpage} - "); - while($logitem = $db->fetch_array($query)) - { - $information = ''; - $trow = alt_trow(); - $logitem['username'] = htmlspecialchars_uni($logitem['username']); - $username = format_name($logitem['username'], $logitem['usergroup'], $logitem['displaygroup']); - - $logitem['data'] = my_unserialize($logitem['data']); - $logitem['profilelink'] = build_profile_link($username, $logitem['uid'], "_blank"); - $logitem['dateline'] = my_date('relative', $logitem['dateline']); - - // Get detailed information from meta - $information = get_admin_log_action($logitem); - - $table->construct_cell($logitem['profilelink']); - $table->construct_cell($logitem['dateline'], array('class' => 'align_center')); - $table->construct_cell($information); - $table->construct_cell(my_inet_ntop($db->unescape_binary($logitem['ipaddress'])), array('class' => 'align_center')); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_adminlogs, array('colspan' => '4')); - $table->construct_row(); - } - - $table->output($lang->admin_logs); - - // Do we need to construct the pagination? - if($rescount > $perpage) - { - echo draw_admin_pagination($pagecnt, $perpage, $rescount, "index.php?module=tools-adminlog&perpage=$perpage&uid={$mybb->input['uid']}&fid={$mybb->input['fid']}&sortby={$mybb->input['sortby']}&order={$order}&filter_module=".htmlspecialchars_uni($mybb->input['filter_module']))."
"; - } - - // Fetch filter options - $sortbysel[$mybb->input['sortby']] = 'selected="selected"'; - $ordersel[$mybb->input['order']] = 'selected="selected"'; - - $user_options[''] = $lang->all_administrators; - $user_options['0'] = '----------'; - - $query = $db->query(" - SELECT DISTINCT l.uid, u.username - FROM ".TABLE_PREFIX."adminlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (l.uid=u.uid) - ORDER BY u.username ASC - "); - while($user = $db->fetch_array($query)) - { - $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); - } - - $module_options = array(); - $module_options[''] = $lang->all_modules; - $module_options['0'] = '----------'; - $query = $db->query(" - SELECT DISTINCT l.module - FROM ".TABLE_PREFIX."adminlog l - ORDER BY l.module ASC - "); - while($module = $db->fetch_array($query)) - { - $module_options[$module['module']] = str_replace(' ', ' -> ', ucwords(str_replace('/', ' ', $module['module']))); - } - - $sort_by = array( - 'dateline' => $lang->date, - 'username' => $lang->username - ); - - $order_array = array( - 'asc' => $lang->asc, - 'desc' => $lang->desc - ); - - $form = new Form("index.php?module=tools-adminlog", "post"); - $form_container = new FormContainer($lang->filter_administrator_logs); - $form_container->output_row($lang->module, "", $form->generate_select_box('filter_module', $module_options, $mybb->input['filter_module'], array('id' => 'filter_module')), 'filter_module'); - $form_container->output_row($lang->administrator, "", $form->generate_select_box('uid', $user_options, $mybb->input['uid'], array('id' => 'uid')), 'uid'); - $form_container->output_row($lang->sort_by, "", $form->generate_select_box('sortby', $sort_by, $mybb->input['sortby'], array('id' => 'sortby'))." {$lang->in} ".$form->generate_select_box('order', $order_array, $order, array('id' => 'order'))." {$lang->order}", 'order'); - $form_container->output_row($lang->results_per_page, "", $form->generate_numeric_field('perpage', $perpage, array('id' => 'perpage', 'min' => 1)), 'perpage'); - - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->filter_administrator_logs); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -/** - * Returns language-friendly string describing $logitem - * @param array $logitem The log item (one row from mybb_adminlogs) - * @return string The description - */ -function get_admin_log_action($logitem) -{ - global $lang, $plugins, $mybb; - - $logitem['module'] = str_replace('/', '-', $logitem['module']); - list($module, $action) = explode('-', $logitem['module']); - $lang_string = 'admin_log_'.$module.'_'.$action.'_'.$logitem['action']; - - // Specific page overrides - switch($lang_string) - { - // == CONFIG == - case 'admin_log_config_banning_add': // Banning IP/Username/Email - case 'admin_log_config_banning_delete': // Removing banned IP/username/emails - switch($logitem['data'][2]) - { - case 1: - $lang_string = 'admin_log_config_banning_'.$logitem['action'].'_ip'; - break; - case 2: - $lang_string = 'admin_log_config_banning_'.$logitem['action'].'_username'; - break; - case 3: - $lang_string = 'admin_log_config_banning_'.$logitem['action'].'_email'; - break; - } - break; - - case 'admin_log_config_help_documents_add': // Help documents and sections - case 'admin_log_config_help_documents_edit': - case 'admin_log_config_help_documents_delete': - $lang_string .= "_{$logitem['data'][2]}"; // adds _section or _document - break; - - case 'admin_log_config_languages_edit': // Editing language variables - $logitem['data'][1] = basename($logitem['data'][1]); - if($logitem['data'][2] == 1) - { - $lang_string = 'admin_log_config_languages_edit_admin'; - } - break; - - case 'admin_log_config_mycode_toggle_status': // Custom MyCode toggle activation - if($logitem['data'][2] == 1) - { - $lang_string .= '_enabled'; - } - else - { - $lang_string .= '_disabled'; - } - break; - case 'admin_log_config_plugins_activate': // Installing plugin - if($logitem['data'][1]) - { - $lang_string .= '_install'; - } - break; - case 'admin_log_config_plugins_deactivate': // Uninstalling plugin - if($logitem['data'][1]) - { - $lang_string .= '_uninstall'; - } - break; - // == FORUM == - case 'admin_log_forum_attachments_delete': // Deleting attachments - if($logitem['data'][2]) - { - $lang_string .= '_post'; - } - break; - case 'admin_log_forum_management_copy': // Forum copy - if($logitem['data'][4]) - { - $lang_string .= '_with_permissions'; - } - break; - case 'admin_log_forum_management_': // add mod, permissions, forum orders - // first parameter already set with action - $lang_string .= $logitem['data'][0]; - if($logitem['data'][0] == 'orders' && $logitem['data'][1]) - { - $lang_string .= '_sub'; // updating forum orders in a subforum - } - break; - case 'admin_log_forum_moderation_queue_': //moderation queue - // first parameter already set with action - $lang_string .= $logitem['data'][0]; - break; - // == HOME == - case 'admin_log_home_preferences_': // 2FA - $lang_string .= $logitem['data'][0]; // either "enabled" or "disabled" - break; - // == STYLE == - case 'admin_log_style_templates_delete_template': // deleting templates - // global template set - if($logitem['data'][2] == -1) - { - $lang_string .= '_global'; - } - break; - case 'admin_log_style_templates_edit_template': // editing templates - // global template set - if($logitem['data'][2] == -1) - { - $lang_string .= '_global'; - } - break; - // == TOOLS == - case 'admin_log_tools_adminlog_prune': // Admin Log Pruning - if($logitem['data'][1] && !$logitem['data'][2]) - { - $lang_string = 'admin_log_tools_adminlog_prune_user'; - } - elseif($logitem['data'][2] && !$logitem['data'][1]) - { - $lang_string = 'admin_log_tools_adminlog_prune_module'; - } - elseif($logitem['data'][1] && $logitem['data'][2]) - { - $lang_string = 'admin_log_tools_adminlog_prune_user_module'; - } - break; - case 'admin_log_tools_modlog_prune': // Moderator Log Pruning - if($logitem['data'][1] && !$logitem['data'][2]) - { - $lang_string = 'admin_log_tools_modlog_prune_user'; - } - elseif($logitem['data'][2] && !$logitem['data'][1]) - { - $lang_string = 'admin_log_tools_modlog_prune_forum'; - } - elseif($logitem['data'][1] && $logitem['data'][2]) - { - $lang_string = 'admin_log_tools_modlog_prune_user_forum'; - } - break; - case 'admin_log_tools_backupdb_backup': // Create backup - if($logitem['data'][0] == 'download') - { - $lang_string = 'admin_log_tools_backupdb_backup_download'; - } - $logitem['data'][1] = '...'.substr($logitem['data'][1], -20); - break; - case 'admin_log_tools_backupdb_dlbackup': // Download backup - $logitem['data'][0] = '...'.substr($logitem['data'][0], -20); - break; - case 'admin_log_tools_backupdb_delete': // Delete backup - $logitem['data'][0] = '...'.substr($logitem['data'][0], -20); - break; - case 'admin_log_tools_optimizedb_': // Optimize DB - $logitem['data'][0] = @implode(', ', my_unserialize($logitem['data'][0])); - break; - case 'admin_log_tools_recount_rebuild_': // Recount and rebuild - $detail_lang_string = $lang_string.$logitem['data'][0]; - if(isset($lang->$detail_lang_string)) - { - $lang_string = $detail_lang_string; - } - break; - case 'admin_log_tools_spamlog_prune': // Spam Log Pruning - if($logitem['data'][1] && !$logitem['data'][2]) - { - $lang_string = 'admin_log_tools_spamlog_prune_user'; - } - elseif($logitem['data'][2] && !$logitem['data'][1]) - { - $lang_string = 'admin_log_tools_spamlog_prune_email'; - } - elseif($logitem['data'][1] && $logitem['data'][2]) - { - $lang_string = 'admin_log_tools_spamlog_prune_user_email'; - } - break; - // == USERS == - case 'admin_log_user_admin_permissions_edit': // editing default/group/user admin permissions - if($logitem['data'][0] > 0) - { - // User - $lang_string .= '_user'; - } - elseif($logitem['data'][0] < 0) - { - // Group - $logitem['data'][0] = abs($logitem['data'][0]); - $lang_string .= '_group'; - } - break; - case 'admin_log_user_admin_permissions_delete': // deleting group/user admin permissions - if($logitem['data'][0] > 0) - { - // User - $lang_string .= '_user'; - } - elseif($logitem['data'][0] < 0) - { - // Group - $logitem['data'][0] = abs($logitem['data'][0]); - $lang_string .= '_group'; - } - break; - case 'admin_log_user_awaiting_activation_activate': - if($logitem['data'][0] == 'deleted') - { - $lang_string .= '_deleted'; - } - else - { - $lang_string .= '_activated'; - } - break; - case 'admin_log_user_banning_': // banning - if($logitem['data'][2] == 0) - { - $lang_string = 'admin_log_user_banning_add_permanent'; - } - else - { - $logitem['data'][2] = my_date($mybb->settings['dateformat'], $logitem['data'][2]); - $lang_string = 'admin_log_user_banning_add_temporary'; - } - break; - case 'admin_log_user_groups_join_requests': - if($logitem['data'][0] == 'approve') - { - $lang_string = 'admin_log_user_groups_join_requests_approve'; - } - else - { - $lang_string = 'admin_log_user_groups_join_requests_deny'; - } - break; - case 'admin_log_user_users_inline_banned': - if($logitem['data'][1] == 0) - { - $lang_string = 'admin_log_user_users_inline_banned_perm'; - } - else - { - $logitem['data'][1] = my_date($mybb->settings['dateformat'], $logitem['data'][1]); - $lang_string = 'admin_log_user_users_inline_banned_temp'; - } - break; - } - - $plugin_array = array('logitem' => &$logitem, 'lang_string' => &$lang_string); - $plugins->run_hooks("admin_tools_get_admin_log_action", $plugin_array); - - if(isset($lang->$lang_string)) - { - array_unshift($logitem['data'], $lang->$lang_string); // First parameter for sprintf is the format string - $string = call_user_func_array(array($lang, 'sprintf'), $logitem['data']); - if(!$string) - { - $string = $lang->$lang_string; // Fall back to the one in the language pack - } - } - else - { - if(isset($logitem['data']['type']) && $logitem['data']['type'] == 'admin_locked_out') - { - $string = $lang->sprintf($lang->admin_log_admin_locked_out, (int) $logitem['data']['uid'], htmlspecialchars_uni($logitem['data']['username'])); - } - else - { - // Build a default string - $string = $logitem['module'].' - '.$logitem['action']; - if(is_array($logitem['data']) && count($logitem['data']) > 0) - { - $string .= '('.implode(', ', $logitem['data']).')'; - } - } - } - return $string; -} - - diff --git a/html/forums/admin/modules/tools/backupdb.php b/html/forums/admin/modules/tools/backupdb.php deleted file mode 100644 index bcb09f6..0000000 --- a/html/forums/admin/modules/tools/backupdb.php +++ /dev/null @@ -1,483 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -/** - * Allows us to refresh cache to prevent over flowing - * - * @param resource $fp - * @param string $contents - */ -function clear_overflow($fp, &$contents) -{ - global $mybb; - - if($mybb->input['method'] == 'disk') - { - if($mybb->input['filetype'] == 'gzip') - { - gzwrite($fp, $contents); - } - else - { - fwrite($fp, $contents); - } - } - else - { - if($mybb->input['filetype'] == "gzip") - { - echo gzencode($contents); - } - else - { - echo $contents; - } - } - - $contents = ''; -} - -$page->add_breadcrumb_item($lang->database_backups, "index.php?module=tools-backupdb"); - -$plugins->run_hooks("admin_tools_backupdb_begin"); - -if($mybb->input['action'] == "dlbackup") -{ - if(empty($mybb->input['file'])) - { - flash_message($lang->error_file_not_specified, 'error'); - admin_redirect("index.php?module=tools-backupdb"); - } - - $plugins->run_hooks("admin_tools_backupdb_dlbackup"); - - $file = basename($mybb->input['file']); - $ext = get_extension($file); - - if(file_exists(MYBB_ADMIN_DIR.'backups/'.$file) && filetype(MYBB_ADMIN_DIR.'backups/'.$file) == 'file' && ($ext == 'gz' || $ext == 'sql')) - { - $plugins->run_hooks("admin_tools_backupdb_dlbackup_commit"); - - // Log admin action - log_admin_action($file); - - header('Content-disposition: attachment; filename='.$file); - header("Content-type: ".$ext); - header("Content-length: ".filesize(MYBB_ADMIN_DIR.'backups/'.$file)); - - $handle = fopen(MYBB_ADMIN_DIR.'backups/'.$file, 'rb'); - while(!feof($handle)) - { - echo fread($handle, 8192); - } - fclose($handle); - } - else - { - flash_message($lang->error_invalid_backup, 'error'); - admin_redirect("index.php?module=tools-backupdb"); - } -} - -if($mybb->input['action'] == "delete") -{ - if($mybb->input['no']) - { - admin_redirect("index.php?module=tools-backupdb"); - } - - $file = basename($mybb->input['file']); - - if(!trim($mybb->input['file']) || !file_exists(MYBB_ADMIN_DIR.'backups/'.$file)) - { - flash_message($lang->error_backup_doesnt_exist, 'error'); - admin_redirect("index.php?module=tools-backupdb"); - } - - $plugins->run_hooks("admin_tools_backupdb_delete"); - - if($mybb->request_method == "post") - { - $delete = @unlink(MYBB_ADMIN_DIR.'backups/'.$file); - - if($delete) - { - $plugins->run_hooks("admin_tools_backupdb_delete_commit"); - - // Log admin action - log_admin_action($file); - - flash_message($lang->success_backup_deleted, 'success'); - admin_redirect("index.php?module=tools-backupdb"); - } - else - { - flash_message($lang->error_backup_not_deleted, 'error'); - admin_redirect("index.php?module=tools-backupdb"); - } - } - else - { - $page->output_confirm_action("index.php?module=tools-backupdb&action=delete&file={$mybb->input['file']}", $lang->confirm_backup_deletion); - } -} - -if($mybb->input['action'] == "backup") -{ - $plugins->run_hooks("admin_tools_backupdb_backup"); - - if($mybb->request_method == "post") - { - if(!is_array($mybb->input['tables'])) - { - flash_message($lang->error_tables_not_selected, 'error'); - admin_redirect("index.php?module=tools-backupdb&action=backup"); - } - - @set_time_limit(0); - - if($mybb->input['method'] == 'disk') - { - $file = MYBB_ADMIN_DIR.'backups/backup_'.date("_Ymd_His_").random_str(16); - - if($mybb->input['filetype'] == 'gzip') - { - if(!function_exists('gzopen')) // check zlib-ness - { - flash_message($lang->error_no_zlib, 'error'); - admin_redirect("index.php?module=tools-backupdb&action=backup"); - } - - $fp = gzopen($file.'.incomplete.sql.gz', 'w9'); - } - else - { - $fp = fopen($file.'.incomplete.sql', 'w'); - } - } - else - { - $file = 'backup_'.substr(md5($mybb->user['uid'].TIME_NOW), 0, 10).random_str(54); - if($mybb->input['filetype'] == 'gzip') - { - if(!function_exists('gzopen')) // check zlib-ness - { - flash_message($lang->error_no_zlib, 'error'); - admin_redirect("index.php?module=tools-backupdb&action=backup"); - } - - // Send headers for gzip file - header('Content-Type: application/x-gzip'); - header('Content-Disposition: attachment; filename="'.$file.'.sql.gz"'); - } - else - { - // Send standard headers for .sql - header('Content-Type: text/x-sql'); - header('Content-Disposition: attachment; filename="'.$file.'.sql"'); - } - } - $db->set_table_prefix(''); - - $time = date('dS F Y \a\t H:i', TIME_NOW); - $header = "-- MyBB Database Backup\n-- Generated: {$time}\n-- -------------------------------------\n\n"; - $contents = $header; - foreach($mybb->input['tables'] as $table) - { - if(!$db->table_exists($db->escape_string($table))) - { - continue; - } - if($mybb->input['analyzeoptimize'] == 1) - { - $db->optimize_table($table); - $db->analyze_table($table); - } - - $field_list = array(); - $fields_array = $db->show_fields_from($table); - foreach($fields_array as $field) - { - $field_list[] = $field['Field']; - } - - $fields = "`".implode("`,`", $field_list)."`"; - if($mybb->input['contents'] != 'data') - { - $structure = $db->show_create_table($table).";\n"; - $contents .= $structure; - clear_overflow($fp, $contents); - } - - if($mybb->input['contents'] != 'structure') - { - if($db->engine == 'mysqli') - { - $query = mysqli_query($db->read_link, "SELECT * FROM {$db->table_prefix}{$table}", MYSQLI_USE_RESULT); - } - else - { - $query = $db->simple_select($table); - } - - while($row = $db->fetch_array($query)) - { - $insert = "INSERT INTO {$table} ($fields) VALUES ("; - $comma = ''; - foreach($field_list as $field) - { - if(!isset($row[$field]) || is_null($row[$field])) - { - $insert .= $comma."NULL"; - } - else if($db->engine == 'mysqli') - { - $insert .= $comma."'".mysqli_real_escape_string($db->read_link, $row[$field])."'"; - } - else - { - $insert .= $comma."'".$db->escape_string($row[$field])."'"; - } - $comma = ','; - } - $insert .= ");\n"; - $contents .= $insert; - clear_overflow($fp, $contents); - } - $db->free_result($query); - } - } - - $db->set_table_prefix(TABLE_PREFIX); - - if($mybb->input['method'] == 'disk') - { - if($mybb->input['filetype'] == 'gzip') - { - gzwrite($fp, $contents); - gzclose($fp); - rename($file.'.incomplete.sql.gz', $file.'.sql.gz'); - } - else - { - fwrite($fp, $contents); - fclose($fp); - rename($file.'.incomplete.sql', $file.'.sql'); - } - - if($mybb->input['filetype'] == 'gzip') - { - $ext = '.sql.gz'; - } - else - { - $ext = '.sql'; - } - - $plugins->run_hooks("admin_tools_backupdb_backup_disk_commit"); - - // Log admin action - log_admin_action("disk", $file.$ext); - - $file_from_admindir = 'index.php?module=tools-backupdb&action=dlbackup&file='.basename($file).$ext; - flash_message("{$lang->success_backup_created}

{$lang->backup_saved_to}
{$file}{$ext} ({$lang->download})

", 'success'); - admin_redirect("index.php?module=tools-backupdb"); - } - else - { - $plugins->run_hooks("admin_tools_backupdb_backup_download_commit"); - - // Log admin action - log_admin_action("download"); - - if($mybb->input['filetype'] == 'gzip') - { - echo gzencode($contents); - } - else - { - echo $contents; - } - } - - exit; - } - - $page->extra_header = " \n"; - - $page->add_breadcrumb_item($lang->new_database_backup); - $page->output_header($lang->new_database_backup); - - $sub_tabs['database_backup'] = array( - 'title' => $lang->database_backups, - 'link' => "index.php?module=tools-backupdb" - ); - - $sub_tabs['new_backup'] = array( - 'title' => $lang->new_backup, - 'link' => "index.php?module=tools-backupdb&action=backup", - 'description' => $lang->new_backup_desc - ); - - $page->output_nav_tabs($sub_tabs, 'new_backup'); - - // Check if file is writable, before allowing submission - if(!is_writable(MYBB_ADMIN_DIR."/backups")) - { - $lang->update_button = ''; - $page->output_alert($lang->alert_not_writable); - $cannot_write = true; - } - - $table = new Table; - $table->construct_header($lang->table_selection); - $table->construct_header($lang->backup_options); - - $table_selects = array(); - $table_list = $db->list_tables($config['database']['database']); - foreach($table_list as $id => $table_name) - { - $table_selects[$table_name] = $table_name; - } - - $form = new Form("index.php?module=tools-backupdb&action=backup", "post", "table_selection", 0, "table_selection"); - - $table->construct_cell("{$lang->table_select_desc}\n

\n{$lang->select_all}
\n{$lang->deselect_all}
\n{$lang->select_forum_tables}\n

\n
".$form->generate_select_box("tables[]", $table_selects, false, array('multiple' => true, 'id' => 'table_select', 'size' => 20))."
", array('rowspan' => 5, 'width' => '50%', 'style' => 'border-bottom: 0px')); - $table->construct_row(); - - $table->construct_cell("{$lang->file_type}
\n{$lang->file_type_desc}
\n
".$form->generate_radio_button("filetype", "gzip", $lang->gzip_compressed, array('checked' => 1))."
\n".$form->generate_radio_button("filetype", "plain", $lang->plain_text)."
", array('width' => '50%')); - $table->construct_row(); - $table->construct_cell("{$lang->save_method}
\n{$lang->save_method_desc}
".$form->generate_radio_button("method", "disk", $lang->backup_directory)."
\n".$form->generate_radio_button("method", "download", $lang->download, array('checked' => 1))."
", array('width' => '50%')); - $table->construct_row(); - $table->construct_cell("{$lang->backup_contents}
\n{$lang->backup_contents_desc}
".$form->generate_radio_button("contents", "both", $lang->structure_and_data, array('checked' => 1))."
\n".$form->generate_radio_button("contents", "structure", $lang->structure_only)."
\n".$form->generate_radio_button("contents", "data", $lang->data_only)."
", array('width' => '50%')); - $table->construct_row(); - $table->construct_cell("{$lang->analyze_and_optimize}
\n{$lang->analyze_and_optimize_desc}
".$form->generate_yes_no_radio("analyzeoptimize")."
", array('width' => '50%')); - $table->construct_row(); - - $table->output($lang->new_database_backup); - - $buttons[] = $form->generate_submit_button($lang->perform_backup); - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $page->add_breadcrumb_item($lang->backups); - $page->output_header($lang->database_backups); - - $sub_tabs['database_backup'] = array( - 'title' => $lang->database_backups, - 'link' => "index.php?module=tools-backupdb", - 'description' => $lang->database_backups_desc - ); - - $sub_tabs['new_backup'] = array( - 'title' => $lang->new_backup, - 'link' => "index.php?module=tools-backupdb&action=backup", - ); - - $plugins->run_hooks("admin_tools_backupdb_start"); - - $page->output_nav_tabs($sub_tabs, 'database_backup'); - - $backups = array(); - $dir = MYBB_ADMIN_DIR.'backups/'; - $handle = opendir($dir); - - if($handle !== false) - { - while(($file = readdir($handle)) !== false) - { - if(filetype(MYBB_ADMIN_DIR.'backups/'.$file) == 'file') - { - $ext = get_extension($file); - if($ext == 'gz' || $ext == 'sql') - { - $backups[@filemtime(MYBB_ADMIN_DIR.'backups/'.$file)] = array( - "file" => $file, - "time" => @filemtime(MYBB_ADMIN_DIR.'backups/'.$file), - "type" => $ext - ); - } - } - } - closedir($handle); - } - - $count = count($backups); - krsort($backups); - - $table = new Table; - $table->construct_header($lang->backup_filename); - $table->construct_header($lang->file_size, array("class" => "align_center")); - $table->construct_header($lang->creation_date); - $table->construct_header($lang->controls, array("class" => "align_center")); - - foreach($backups as $backup) - { - $time = "-"; - if($backup['time']) - { - $time = my_date('relative', $backup['time']); - } - - $table->construct_cell("{$backup['file']}"); - $table->construct_cell(get_friendly_size(filesize(MYBB_ADMIN_DIR.'backups/'.$backup['file'])), array("class" => "align_center")); - $table->construct_cell($time); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_backup_deletion}')\">{$lang->delete}", array("class" => "align_center")); - $table->construct_row(); - } - - if($count == 0) - { - $table->construct_cell($lang->no_backups, array('colspan' => 4)); - $table->construct_row(); - } - - $table->output($lang->existing_database_backups); - $page->output_footer(); -} diff --git a/html/forums/admin/modules/tools/cache.php b/html/forums/admin/modules/tools/cache.php deleted file mode 100644 index dd28f4a..0000000 --- a/html/forums/admin/modules/tools/cache.php +++ /dev/null @@ -1,276 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->cache_manager, "index.php?module=tools-cache"); - -$plugins->run_hooks("admin_tools_cache_begin"); - -if($mybb->input['action'] == 'view') -{ - if(!trim($mybb->input['title'])) - { - flash_message($lang->error_no_cache_specified, 'error'); - admin_redirect("index.php?module=tools-cache"); - } - - $plugins->run_hooks("admin_tools_cache_view"); - - // Rebuilds forum settings - if($mybb->input['title'] == 'settings') - { - $cachedsettings = (array)$mybb->settings; - if(isset($cachedsettings['internal'])) - { - unset($cachedsettings['internal']); - } - - $cacheitem = array( - 'title' => 'settings', - 'cache' => my_serialize($cachedsettings) - ); - } - else - { - $query = $db->simple_select("datacache", "*", "title = '".$db->escape_string($mybb->input['title'])."'"); - $cacheitem = $db->fetch_array($query); - } - - if(!$cacheitem) - { - flash_message($lang->error_incorrect_cache, 'error'); - admin_redirect("index.php?module=tools-cache"); - } - - $cachecontents = unserialize($cacheitem['cache']); - if(empty($cachecontents)) - { - $cachecontents = $lang->error_empty_cache; - } - ob_start(); - print_r($cachecontents); - $cachecontents = htmlspecialchars_uni(ob_get_contents()); - ob_end_clean(); - - $page->add_breadcrumb_item($lang->view); - $page->output_header($lang->cache_manager); - - $table = new Table; - - $table->construct_cell("
\n{$cachecontents}\n
"); - $table->construct_row(); - $table->output($lang->cache." {$cacheitem['title']}"); - - $page->output_footer(); - -} - -if($mybb->input['action'] == "rebuild" || $mybb->input['action'] == "reload") -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=tools-cache"); - } - - $plugins->run_hooks("admin_tools_cache_rebuild"); - - // Rebuilds forum settings - if($mybb->input['title'] == 'settings') - { - rebuild_settings(); - - $plugins->run_hooks("admin_tools_cache_rebuild_commit"); - - // Log admin action - log_admin_action($mybb->input['title']); - - flash_message($lang->success_cache_reloaded, 'success'); - admin_redirect("index.php?module=tools-cache"); - } - - if(method_exists($cache, "update_{$mybb->input['title']}")) - { - $func = "update_{$mybb->input['title']}"; - $cache->$func(); - - $plugins->run_hooks("admin_tools_cache_rebuild_commit"); - - // Log admin action - log_admin_action($mybb->input['title']); - - flash_message($lang->success_cache_rebuilt, 'success'); - admin_redirect("index.php?module=tools-cache"); - } - elseif(method_exists($cache, "reload_{$mybb->input['title']}")) - { - $func = "reload_{$mybb->input['title']}"; - $cache->$func(); - - $plugins->run_hooks("admin_tools_cache_rebuild_commit"); - - // Log admin action - log_admin_action($mybb->input['title']); - - flash_message($lang->success_cache_reloaded, 'success'); - admin_redirect("index.php?module=tools-cache"); - } - elseif(function_exists("update_{$mybb->input['title']}")) - { - $func = "update_{$mybb->input['title']}"; - $func(); - - $plugins->run_hooks("admin_tools_cache_rebuild_commit"); - - // Log admin action - log_admin_action($mybb->input['title']); - - flash_message($lang->success_cache_rebuilt, 'success'); - admin_redirect("index.php?module=tools-cache"); - } - elseif(function_exists("reload_{$mybb->input['title']}")) - { - $func = "reload_{$mybb->input['title']}"; - $func(); - - $plugins->run_hooks("admin_tools_cache_rebuild_commit"); - - // Log admin action - log_admin_action($mybb->input['title']); - - flash_message($lang->success_cache_reloaded, 'success'); - admin_redirect("index.php?module=tools-cache"); - } - else - { - flash_message($lang->error_cannot_rebuild, 'error'); - admin_redirect("index.php?module=tools-cache"); - } -} - -if($mybb->input['action'] == "rebuild_all") -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=tools-cache"); - } - - $plugins->run_hooks("admin_tools_cache_rebuild_all"); - - $query = $db->simple_select("datacache"); - while($cacheitem = $db->fetch_array($query)) - { - if(method_exists($cache, "update_{$cacheitem['title']}")) - { - $func = "update_{$cacheitem['title']}"; - $cache->$func(); - } - elseif(method_exists($cache, "reload_{$cacheitem['title']}")) - { - $func = "reload_{$cacheitem['title']}"; - $cache->$func(); - } - elseif(function_exists("update_{$cacheitem['title']}")) - { - $func = "update_{$cacheitem['title']}"; - $func(); - } - elseif(function_exists("reload_{$cacheitem['title']}")) - { - $func = "reload_{$cacheitem['title']}"; - $func(); - } - } - - // Rebuilds forum settings - rebuild_settings(); - - $plugins->run_hooks("admin_tools_cache_rebuild_all_commit"); - - // Log admin action - log_admin_action(); - - flash_message($lang->success_cache_reloaded, 'success'); - admin_redirect("index.php?module=tools-cache"); -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->cache_manager); - - $sub_tabs['cache_manager'] = array( - 'title' => $lang->cache_manager, - 'link' => "index.php?module=tools-cache", - 'description' => $lang->cache_manager_description - ); - - $plugins->run_hooks("admin_tools_cache_start"); - - $page->output_nav_tabs($sub_tabs, 'cache_manager'); - - $table = new Table; - $table->construct_header($lang->name); - $table->construct_header($lang->size, array("class" => "align_center", "width" => 100)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - $query = $db->simple_select("datacache"); - while($cacheitem = $db->fetch_array($query)) - { - $table->construct_cell("{$cacheitem['title']}"); - $table->construct_cell(get_friendly_size(strlen($cacheitem['cache'])), array("class" => "align_center")); - - if(method_exists($cache, "update_".$cacheitem['title'])) - { - $table->construct_cell("post_code}\">".$lang->rebuild_cache."", array("class" => "align_center")); - } - elseif(method_exists($cache, "reload_".$cacheitem['title'])) - { - $table->construct_cell("post_code}\">".$lang->reload_cache."", array("class" => "align_center")); - } - elseif(function_exists("update_".$cacheitem['title'])) - { - $table->construct_cell("post_code}\">".$lang->rebuild_cache."", array("class" => "align_center")); - } - elseif(function_exists("reload_".$cacheitem['title'])) - { - $table->construct_cell("post_code}\">".$lang->reload_cache."", array("class" => "align_center")); - } - else - { - $table->construct_cell(""); - } - - $table->construct_row(); - } - - // Rebuilds forum settings - $cachedsettings = (array)$mybb->settings; - if(isset($cachedsettings['internal'])) - { - unset($cachedsettings['internal']); - } - - $table->construct_cell("settings"); - $table->construct_cell(get_friendly_size(strlen(my_serialize($cachedsettings))), array("class" => "align_center")); - $table->construct_cell("post_code}\">".$lang->reload_cache."", array("class" => "align_center")); - - $table->construct_row(); - - $table->output("".$lang->cache_manager); - - $page->output_footer(); -} - diff --git a/html/forums/admin/modules/tools/file_verification.php b/html/forums/admin/modules/tools/file_verification.php deleted file mode 100644 index 65304d3..0000000 --- a/html/forums/admin/modules/tools/file_verification.php +++ /dev/null @@ -1,137 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -@set_time_limit(0); - -$page->add_breadcrumb_item($lang->file_verification, "index.php?module=tools-file_verification"); - -$plugins->run_hooks("admin_tools_file_verification_begin"); - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_tools_file_verification_check"); - - if($mybb->request_method == "post") - { - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=tools-system_health"); - } - - $page->add_breadcrumb_item($lang->checking, "index.php?module=tools-file_verification"); - - $page->output_header($lang->file_verification." - ".$lang->checking); - - $file = explode("\n", fetch_remote_file("https://mybb.com/checksums/release_mybb_{$mybb->version_code}.txt")); - - if(strstr($file[0], "output_inline_error($lang->error_communication); - $page->output_footer(); - exit; - } - - // Parser-up our checksum file from the MyBB Server - foreach($file as $line) - { - $parts = explode(" ", $line, 2); - if(empty($parts[0]) || empty($parts[1])) - { - continue; - } - - if(substr($parts[1], 0, 7) == "./admin") - { - $parts[1] = "./{$mybb->config['admin_dir']}".substr($parts[1], 7); - } - - if(file_exists(MYBB_ROOT."forums.php") && !file_exists(MYBB_ROOT."portal.php")) - { - if(trim($parts[1]) == "./index.php") - { - $parts[1] = "./forums.php"; - } - elseif($parts[1] == "./portal.php") - { - $parts[1] = "./index.php"; - } - } - - if(!file_exists(MYBB_ROOT."inc/plugins/hello.php") && $parts[1] == "./inc/plugins/hello.php") - { - continue; - } - - if(!is_dir(MYBB_ROOT."install/") && substr($parts[1], 0, 10) == "./install/") - { - continue; - } - - $checksums[trim($parts[1])][] = $parts[0]; - } - - $bad_files = verify_files(); - - $plugins->run_hooks("admin_tools_file_verification_check_commit_start"); - - $table = new Table; - $table->construct_header($lang->file); - $table->construct_header($lang->status, array("class" => "align_center", "width" => 100)); - - foreach($bad_files as $file) - { - switch($file['status']) - { - case "changed": - $file['status'] = $lang->changed; - $color = "#F22B48"; - break; - case "missing": - $file['status'] = $lang->missing; - $color = "#5B5658"; - break; - } - - $table->construct_cell("".htmlspecialchars_uni(substr($file['path'], 2)).""); - - $table->construct_cell("{$file['status']}", array("class" => "align_center")); - $table->construct_row(); - } - - $no_errors = false; - if($table->num_rows() == 0) - { - $no_errors = true; - $table->construct_cell($lang->no_corrupt_files_found, array('colspan' => 3)); - $table->construct_row(); - } - - if($no_errors) - { - $table->output($lang->file_verification.": ".$lang->no_problems_found); - } - else - { - $table->output($lang->file_verification.": ".$lang->found_problems); - } - - $page->output_footer(); - exit; - } - - $page->output_confirm_action("index.php?module=tools-file_verification", $lang->file_verification_message, $lang->file_verification); -} diff --git a/html/forums/admin/modules/tools/index.html b/html/forums/admin/modules/tools/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/modules/tools/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/modules/tools/mailerrors.php b/html/forums/admin/modules/tools/mailerrors.php deleted file mode 100644 index c10d9a3..0000000 --- a/html/forums/admin/modules/tools/mailerrors.php +++ /dev/null @@ -1,263 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->system_email_log, "index.php?module=tools-mailerrors"); - -$plugins->run_hooks("admin_tools_mailerrors_begin"); - -if($mybb->input['action'] == "prune" && $mybb->request_method == "post") -{ - $plugins->run_hooks("admin_tools_mailerrors_prune"); - - if($mybb->input['delete_all']) - { - $db->delete_query("mailerrors"); - $num_deleted = $db->affected_rows(); - - $plugins->run_hooks("admin_tools_mailerrors_prune_delete_all_commit"); - - // Log admin action - log_admin_action($num_deleted); - - flash_message($lang->all_logs_deleted, 'success'); - admin_redirect("index.php?module=tools-mailerrors"); - } - else if(is_array($mybb->input['log'])) - { - $log_ids = implode(",", array_map("intval", $mybb->input['log'])); - if($log_ids) - { - $db->delete_query("mailerrors", "eid IN ({$log_ids})"); - $num_deleted = $db->affected_rows(); - } - - // Log admin action - log_admin_action($num_deleted); - } - - $plugins->run_hooks("admin_tools_mailerrors_prune_commit"); - - flash_message($lang->selected_logs_deleted, 'success'); - admin_redirect("index.php?module=tools-mailerrors"); -} - -if($mybb->input['action'] == "view") -{ - $query = $db->simple_select("mailerrors", "*", "eid='".$mybb->get_input('eid', MyBB::INPUT_INT)."'"); - $log = $db->fetch_array($query); - - if(!$log['eid']) - { - exit; - } - - $plugins->run_hooks("admin_tools_mailerrors_view"); - - $log['toaddress'] = htmlspecialchars_uni($log['toaddress']); - $log['fromaddress'] = htmlspecialchars_uni($log['fromaddress']); - $log['subject'] = htmlspecialchars_uni($log['subject']); - $log['error'] = htmlspecialchars_uni($log['error']); - $log['smtperror'] = htmlspecialchars_uni($log['smtpcode']); - $log['dateline'] = date($mybb->settings['dateformat'], $log['dateline']).", ".date($mybb->settings['timeformat'], $log['dateline']); - $log['message'] = nl2br(htmlspecialchars_uni($log['message'])); - - ?> - - - input['action']) -{ - $per_page = 20; - - if($mybb->input['page'] && $mybb->input['page'] > 1) - { - $mybb->input['page'] = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($mybb->input['page']*$per_page)-$per_page; - } - else - { - $mybb->input['page'] = 1; - $start = 0; - } - - $additional_criteria = array(); - - $plugins->run_hooks("admin_tools_mailerrors_start"); - - $page->output_header($lang->system_email_log); - - $sub_tabs['mailerrors'] = array( - 'title' => $lang->system_email_log, - 'link' => "index.php?module=tools-mailerrors", - 'description' => $lang->system_email_log_desc - ); - - $page->output_nav_tabs($sub_tabs, 'mailerrors'); - - $form = new Form("index.php?module=tools-mailerrors&action=prune", "post"); - - // Begin criteria filtering - if($mybb->input['subject']) - { - $additional_sql_criteria .= " AND subject LIKE '%".$db->escape_string_like($mybb->input['subject'])."%'"; - $additional_criteria[] = "subject=".htmlspecialchars_uni($mybb->input['subject']); - $form->generate_hidden_field("subject", $mybb->input['subject']); - } - - if($mybb->input['fromaddress']) - { - $additional_sql_criteria .= " AND fromaddress LIKE '%".$db->escape_string_like($mybb->input['fromaddress'])."%'"; - $additional_criteria[] = "fromaddress=".urlencode($mybb->input['fromaddress']); - $form->generate_hidden_field("fromaddress", $mybb->input['fromaddress']); - } - - if($mybb->input['toaddress']) - { - $additional_sql_criteria .= " AND toaddress LIKE '%".$db->escape_string_like($mybb->input['toaddress'])."%'"; - $additional_criteria[] = "toaddress=".urlencode($mybb->input['toaddress']); - $form->generate_hidden_field("toaddress", $mybb->input['toaddress']); - } - - if($mybb->input['error']) - { - $additional_sql_criteria .= " AND error LIKE '%".$db->escape_string_like($mybb->input['error'])."%'"; - $additional_criteria[] = "error=".urlencode($mybb->input['error']); - $form->generate_hidden_field("error", $mybb->input['error']); - } - - if($additional_criteria) - { - $additional_criteria = "&".implode("&", $additional_criteria); - } - else - { - $additional_criteria = ''; - } - - $table = new Table; - $table->construct_header($form->generate_check_box("allbox", 1, '', array('class' => 'checkall'))); - $table->construct_header($lang->subject); - $table->construct_header($lang->to, array("class" => "align_center", "width" => "20%")); - $table->construct_header($lang->error_message, array("class" => "align_center", "width" => "30%")); - $table->construct_header($lang->date_sent, array("class" => "align_center", "width" => "20%")); - - $query = $db->simple_select('mailerrors', '*', "1=1 $additional_sql_criteria", array('order_by' => 'dateline', 'order_dir' => 'DESC', 'limit_start' => $start, 'limit' => $per_page)); - - while($log = $db->fetch_array($query)) - { - $log['subject'] = htmlspecialchars_uni($log['subject']); - $log['toemail'] = htmlspecialchars_uni($log['toemail']); - $log['error'] = htmlspecialchars_uni($log['error']); - $log['dateline'] = date($mybb->settings['dateformat'], $log['dateline']).", ".date($mybb->settings['timeformat'], $log['dateline']); - - $table->construct_cell($form->generate_check_box("log[{$log['eid']}]", $log['eid'], '')); - $table->construct_cell("{$log['subject']}"); - $find_from = ""; - $table->construct_cell("{$find_from}
{$log['toaddress']}
"); - $table->construct_cell($log['error']); - $table->construct_cell($log['dateline'], array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_logs, array("colspan" => 5)); - $table->construct_row(); - $table->output($lang->system_email_log); - } - else - { - $table->output($lang->system_email_log); - $buttons[] = $form->generate_submit_button($lang->delete_selected, array('onclick' => "return confirm('{$lang->confirm_delete_logs}');")); - $buttons[] = $form->generate_submit_button($lang->delete_all, array('name' => 'delete_all', 'onclick' => "return confirm('{$lang->confirm_delete_all_logs}');")); - $form->output_submit_wrapper($buttons); - } - - $form->end(); - - $query = $db->simple_select("mailerrors l", "COUNT(eid) AS logs", "1=1 {$additional_sql_criteria}"); - $total_rows = $db->fetch_field($query, "logs"); - - echo "
".draw_admin_pagination($mybb->input['page'], $per_page, $total_rows, "index.php?module=tools-mailerrors&page={page}{$additional_criteria}"); - - $form = new Form("index.php?module=tools-mailerrors", "post"); - $form_container = new FormContainer($lang->filter_system_email_log); - $form_container->output_row($lang->subject_contains, "", $form->generate_text_box('subject', $mybb->input['subject'], array('id' => 'subject')), 'subject'); - $form_container->output_row($lang->error_message_contains, "", $form->generate_text_box('error', $mybb->input['error'], array('id' => 'error')), 'error'); - $form_container->output_row($lang->to_address_contains, "", $form->generate_text_box('toaddress', $mybb->input['toaddress'], array('id' => 'toaddress')), 'toaddress'); - $form_container->output_row($lang->from_address_contains, "", $form->generate_text_box('fromaddress', $mybb->input['fromaddress'], array('id' => 'fromaddress')), 'fromaddress'); - - $form_container->end(); - $buttons = array(); - $buttons[] = $form->generate_submit_button($lang->filter_system_email_log); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/tools/maillogs.php b/html/forums/admin/modules/tools/maillogs.php deleted file mode 100644 index be8f4f9..0000000 --- a/html/forums/admin/modules/tools/maillogs.php +++ /dev/null @@ -1,450 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->user_email_log, "index.php?module=tools-maillogs"); - -$plugins->run_hooks("admin_tools_maillogs_begin"); - -if($mybb->input['action'] == "prune" && $mybb->request_method == "post") -{ - $plugins->run_hooks("admin_tools_maillogs_prune"); - - if($mybb->input['delete_all']) - { - $db->delete_query("maillogs"); - $num_deleted = $db->affected_rows(); - - $plugins->run_hooks("admin_tools_maillogs_prune_delete_all_commit"); - - // Log admin action - log_admin_action($num_deleted); - - flash_message($lang->all_logs_deleted, 'success'); - admin_redirect("index.php?module=tools-maillogs"); - } - else if(is_array($mybb->input['log'])) - { - $log_ids = implode(",", array_map("intval", $mybb->input['log'])); - if($log_ids) - { - $db->delete_query("maillogs", "mid IN ({$log_ids})"); - $num_deleted = $db->affected_rows(); - } - - // Log admin action - log_admin_action($num_deleted); - } - - $plugins->run_hooks("admin_tools_maillogs_prune_commit"); - - flash_message($lang->selected_logs_deleted, 'success'); - admin_redirect("index.php?module=tools-maillogs"); -} - -if($mybb->input['action'] == "view") -{ - $query = $db->simple_select("maillogs", "*", "mid='".$mybb->get_input('mid', MyBB::INPUT_INT)."'"); - $log = $db->fetch_array($query); - - if(!$log['mid']) - { - exit; - } - - $plugins->run_hooks("admin_tools_maillogs_view"); - - $log['toemail'] = htmlspecialchars_uni($log['toemail']); - $log['fromemail'] = htmlspecialchars_uni($log['fromemail']); - $log['subject'] = htmlspecialchars_uni($log['subject']); - $log['dateline'] = date($mybb->settings['dateformat'], $log['dateline']).", ".date($mybb->settings['timeformat'], $log['dateline']); - if($mybb->settings['mail_logging'] == 1) - { - $log['message'] = $lang->na; - } - else - { - $log['message'] = nl2br(htmlspecialchars_uni($log['message'])); - } - - ?> - - input['action']) -{ - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - $per_page = $mybb->settings['threadsperpage']; - - if(!$per_page) - { - $per_page = 20; - } - - if($mybb->input['page'] && $mybb->input['page'] > 1) - { - $mybb->input['page'] = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($mybb->input['page']*$per_page)-$per_page; - } - else - { - $mybb->input['page'] = 1; - $start = 0; - } - - $additional_criteria = array(); - - $plugins->run_hooks("admin_tools_maillogs_start"); - - // Filter form was submitted - play around with the values - if($mybb->request_method == "post") - { - if($mybb->input['from_type'] == "user") - { - $mybb->input['fromname'] = $mybb->input['from_value']; - } - else if($mybb->input['from_type'] == "email") - { - $mybb->input['fromemail'] = $mybb->input['from_value']; - } - - if($mybb->input['to_type'] == "user") - { - $mybb->input['toname'] = $mybb->input['to_value']; - } - else if($mybb->input['to_type'] == "email") - { - $mybb->input['toemail'] = $mybb->input['to_value']; - } - } - - $touid = $mybb->get_input('touid', MyBB::INPUT_INT); - $toname = $db->escape_string($mybb->input['toname']); - $toemail = $db->escape_string_like($mybb->input['toemail']); - - $fromuid = $mybb->get_input('fromuid', MyBB::INPUT_INT); - $fromemail = $db->escape_string_like($mybb->input['fromemail']); - - $subject = $db->escape_string_like($mybb->input['subject']); - - // Begin criteria filtering - if($mybb->input['subject']) - { - $additional_sql_criteria .= " AND l.subject LIKE '%{$subject}%'"; - $additional_criteria[] = "subject=".urlencode($mybb->input['subject']); - } - - if($mybb->input['fromuid']) - { - $query = $db->simple_select("users", "uid, username", "uid = '{$fromuid}'"); - $user = $db->fetch_array($query); - $from_filter = $user['username']; - - $additional_sql_criteria .= " AND l.fromuid = '{$fromuid}'"; - $additional_criteria[] = "fromuid={$fromuid}"; - } - else if($mybb->input['fromname']) - { - $user = get_user_by_username($mybb->input['fromname'], array('fields' => 'uid, username')); - $from_filter = $user['username']; - - if(!$user['uid']) - { - flash_message($lang->error_invalid_user, 'error'); - admin_redirect("index.php?module=tools-maillogs"); - } - - $additional_sql_criteria .= "AND l.fromuid = '{$user['uid']}'"; - $additional_criteria[] = "fromuid={$user['uid']}"; - } - - if($mybb->input['fromemail']) - { - $additional_sql_criteria .= " AND l.fromemail LIKE '%{$fromemail}%'"; - $additional_criteria[] = "fromemail=".urlencode($mybb->input['fromemail']); - $from_filter = $mybb->input['fromemail']; - } - - if($mybb->input['touid']) - { - $query = $db->simple_select("users", "uid, username", "uid = '{$touid}'"); - $user = $db->fetch_array($query); - $to_filter = $user['username']; - - $additional_sql_criteria .= " AND l.touid = '{$touid}'"; - $additional_criteria[] = "touid={$touid}"; - } - else if($mybb->input['toname']) - { - $user = get_user_by_username($toname, array('fields' => 'username')); - $to_filter = $user['username']; - - if(!$user['uid']) - { - flash_message($lang->error_invalid_user, 'error'); - admin_redirect("index.php?module=tools-maillogs"); - } - - $additional_sql_criteria .= "AND l.touid='{$user['uid']}'"; - $additional_criteria[] = "touid={$user['uid']}"; - } - - if($mybb->input['toemail']) - { - $additional_sql_criteria .= " AND l.toemail LIKE '%{$toemail}%'"; - $additional_criteria[] = "toemail=".urlencode($mybb->input['toemail']); - $to_filter = $mybb->input['toemail']; - } - - if(!empty($additional_criteria)) - { - $additional_criteria = "&".implode("&", $additional_criteria); - } - else - { - $additional_criteria = ''; - } - - $page->output_header($lang->user_email_log); - - $sub_tabs['maillogs'] = array( - 'title' => $lang->user_email_log, - 'link' => "index.php?module=tools-maillogs", - 'description' => $lang->user_email_log_desc - ); - - $page->output_nav_tabs($sub_tabs, 'maillogs'); - - $form = new Form("index.php?module=tools-maillogs&action=prune", "post"); - - $table = new Table; - $table->construct_header($form->generate_check_box("allbox", 1, '', array('class' => 'checkall'))); - $table->construct_header($lang->subject, array("colspan" => 2)); - $table->construct_header($lang->from, array("class" => "align_center", "width" => "20%")); - $table->construct_header($lang->to, array("class" => "align_center", "width" => "20%")); - $table->construct_header($lang->date_sent, array("class" => "align_center", "width" => "20%")); - $table->construct_header($lang->ip_address, array("class" => "align_center", 'width' => '10%')); - - $query = $db->query(" - SELECT l.*, r.username AS to_username, f.username AS from_username, t.subject AS thread_subject - FROM ".TABLE_PREFIX."maillogs l - LEFT JOIN ".TABLE_PREFIX."users r ON (r.uid=l.touid) - LEFT JOIN ".TABLE_PREFIX."users f ON (f.uid=l.fromuid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=l.tid) - WHERE 1=1 {$additional_sql_criteria} - ORDER BY l.dateline DESC - LIMIT {$start}, {$per_page} - "); - while($log = $db->fetch_array($query)) - { - $table->construct_cell($form->generate_check_box("log[{$log['mid']}]", $log['mid'], ''), array("width" => 1)); - $log['subject'] = htmlspecialchars_uni($log['subject']); - $log['dateline'] = date($mybb->settings['dateformat'], $log['dateline']).", ".date($mybb->settings['timeformat'], $log['dateline']); - - if($log['type'] == 2) - { - if($log['thread_subject']) - { - $log['thread_subject'] = htmlspecialchars_uni($log['thread_subject']); - $thread_link = "".$log['thread_subject'].""; - } - else - { - $thread_link = $lang->deleted; - } - $table->construct_cell("style}/images/icons/maillogs_thread.png\" title=\"{$lang->sent_using_send_thread_feature}\" alt=\"\" />", array("width" => 1)); - $table->construct_cell("{$log['subject']}
{$lang->thread} {$thread_link}"); - - if($log['fromuid'] > 0) - { - $find_from = ""; - } - - if(!$log['from_username'] && $log['fromuid'] > 0) - { - $table->construct_cell("{$find_from}
{$lang->deleted_user}
"); - } - elseif($log['fromuid'] == 0) - { - $log['fromemail'] = htmlspecialchars_uni($log['fromemail']); - $table->construct_cell("{$find_from}
{$log['fromemail']}
"); - } - else - { - $table->construct_cell("{$find_from}"); - } - - $log['toemail'] = htmlspecialchars_uni($log['toemail']); - $table->construct_cell($log['toemail']); - } - elseif($log['type'] == 1) - { - $table->construct_cell("style}/images/icons/maillogs_user.png\" title=\"{$lang->email_sent_to_user}\" alt=\"\" />", array("width" => 1)); - $table->construct_cell("{$log['subject']}"); - - if($log['fromuid'] > 0) - { - $find_from = ""; - } - - if(!$log['from_username'] && $log['fromuid'] > 0) - { - $table->construct_cell("{$find_from}
{$lang->deleted_user}
"); - } - elseif($log['fromuid'] == 0) - { - $log['fromemail'] = htmlspecialchars_uni($log['fromemail']); - $table->construct_cell("{$find_from}
{$log['fromemail']}
"); - } - else - { - $table->construct_cell("{$find_from}"); - } - - $find_to = ""; - if(!$log['to_username']) - { - $table->construct_cell("{$find_to}
{$lang->deleted_user}
"); - } - else - { - $table->construct_cell("{$find_to}"); - } - } - elseif($log['type'] == 3) - { - $table->construct_cell("style}/images/icons/maillogs_contact.png\" title=\"{$lang->email_sent_using_contact_form}\" alt=\"\" />", array("width" => 1)); - $table->construct_cell("{$log['subject']}"); - - if($log['fromuid'] > 0) - { - $find_from = ""; - } - - if(!$log['from_username'] && $log['fromuid'] > 0) - { - $table->construct_cell("{$find_from}
{$lang->deleted_user}
"); - } - elseif($log['fromuid'] == 0) - { - $log['fromemail'] = htmlspecialchars_uni($log['fromemail']); - $table->construct_cell("{$find_from}
{$log['fromemail']}
"); - } - else - { - $table->construct_cell("{$find_from}"); - } - - $log['toemail'] = htmlspecialchars_uni($log['toemail']); - $table->construct_cell($log['toemail']); - } - - $table->construct_cell($log['dateline'], array("class" => "align_center")); - $table->construct_cell(my_inet_ntop($db->unescape_binary($log['ipaddress'])), array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_logs, array("colspan" => "7")); - $table->construct_row(); - $table->output($lang->user_email_log); - } - else - { - $table->output($lang->user_email_log); - $buttons[] = $form->generate_submit_button($lang->delete_selected, array('onclick' => "return confirm('{$lang->confirm_delete_logs}');")); - $buttons[] = $form->generate_submit_button($lang->delete_all, array('name' => 'delete_all', 'onclick' => "return confirm('{$lang->confirm_delete_all_logs}');")); - $form->output_submit_wrapper($buttons); - } - - $form->end(); - - $query = $db->simple_select("maillogs l", "COUNT(l.mid) as logs", "1=1 {$additional_sql_criteria}"); - $total_rows = $db->fetch_field($query, "logs"); - - echo "
".draw_admin_pagination($mybb->input['page'], $per_page, $total_rows, "index.php?module=tools-maillogs&page={page}{$additional_criteria}"); - - $form = new Form("index.php?module=tools-maillogs", "post"); - $form_container = new FormContainer($lang->filter_user_email_log); - $user_email = array( - "user" => $lang->username_is, - "email" => $lang->email_contains - ); - $form_container->output_row($lang->subject_contains, "", $form->generate_text_box('subject', $mybb->input['subject'], array('id' => 'subject')), 'subject'); - if($from_username) - { - $from_type = "user"; - } - else if($mybb->input['fromemail']) - { - $from_type = "email"; - } - $form_container->output_row($lang->from, "", $form->generate_select_box('from_type', $user_email, $from_type)." ".$form->generate_text_box('from_value', htmlspecialchars_uni($from_filter), array('id' => 'from_value')), 'from_value'); - if($to_username) - { - $to_type = "user"; - } - else if($mybb->input['toemail']) - { - $to_type = "email"; - } - $form_container->output_row($lang->to, "", $form->generate_select_box('to_type', $user_email, $to_type)." ".$form->generate_text_box('to_value', htmlspecialchars_uni($to_filter), array('id' => 'to_value')), 'to_value'); - $form_container->end(); - $buttons = array(); - $buttons[] = $form->generate_submit_button($lang->filter_user_email_log); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/tools/modlog.php b/html/forums/admin/modules/tools/modlog.php deleted file mode 100644 index 096fbcb..0000000 --- a/html/forums/admin/modules/tools/modlog.php +++ /dev/null @@ -1,341 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->mod_logs, "index.php?module=tools-modlog"); - -$sub_tabs['mod_logs'] = array( - 'title' => $lang->mod_logs, - 'link' => "index.php?module=tools-modlog", - 'description' => $lang->mod_logs_desc -); -$sub_tabs['prune_mod_logs'] = array( - 'title' => $lang->prune_mod_logs, - 'link' => "index.php?module=tools-modlog&action=prune", - 'description' => $lang->prune_mod_logs_desc -); - -$plugins->run_hooks("admin_tools_modlog_begin"); - -if($mybb->input['action'] == 'prune') -{ - $plugins->run_hooks("admin_tools_modlog_prune"); - - if($mybb->request_method == 'post') - { - $is_today = false; - $mybb->input['older_than'] = $mybb->get_input('older_than', MyBB::INPUT_INT); - if($mybb->input['older_than'] <= 0) - { - $is_today = true; - $mybb->input['older_than'] = 1; - } - $where = 'dateline < '.(TIME_NOW-($mybb->input['older_than']*86400)); - - // Searching for entries by a particular user - if($mybb->input['uid']) - { - $where .= " AND uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"; - } - - // Searching for entries in a specific module - if($mybb->input['fid'] > 0) - { - $where .= " AND fid='".$db->escape_string($mybb->input['fid'])."'"; - } - else - { - $mybb->input['fid'] = 0; - } - - $db->delete_query("moderatorlog", $where); - $num_deleted = $db->affected_rows(); - - $plugins->run_hooks("admin_tools_modlog_prune_commit"); - - if(!is_array($forum_cache)) - { - $forum_cache = cache_forums(); - } - - // Log admin action - log_admin_action($mybb->input['older_than'], $mybb->input['uid'], $mybb->input['fid'], $num_deleted, $forum_cache[$mybb->input['fid']]['name']); - - $success = $lang->success_pruned_mod_logs; - if($is_today == true && $num_deleted > 0) - { - $success .= ' '.$lang->note_logs_locked; - } - elseif($is_today == true && $num_deleted == 0) - { - flash_message($lang->note_logs_locked, 'error'); - admin_redirect("index.php?module=tools-modlog"); - } - flash_message($success, 'success'); - admin_redirect("index.php?module=tools-modlog"); - } - $page->add_breadcrumb_item($lang->prune_mod_logs, "index.php?module=tools-modlog&action=prune"); - $page->output_header($lang->prune_mod_logs); - $page->output_nav_tabs($sub_tabs, 'prune_mod_logs'); - - // Fetch filter options - $sortbysel[$mybb->input['sortby']] = 'selected="selected"'; - $ordersel[$mybb->input['order']] = 'selected="selected"'; - - $user_options[''] = $lang->all_moderators; - $user_options['0'] = '----------'; - - $query = $db->query(" - SELECT DISTINCT l.uid, u.username - FROM ".TABLE_PREFIX."moderatorlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (l.uid=u.uid) - ORDER BY u.username ASC - "); - while($user = $db->fetch_array($query)) - { - $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); - } - - $form = new Form("index.php?module=tools-modlog&action=prune", "post"); - $form_container = new FormContainer($lang->prune_moderator_logs); - $form_container->output_row($lang->forum, "", $form->generate_forum_select('fid', $mybb->input['fid'], array('id' => 'fid', 'main_option' => $lang->all_forums)), 'fid'); - $form_container->output_row($lang->forum_moderator, "", $form->generate_select_box('uid', $user_options, $mybb->input['uid'], array('id' => 'uid')), 'uid'); - if(!$mybb->input['older_than']) - { - $mybb->input['older_than'] = '30'; - } - $form_container->output_row($lang->date_range, "", $lang->older_than.$form->generate_numeric_field('older_than', $mybb->input['older_than'], array('id' => 'older_than', 'style' => 'width: 50px', 'min' => 0)).' '.$lang->days, 'older_than'); - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->prune_moderator_logs); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_tools_modlog_start"); - - $page->output_header($lang->mod_logs); - - $page->output_nav_tabs($sub_tabs, 'mod_logs'); - - $perpage = $mybb->get_input('perpage', MyBB::INPUT_INT); - if(!$perpage) - { - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - $perpage = $mybb->settings['threadsperpage']; - } - - $where = 'WHERE 1=1'; - - // Searching for entries by a particular user - if($mybb->input['uid']) - { - $where .= " AND l.uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"; - } - - // Searching for entries in a specific forum - if($mybb->input['fid'] > 0) - { - $where .= " AND l.fid='".$mybb->get_input('fid', MyBB::INPUT_INT)."'"; - } - - // Order? - switch($mybb->input['sortby']) - { - case "username": - $sortby = "u.username"; - break; - case "forum": - $sortby = "f.name"; - break; - case "thread": - $sortby = "t.subject"; - break; - default: - $sortby = "l.dateline"; - } - $order = $mybb->input['order']; - if($order != "asc") - { - $order = "desc"; - } - - $query = $db->query(" - SELECT COUNT(l.dateline) AS count - FROM ".TABLE_PREFIX."moderatorlog l - {$where} - "); - $rescount = $db->fetch_field($query, "count"); - - // Figure out if we need to display multiple pages. - if($mybb->input['page'] != "last") - { - $pagecnt = $mybb->get_input('page', MyBB::INPUT_INT); - } - - $postcount = (int)$rescount; - $pages = $postcount / $perpage; - $pages = ceil($pages); - - if($mybb->input['page'] == "last") - { - $pagecnt = $pages; - } - - if($pagecnt > $pages) - { - $pagecnt = 1; - } - - if($pagecnt) - { - $start = ($pagecnt-1) * $perpage; - } - else - { - $start = 0; - $pagecnt = 1; - } - - $table = new Table; - $table->construct_header($lang->username, array('width' => '10%')); - $table->construct_header($lang->date, array("class" => "align_center", 'width' => '15%')); - $table->construct_header($lang->action, array("class" => "align_center", 'width' => '35%')); - $table->construct_header($lang->information, array("class" => "align_center", 'width' => '30%')); - $table->construct_header($lang->ipaddress, array("class" => "align_center", 'width' => '10%')); - - $query = $db->query(" - SELECT l.*, u.username, u.usergroup, u.displaygroup, t.subject AS tsubject, f.name AS fname, p.subject AS psubject - FROM ".TABLE_PREFIX."moderatorlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=l.uid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=l.tid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=l.fid) - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=l.pid) - {$where} - ORDER BY {$sortby} {$order} - LIMIT {$start}, {$perpage} - "); - while($logitem = $db->fetch_array($query)) - { - $information = ''; - $logitem['action'] = htmlspecialchars_uni($logitem['action']); - $logitem['dateline'] = my_date('relative', $logitem['dateline']); - $trow = alt_trow(); - $username = format_name(htmlspecialchars_uni($logitem['username']), $logitem['usergroup'], $logitem['displaygroup']); - $logitem['profilelink'] = build_profile_link($username, $logitem['uid'], "_blank"); - if($logitem['tsubject']) - { - $information = "{$lang->thread} ".htmlspecialchars_uni($logitem['tsubject'])."
"; - } - if($logitem['fname']) - { - $information .= "{$lang->forum} ".htmlspecialchars_uni($logitem['fname'])."
"; - } - if($logitem['psubject']) - { - $information .= "{$lang->post} ".htmlspecialchars_uni($logitem['psubject']).""; - } - - if(!$logitem['tsubject'] || !$logitem['fname'] || !$logitem['psubject']) - { - $data = my_unserialize($logitem['data']); - if($data['uid']) - { - $information = "{$lang->user_info} ".htmlspecialchars_uni($data['username']).""; - } - if($data['aid']) - { - $information = "{$lang->announcement} ".htmlspecialchars_uni($data['subject']).""; - } - } - - $table->construct_cell($logitem['profilelink']); - $table->construct_cell($logitem['dateline'], array("class" => "align_center")); - $table->construct_cell($logitem['action'], array("class" => "align_center")); - $table->construct_cell($information); - $table->construct_cell(my_inet_ntop($db->unescape_binary($logitem['ipaddress'])), array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_modlogs, array("colspan" => "5")); - $table->construct_row(); - } - - $table->output($lang->mod_logs); - - // Do we need to construct the pagination? - if($rescount > $perpage) - { - echo draw_admin_pagination($pagecnt, $perpage, $rescount, "index.php?module=tools-modlog&perpage=$perpage&uid={$mybb->input['uid']}&fid={$mybb->input['fid']}&sortby={$mybb->input['sortby']}&order={$order}")."
"; - } - - // Fetch filter options - $sortbysel[$mybb->input['sortby']] = "selected=\"selected\""; - $ordersel[$mybb->input['order']] = "selected=\"selected\""; - - $user_options[''] = $lang->all_moderators; - $user_options['0'] = '----------'; - - $query = $db->query(" - SELECT DISTINCT l.uid, u.username - FROM ".TABLE_PREFIX."moderatorlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (l.uid=u.uid) - ORDER BY u.username ASC - "); - while($user = $db->fetch_array($query)) - { - $selected = ''; - if($mybb->input['uid'] == $user['uid']) - { - $selected = "selected=\"selected\""; - } - $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); - } - - $sort_by = array( - 'dateline' => $lang->date, - 'username' => $lang->username, - 'forum' => $lang->forum_name, - 'thread' => $lang->thread_subject - ); - - $order_array = array( - 'asc' => $lang->asc, - 'desc' => $lang->desc - ); - - $form = new Form("index.php?module=tools-modlog", "post"); - $form_container = new FormContainer($lang->filter_moderator_logs); - $form_container->output_row($lang->forum, "", $form->generate_forum_select('fid', $mybb->input['fid'], array('id' => 'fid', 'main_option' => $lang->all_forums)), 'fid'); - $form_container->output_row($lang->forum_moderator, "", $form->generate_select_box('uid', $user_options, $mybb->input['uid'], array('id' => 'uid')), 'uid'); - $form_container->output_row($lang->sort_by, "", $form->generate_select_box('sortby', $sort_by, $mybb->input['sortby'], array('id' => 'sortby'))." {$lang->in} ".$form->generate_select_box('order', $order_array, $order, array('id' => 'order'))." {$lang->order}", 'order'); - $form_container->output_row($lang->results_per_page, "", $form->generate_numeric_field('perpage', $perpage, array('id' => 'perpage', 'min' => 1)), 'perpage'); - - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->filter_moderator_logs); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/tools/module_meta.php b/html/forums/admin/modules/tools/module_meta.php deleted file mode 100644 index 11e2455..0000000 --- a/html/forums/admin/modules/tools/module_meta.php +++ /dev/null @@ -1,133 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -/** - * @return bool true - */ -function tools_meta() -{ - global $page, $lang, $plugins; - - $sub_menu = array(); - $sub_menu['10'] = array("id" => "system_health", "title" => $lang->system_health, "link" => "index.php?module=tools-system_health"); - $sub_menu['20'] = array("id" => "cache", "title" => $lang->cache_manager, "link" => "index.php?module=tools-cache"); - $sub_menu['30'] = array("id" => "tasks", "title" => $lang->task_manager, "link" => "index.php?module=tools-tasks"); - $sub_menu['40'] = array("id" => "recount_rebuild", "title" => $lang->recount_and_rebuild, "link" => "index.php?module=tools-recount_rebuild"); - $sub_menu['50'] = array("id" => "php_info", "title" => $lang->view_php_info, "link" => "index.php?module=tools-php_info"); - $sub_menu['60'] = array("id" => "backupdb", "title" => $lang->database_backups, "link" => "index.php?module=tools-backupdb"); - $sub_menu['70'] = array("id" => "optimizedb", "title" => $lang->optimize_database, "link" => "index.php?module=tools-optimizedb"); - $sub_menu['80'] = array("id" => "file_verification", "title" => $lang->file_verification, "link" => "index.php?module=tools-file_verification"); - - $sub_menu = $plugins->run_hooks("admin_tools_menu", $sub_menu); - - $page->add_menu_item($lang->tools_and_maintenance, "tools", "index.php?module=tools", 50, $sub_menu); - - return true; -} - -/** - * @param string $action - * - * @return string - */ -function tools_action_handler($action) -{ - global $page, $lang, $plugins; - - $page->active_module = "tools"; - - $actions = array( - 'php_info' => array('active' => 'php_info', 'file' => 'php_info.php'), - 'tasks' => array('active' => 'tasks', 'file' => 'tasks.php'), - 'backupdb' => array('active' => 'backupdb', 'file' => 'backupdb.php'), - 'optimizedb' => array('active' => 'optimizedb', 'file' => 'optimizedb.php'), - 'cache' => array('active' => 'cache', 'file' => 'cache.php'), - 'recount_rebuild' => array('active' => 'recount_rebuild', 'file' => 'recount_rebuild.php'), - 'maillogs' => array('active' => 'maillogs', 'file' => 'maillogs.php'), - 'mailerrors' => array('active' => 'mailerrors', 'file' => 'mailerrors.php'), - 'adminlog' => array('active' => 'adminlog', 'file' => 'adminlog.php'), - 'modlog' => array('active' => 'modlog', 'file' => 'modlog.php'), - 'warninglog' => array('active' => 'warninglog', 'file' => 'warninglog.php'), - 'spamlog' => array('active' => 'spamlog', 'file' => 'spamlog.php'), - 'system_health' => array('active' => 'system_health', 'file' => 'system_health.php'), - 'file_verification' => array('active' => 'file_verification', 'file' => 'file_verification.php'), - 'statistics' => array('active' => 'statistics', 'file' => 'statistics.php'), - ); - - $actions = $plugins->run_hooks("admin_tools_action_handler", $actions); - - $sub_menu = array(); - $sub_menu['10'] = array("id" => "adminlog", "title" => $lang->administrator_log, "link" => "index.php?module=tools-adminlog"); - $sub_menu['20'] = array("id" => "modlog", "title" => $lang->moderator_log, "link" => "index.php?module=tools-modlog"); - $sub_menu['30'] = array("id" => "maillogs", "title" => $lang->user_email_log, "link" => "index.php?module=tools-maillogs"); - $sub_menu['40'] = array("id" => "mailerrors", "title" => $lang->system_mail_log, "link" => "index.php?module=tools-mailerrors"); - $sub_menu['50'] = array("id" => "warninglog", "title" => $lang->user_warning_log, "link" => "index.php?module=tools-warninglog"); - $sub_menu['60'] = array("id" => "spamlog", "title" => $lang->spam_log, "link" => "index.php?module=tools-spamlog"); - $sub_menu['70'] = array("id" => "statistics", "title" => $lang->statistics, "link" => "index.php?module=tools-statistics"); - - $sub_menu = $plugins->run_hooks("admin_tools_menu_logs", $sub_menu); - - if(!isset($actions[$action])) - { - $page->active_action = "system_health"; - } - - $sidebar = new SidebarItem($lang->logs); - $sidebar->add_menu_items($sub_menu, $actions[$action]['active']); - - $page->sidebar .= $sidebar->get_markup(); - - if(isset($actions[$action])) - { - $page->active_action = $actions[$action]['active']; - return $actions[$action]['file']; - } - else - { - return "system_health.php"; - } -} - -/** - * @return array - */ -function tools_admin_permissions() -{ - global $lang, $plugins; - - $admin_permissions = array( - "system_health" => $lang->can_access_system_health, - "cache" => $lang->can_manage_cache, - "tasks" => $lang->can_manage_tasks, - "backupdb" => $lang->can_manage_db_backup, - "optimizedb" => $lang->can_optimize_db, - "recount_rebuild" => $lang->can_recount_and_rebuild, - "adminlog" => $lang->can_manage_admin_logs, - "modlog" => $lang->can_manage_mod_logs, - "maillogs" => $lang->can_manage_user_mail_log, - "mailerrors" => $lang->can_manage_system_mail_log, - "warninglog" => $lang->can_manage_user_warning_log, - "spamlog" => $lang->can_manage_spam_log, - "php_info" => $lang->can_view_php_info, - "file_verification" => $lang->can_manage_file_verification, - "statistics" => $lang->can_view_statistics, - ); - - $admin_permissions = $plugins->run_hooks("admin_tools_permissions", $admin_permissions); - - return array("name" => $lang->tools_and_maintenance, "permissions" => $admin_permissions, "disporder" => 50); -} - diff --git a/html/forums/admin/modules/tools/optimizedb.php b/html/forums/admin/modules/tools/optimizedb.php deleted file mode 100644 index b7c7c98..0000000 --- a/html/forums/admin/modules/tools/optimizedb.php +++ /dev/null @@ -1,112 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->optimize_database, "index.php?module=tools-optimizedb"); - -$plugins->run_hooks("admin_tools_optimizedb_begin"); - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_tools_optimizedb_start"); - - if($mybb->request_method == "post") - { - if(!is_array($mybb->input['tables'])) - { - flash_message($lang->error_no_tables_selected, 'error'); - admin_redirect("index.php?module=tools-optimizedb"); - } - - @set_time_limit(0); - - $db->set_table_prefix(''); - - foreach($mybb->input['tables'] as $table) - { - if($db->table_exists($db->escape_string($table))) - { - $db->optimize_table($table); - $db->analyze_table($table); - } - } - - $db->set_table_prefix(TABLE_PREFIX); - - $plugins->run_hooks("admin_tools_optimizedb_start_begin"); - - // Log admin action - log_admin_action(my_serialize($mybb->input['tables'])); - - flash_message($lang->success_tables_optimized, 'success'); - admin_redirect("index.php?module=tools-optimizedb"); - } - - $page->extra_header = " \n"; - - $page->output_header($lang->optimize_database); - - $table = new Table; - $table->construct_header($lang->table_selection); - - $table_selects = array(); - $table_list = $db->list_tables($config['database']['database']); - foreach($table_list as $id => $table_name) - { - $table_selects[$table_name] = $table_name; - } - - $form = new Form("index.php?module=tools-optimizedb", "post", "table_selection", 0, "table_selection"); - - $table->construct_cell("{$lang->tables_select_desc}\n

\n{$lang->select_all}
\n{$lang->deselect_all}
\n{$lang->select_forum_tables}\n

\n
".$form->generate_select_box("tables[]", $table_selects, false, array('multiple' => true, 'id' => 'table_select', 'size' => 20))."
", array('rowspan' => 5, 'width' => '50%')); - $table->construct_row(); - - $table->output($lang->optimize_database); - - $buttons[] = $form->generate_submit_button($lang->optimize_selected_tables); - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - diff --git a/html/forums/admin/modules/tools/php_info.php b/html/forums/admin/modules/tools/php_info.php deleted file mode 100644 index 48a8e61..0000000 --- a/html/forums/admin/modules/tools/php_info.php +++ /dev/null @@ -1,42 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -if($mybb->input['action'] == 'phpinfo') -{ - $plugins->run_hooks("admin_tools_php_info_phpinfo"); - - // Log admin action - log_admin_action(); - - phpinfo(); - exit; -} - -$page->add_breadcrumb_item($lang->php_info, "index.php?module=tools-php_info"); - -$plugins->run_hooks("admin_tools_php_info_begin"); - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_tools_php_info_start"); - - $page->output_header($lang->php_info); - - echo ""; - - $page->output_footer(); -} - diff --git a/html/forums/admin/modules/tools/recount_rebuild.php b/html/forums/admin/modules/tools/recount_rebuild.php deleted file mode 100644 index 56998db..0000000 --- a/html/forums/admin/modules/tools/recount_rebuild.php +++ /dev/null @@ -1,764 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->recount_rebuild, "index.php?module=tools-recount_rebuild"); - -$plugins->run_hooks("admin_tools_recount_rebuild"); - -/** - * Rebuild forum counters - */ -function acp_rebuild_forum_counters() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("forums", "COUNT(*) as num_forums"); - $num_forums = $db->fetch_field($query, 'num_forums'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('forumcounters', MyBB::INPUT_INT); - if($per_page <= 0) - { - $per_page = 50; - } - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - $query = $db->simple_select("forums", "fid", '', array('order_by' => 'fid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($forum = $db->fetch_array($query)) - { - $update['parentlist'] = make_parent_list($forum['fid']); - $db->update_query("forums", $update, "fid='{$forum['fid']}'"); - rebuild_forum_counters($forum['fid']); - } - - check_proceed($num_forums, $end, ++$page, $per_page, "forumcounters", "do_rebuildforumcounters", $lang->success_rebuilt_forum_counters); -} - -/** - * Rebuild thread counters - */ -function acp_rebuild_thread_counters() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("threads", "COUNT(*) as num_threads"); - $num_threads = $db->fetch_field($query, 'num_threads'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('threadcounters', MyBB::INPUT_INT); - if($per_page <= 0) - { - $per_page = 500; - } - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - $query = $db->simple_select("threads", "tid", '', array('order_by' => 'tid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($thread = $db->fetch_array($query)) - { - rebuild_thread_counters($thread['tid']); - } - - check_proceed($num_threads, $end, ++$page, $per_page, "threadcounters", "do_rebuildthreadcounters", $lang->success_rebuilt_thread_counters); -} - -/** - * Rebuild poll counters - */ -function acp_rebuild_poll_counters() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("polls", "COUNT(*) as num_polls"); - $num_polls = $db->fetch_field($query, 'num_polls'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('pollcounters', MyBB::INPUT_INT); - if($per_page <= 0) - { - $per_page = 500; - } - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - $query = $db->simple_select("polls", "pid", '', array('order_by' => 'pid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($poll = $db->fetch_array($query)) - { - rebuild_poll_counters($poll['pid']); - } - - check_proceed($num_polls, $end, ++$page, $per_page, "pollcounters", "do_rebuildpollcounters", $lang->success_rebuilt_poll_counters); -} - -/** - * Recount user posts - */ -function acp_recount_user_posts() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("users", "COUNT(uid) as num_users"); - $num_users = $db->fetch_field($query, 'num_users'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('userposts', MyBB::INPUT_INT); - if($per_page <= 0) - { - $per_page = 500; - } - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - $query = $db->simple_select("forums", "fid", "usepostcounts = 0"); - while($forum = $db->fetch_array($query)) - { - $fids[] = $forum['fid']; - } - if(is_array($fids)) - { - $fids = implode(',', $fids); - } - if($fids) - { - $fids = " AND p.fid NOT IN($fids)"; - } - else - { - $fids = ""; - } - - $query = $db->simple_select("users", "uid", '', array('order_by' => 'uid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($user = $db->fetch_array($query)) - { - $query2 = $db->query(" - SELECT COUNT(p.pid) AS post_count - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.uid='{$user['uid']}' AND t.visible > 0 AND p.visible > 0{$fids} - "); - $num_posts = $db->fetch_field($query2, "post_count"); - - $db->update_query("users", array("postnum" => (int)$num_posts), "uid='{$user['uid']}'"); - } - - check_proceed($num_users, $end, ++$page, $per_page, "userposts", "do_recountuserposts", $lang->success_rebuilt_user_post_counters); -} - -/** - * Recount user threads - */ -function acp_recount_user_threads() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("users", "COUNT(uid) as num_users"); - $num_users = $db->fetch_field($query, 'num_users'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('userthreads', MyBB::INPUT_INT); - if($per_page <= 0) - { - $per_page = 500; - } - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - $query = $db->simple_select("forums", "fid", "usethreadcounts = 0"); - while($forum = $db->fetch_array($query)) - { - $fids[] = $forum['fid']; - } - if(is_array($fids)) - { - $fids = implode(',', $fids); - } - if($fids) - { - $fids = " AND t.fid NOT IN($fids)"; - } - else - { - $fids = ""; - } - - $query = $db->simple_select("users", "uid", '', array('order_by' => 'uid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($user = $db->fetch_array($query)) - { - $query2 = $db->query(" - SELECT COUNT(t.tid) AS thread_count - FROM ".TABLE_PREFIX."threads t - WHERE t.uid='{$user['uid']}' AND t.visible > 0 AND t.closed NOT LIKE 'moved|%'{$fids} - "); - $num_threads = $db->fetch_field($query2, "thread_count"); - - $db->update_query("users", array("threadnum" => (int)$num_threads), "uid='{$user['uid']}'"); - } - - check_proceed($num_users, $end, ++$page, $per_page, "userthreads", "do_recountuserthreads", $lang->success_rebuilt_user_thread_counters); -} - -/** - * Recount reputation values - */ -function acp_recount_reputation() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("users", "COUNT(uid) as num_users"); - $num_users = $db->fetch_field($query, 'num_users'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('reputation', MyBB::INPUT_INT); - if($per_page <= 0) - { - $per_page = 500; - } - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - $query = $db->simple_select("users", "uid", '', array('order_by' => 'uid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($user = $db->fetch_array($query)) - { - $query2 = $db->query(" - SELECT SUM(reputation) as total_rep - FROM ".TABLE_PREFIX."reputation - WHERE `uid`='{$user['uid']}' - "); - $total_rep = $db->fetch_field($query2, "total_rep"); - - $db->update_query("users", array("reputation" => (int)$total_rep), "uid='{$user['uid']}'"); - } - - check_proceed($num_users, $end, ++$page, $per_page, "reputation", "do_recountreputation", $lang->success_rebuilt_reputation); -} - -/** - * Recount warnings for users - */ -function acp_recount_warning() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("users", "COUNT(uid) as num_users"); - $num_users = $db->fetch_field($query, 'num_users'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('warning', MyBB::INPUT_INT); - if($per_page <= 0) - { - $per_page = 500; - } - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - $query = $db->simple_select("users", "uid", '', array('order_by' => 'uid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($user = $db->fetch_array($query)) - { - $query2 = $db->query(" - SELECT SUM(points) as warn_lev - FROM ".TABLE_PREFIX."warnings - WHERE uid='{$user['uid']}' AND expired='0' - "); - $warn_lev = $db->fetch_field($query2, "warn_lev"); - - $db->update_query("users", array("warningpoints" => (int)$warn_lev), "uid='{$user['uid']}'"); - } - - check_proceed($num_users, $end, ++$page, $per_page, "warning", "do_recountwarning", $lang->success_rebuilt_warning); -} - -/** - * Recount private messages (total and unread) for users - */ -function acp_recount_private_messages() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("users", "COUNT(uid) as num_users"); - $num_users = $db->fetch_field($query, 'num_users'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('privatemessages', MyBB::INPUT_INT); - if($per_page <= 0) - { - $per_page = 500; - } - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - require_once MYBB_ROOT."inc/functions_user.php"; - - $query = $db->simple_select("users", "uid", '', array('order_by' => 'uid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($user = $db->fetch_array($query)) - { - update_pm_count($user['uid']); - } - - check_proceed($num_users, $end, ++$page, $per_page, "privatemessages", "do_recountprivatemessages", $lang->success_rebuilt_private_messages); -} - -/** - * Recount referrals for users - */ -function acp_recount_referrals() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("users", "COUNT(uid) as num_users"); - $num_users = $db->fetch_field($query, 'num_users'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('referral', MyBB::INPUT_INT); - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - $query = $db->simple_select("users", "uid", '', array('order_by' => 'uid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($user = $db->fetch_array($query)) - { - $query2 = $db->query(" - SELECT COUNT(uid) as num_referrers - FROM ".TABLE_PREFIX."users - WHERE referrer='{$user['uid']}' - "); - $num_referrers = $db->fetch_field($query2, "num_referrers"); - - $db->update_query("users", array("referrals" => (int)$num_referrers), "uid='{$user['uid']}'"); - } - - check_proceed($num_users, $end, ++$page, $per_page, "referral", "do_recountreferral", $lang->success_rebuilt_referral); -} - -/** - * Recount thread ratings - */ -function acp_recount_thread_ratings() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("threads", "COUNT(*) as num_threads"); - $num_threads = $db->fetch_field($query, 'num_threads'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('threadrating', MyBB::INPUT_INT); - if($per_page <= 0) - { - $per_page = 500; - } - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - $query = $db->simple_select("threads", "tid", '', array('order_by' => 'tid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($thread = $db->fetch_array($query)) - { - $query2 = $db->query(" - SELECT COUNT(tid) as num_ratings, SUM(rating) as total_rating - FROM ".TABLE_PREFIX."threadratings - WHERE tid='{$thread['tid']}' - "); - $recount = $db->fetch_array($query2); - - $db->update_query("threads", array("numratings" => (int)$recount['num_ratings'], "totalratings" => (int)$recount['total_rating']), "tid='{$thread['tid']}'"); - } - - check_proceed($num_threads, $end, ++$page, $per_page, "threadrating", "do_recountthreadrating", $lang->success_rebuilt_thread_ratings); -} - -/** - * Rebuild thumbnails for attachments - */ -function acp_rebuild_attachment_thumbnails() -{ - global $db, $mybb, $lang; - - $query = $db->simple_select("attachments", "COUNT(aid) as num_attachments"); - $num_attachments = $db->fetch_field($query, 'num_attachments'); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $per_page = $mybb->get_input('attachmentthumbs', MyBB::INPUT_INT); - if($per_page <= 0) - { - $per_page = 20; - } - $start = ($page-1) * $per_page; - $end = $start + $per_page; - - $uploadspath = $mybb->settings['uploadspath']; - if(my_substr($uploadspath, 0, 1) == '.') - { - $uploadspath = MYBB_ROOT . $mybb->settings['uploadspath']; - } - - require_once MYBB_ROOT."inc/functions_image.php"; - - $query = $db->simple_select("attachments", "*", '', array('order_by' => 'aid', 'order_dir' => 'asc', 'limit_start' => $start, 'limit' => $per_page)); - while($attachment = $db->fetch_array($query)) - { - $ext = my_strtolower(my_substr(strrchr($attachment['filename'], "."), 1)); - if($ext == "gif" || $ext == "png" || $ext == "jpg" || $ext == "jpeg" || $ext == "jpe") - { - $thumbname = str_replace(".attach", "_thumb.$ext", $attachment['attachname']); - $thumbnail = generate_thumbnail($uploadspath."/".$attachment['attachname'], $uploadspath, $thumbname, $mybb->settings['attachthumbh'], $mybb->settings['attachthumbw']); - if($thumbnail['code'] == 4) - { - $thumbnail['filename'] = "SMALL"; - } - $db->update_query("attachments", array("thumbnail" => $thumbnail['filename']), "aid='{$attachment['aid']}'"); - } - } - - check_proceed($num_attachments, $end, ++$page, $per_page, "attachmentthumbs", "do_rebuildattachmentthumbs", $lang->success_rebuilt_attachment_thumbnails); -} - -/** - * @param int $current - * @param int $finish - * @param int $next_page - * @param int $per_page - * @param string $name - * @param string $name2 - * @param string $message - */ -function check_proceed($current, $finish, $next_page, $per_page, $name, $name2, $message) -{ - global $page, $lang; - - if($finish >= $current) - { - flash_message($message, 'success'); - admin_redirect("index.php?module=tools-recount_rebuild"); - } - else - { - $page->output_header(); - - $form = new Form("index.php?module=tools-recount_rebuild", 'post'); - - echo $form->generate_hidden_field("page", $next_page); - echo $form->generate_hidden_field($name, $per_page); - echo $form->generate_hidden_field($name2, $lang->go); - echo "
\n"; - echo "

{$lang->confirm_proceed_rebuild}

\n"; - echo "
\n"; - echo ""; - echo "

\n"; - echo $form->generate_submit_button($lang->proceed, array('class' => 'button_yes', 'id' => 'proceed_button')); - echo "

\n"; - echo "
\n"; - - $form->end(); - - $page->output_footer(); - exit; - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_tools_recount_rebuild_start"); - - if($mybb->request_method == "post") - { - require_once MYBB_ROOT."inc/functions_rebuild.php"; - - if(!isset($mybb->input['page']) || $mybb->get_input('page', MyBB::INPUT_INT) < 1) - { - $mybb->input['page'] = 1; - } - - if(isset($mybb->input['do_rebuildforumcounters'])) - { - $plugins->run_hooks("admin_tools_recount_rebuild_forum_counters"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("forum"); - } - if(!$mybb->get_input('forumcounters', MyBB::INPUT_INT)) - { - $mybb->input['forumcounters'] = 50; - } - - acp_rebuild_forum_counters(); - } - elseif(isset($mybb->input['do_rebuildthreadcounters'])) - { - $plugins->run_hooks("admin_tools_recount_rebuild_thread_counters"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("thread"); - } - if(!$mybb->get_input('threadcounters', MyBB::INPUT_INT)) - { - $mybb->input['threadcounters'] = 500; - } - - acp_rebuild_thread_counters(); - } - elseif(isset($mybb->input['do_recountuserposts'])) - { - $plugins->run_hooks("admin_tools_recount_rebuild_user_posts"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("userposts"); - } - if(!$mybb->get_input('userposts', MyBB::INPUT_INT)) - { - $mybb->input['userposts'] = 500; - } - - acp_recount_user_posts(); - } - elseif(isset($mybb->input['do_recountuserthreads'])) - { - $plugins->run_hooks("admin_tools_recount_rebuild_user_threads"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("userthreads"); - } - if(!$mybb->get_input('userthreads', MyBB::INPUT_INT)) - { - $mybb->input['userthreads'] = 500; - } - - acp_recount_user_threads(); - } - elseif(isset($mybb->input['do_rebuildattachmentthumbs'])) - { - $plugins->run_hooks("admin_tools_recount_rebuild_attachment_thumbs"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("attachmentthumbs"); - } - - if(!$mybb->get_input('attachmentthumbs', MyBB::INPUT_INT)) - { - $mybb->input['attachmentthumbs'] = 500; - } - - acp_rebuild_attachment_thumbnails(); - } - elseif(isset($mybb->input['do_recountreputation'])) - { - $plugins->run_hooks("admin_tools_recount_recount_reputation"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("reputation"); - } - - if(!$mybb->get_input('reputation', MyBB::INPUT_INT)) - { - $mybb->input['reputation'] = 500; - } - - acp_recount_reputation(); - } - elseif(isset($mybb->input['do_recountwarning'])) - { - $plugins->run_hooks("admin_tools_recount_recount_warning"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("warning"); - } - - if(!$mybb->get_input('warning', MyBB::INPUT_INT)) - { - $mybb->input['warning'] = 500; - } - - acp_recount_warning(); - } - elseif(isset($mybb->input['do_recountprivatemessages'])) - { - $plugins->run_hooks("admin_tools_recount_recount_private_messages"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("privatemessages"); - } - - if(!$mybb->get_input('privatemessages', MyBB::INPUT_INT)) - { - $mybb->input['privatemessages'] = 500; - } - - acp_recount_private_messages(); - } - elseif(isset($mybb->input['do_recountreferral'])) - { - $plugins->run_hooks("admin_tools_recount_recount_referral"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("referral"); - } - - if(!$mybb->get_input('referral', MyBB::INPUT_INT)) - { - $mybb->input['referral'] = 500; - } - - acp_recount_referrals(); - } - elseif(isset($mybb->input['do_recountthreadrating'])) - { - $plugins->run_hooks("admin_tools_recount_recount_thread_ratings"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("threadrating"); - } - - if(!$mybb->get_input('threadrating', MyBB::INPUT_INT)) - { - $mybb->input['threadrating'] = 500; - } - - acp_recount_thread_ratings(); - } - elseif(isset($mybb->input['do_rebuildpollcounters'])) - { - $plugins->run_hooks("admin_tools_recount_rebuild_poll_counters"); - - if($mybb->input['page'] == 1) - { - // Log admin action - log_admin_action("poll"); - } - - if(!$mybb->get_input('pollcounters', MyBB::INPUT_INT)) - { - $mybb->input['pollcounters'] = 500; - } - - acp_rebuild_poll_counters(); - } - else - { - $plugins->run_hooks("admin_tools_recount_rebuild_stats"); - - $cache->update_stats(); - - // Log admin action - log_admin_action("stats"); - - flash_message($lang->success_rebuilt_forum_stats, 'success'); - admin_redirect("index.php?module=tools-recount_rebuild"); - } - } - - $page->output_header($lang->recount_rebuild); - - $sub_tabs['recount_rebuild'] = array( - 'title' => $lang->recount_rebuild, - 'link' => "index.php?module=tools-recount_rebuild", - 'description' => $lang->recount_rebuild_desc - ); - - $page->output_nav_tabs($sub_tabs, 'recount_rebuild'); - - $form = new Form("index.php?module=tools-recount_rebuild", "post"); - - $form_container = new FormContainer($lang->recount_rebuild); - $form_container->output_row_header($lang->name); - $form_container->output_row_header($lang->data_per_page, array('width' => 50)); - $form_container->output_row_header(" "); - - $form_container->output_cell("
{$lang->rebuild_forum_counters_desc}
"); - $form_container->output_cell($form->generate_numeric_field("forumcounters", 50, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_rebuildforumcounters"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->rebuild_thread_counters_desc}
"); - $form_container->output_cell($form->generate_numeric_field("threadcounters", 500, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_rebuildthreadcounters"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->rebuild_poll_counters_desc}
"); - $form_container->output_cell($form->generate_numeric_field("pollcounters", 500, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_rebuildpollcounters"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->recount_user_posts_desc}
"); - $form_container->output_cell($form->generate_numeric_field("userposts", 500, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_recountuserposts"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->recount_user_threads_desc}
"); - $form_container->output_cell($form->generate_numeric_field("userthreads", 500, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_recountuserthreads"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->rebuild_attachment_thumbs_desc}
"); - $form_container->output_cell($form->generate_numeric_field("attachmentthumbs", 20, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_rebuildattachmentthumbs"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->recount_stats_desc}
"); - $form_container->output_cell($lang->na); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_recountstats"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->recount_reputation_desc}
"); - $form_container->output_cell($form->generate_numeric_field("reputation", 500, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_recountreputation"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->recount_warning_desc}
"); - $form_container->output_cell($form->generate_numeric_field("warning", 500, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_recountwarning"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->recount_private_messages_desc}
"); - $form_container->output_cell($form->generate_numeric_field("privatemessages", 500, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_recountprivatemessages"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->recount_referrals_desc}
"); - $form_container->output_cell($form->generate_numeric_field("referral", 500, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_recountreferral"))); - $form_container->construct_row(); - - $form_container->output_cell("
{$lang->recount_thread_ratings_desc}
"); - $form_container->output_cell($form->generate_numeric_field("threadrating", 500, array('style' => 'width: 150px;', 'min' => 0))); - $form_container->output_cell($form->generate_submit_button($lang->go, array("name" => "do_recountthreadrating"))); - $form_container->construct_row(); - - $plugins->run_hooks("admin_tools_recount_rebuild_output_list"); - - $form_container->end(); - - $form->end(); - - $page->output_footer(); -} - diff --git a/html/forums/admin/modules/tools/spamlog.php b/html/forums/admin/modules/tools/spamlog.php deleted file mode 100644 index a34dc9c..0000000 --- a/html/forums/admin/modules/tools/spamlog.php +++ /dev/null @@ -1,296 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->spam_logs, "index.php?module=tools-spamlog"); - -$sub_tabs['spam_logs'] = array( - 'title' => $lang->spam_logs, - 'link' => "index.php?module=tools-spamlog", - 'description' => $lang->spam_logs_desc -); -$sub_tabs['prune_spam_logs'] = array( - 'title' => $lang->prune_spam_logs, - 'link' => "index.php?module=tools-spamlog&action=prune", - 'description' => $lang->prune_spam_logs_desc -); - -$plugins->run_hooks("admin_tools_spamlog_begin"); - -if($mybb->input['action'] == 'prune') -{ - if(!is_super_admin($mybb->user['uid'])) - { - flash_message($lang->cannot_perform_action_super_admin_general, 'error'); - admin_redirect("index.php?module=tools-spamlog"); - } - - $plugins->run_hooks("admin_tools_spamlog_prune"); - - if($mybb->request_method == 'post') - { - $is_today = false; - $mybb->input['older_than'] = $mybb->get_input('older_than', MyBB::INPUT_INT); - if($mybb->input['older_than'] <= 0) - { - $is_today = true; - $mybb->input['older_than'] = 1; - } - $where = 'dateline < '.(TIME_NOW-($mybb->input['older_than']*86400)); - - // Searching for entries in a specific module - if($mybb->input['filter_username']) - { - $where .= " AND username='".$db->escape_string($mybb->input['filter_username'])."'"; - } - - // Searching for entries in a specific module - if($mybb->input['filter_email']) - { - $where .= " AND email='".$db->escape_string($mybb->input['filter_email'])."'"; - } - - $query = $db->delete_query("spamlog", $where); - $num_deleted = $db->affected_rows(); - - $plugins->run_hooks("admin_tools_spamlog_prune_commit"); - - // Log admin action - log_admin_action($mybb->input['older_than'], $mybb->input['filter_username'], $mybb->input['filter_email'], $num_deleted); - - $success = $lang->success_pruned_spam_logs; - if($is_today == true && $num_deleted > 0) - { - $success .= ' '.$lang->note_logs_locked; - } - elseif($is_today == true && $num_deleted == 0) - { - flash_message($lang->note_logs_locked, 'error'); - admin_redirect('index.php?module=tools-spamlog'); - } - flash_message($success, 'success'); - admin_redirect('index.php?module=tools-spamlog'); - } - $page->add_breadcrumb_item($lang->prune_spam_logs, 'index.php?module=tools-spamlog&action=prune'); - $page->output_header($lang->prune_spam_logs); - $page->output_nav_tabs($sub_tabs, 'prune_spam_logs'); - - // Fetch filter options - $sortbysel[$mybb->input['sortby']] = 'selected="selected"'; - $ordersel[$mybb->input['order']] = 'selected="selected"'; - - $form = new Form("index.php?module=tools-spamlog&action=prune", "post"); - $form_container = new FormContainer($lang->prune_spam_logs); - $form_container->output_row($lang->spam_username, "", $form->generate_text_box('filter_username', $mybb->input['filter_username'], array('id' => 'filter_username')), 'filter_username'); - $form_container->output_row($lang->spam_email, "", $form->generate_text_box('filter_email', $mybb->input['filter_email'], array('id' => 'filter_email')), 'filter_email'); - if(!$mybb->input['older_than']) - { - $mybb->input['older_than'] = '30'; - } - $form_container->output_row($lang->date_range, "", $lang->older_than.$form->generate_numeric_field('older_than', $mybb->input['older_than'], array('id' => 'older_than', 'style' => 'width: 50px', 'min' => 0))." {$lang->days}", 'older_than'); - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->prune_spam_logs); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_tools_spamlog_start"); - - $page->output_header($lang->spam_logs); - - $page->output_nav_tabs($sub_tabs, 'spam_logs'); - - $perpage = $mybb->get_input('perpage', MyBB::INPUT_INT); - if(!$perpage) - { - $perpage = 20; - } - - $where = '1=1'; - - $additional_criteria = array(); - - // Searching for entries witha specific username - if($mybb->input['username']) - { - $where .= " AND username='".$db->escape_string($mybb->input['username'])."'"; - $additional_criteria[] = "username=".urlencode($mybb->input['username']); - } - - // Searching for entries with a specific email - if($mybb->input['email']) - { - $where .= " AND email='".$db->escape_string($mybb->input['email'])."'"; - $additional_criteria[] = "email=".urlencode($mybb->input['email']); - } - - // Searching for entries with a specific IP - if($mybb->input['ipaddress'] > 0) - { - $where .= " AND ipaddress=".$db->escape_binary(my_inet_pton($mybb->input['ipaddress'])); - $additional_criteria[] = "ipaddress=".urlencode($mybb->input['ipaddress']); - } - - if($additional_criteria) - { - $additional_criteria = "&".implode("&", $additional_criteria); - } - else - { - $additional_criteria = ''; - } - - // Order? - switch($mybb->input['sortby']) - { - case "username": - $sortby = "username"; - break; - case "email": - $sortby = "email"; - break; - case "ipaddress": - $sortby = "ipaddress"; - break; - default: - $sortby = "dateline"; - } - $order = $mybb->input['order']; - if($order != "asc") - { - $order = "desc"; - } - - $query = $db->simple_select("spamlog", "COUNT(sid) AS count", $where); - $rescount = $db->fetch_field($query, "count"); - - // Figure out if we need to display multiple pages. - if($mybb->input['page'] != "last") - { - $pagecnt = $mybb->get_input('page', MyBB::INPUT_INT); - } - - $logcount = (int)$rescount; - $pages = $logcount / $perpage; - $pages = ceil($pages); - - if($mybb->input['page'] == "last") - { - $pagecnt = $pages; - } - - if($pagecnt > $pages) - { - $pagecnt = 1; - } - - if($pagecnt) - { - $start = ($pagecnt-1) * $perpage; - } - else - { - $start = 0; - $pagecnt = 1; - } - - $table = new Table; - $table->construct_header($lang->spam_username, array('width' => '20%')); - $table->construct_header($lang->spam_email, array("class" => "align_center", 'width' => '20%')); - $table->construct_header($lang->spam_ip, array("class" => "align_center", 'width' => '20%')); - $table->construct_header($lang->spam_date, array("class" => "align_center", 'width' => '20%')); - $table->construct_header($lang->spam_confidence, array("class" => "align_center", 'width' => '20%')); - - $query = $db->simple_select("spamlog", "*", $where, array('order_by' => $sortby, 'order_dir' => $order, 'limit_start' => $start, 'limit' => $perpage)); - while($row = $db->fetch_array($query)) - { - $username = htmlspecialchars_uni($row['username']); - $email = htmlspecialchars_uni($row['email']); - $ip_address = my_inet_ntop($db->unescape_binary($row['ipaddress'])); - - $dateline = ''; - if($row['dateline'] > 0) - { - $dateline = my_date('relative', $row['dateline']); - } - - $confidence = '0%'; - $data = @my_unserialize($row['data']); - if(is_array($data) && !empty($data)) - { - if(isset($data['confidence'])) - { - $confidence = (double)$data['confidence'].'%'; - } - } - - $search_sfs = ""; - - $table->construct_cell($username); - $table->construct_cell($email); - $table->construct_cell("{$search_sfs}
{$ip_address}
"); - $table->construct_cell($dateline); - $table->construct_cell($confidence); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_spam_logs, array("colspan" => "5")); - $table->construct_row(); - } - - $table->output($lang->spam_logs); - - // Do we need to construct the pagination? - if($rescount > $perpage) - { - echo draw_admin_pagination($pagecnt, $perpage, $rescount, "index.php?module=tools-spamlog&perpage={$perpage}{$additional_criteria}&sortby={$mybb->input['sortby']}&order={$order}")."
"; - } - - // Fetch filter options - $sortbysel[$mybb->input['sortby']] = "selected=\"selected\""; - $ordersel[$mybb->input['order']] = "selected=\"selected\""; - - $sort_by = array( - 'dateline' => $lang->spam_date, - 'username' => $lang->spam_username, - 'email' => $lang->spam_email, - 'ipaddress' => $lang->spam_ip, - ); - - $order_array = array( - 'asc' => $lang->asc, - 'desc' => $lang->desc - ); - - $form = new Form("index.php?module=tools-spamlog", "post"); - $form_container = new FormContainer($lang->filter_spam_logs); - $form_container->output_row($lang->spam_username, "", $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'suername'); - $form_container->output_row($lang->spam_email, "", $form->generate_text_box('email', $mybb->input['email'], array('id' => 'email')), 'email'); - $form_container->output_row($lang->spam_ip, "", $form->generate_text_box('ipaddress', $mybb->input['ipaddress'], array('id' => 'ipaddress')), 'ipaddress'); - $form_container->output_row($lang->sort_by, "", $form->generate_select_box('sortby', $sort_by, $mybb->input['sortby'], array('id' => 'sortby'))." {$lang->in} ".$form->generate_select_box('order', $order_array, $order, array('id' => 'order'))." {$lang->order}", 'order'); - $form_container->output_row($lang->results_per_page, "", $form->generate_numeric_field('perpage', $perpage, array('id' => 'perpage', 'min' => 1)), 'perpage'); - - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->filter_spam_logs); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/tools/statistics.php b/html/forums/admin/modules/tools/statistics.php deleted file mode 100644 index 75d5af9..0000000 --- a/html/forums/admin/modules/tools/statistics.php +++ /dev/null @@ -1,282 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -if($mybb->input['action'] == "do_graph") -{ - $range = array( - 'start' => $mybb->get_input('start', MyBB::INPUT_INT), - 'end' => $mybb->get_input('end', MyBB::INPUT_INT) - ); - create_graph($mybb->input['type'], $range); - die; -} - -$page->add_breadcrumb_item($lang->statistics, "index.php?module=tools-statistics"); - -$sub_tabs['overall_statistics'] = array( - 'title' => $lang->overall_statistics, - 'link' => "index.php?module=tools-statistics", - 'description' => $lang->overall_statistics_desc -); - -$plugins->run_hooks("admin_tools_statistics_begin"); - -if(!$mybb->input['action']) -{ - $query = $db->simple_select("stats", "COUNT(*) as total"); - if($db->fetch_field($query, "total") == 0) - { - flash_message($lang->error_no_statistics_available_yet, 'error'); - admin_redirect("index.php?module=tools"); - } - - $per_page = 20; - - $plugins->run_hooks("admin_tools_statistics_overall_begin"); - - // Do we have date range criteria? - if($mybb->input['from_year']) - { - $start_dateline = mktime(0, 0, 0, $mybb->get_input('from_month', MyBB::INPUT_INT), $mybb->get_input('from_day', MyBB::INPUT_INT), $mybb->get_input('from_year', MyBB::INPUT_INT)); - $end_dateline = mktime(23, 59, 59, $mybb->get_input('to_month', MyBB::INPUT_INT), $mybb->get_input('to_day', MyBB::INPUT_INT), $mybb->get_input('to_year', MyBB::INPUT_INT)); - $range = "&start={$start_dateline}&end={$end_dateline}"; - } - - // Otherwise default to the last 30 days - if(!$mybb->input['from_year'] || $start_dateline > TIME_NOW || $end_dateline > mktime(23, 59, 59)) - { - $start_dateline = TIME_NOW-(60*60*24*30); - $end_dateline = TIME_NOW; - - list($mybb->input['from_day'], $mybb->input['from_month'], $mybb->input['from_year']) = explode('-', date('j-n-Y', $start_dateline)); - list($mybb->input['to_day'], $mybb->input['to_month'], $mybb->input['to_year']) = explode('-', date('j-n-Y', $end_dateline)); - - $range = "&start={$start_dateline}&end={$end_dateline}"; - } - - $last_dateline = 0; - - if($mybb->input['page'] && $mybb->input['page'] > 1) - { - $mybb->input['page'] = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($mybb->input['page']*$per_page)-$per_page; - } - else - { - $mybb->input['page'] = 1; - $start = 0; - } - - $query = $db->simple_select("stats", "*", "dateline >= '".(int)$start_dateline."' AND dateline <= '".(int)$end_dateline."'", array('order_by' => 'dateline', 'order_dir' => 'asc')); - - $stats = array(); - while($stat = $db->fetch_array($query)) - { - if($last_dateline) - { - $stat['change_users'] = ($stat['numusers'] - $stats[$last_dateline]['numusers']); - $stat['change_threads'] = ($stat['numthreads'] - $stats[$last_dateline]['numthreads']); - $stat['change_posts'] = ($stat['numposts'] - $stats[$last_dateline]['numposts']); - } - - $stats[$stat['dateline']] = $stat; - - $last_dateline = $stat['dateline']; - } - - if(empty($stats)) - { - flash_message($lang->error_no_results_found_for_criteria, 'error'); - admin_redirect("index.php?module=tools"); - } - - krsort($stats, SORT_NUMERIC); - - $page->add_breadcrumb_item($lang->overall_statistics, "index.php?module=tools-statistics"); - - $page->output_header($lang->statistics." - ".$lang->overall_statistics); - - $page->output_nav_tabs($sub_tabs, 'overall_statistics'); - - // Date range fields - $form = new Form("index.php?module=tools-statistics", "post", "overall"); - echo "
{$lang->date_range}\n"; - echo "{$lang->from} ".$form->generate_date_select('from', $mybb->input['from_day'], $mybb->input['from_month'], $mybb->input['from_year']); - echo " {$lang->to} ".$form->generate_date_select('to', $mybb->input['to_day'], $mybb->input['to_month'], $mybb->input['to_year']); - echo " ".$form->generate_submit_button($lang->view); - echo "
\n"; - $form->end(); - - echo "
{$lang->users}\n"; - echo "\n"; - echo "
\n"; - - echo "
{$lang->threads}\n"; - echo "\n"; - echo "
\n"; - - echo "
{$lang->posts}\n"; - echo "\n"; - echo "
\n"; - - $total_rows = count($stats); - - $table = new Table; - $table->construct_header($lang->date); - $table->construct_header($lang->users); - $table->construct_header($lang->threads); - $table->construct_header($lang->posts); - $query = $db->simple_select("stats", "*", "dateline >= '".(int)$start_dateline."' AND dateline <= '".(int)$end_dateline."'", array('order_by' => 'dateline', 'order_dir' => 'desc', 'limit_start' => $start, 'limit' => $per_page)); - while($stat = $db->fetch_array($query)) - { - $table->construct_cell("".date($mybb->settings['dateformat'], $stat['dateline']).""); - $table->construct_cell(my_number_format($stat['numusers'])." ".generate_growth_string($stats[$stat['dateline']]['change_users']).""); - $table->construct_cell(my_number_format($stat['numthreads'])." ".generate_growth_string($stats[$stat['dateline']]['change_threads']).""); - $table->construct_cell(my_number_format($stat['numposts'])." ".generate_growth_string($stats[$stat['dateline']]['change_posts']).""); - $table->construct_row(); - } - $table->output($lang->overall_statistics); - - $url_range = "&from_month=".$mybb->get_input('from_month', MyBB::INPUT_INT)."&from_day=".$mybb->get_input('from_day', MyBB::INPUT_INT)."&from_year=".$mybb->get_input('from_year', MyBB::INPUT_INT); - $url_range .= "&to_month=".$mybb->get_input('to_month', MyBB::INPUT_INT)."&to_day=".$mybb->get_input('to_day', MyBB::INPUT_INT)."&to_year=".$mybb->get_input('to_year', MyBB::INPUT_INT); - - echo draw_admin_pagination($mybb->input['page'], $per_page, $total_rows, "index.php?module=tools-statistics{$url_range}&page={page}"); - - $page->output_footer(); -} - -/** - * @param int $number - * - * @return string - */ -function generate_growth_string($number) -{ - global $lang, $cp_style; - - if($number === null) - { - return ""; - } - - $number = (int)$number; - $friendly_number = my_number_format(abs($number)); - - if($number > 0) - { - $growth_string = "(\"{$lang-increase}\" title=\"{$lang->increase}\" style=\"vertical-align: middle; margin-top: -2px;\" /> {$friendly_number})"; - } - elseif($number == 0) - { - $growth_string = "(\"{$lang-no_change}\" title=\"{$lang->no_change}\" style=\"vertical-align: middle; margin-top: -2px;\" /> {$friendly_number})"; - } - else - { - $growth_string = "(\"{$lang-decrease}\" title=\"{$lang->decrease}\" style=\"vertical-align: middle; margin-top: -2px;\" /> {$friendly_number})"; - } - - return $growth_string; -} - -/** - * @param string $type users, threads, posts - * @param array $range - */ -function create_graph($type, $range=null) -{ - global $db; - - // Do we have date range criteria? - if($range['end'] || $range['start']) - { - $start = (int)$range['start']; - $end = (int)$range['end']; - } - // Otherwise default to the last 30 days - else - { - $start = TIME_NOW-(60*60*24*30); - $end = TIME_NOW; - } - - $allowed_types = array('users', 'threads', 'posts'); - if(!in_array($type, $allowed_types)) - { - die; - } - - require_once MYBB_ROOT.'inc/class_graph.php'; - - $points = $stats = $datelines = array(); - if($start == 0) - { - $query = $db->simple_select("stats", "dateline,num{$type}", "dateline <= '".(int)$end."'", array('order_by' => 'dateline', 'order_dir' => 'desc', 'limit' => 2)); - while($stat = $db->fetch_array($query)) - { - $stats[] = $stat['num'.$type]; - $datelines[] = $stat['dateline']; - $x_labels[] = date("m/j", $stat['dateline']); - } - $points[$datelines[0]] = 0; - $points[$datelines[1]] = $stats[0]-$stats[1]; - ksort($points, SORT_NUMERIC); - } - elseif($end == 0) - { - $query = $db->simple_select("stats", "dateline,num{$type}", "dateline >= '".(int)$start."'", array('order_by' => 'dateline', 'order_dir' => 'asc', 'limit' => 2)); - while($stat = $db->fetch_array($query)) - { - $stats[] = $stat['num'.$type]; - $datelines[] = $stat['dateline']; - $x_labels[] = date("m/j", $stat['dateline']); - } - $points[$datelines[0]] = 0; - $points[$datelines[1]] = $stats[1]-$stats[0]; - ksort($points, SORT_NUMERIC); - } - else - { - $query = $db->simple_select("stats", "dateline,num{$type}", "dateline >= '".(int)$start."' AND dateline <= '".(int)$end."'", array('order_by' => 'dateline', 'order_dir' => 'asc')); - while($stat = $db->fetch_array($query)) - { - $points[$stat['dateline']] = $stat['num'.$type]; - $datelines[] = $stat['dateline']; - $x_labels[] = date("m/j", $stat['dateline']); - } - } - - sort($datelines, SORT_NUMERIC); - - // Find our year(s) label - $start_year = date('Y', $datelines[0]); - $last_year = date('Y', $datelines[count($datelines)-1]); - if(($last_year - $start_year) == 0) - { - $bottom_label = $start_year; - } - else - { - $bottom_label = $start_year." - ".$last_year; - } - - // Create the graph outline - $graph = new Graph(); - $graph->add_points(array_values($points)); - $graph->add_x_labels($x_labels); - $graph->set_bottom_label($bottom_label); - $graph->render(); - $graph->output(); -} diff --git a/html/forums/admin/modules/tools/system_health.php b/html/forums/admin/modules/tools/system_health.php deleted file mode 100644 index 120e336..0000000 --- a/html/forums/admin/modules/tools/system_health.php +++ /dev/null @@ -1,981 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->system_health, "index.php?module=tools-system_health"); - -$sub_tabs['system_health'] = array( - 'title' => $lang->system_health, - 'link' => "index.php?module=tools-system_health", - 'description' => $lang->system_health_desc -); - -$sub_tabs['utf8_conversion'] = array( - 'title' => $lang->utf8_conversion, - 'link' => "index.php?module=tools-system_health&action=utf8_conversion", - 'description' => $lang->utf8_conversion_desc2 -); - -$sub_tabs['template_check'] = array( - 'title' => $lang->check_templates, - 'link' => "index.php?module=tools-system_health&action=check_templates", - 'description' => $lang->check_templates_desc -); - -$plugins->run_hooks("admin_tools_system_health_begin"); - -if($mybb->input['action'] == "do_check_templates" && $mybb->request_method == "post") -{ - $query = $db->simple_select("templates", "*", "", array("order_by" => "sid, title", "order_dir" => "ASC")); - - if(!$db->num_rows($query)) - { - flash_message($lang->error_invalid_input, 'error'); - admin_redirect("index.php?module=tools-system_health"); - } - - $plugins->run_hooks("admin_tools_system_health_template_do_check_start"); - - $t_cache = array(); - while($template = $db->fetch_array($query)) - { - if(check_template($template['template']) == true) - { - $t_cache[$template['sid']][] = $template; - } - } - - if(empty($t_cache)) - { - flash_message($lang->success_templates_checked, 'success'); - admin_redirect("index.php?module=tools-system_health"); - } - - $plugins->run_hooks("admin_tools_system_health_template_do_check"); - - $page->add_breadcrumb_item($lang->check_templates); - $page->output_header($lang->check_templates); - - $page->output_nav_tabs($sub_tabs, 'template_check'); - $page->output_inline_error(array($lang->check_templates_info_desc)); - - $templatesets = array( - -2 => array( - "title" => "MyBB Master Templates" - ) - ); - $query = $db->simple_select("templatesets", "*"); - while($set = $db->fetch_array($query)) - { - $templatesets[$set['sid']] = $set; - } - - $count = 0; - foreach($t_cache as $sid => $templates) - { - if(!$done_set[$sid]) - { - $table = new Table(); - $table->construct_header($templatesets[$sid]['title'], array("colspan" => 2)); - - $done_set[$sid] = 1; - ++$count; - } - - if($sid == -2) - { - // Some cheeky clown has altered the master templates! - $table->construct_cell($lang->error_master_templates_altered, array("colspan" => 2)); - $table->construct_row(); - } - - foreach($templates as $template) - { - if($sid == -2) - { - $table->construct_cell($template['title'], array('colspan' => 2)); - } - else - { - $popup = new PopupMenu("template_{$template['tid']}", $lang->options); - $popup->add_item($lang->full_edit, "index.php?module=style-templates&action=edit_template&title=".urlencode($template['title'])."&sid={$sid}"); - - $table->construct_cell("{$template['title']}", array('width' => '80%')); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - } - - $table->construct_row(); - } - - if($done_set[$sid] && !$done_output[$sid]) - { - $done_output[$sid] = 1; - if($count == 1) - { - $table->output($lang->check_templates); - } - else - { - $table->output(); - } - } - } - - $page->output_footer(); -} - -if($mybb->input['action'] == "check_templates") -{ - $page->add_breadcrumb_item($lang->check_templates); - $page->output_header($lang->check_templates); - - $plugins->run_hooks("admin_tools_system_health_template_check"); - - $page->output_nav_tabs($sub_tabs, 'template_check'); - - if($errors) - { - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=tools-system_health", "post", "check_set"); - echo $form->generate_hidden_field("action", "do_check_templates"); - - $form_container = new FormContainer($lang->check_templates); - $form_container->output_row($lang->check_templates_title, "", $lang->check_templates_info); - $form_container->end(); - - $buttons = array(); - $buttons[] = $form->generate_submit_button($lang->proceed); - - $form->output_submit_wrapper($buttons); - - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "utf8_conversion") -{ - if($db->type == "sqlite" || $db->type == "pgsql") - { - flash_message($lang->error_not_supported, 'error'); - admin_redirect("index.php?module=tools-system_health"); - } - - $plugins->run_hooks("admin_tools_system_health_utf8_conversion"); - - if($mybb->request_method == "post" || ($mybb->input['do'] == "all" && !empty($mybb->input['table']))) - { - if(!empty($mybb->input['mb4']) && version_compare($db->get_version(), '5.5.3', '<')) - { - flash_message($lang->error_utf8mb4_version, 'error'); - admin_redirect("index.php?module=tools-system_health&action=utf8_conversion"); - } - @set_time_limit(0); - - $old_table_prefix = $db->table_prefix; - $db->set_table_prefix(''); - - if(!$db->table_exists($db->escape_string($mybb->input['table']))) - { - $db->set_table_prefix($old_table_prefix); - flash_message($lang->error_invalid_table, 'error'); - admin_redirect("index.php?module=tools-system_health&action=utf8_conversion"); - } - - $db->set_table_prefix($old_table_prefix); - - $page->add_breadcrumb_item($lang->utf8_conversion, "index.php?module=tools-system_health&action=utf8_conversion"); - - $page->output_header($lang->system_health." - ".$lang->utf8_conversion); - - $sub_tabs['system_health'] = array( - 'title' => $lang->system_health, - 'link' => "index.php?module=tools-system_health", - 'description' => $lang->system_health_desc - ); - - $sub_tabs['utf8_conversion'] = array( - 'title' => $lang->utf8_conversion, - 'link' => "index.php?module=tools-system_health&action=utf8_conversion", - 'description' => $lang->utf8_conversion_desc2 - ); - - $page->output_nav_tabs($sub_tabs, 'utf8_conversion'); - - $old_table_prefix = $db->table_prefix; - $db->set_table_prefix(''); - - $table = new Table; - - $table1 = $db->show_create_table($db->escape_string($mybb->input['table'])); - preg_match("#CHARSET=([a-zA-Z0-9_]+)\s?#i", $table1, $matches); - $charset = $matches[1]; - - if(!empty($mybb->input['mb4'])) - { - $table->construct_cell("".$lang->sprintf($lang->converting_to_utf8mb4, $mybb->input['table'], $charset).""); - } - else - { - $table->construct_cell("".$lang->sprintf($lang->converting_to_utf8, $mybb->input['table'], $charset).""); - } - $table->construct_row(); - - $table->construct_cell($lang->please_wait); - $table->construct_row(); - - $table->output($converting_table." {$mybb->input['table']}"); - - $db->set_table_prefix($old_table_prefix); - - $page->output_footer(false); - - $old_table_prefix = $db->table_prefix; - $db->set_table_prefix(''); - - flush(); - - $types = array( - 'text' => 'blob', - 'mediumtext' => 'mediumblob', - 'longtext' => 'longblob', - 'char' => 'varbinary', - 'varchar' => 'varbinary', - 'tinytext' => 'tinyblob' - ); - - $blob_types = array( 'blob', 'tinyblob', 'mediumblog', 'longblob', 'text', 'tinytext', 'mediumtext', 'longtext' ); - - // Get next table in list - $convert_to_binary = ''; - $convert_to_utf8 = ''; - $comma = ''; - - if(!empty($mybb->input['mb4'])) - { - $character_set = 'utf8mb4'; - $collation = 'utf8mb4_general_ci'; - } - else - { - $character_set = 'utf8'; - $collation = 'utf8_general_ci'; - } - - // Set table default charset - $db->write_query("ALTER TABLE {$mybb->input['table']} DEFAULT CHARACTER SET {$character_set} COLLATE {$collation}"); - - // Fetch any fulltext keys - if($db->supports_fulltext($mybb->input['table'])) - { - $table_structure = $db->show_create_table($mybb->input['table']); - switch($db->type) - { - case "mysql": - case "mysqli": - preg_match_all("#FULLTEXT KEY `?([a-zA-Z0-9_]+)`? \(([a-zA-Z0-9_`,']+)\)#i", $table_structure, $matches); - if(is_array($matches)) - { - foreach($matches[0] as $key => $matched) - { - $db->write_query("ALTER TABLE {$mybb->input['table']} DROP INDEX {$matches[1][$key]}"); - $fulltext_to_create[$matches[1][$key]] = $matches[2][$key]; - } - } - } - } - - // Find out which columns need converting and build SQL statements - $query = $db->query("SHOW FULL COLUMNS FROM {$mybb->input['table']}"); - while($column = $db->fetch_array($query)) - { - list($type) = explode('(', $column['Type']); - if(array_key_exists($type, $types)) - { - // Build the actual strings for converting the columns - $names = "CHANGE `{$column['Field']}` `{$column['Field']}` "; - - if(($db->type == 'mysql' || $db->type == 'mysqli') && in_array($type, $blob_types)) - { - if($column['Null'] == 'YES') - { - $attributes = 'NULL'; - } - else - { - $attributes = 'NOT NULL'; - } - } - else - { - $attributes = " DEFAULT "; - if($column['Default'] == 'NULL') - { - $attributes .= "NULL "; - } - else - { - $attributes .= "'".$db->escape_string($column['Default'])."' "; - - if($column['Null'] == 'YES') - { - $attributes .= 'NULL'; - } - else - { - $attributes .= 'NOT NULL'; - } - } - } - - $convert_to_binary .= $comma.$names.preg_replace('/'.$type.'/i', $types[$type], $column['Type']).' '.$attributes; - $convert_to_utf8 .= "{$comma}{$names}{$column['Type']} CHARACTER SET {$character_set} COLLATE {$collation} {$attributes}"; - - $comma = ','; - } - } - - if(!empty($convert_to_binary)) - { - // This converts the columns to UTF-8 while also doing the same for data - $db->write_query("ALTER TABLE {$mybb->input['table']} {$convert_to_binary}"); - $db->write_query("ALTER TABLE {$mybb->input['table']} {$convert_to_utf8}"); - } - - // Any fulltext indexes to recreate? - if(is_array($fulltext_to_create)) - { - foreach($fulltext_to_create as $name => $fields) - { - $db->create_fulltext_index($mybb->input['table'], $fields, $name); - } - } - - $db->set_table_prefix($old_table_prefix); - - $plugins->run_hooks("admin_tools_system_health_utf8_conversion_commit"); - - // Log admin action - log_admin_action($mybb->input['table']); - - flash_message($lang->sprintf($lang->success_table_converted, $mybb->input['table']), 'success'); - - if($mybb->input['do'] == "all") - { - $old_table_prefix = $db->table_prefix; - $db->set_table_prefix(''); - - $tables = $db->list_tables($mybb->config['database']['database']); - foreach($tables as $key => $tablename) - { - if(substr($tablename, 0, strlen(TABLE_PREFIX)) == TABLE_PREFIX) - { - $table = $db->show_create_table($tablename); - preg_match("#CHARSET=([a-zA-Z0-9_]+)\s?#i", $table, $matches); - if(empty($mybb->input['mb4']) && (fetch_iconv_encoding($matches[1]) == 'utf-8' || $matches[1] == 'utf8mb4') && $mybb->input['table'] != $tablename) - { - continue; - } - elseif(!empty($mybb->input['mb4']) && fetch_iconv_encoding($matches[1]) != 'utf-8' && $mybb->input['table'] != $tablename) - { - continue; - } - - $mybb_tables[$key] = $tablename; - } - } - - asort($mybb_tables); - reset($mybb_tables); - - $is_next = false; - $nexttable = ""; - - foreach($mybb_tables as $key => $tablename) - { - if($is_next == true) - { - $nexttable = $tablename; - break; - } - else if($mybb->input['table'] == $tablename) - { - $is_next = true; - } - } - - $db->set_table_prefix($old_table_prefix); - - if($nexttable) - { - $nexttable = $db->escape_string($nexttable); - $mb4 = ''; - if(!empty($mybb->input['mb4'])) - { - $mb4 = "&mb4=1"; - } - admin_redirect("index.php?module=tools-system_health&action=utf8_conversion&do=all&table={$nexttable}{$mb4}"); - exit; - } - } - - admin_redirect("index.php?module=tools-system_health&action=utf8_conversion"); - - exit; - } - - if($mybb->input['table'] || $mybb->input['do'] == "all") - { - if(!empty($mybb->input['mb4']) && version_compare($db->get_version(), '5.5.3', '<')) - { - flash_message($lang->error_utf8mb4_version, 'error'); - admin_redirect("index.php?module=tools-system_health&action=utf8_conversion"); - } - - $old_table_prefix = $db->table_prefix; - $db->set_table_prefix(''); - - if($mybb->input['do'] != "all" && !$db->table_exists($db->escape_string($mybb->input['table']))) - { - $db->set_table_prefix($old_table_prefix); - flash_message($lang->error_invalid_table, 'error'); - admin_redirect("index.php?module=tools-system_health&action=utf8_conversion"); - } - - if($mybb->input['do'] == "all") - { - $tables = $db->list_tables($mybb->config['database']['database']); - foreach($tables as $key => $tablename) - { - if(substr($tablename, 0, strlen(TABLE_PREFIX)) == TABLE_PREFIX) - { - $table = $db->show_create_table($tablename); - preg_match("#CHARSET=([a-zA-Z0-9_]+)\s?#i", $table, $matches); - if(empty($mybb->input['mb4']) && (fetch_iconv_encoding($matches[1]) == 'utf-8' || $matches[1] == 'utf8mb4')) - { - continue; - } - elseif(!empty($mybb->input['mb4']) && fetch_iconv_encoding($matches[1]) != 'utf-8') - { - continue; - } - $mybb_tables[$key] = $tablename; - } - } - - if(is_array($mybb_tables)) - { - asort($mybb_tables); - reset($mybb_tables); - $nexttable = current($mybb_tables); - $table = $db->show_create_table($db->escape_string($nexttable)); - $mybb->input['table'] = $nexttable; - } - else - { - $db->set_table_prefix($old_table_prefix); - flash_message($lang->success_all_tables_already_converted, 'success'); - admin_redirect("index.php?module=tools-system_health"); - } - } - else - { - $table = $db->show_create_table($db->escape_string($mybb->input['table'])); - } - - $page->add_breadcrumb_item($lang->utf8_conversion, "index.php?module=tools-system_health&action=utf8_conversion"); - - $db->set_table_prefix($old_table_prefix); - - $page->output_header($lang->system_health." - ".$lang->utf8_conversion); - - $sub_tabs['system_health'] = array( - 'title' => $lang->system_health, - 'link' => "index.php?module=tools-system_health", - 'description' => $lang->system_health_desc - ); - - $sub_tabs['utf8_conversion'] = array( - 'title' => $lang->utf8_conversion, - 'link' => "index.php?module=tools-system_health&action=utf8_conversion", - 'description' => $lang->utf8_conversion_desc2 - ); - - $page->output_nav_tabs($sub_tabs, 'utf8_conversion'); - - $old_table_prefix = $db->table_prefix; - $db->set_table_prefix(''); - - preg_match("#CHARSET=([a-zA-Z0-9_]+)\s?#i", $table, $matches); - $charset = $matches[1]; - - $mb4 = ''; - if(!empty($mybb->input['mb4'])) - { - $mb4 = "&mb4=1"; - } - - $form = new Form("index.php?module=tools-system_health&action=utf8_conversion{$mb4}", "post", "utf8_conversion"); - echo $form->generate_hidden_field("table", $mybb->input['table']); - - if($mybb->input['do'] == "all") - { - echo $form->generate_hidden_field("do", "all"); - } - - $table = new Table; - - if(!empty($mybb->input['mb4'])) - { - $table->construct_cell("".$lang->sprintf($lang->convert_all_to_utf8mb4, $charset).""); - $lang->notice_process_long_time .= "

{$lang->notice_mb4_warning}"; - } - else - { - if($mybb->input['do'] == "all") - { - $table->construct_cell("".$lang->sprintf($lang->convert_all_to_utf, $charset).""); - } - else - { - $table->construct_cell("".$lang->sprintf($lang->convert_to_utf8, $mybb->input['table'], $charset).""); - } - } - - $table->construct_row(); - - $table->construct_cell($lang->notice_process_long_time); - $table->construct_row(); - - if($mybb->input['do'] == "all") - { - $table->output($lang->convert_tables); - $buttons[] = $form->generate_submit_button($lang->convert_database_tables); - } - else - { - $table->output($lang->convert_table.": {$mybb->input['table']}"); - $buttons[] = $form->generate_submit_button($lang->convert_database_table); - } - - $form->output_submit_wrapper($buttons); - - $form->end(); - - $db->set_table_prefix($old_table_prefix); - - $page->output_footer(); - - exit; - } - - if(!$mybb->config['database']['encoding']) - { - flash_message($lang->error_db_encoding_not_set, 'error'); - admin_redirect("index.php?module=tools-system_health"); - } - - $tables = $db->list_tables($mybb->config['database']['database']); - - $old_table_prefix = $db->table_prefix; - $db->set_table_prefix(''); - - $encodings = array(); - - foreach($tables as $key => $tablename) - { - if(substr($tablename, 0, strlen($old_table_prefix)) == $old_table_prefix) - { - $table = $db->show_create_table($tablename); - preg_match("#CHARSET=([a-zA-Z0-9_]+)\s?#i", $table, $matches); - $encodings[$key] = fetch_iconv_encoding($matches[1]); - $mybb_tables[$key] = $tablename; - } - } - - $db->set_table_prefix($old_table_prefix); - - $page->add_breadcrumb_item($lang->utf8_conversion, "index.php?module=tools-system_health&action=utf8_conversion"); - - $page->output_header($lang->system_health." - ".$lang->utf8_conversion); - - $page->output_nav_tabs($sub_tabs, 'utf8_conversion'); - - asort($mybb_tables); - - $unique = array_unique($encodings); - - $convert_utf8 = $convert_utf8mb4 = false; - foreach($unique as $encoding) - { - if($encoding == 'utf-8') - { - $convert_utf8mb4 = true; - } - elseif($encoding != 'utf8mb4') - { - $convert_utf8 = true; - } - } - - if(count($unique) > 1) - { - $page->output_error("

{$lang->warning_multiple_encodings}

"); - } - - if(in_array('utf8mb4', $unique) && $mybb->config['database']['encoding'] != 'utf8mb4') - { - $page->output_error("

{$lang->warning_utf8mb4_config}

"); - } - - $table = new Table; - $table->construct_header($lang->table); - $table->construct_header($lang->status_utf8, array("class" => "align_center")); - $table->construct_header($lang->status_utf8mb4, array("class" => "align_center")); - - $all_utf8 = $all_utf8mb4 = '-'; - if($convert_utf8) - { - $all_utf8 = "{$lang->convert_all}"; - } - if($convert_utf8mb4) - { - $all_utf8mb4 = "{$lang->convert_all}"; - } - $table->construct_cell("{$lang->all_tables}"); - $table->construct_cell($all_utf8, array("class" => "align_center", 'width' => '15%')); - $table->construct_cell($all_utf8mb4, array("class" => "align_center", 'width' => '25%')); - $table->construct_row(); - - $db_version = $db->get_version(); - - foreach($mybb_tables as $key => $tablename) - { - if($encodings[$key] != 'utf-8' && $encodings[$key] != 'utf8mb4') - { - $status = "style}/images/icons/cross.png) no-repeat; padding-left: 20px;\">{$lang->convert_now}"; - } - else - { - $status = "style}/images/icons/tick.png\" alt=\"{$lang->ok}\" />"; - } - if(version_compare($db_version, '5.5.3', '<')) - { - $utf8mb4 = $lang->not_available; - } - elseif($encodings[$key] == 'utf8mb4') - { - $utf8mb4 = "style}/images/icons/tick.png\" alt=\"{$lang->ok}\" />"; - } - elseif($encodings[$key] == 'utf-8') - { - $utf8mb4 = "style}/images/icons/cross.png) no-repeat; padding-left: 20px;\">{$lang->convert_now}"; - } - else - { - $utf8mb4 = "-"; - } - $table->construct_cell("{$tablename}"); - $table->construct_cell($status, array("class" => "align_center", 'width' => '15%')); - $table->construct_cell($utf8mb4, array("class" => "align_center", 'width' => '25%')); - $table->construct_row(); - } - - $table->output("
{$lang->utf8_conversion}
"); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->system_health); - - $plugins->run_hooks("admin_tools_system_health_start"); - - $page->output_nav_tabs($sub_tabs, 'system_health'); - - $table = new Table; - $table->construct_header($lang->totals, array("colspan" => 2)); - $table->construct_header($lang->attachments, array("colspan" => 2)); - - $query = $db->simple_select("attachments", "COUNT(*) AS numattachs, SUM(filesize) as spaceused, SUM(downloads*filesize) as bandwidthused", "visible='1' AND pid > '0'"); - $attachs = $db->fetch_array($query); - - $table->construct_cell("{$lang->total_database_size}", array('width' => '25%')); - $table->construct_cell(get_friendly_size($db->fetch_size()), array('width' => '25%')); - $table->construct_cell("{$lang->attachment_space_used}", array('width' => '200')); - $table->construct_cell(get_friendly_size((int)$attachs['spaceused']), array('width' => '200')); - $table->construct_row(); - - if($attachs['spaceused'] > 0) - { - $attach_average_size = round($attachs['spaceused']/$attachs['numattachs']); - $bandwidth_average_usage = round($attachs['bandwidthused']); - } - else - { - $attach_average_size = 0; - $bandwidth_average_usage = 0; - } - - $table->construct_cell("{$lang->total_cache_size}", array('width' => '25%')); - $table->construct_cell(get_friendly_size($cache->size_of()), array('width' => '25%')); - $table->construct_cell("{$lang->estimated_attachment_bandwidth_usage}", array('width' => '25%')); - $table->construct_cell(get_friendly_size($bandwidth_average_usage), array('width' => '25%')); - $table->construct_row(); - - - $table->construct_cell("{$lang->max_upload_post_size}", array('width' => '200')); - $table->construct_cell(@ini_get('upload_max_filesize').' / '.@ini_get('post_max_size'), array('width' => '200')); - $table->construct_cell("{$lang->average_attachment_size}", array('width' => '25%')); - $table->construct_cell(get_friendly_size($attach_average_size), array('width' => '25%')); - $table->construct_row(); - - $table->output($lang->stats); - - $table->construct_header($lang->task); - $table->construct_header($lang->run_time, array("width" => 200, "class" => "align_center")); - - $task_cache = $cache->read("tasks"); - $nextrun = $task_cache['nextrun']; - - $query = $db->simple_select("tasks", "*", "nextrun >= '{$nextrun}' AND enabled='1'", array("order_by" => "nextrun", "order_dir" => "asc", 'limit' => 3)); - while($task = $db->fetch_array($query)) - { - $task['title'] = htmlspecialchars_uni($task['title']); - $next_run = date($mybb->settings['dateformat'], $task['nextrun']).", ".date($mybb->settings['timeformat'], $task['nextrun']); - $table->construct_cell("{$task['title']}"); - $table->construct_cell($next_run, array("class" => "align_center")); - - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_tasks, array('colspan' => 2)); - $table->construct_row(); - } - - $table->output($lang->next_3_tasks); - - if(isset($mybb->admin['permissions']['tools']['backupdb']) && $mybb->admin['permissions']['tools']['backupdb'] == 1) - { - $backups = array(); - $dir = MYBB_ADMIN_DIR.'backups/'; - $handle = opendir($dir); - while(($file = readdir($handle)) !== false) - { - if(filetype(MYBB_ADMIN_DIR.'backups/'.$file) == 'file') - { - $ext = get_extension($file); - if($ext == 'gz' || $ext == 'sql') - { - $backups[@filemtime(MYBB_ADMIN_DIR.'backups/'.$file)] = array( - "file" => $file, - "time" => @filemtime(MYBB_ADMIN_DIR.'backups/'.$file), - "type" => $ext - ); - } - } - } - - $count = count($backups); - krsort($backups); - - $table = new Table; - $table->construct_header($lang->name); - $table->construct_header($lang->backup_time, array("width" => 200, "class" => "align_center")); - - $backupscnt = 0; - foreach($backups as $backup) - { - ++$backupscnt; - - if($backupscnt == 4) - { - break; - } - - $time = "-"; - if($backup['time']) - { - $time = my_date('relative', $backup['time']); - } - - $table->construct_cell("{$backup['file']}"); - $table->construct_cell($time, array("class" => "align_center")); - $table->construct_row(); - } - - if($count == 0) - { - $table->construct_cell($lang->no_backups, array('colspan' => 2)); - $table->construct_row(); - } - - $table->output($lang->existing_db_backups); - } - - if(is_writable(MYBB_ROOT.'inc/settings.php')) - { - $message_settings = "{$lang->writable}"; - } - else - { - $message_settings = "{$lang->not_writable}
{$lang->please_chmod_777}"; - ++$errors; - } - - if(is_writable(MYBB_ROOT.'inc/config.php')) - { - $message_config = "{$lang->writable}"; - } - else - { - $message_config = "{$lang->not_writable}
{$lang->please_chmod_777}"; - ++$errors; - } - - $uploadspath = $mybb->settings['uploadspath']; - if(my_substr($uploadspath, 0, 1) == '.') - { - $uploadspath = MYBB_ROOT . $mybb->settings['uploadspath']; - } - if(is_writable($uploadspath)) - { - $message_upload = "{$lang->writable}"; - } - else - { - $message_upload = "{$lang->not_writable}
{$lang->please_chmod_777}"; - ++$errors; - } - - $avataruploadpath = $mybb->settings['avataruploadpath']; - if(my_substr($avataruploadpath, 0, 1) == '.') - { - $avataruploadpath = MYBB_ROOT . $mybb->settings['avataruploadpath']; - } - if(is_writable($avataruploadpath)) - { - $message_avatar = "{$lang->writable}"; - } - else - { - $message_avatar = "{$lang->not_writable}
{$lang->please_chmod_777}"; - ++$errors; - } - - if(is_writable(MYBB_ROOT.'inc/languages/')) - { - $message_language = "{$lang->writable}"; - } - else - { - $message_language = "{$lang->not_writable}
{$lang->please_chmod_777}"; - ++$errors; - } - - if(is_writable(MYBB_ROOT.$config['admin_dir'].'/backups/')) - { - $message_backup = "{$lang->writable}"; - } - else - { - $message_backup = "{$lang->not_writable}
{$lang->please_chmod_777}"; - ++$errors; - } - - if(is_writable(MYBB_ROOT.'/cache/')) - { - $message_cache = "{$lang->writable}"; - } - else - { - $message_cache = "{$lang->not_writable}
{$lang->please_chmod_777}"; - ++$errors; - } - - if(is_writable(MYBB_ROOT.'/cache/themes/')) - { - $message_themes = "{$lang->writable}"; - } - else - { - $message_themes = "{$lang->not_writable}
{$lang->please_chmod_777}"; - ++$errors; - } - - if($errors) - { - $page->output_error("

{$errors} {$lang->error_chmod} {$lang->chmod_info} MyBB Docs.

"); - } - else - { - $page->output_success("

{$lang->success_chmod}

"); - } - - $table = new Table; - $table->construct_header($lang->file); - $table->construct_header($lang->location, array("colspan" => 2, 'width' => 250)); - - $table->construct_cell("{$lang->config_file}"); - $table->construct_cell("./inc/config.php"); - $table->construct_cell($message_config); - $table->construct_row(); - - $table->construct_cell("{$lang->settings_file}"); - $table->construct_cell("./inc/settings.php"); - $table->construct_cell($message_settings); - $table->construct_row(); - - $table->construct_cell("{$lang->file_upload_dir}"); - $table->construct_cell($mybb->settings['uploadspath']); - $table->construct_cell($message_upload); - $table->construct_row(); - - $table->construct_cell("{$lang->avatar_upload_dir}"); - $table->construct_cell($mybb->settings['avataruploadpath']); - $table->construct_cell($message_avatar); - $table->construct_row(); - - $table->construct_cell("{$lang->language_files}"); - $table->construct_cell("./inc/languages"); - $table->construct_cell($message_language); - $table->construct_row(); - - $table->construct_cell("{$lang->backup_dir}"); - $table->construct_cell('./'.$config['admin_dir'].'/backups'); - $table->construct_cell($message_backup); - $table->construct_row(); - - $table->construct_cell("{$lang->cache_dir}"); - $table->construct_cell('./cache'); - $table->construct_cell($message_cache); - $table->construct_row(); - - $table->construct_cell("{$lang->themes_dir}"); - $table->construct_cell('./cache/themes'); - $table->construct_cell($message_themes); - $table->construct_row(); - - $plugins->run_hooks("admin_tools_system_health_output_chmod_list"); - - $table->output($lang->chmod_files_and_dirs); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/tools/tasks.php b/html/forums/admin/modules/tools/tasks.php deleted file mode 100644 index 930326a..0000000 --- a/html/forums/admin/modules/tools/tasks.php +++ /dev/null @@ -1,770 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -require_once MYBB_ROOT."/inc/functions_task.php"; - -$page->add_breadcrumb_item($lang->task_manager, "index.php?module=tools-tasks"); - -$plugins->run_hooks("admin_tools_tasks_begin"); - -/** - * Validates a string or array of values - * - * @param string|array $value Comma-separated list or array of values - * @param int $min Minimum value - * @param int $max Maximum value - * @param string $return_type Set "string" to return in a comma-separated list, or "array" to return in an array - * @return string|array String or array of valid values OR false if string/array is invalid - */ -function check_time_values($value, $min, $max, $return_type) -{ - // If the values aren't in an array form, make them into an array - if(!is_array($value)) - { - // Empty value == * - if($value === '') - { - return ($return_type == 'string') ? '*' : array('*'); - } - $implode = 1; - $value = explode(',', $value); - } - // If * is in the array, always return with * because it overrides all - if(in_array('*', $value)) - { - return ($return_type == 'string') ? '*' : array('*'); - } - // Validate each value in array - foreach($value as $time) - { - if($time < $min || $time > $max) - { - return false; - } - } - // Return based on return type - if($return_type == 'string') - { - $value = implode(',', $value); - } - return $value; -} - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_tools_tasks_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(!trim($mybb->input['description'])) - { - $errors[] = $lang->error_missing_description; - } - - if(!file_exists(MYBB_ROOT."inc/tasks/".$mybb->input['file'].".php")) - { - $errors[] = $lang->error_invalid_task_file; - } - - $mybb->input['minute'] = check_time_values($mybb->input['minute'], 0, 59, 'string'); - if($mybb->input['minute'] === false) - { - $errors[] = $lang->error_invalid_minute; - } - - $mybb->input['hour'] = check_time_values($mybb->input['hour'], 0, 59, 'string'); - if($mybb->input['hour'] === false) - { - $errors[] = $lang->error_invalid_hour; - } - - if($mybb->input['day'] != "*" && $mybb->input['day'] != '') - { - $mybb->input['day'] = check_time_values($mybb->input['day'], 1, 31, 'string'); - if($mybb->input['day'] === false) - { - $errors[] = $lang->error_invalid_day; - } - $mybb->input['weekday'] = array('*'); - } - else - { - $mybb->input['weekday'] = check_time_values($mybb->input['weekday'], 0, 6, 'array'); - if($mybb->input['weekday'] === false) - { - $errors[] = $lang->error_invalid_weekday; - } - $mybb->input['day'] = '*'; - } - - $mybb->input['month'] = check_time_values($mybb->input['month'], 1, 12, 'array'); - if($mybb->input['month'] === false) - { - $errors[] = $lang->error_invalid_month; - } - - if(!$errors) - { - $new_task = array( - "title" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "file" => $db->escape_string($mybb->input['file']), - "minute" => $db->escape_string($mybb->input['minute']), - "hour" => $db->escape_string($mybb->input['hour']), - "day" => $db->escape_string($mybb->input['day']), - "month" => $db->escape_string(implode(',', $mybb->input['month'])), - "weekday" => $db->escape_string(implode(',', $mybb->input['weekday'])), - "enabled" => $mybb->get_input('enabled', MyBB::INPUT_INT), - "logging" => $mybb->get_input('logging', MyBB::INPUT_INT) - ); - - $new_task['nextrun'] = fetch_next_run($new_task); - $tid = $db->insert_query("tasks", $new_task); - - $plugins->run_hooks("admin_tools_tasks_add_commit"); - - $cache->update_tasks(); - - // Log admin action - log_admin_action($tid, htmlspecialchars_uni($mybb->input['title'])); - - flash_message($lang->success_task_created, 'success'); - admin_redirect("index.php?module=tools-tasks"); - } - } - $page->add_breadcrumb_item($lang->add_new_task); - $page->output_header($lang->scheduled_tasks." - ".$lang->add_new_task); - - - $sub_tabs['scheduled_tasks'] = array( - 'title' => $lang->scheduled_tasks, - 'link' => "index.php?module=tools-tasks" - ); - - $sub_tabs['add_task'] = array( - 'title' => $lang->add_new_task, - 'link' => "index.php?module=tools-tasks&action=add", - 'description' => $lang->add_new_task_desc - ); - - $sub_tabs['task_logs'] = array( - 'title' => $lang->view_task_logs, - 'link' => "index.php?module=tools-tasks&action=logs" - ); - - $page->output_nav_tabs($sub_tabs, 'add_task'); - $form = new Form("index.php?module=tools-tasks&action=add", "post", "add"); - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['minute'] = '*'; - $mybb->input['hour'] = '*'; - $mybb->input['day'] = '*'; - $mybb->input['weekday'] = '*'; - $mybb->input['month'] = '*'; - } - $form_container = new FormContainer($lang->add_new_task); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_description." *", "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - - $task_list = array(); - $task_files = scandir(MYBB_ROOT."inc/tasks/"); - foreach($task_files as $task_file) - { - if(is_file(MYBB_ROOT."inc/tasks/{$task_file}") && get_extension($task_file) == "php") - { - $file_id = preg_replace("#\.".get_extension($task_file)."$#i", "$1", $task_file); - $task_list[$file_id] = $task_file; - } - } - $form_container->output_row($lang->task_file." *", $lang->task_file_desc, $form->generate_select_box("file", $task_list, $mybb->input['file'], array('id' => 'file')), 'file'); - $form_container->output_row($lang->time_minutes, $lang->time_minutes_desc, $form->generate_text_box('minute', $mybb->input['minute'], array('id' => 'minute')), 'minute'); - $form_container->output_row($lang->time_hours, $lang->time_hours_desc, $form->generate_text_box('hour', $mybb->input['hour'], array('id' => 'hour')), 'hour'); - $form_container->output_row($lang->time_days_of_month, $lang->time_days_of_month_desc, $form->generate_text_box('day', $mybb->input['day'], array('id' => 'day')), 'day'); - - $options = array( - "*" => $lang->every_weekday, - "0" => $lang->sunday, - "1" => $lang->monday, - "2" => $lang->tuesday, - "3" => $lang->wednesday, - "4" => $lang->thursday, - "5" => $lang->friday, - "6" => $lang->saturday - ); - $form_container->output_row($lang->time_weekdays, $lang->time_weekdays_desc, $form->generate_select_box('weekday[]', $options, $mybb->input['weekday'], array('id' => 'weekday', 'multiple' => true, 'size' => 8)), 'weekday'); - - $options = array( - "*" => $lang->every_month, - "1" => $lang->january, - "2" => $lang->february, - "3" => $lang->march, - "4" => $lang->april, - "5" => $lang->may, - "6" => $lang->june, - "7" => $lang->july, - "8" => $lang->august, - "9" => $lang->september, - "10" => $lang->october, - "11" => $lang->november, - "12" => $lang->december - ); - $form_container->output_row($lang->time_months, $lang->time_months_desc, $form->generate_select_box('month[]', $options, $mybb->input['month'], array('id' => 'month', 'multiple' => true, 'size' => 13)), 'month'); - - $form_container->output_row($lang->enable_logging." *", "", $form->generate_yes_no_radio("logging", $mybb->input['logging'], true)); - - $form_container->output_row($lang->enabled." *", "", $form->generate_yes_no_radio("enabled", $mybb->input['enabled'], true)); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_task); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("tasks", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $task = $db->fetch_array($query); - - // Does the task not exist? - if(!$task['tid']) - { - flash_message($lang->error_invalid_task, 'error'); - admin_redirect("index.php?module=tools-tasks"); - } - - $plugins->run_hooks("admin_tools_tasks_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(!trim($mybb->input['description'])) - { - $errors[] = $lang->error_missing_description; - } - - if(!file_exists(MYBB_ROOT."inc/tasks/".$mybb->input['file'].".php")) - { - $errors[] = $lang->error_invalid_task_file; - } - - $mybb->input['minute'] = check_time_values($mybb->input['minute'], 0, 59, 'string'); - if($mybb->input['minute'] === false) - { - $errors[] = $lang->error_invalid_minute; - } - - $mybb->input['hour'] = check_time_values($mybb->input['hour'], 0, 59, 'string'); - if($mybb->input['hour'] === false) - { - $errors[] = $lang->error_invalid_hour; - } - - if($mybb->input['day'] != "*" && $mybb->input['day'] != '') - { - $mybb->input['day'] = check_time_values($mybb->input['day'], 1, 31, 'string'); - if($mybb->input['day'] === false) - { - $errors[] = $lang->error_invalid_day; - } - $mybb->input['weekday'] = array('*'); - } - else - { - $mybb->input['weekday'] = check_time_values($mybb->input['weekday'], 0, 6, 'array'); - if($mybb->input['weekday'] === false) - { - $errors[] = $lang->error_invalid_weekday; - } - $mybb->input['day'] = '*'; - } - - $mybb->input['month'] = check_time_values($mybb->input['month'], 1, 12, 'array'); - if($mybb->input['month'] === false) - { - $errors[] = $lang->error_invalid_month; - } - - if(!$errors) - { - $enable_confirmation = false; - // Check if we need to ask the user to confirm turning on the task - if(($task['file'] == "backupdb" || $task['file'] == "checktables") && $task['enabled'] == 0 && $mybb->input['enabled'] == 1) - { - $mybb->input['enabled'] = 0; - $enable_confirmation = true; - } - - $updated_task = array( - "title" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "file" => $db->escape_string($mybb->input['file']), - "minute" => $db->escape_string($mybb->input['minute']), - "hour" => $db->escape_string($mybb->input['hour']), - "day" => $db->escape_string($mybb->input['day']), - "month" => $db->escape_string(implode(',', $mybb->input['month'])), - "weekday" => $db->escape_string(implode(',', $mybb->input['weekday'])), - "enabled" => $mybb->get_input('enabled', MyBB::INPUT_INT), - "logging" => $mybb->get_input('logging', MyBB::INPUT_INT) - ); - - $updated_task['nextrun'] = fetch_next_run($updated_task); - - $plugins->run_hooks("admin_tools_tasks_edit_commit"); - - $db->update_query("tasks", $updated_task, "tid='{$task['tid']}'"); - - $cache->update_tasks(); - - // Log admin action - log_admin_action($task['tid'], htmlspecialchars_uni($mybb->input['title'])); - - flash_message($lang->success_task_updated, 'success'); - - if($enable_confirmation == true) - { - admin_redirect("index.php?module=tools-tasks&action=enable&tid={$task['tid']}&my_post_key={$mybb->post_code}"); - } - else - { - admin_redirect("index.php?module=tools-tasks"); - } - } - } - - $page->add_breadcrumb_item($lang->edit_task); - $page->output_header($lang->scheduled_tasks." - ".$lang->edit_task); - - $sub_tabs['edit_task'] = array( - 'title' => $lang->edit_task, - 'description' => $lang->edit_task_desc, - 'link' => "index.php?module=tools-tasks&action=edit&tid={$task['tid']}" - ); - - $page->output_nav_tabs($sub_tabs, 'edit_task'); - - $form = new Form("index.php?module=tools-tasks&action=edit", "post"); - - if($errors) - { - $page->output_inline_error($errors); - $task_data = $mybb->input; - } - else - { - $task_data = $task; - $task_data['weekday'] = explode(',', $task['weekday']); - $task_data['month'] = explode(',', $task['month']); - } - - $form_container = new FormContainer($lang->edit_task); - echo $form->generate_hidden_field("tid", $task['tid']); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $task_data['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_description." *", "", $form->generate_text_box('description', $task_data['description'], array('id' => 'description')), 'description'); - - $task_list = array(); - $task_files = scandir(MYBB_ROOT."inc/tasks/"); - foreach($task_files as $task_file) - { - if(is_file(MYBB_ROOT."inc/tasks/{$task_file}") && get_extension($task_file) == "php") - { - $file_id = preg_replace("#\.".get_extension($task_file)."$#i", "$1", $task_file); - $task_list[$file_id] = $task_file; - } - } - $form_container->output_row($lang->task." *", $lang->task_file_desc, $form->generate_select_box("file", $task_list, $task_data['file'], array('id' => 'file')), 'file'); - $form_container->output_row($lang->time_minutes, $lang->time_minutes_desc, $form->generate_text_box('minute', $task_data['minute'], array('id' => 'minute')), 'minute'); - $form_container->output_row($lang->time_hours, $lang->time_hours_desc, $form->generate_text_box('hour', $task_data['hour'], array('id' => 'hour')), 'hour'); - $form_container->output_row($lang->time_days_of_month, $lang->time_days_of_month_desc, $form->generate_text_box('day', $task_data['day'], array('id' => 'day')), 'day'); - - $options = array( - "*" => $lang->every_weekday, - "0" => $lang->sunday, - "1" => $lang->monday, - "2" => $lang->tuesday, - "3" => $lang->wednesday, - "4" => $lang->thursday, - "5" => $lang->friday, - "6" => $lang->saturday - ); - $form_container->output_row($lang->time_weekdays, $lang->time_weekdays_desc, $form->generate_select_box('weekday[]', $options, $task_data['weekday'], array('id' => 'weekday', 'multiple' => true)), 'weekday'); - - $options = array( - "*" => $lang->every_month, - "1" => $lang->january, - "2" => $lang->february, - "3" => $lang->march, - "4" => $lang->april, - "5" => $lang->may, - "6" => $lang->june, - "7" => $lang->july, - "8" => $lang->august, - "9" => $lang->september, - "10" => $lang->october, - "11" => $lang->november, - "12" => $lang->december - ); - $form_container->output_row($lang->time_months, $lang->time_months_desc, $form->generate_select_box('month[]', $options, $task_data['month'], array('id' => 'month', 'multiple' => true)), 'month'); - - $form_container->output_row($lang->enable_logging." *", "", $form->generate_yes_no_radio("logging", $task_data['logging'], true)); - - $form_container->output_row($lang->enabled." *", "", $form->generate_yes_no_radio("enabled", $task_data['enabled'], true)); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_task); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("tasks", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $task = $db->fetch_array($query); - - // Does the task not exist? - if(!$task['tid']) - { - flash_message($lang->error_invalid_task, 'error'); - admin_redirect("index.php?module=tools-tasks"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=tools-tasks"); - } - - $plugins->run_hooks("admin_tools_tasks_delete"); - - if($mybb->request_method == "post") - { - // Delete the task & any associated task log entries - $db->delete_query("tasks", "tid='{$task['tid']}'"); - $db->delete_query("tasklog", "tid='{$task['tid']}'"); - - // Fetch next task run - - $plugins->run_hooks("admin_tools_tasks_delete_commit"); - - $cache->update_tasks(); - - // Log admin action - log_admin_action($task['tid'], htmlspecialchars_uni($task['title'])); - - flash_message($lang->success_task_deleted, 'success'); - admin_redirect("index.php?module=tools-tasks"); - } - else - { - $page->output_confirm_action("index.php?module=tools-tasks&action=delete&tid={$task['tid']}", $lang->confirm_task_deletion); - } -} - -if($mybb->input['action'] == "enable" || $mybb->input['action'] == "disable") -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=tools-tasks"); - } - - $query = $db->simple_select("tasks", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $task = $db->fetch_array($query); - - // Does the task not exist? - if(!$task['tid']) - { - flash_message($lang->error_invalid_task, 'error'); - admin_redirect("index.php?module=tools-tasks"); - } - - if($mybb->input['action'] == "enable") - { - $plugins->run_hooks("admin_tools_tasks_enable"); - } - else - { - $plugins->run_hooks("admin_tools_tasks_disable"); - } - - if($mybb->input['action'] == "enable") - { - if($task['file'] == "backupdb" || $task['file'] == "checktables") - { - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=tools-tasks"); - } - - if($mybb->request_method == "post") - { - $nextrun = fetch_next_run($task); - $db->update_query("tasks", array("nextrun" => $nextrun, "enabled" => 1), "tid='{$task['tid']}'"); - - $plugins->run_hooks("admin_tools_tasks_enable_commit"); - - $cache->update_tasks(); - - // Log admin action - log_admin_action($task['tid'], htmlspecialchars_uni($task['title']), $mybb->input['action']); - - flash_message($lang->success_task_enabled, 'success'); - admin_redirect("index.php?module=tools-tasks"); - } - else - { - $page->output_confirm_action("index.php?module=tools-tasks&action=enable&tid={$task['tid']}", $lang->confirm_task_enable); - } - } - else - { - $nextrun = fetch_next_run($task); - $db->update_query("tasks", array("nextrun" => $nextrun, "enabled" => 1), "tid='{$task['tid']}'"); - - $plugins->run_hooks("admin_tools_tasks_enable_commit"); - - $cache->update_tasks(); - - // Log admin action - log_admin_action($task['tid'], htmlspecialchars_uni($task['title']), $mybb->input['action']); - - flash_message($lang->success_task_enabled, 'success'); - admin_redirect("index.php?module=tools-tasks"); - } - } - else - { - $db->update_query("tasks", array("enabled" => 0), "tid='{$task['tid']}'"); - - $plugins->run_hooks("admin_tools_tasks_disable_commit"); - - $cache->update_tasks(); - - // Log admin action - log_admin_action($task['tid'], htmlspecialchars_uni($task['title']), htmlspecialchars_uni($mybb->input['action'])); - - flash_message($lang->success_task_disabled, 'success'); - admin_redirect("index.php?module=tools-tasks"); - } -} - -if($mybb->input['action'] == "run") -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=tools-tasks"); - } - - ignore_user_abort(true); - @set_time_limit(0); - - $plugins->run_hooks("admin_tools_tasks_run"); - - $query = $db->simple_select("tasks", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."'"); - $task = $db->fetch_array($query); - - // Does the task not exist? - if(!$task['tid']) - { - flash_message($lang->error_invalid_task, 'error'); - admin_redirect("index.php?module=tools-tasks"); - } - - run_task($task['tid']); - - $plugins->run_hooks("admin_tools_tasks_run_commit"); - - // Log admin action - log_admin_action($task['tid'], htmlspecialchars_uni($task['title'])); - - flash_message($lang->success_task_run, 'success'); - admin_redirect("index.php?module=tools-tasks"); -} - -if($mybb->input['action'] == "logs") -{ - $plugins->run_hooks("admin_tools_tasks_logs"); - - $page->output_header($lang->task_logs); - - $sub_tabs['scheduled_tasks'] = array( - 'title' => $lang->scheduled_tasks, - 'link' => "index.php?module=tools-tasks" - ); - - $sub_tabs['add_task'] = array( - 'title' => $lang->add_new_task, - 'link' => "index.php?module=tools-tasks&action=add" - ); - - $sub_tabs['task_logs'] = array( - 'title' => $lang->view_task_logs, - 'link' => "index.php?module=tools-tasks&action=logs", - 'description' => $lang->view_task_logs_desc - ); - - $page->output_nav_tabs($sub_tabs, 'task_logs'); - - $table = new Table; - $table->construct_header($lang->task); - $table->construct_header($lang->date, array("class" => "align_center", "width" => 200)); - $table->construct_header($lang->data, array("width" => "60%")); - - $query = $db->simple_select("tasklog", "COUNT(*) AS log_count"); - $log_count = $db->fetch_field($query, "log_count"); - - $start = 0; - $per_page = 50; - $current_page = 1; - - if($mybb->input['page'] > 0) - { - $current_page = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($current_page-1)*$per_page; - $pages = $log_count / $per_page; - $pages = ceil($pages); - if($current_page > $pages) - { - $start = 0; - $current_page = 1; - } - } - - $pagination = draw_admin_pagination($current_page, $per_page, $log_count, "index.php?module=tools-tasks&action=logs&page={page}"); - - $query = $db->query(" - SELECT l.*, t.title - FROM ".TABLE_PREFIX."tasklog l - LEFT JOIN ".TABLE_PREFIX."tasks t ON (t.tid=l.tid) - ORDER BY l.dateline DESC - LIMIT {$start}, {$per_page} - "); - while($log_entry = $db->fetch_array($query)) - { - $log_entry['title'] = htmlspecialchars_uni($log_entry['title']); - $log_entry['data'] = htmlspecialchars_uni($log_entry['data']); - - $date = my_date('relative', $log_entry['dateline']); - $table->construct_cell("{$log_entry['title']}"); - $table->construct_cell($date, array("class" => "align_center")); - $table->construct_cell($log_entry['data']); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_task_logs, array("colspan" => "3")); - $table->construct_row(); - } - - $table->output($lang->task_logs); - echo $pagination; - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->task_manager); - - $sub_tabs['scheduled_tasks'] = array( - 'title' => $lang->scheduled_tasks, - 'link' => "index.php?module=tools-tasks", - 'description' => $lang->scheduled_tasks_desc - ); - - $sub_tabs['add_task'] = array( - 'title' => $lang->add_new_task, - 'link' => "index.php?module=tools-tasks&action=add" - ); - - $sub_tabs['task_logs'] = array( - 'title' => $lang->view_task_logs, - 'link' => "index.php?module=tools-tasks&action=logs" - ); - - $plugins->run_hooks("admin_tools_tasks_start"); - - $page->output_nav_tabs($sub_tabs, 'scheduled_tasks'); - - $table = new Table; - $table->construct_header($lang->task); - $table->construct_header($lang->next_run, array("class" => "align_center", "width" => 200)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - $query = $db->simple_select("tasks", "*", "", array("order_by" => "title", "order_dir" => "asc")); - while($task = $db->fetch_array($query)) - { - $task['title'] = htmlspecialchars_uni($task['title']); - $task['description'] = htmlspecialchars_uni($task['description']); - $next_run = date($mybb->settings['dateformat'], $task['nextrun']).", ".date($mybb->settings['timeformat'], $task['nextrun']); - if($task['enabled'] == 1) - { - $icon = "style}/images/icons/bullet_on.png\" alt=\"({$lang->alt_enabled})\" title=\"{$lang->alt_enabled}\" style=\"vertical-align: middle;\" /> "; - } - else - { - $icon = "style}/images/icons/bullet_off.png\" alt=\"({$lang->alt_disabled})\" title=\"{$lang->alt_disabled}\" style=\"vertical-align: middle;\" /> "; - } - $table->construct_cell("
{$icon}{$task['title']}
{$task['description']}
"); - $table->construct_cell($next_run, array("class" => "align_center")); - - $popup = new PopupMenu("task_{$task['tid']}", $lang->options); - $popup->add_item($lang->edit_task, "index.php?module=tools-tasks&action=edit&tid={$task['tid']}"); - if($task['enabled'] == 1) - { - $popup->add_item($lang->run_task, "index.php?module=tools-tasks&action=run&tid={$task['tid']}&my_post_key={$mybb->post_code}"); - $popup->add_item($lang->disable_task, "index.php?module=tools-tasks&action=disable&tid={$task['tid']}&my_post_key={$mybb->post_code}"); - } - else - { - $popup->add_item($lang->enable_task, "index.php?module=tools-tasks&action=enable&tid={$task['tid']}&my_post_key={$mybb->post_code}"); - } - $popup->add_item($lang->delete_task, "index.php?module=tools-tasks&action=delete&tid={$task['tid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_task_deletion}')"); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_tasks, array('colspan' => 3)); - $table->construct_row(); - } - - $table->output($lang->scheduled_tasks); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/tools/warninglog.php b/html/forums/admin/modules/tools/warninglog.php deleted file mode 100644 index 903255a..0000000 --- a/html/forums/admin/modules/tools/warninglog.php +++ /dev/null @@ -1,480 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->warning_logs, "index.php?module=tools-warninglog"); - -$plugins->run_hooks("admin_tools_warninglog_begin"); - -// Revoke a warning -if($mybb->input['action'] == "do_revoke" && $mybb->request_method == "post") -{ - $query = $db->simple_select("warnings", "*", "wid='".$mybb->get_input('wid', MyBB::INPUT_INT)."'"); - $warning = $db->fetch_array($query); - - if(!$warning['wid']) - { - flash_message($lang->error_invalid_warning, 'error'); - admin_redirect("index.php?module=tools-warninglog"); - } - else if($warning['daterevoked']) - { - flash_message($lang->error_already_revoked, 'error'); - admin_redirect("index.php?module=tools-warninglog&action=view&wid={$warning['wid']}"); - } - - $user = get_user($warning['uid']); - - $plugins->run_hooks("admin_tools_warninglog_do_revoke"); - - if(!trim($mybb->input['reason'])) - { - $warn_errors[] = $lang->error_no_revoke_reason; - $mybb->input['action'] = "view"; - } - else - { - // Warning is still active, lower users point count - if($warning['expired'] != 1) - { - $new_warning_points = $user['warningpoints']-$warning['points']; - if($new_warning_points < 0) - { - $new_warning_points = 0; - } - - // Update user - $updated_user = array( - "warningpoints" => $new_warning_points - ); - } - - // Update warning - $updated_warning = array( - "expired" => 1, - "daterevoked" => TIME_NOW, - "revokedby" => $mybb->user['uid'], - "revokereason" => $db->escape_string($mybb->input['reason']) - ); - - $plugins->run_hooks("admin_tools_warninglog_do_revoke_commit"); - - if($warning['expired'] != 1) - { - $db->update_query("users", $updated_user, "uid='{$warning['uid']}'"); - } - - $db->update_query("warnings", $updated_warning, "wid='{$warning['wid']}'"); - - flash_message($lang->redirect_warning_revoked, 'success'); - admin_redirect("index.php?module=tools-warninglog&action=view&wid={$warning['wid']}"); - } -} - -// Detailed view of a warning -if($mybb->input['action'] == "view") -{ - $query = $db->query(" - SELECT w.*, t.title AS type_title, u.username, p.subject AS post_subject - FROM ".TABLE_PREFIX."warnings w - LEFT JOIN ".TABLE_PREFIX."warningtypes t ON (t.tid=w.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=w.issuedby) - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=w.pid) - WHERE w.wid='".$mybb->get_input('wid', MyBB::INPUT_INT)."' - "); - $warning = $db->fetch_array($query); - - if(!$warning['wid']) - { - flash_message($lang->error_invalid_warning, 'error'); - admin_redirect("index.php?module=tools-warninglog"); - } - - $user = get_user((int)$warning['uid']); - - $plugins->run_hooks("admin_tools_warninglog_view"); - - $page->add_breadcrumb_item($lang->warning_details, "index.php?module=tools-warninglog&action=view&wid={$warning['wid']}"); - - $page->output_header($lang->warning_details); - - $user_link = build_profile_link(htmlspecialchars_uni($user['username']), $user['uid'], "_blank"); - - if(is_array($warn_errors)) - { - $page->output_inline_error($warn_errors); - $mybb->input['reason'] = htmlspecialchars_uni($mybb->input['reason']); - } - - $table = new Table; - - $post_link = ""; - if($warning['post_subject']) - { - if(!is_object($parser)) - { - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - } - - $warning['post_subject'] = $parser->parse_badwords($warning['post_subject']); - $warning['post_subject'] = htmlspecialchars_uni($warning['post_subject']); - $post_link = get_post_link($warning['pid']); - $table->construct_cell("{$lang->warned_user}

{$user_link}"); - $table->construct_cell("{$lang->post}

settings['bburl']}/{$post_link}\" target=\"_blank\">{$warning['post_subject']}"); - $table->construct_row(); - } - else - { - $table->construct_cell("{$lang->warned_user}

{$user_link}", array('colspan' => 2)); - $table->construct_row(); - } - - $issuedby = build_profile_link(htmlspecialchars_uni($warning['username']), $warning['issuedby'], "_blank"); - $notes = nl2br(htmlspecialchars_uni($warning['notes'])); - - $date_issued = my_date('relative', $warning['dateline']); - if($warning['type_title']) - { - $warning_type = $warning['type_title']; - } - else - { - $warning_type = $warning['title']; - } - $warning_type = htmlspecialchars_uni($warning_type); - if($warning['points'] > 0) - { - $warning['points'] = "+{$warning['points']}"; - } - - $points = $lang->sprintf($lang->warning_points, $warning['points']); - if($warning['expired'] != 1) - { - if($warning['expires'] == 0) - { - $expires = $lang->never; - } - else - { - $expires = my_date('relative', $warning['expires']); - } - $status = $lang->warning_active; - } - else - { - if($warning['daterevoked']) - { - $expires = $status = $lang->warning_revoked; - } - else if($warning['expires']) - { - $expires = $status = $lang->already_expired; - } - } - - $table->construct_cell("{$lang->warning}

{$warning_type} {$points}", array('width' => '50%')); - $table->construct_cell("{$lang->date_issued}

{$date_issued}", array('width' => '50%')); - $table->construct_row(); - - $table->construct_cell("{$lang->issued_by}

{$issuedby}", array('width' => '50%')); - $table->construct_cell("{$lang->expires}

{$expires}", array('width' => '50%')); - $table->construct_row(); - - $table->construct_cell("{$lang->warning_note}

{$notes}", array('colspan' => 2)); - $table->construct_row(); - - $table->output("
{$status}
".$lang->warning_details); - - if(!$warning['daterevoked']) - { - $form = new Form("index.php?module=tools-warninglog", "post"); - $form_container = new FormContainer($lang->revoke_warning); - echo $form->generate_hidden_field('action', 'do_revoke'); - echo $form->generate_hidden_field('wid', $warning['wid']); - $form_container->output_row("", $lang->revoke_warning_desc, $form->generate_text_area('reason', $mybb->input['reason'], array('id' => 'reason')), 'reason'); - - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->revoke_warning); - $form->output_submit_wrapper($buttons); - $form->end(); - } - else - { - $date_revoked = my_date('relative', $warning['daterevoked']); - $revoked_user = get_user($warning['revokedby']); - $revoked_by = build_profile_link(htmlspecialchars_uni($revoked_user['username']), $revoked_user['uid'], "_blank"); - $revoke_reason = nl2br(htmlspecialchars_uni($warning['revokereason'])); - - $revoke_table = new Table; - $revoke_table->construct_cell("{$lang->revoked_by}

{$revoked_by}", array('width' => '50%')); - $revoke_table->construct_cell("{$lang->date_revoked}

{$date_revoked}", array('width' => '50%')); - $revoke_table->construct_row(); - - $revoke_table->construct_cell("{$lang->reason}

{$revoke_reason}", array('colspan' => 2)); - $revoke_table->construct_row(); - - $revoke_table->output($lang->warning_is_revoked); - } - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_tools_warninglog_start"); - - $page->output_header($lang->warning_logs); - - $sub_tabs['warning_logs'] = array( - 'title' => $lang->warning_logs, - 'link' => "index.php?module=tools-warninglog", - 'description' => $lang->warning_logs_desc - ); - - $page->output_nav_tabs($sub_tabs, 'warning_logs'); - - // Filter options - $where_sql = ''; - if(!empty($mybb->input['filter']['username'])) - { - $search_user = get_user_by_username($mybb->input['filter']['username']); - - $mybb->input['filter']['uid'] = (int)$search_user['uid']; - $mybb->input['filter']['uid'] = $db->fetch_field($query, "uid"); - } - if($mybb->input['filter']['uid']) - { - $search['uid'] = (int)$mybb->input['filter']['uid']; - $where_sql .= " AND w.uid='{$search['uid']}'"; - if(!isset($mybb->input['search']['username'])) - { - $user = get_user($mybb->input['search']['uid']); - $mybb->input['search']['username'] = $user['username']; - } - } - if(!empty($mybb->input['filter']['mod_username'])) - { - $mod_user = get_user_by_username($mybb->input['filter']['mod_username']); - - $mybb->input['filter']['mod_uid'] = (int)$mod_user['uid']; - } - if($mybb->input['filter']['mod_uid']) - { - $search['mod_uid'] = (int)$mybb->input['filter']['mod_uid']; - $where_sql .= " AND w.issuedby='{$search['mod_uid']}'"; - if(!isset($mybb->input['search']['mod_username'])) - { - $mod_user = get_user($mybb->input['search']['uid']); - $mybb->input['search']['mod_username'] = $mod_user['username']; - } - } - if($mybb->input['filter']['reason']) - { - $search['reason'] = $db->escape_string_like($mybb->input['filter']['reason']); - $where_sql .= " AND (w.notes LIKE '%{$search['reason']}%' OR t.title LIKE '%{$search['reason']}%' OR w.title LIKE '%{$search['reason']}%')"; - } - $sortbysel = array(); - switch($mybb->input['filter']['sortby']) - { - case "username": - $sortby = "u.username"; - $sortbysel['username'] = ' selected="selected"'; - break; - case "expires": - $sortby = "w.expires"; - $sortbysel['expires'] = ' selected="selected"'; - break; - case "issuedby": - $sortby = "i.username"; - $sortbysel['issuedby'] = ' selected="selected"'; - break; - default: // "dateline" - $sortby = "w.dateline"; - $sortbysel['dateline'] = ' selected="selected"'; - } - $order = $mybb->input['filter']['order']; - $ordersel = array(); - if($order != "asc") - { - $order = "desc"; - $ordersel['desc'] = ' selected="selected"'; - } - else - { - $ordersel['asc'] = ' selected="selected"'; - } - - // Expire any warnings past their expiration date - require_once MYBB_ROOT.'inc/datahandlers/warnings.php'; - $warningshandler = new WarningsHandler('update'); - - $warningshandler->expire_warnings(); - - // Pagination stuff - $sql = " - SELECT COUNT(wid) as count - FROM - ".TABLE_PREFIX."warnings w - LEFT JOIN ".TABLE_PREFIX."warningtypes t ON (w.tid=t.tid) - WHERE 1=1 - {$where_sql} - "; - $query = $db->query($sql); - $total_warnings = $db->fetch_field($query, 'count'); - $view_page = 1; - if(isset($mybb->input['page']) && $mybb->get_input('page', MyBB::INPUT_INT) > 0) - { - $view_page = $mybb->get_input('page', MyBB::INPUT_INT); - } - $per_page = 20; - if(isset($mybb->input['filter']['per_page']) && (int)$mybb->input['filter']['per_page'] > 0) - { - $per_page = (int)$mybb->input['filter']['per_page']; - } - $start = ($view_page-1) * $per_page; - // Build the base URL for pagination links - $url = 'index.php?module=tools-warninglog'; - if(is_array($mybb->input['filter']) && count($mybb->input['filter'])) - { - foreach($mybb->input['filter'] as $field => $value) - { - $value = urlencode($value); - $url .= "&filter[{$field}]={$value}"; - } - } - - // The actual query - $sql = " - SELECT - w.wid, w.title as custom_title, w.points, w.dateline, w.issuedby, w.expires, w.expired, w.daterevoked, w.revokedby, - t.title, - u.uid, u.username, u.usergroup, u.displaygroup, - i.uid as mod_uid, i.username as mod_username, i.usergroup as mod_usergroup, i.displaygroup as mod_displaygroup - FROM ".TABLE_PREFIX."warnings w - LEFT JOIN ".TABLE_PREFIX."users u on (w.uid=u.uid) - LEFT JOIN ".TABLE_PREFIX."warningtypes t ON (w.tid=t.tid) - LEFT JOIN ".TABLE_PREFIX."users i ON (i.uid=w.issuedby) - WHERE 1=1 - {$where_sql} - ORDER BY {$sortby} {$order} - LIMIT {$start}, {$per_page} - "; - $query = $db->query($sql); - - - $table = new Table; - $table->construct_header($lang->warned_user, array('width' => '15%')); - $table->construct_header($lang->warning, array("class" => "align_center", 'width' => '25%')); - $table->construct_header($lang->date_issued, array("class" => "align_center", 'width' => '20%')); - $table->construct_header($lang->expires, array("class" => "align_center", 'width' => '20%')); - $table->construct_header($lang->issued_by, array("class" => "align_center", 'width' => '15%')); - $table->construct_header($lang->options, array("class" => "align_center", 'width' => '5%')); - - while($row = $db->fetch_array($query)) - { - if(!$row['username']) - { - $row['username'] = $lang->guest; - } - - $trow = alt_trow(); - $username = format_name(htmlspecialchars_uni($row['username']), $row['usergroup'], $row['displaygroup']); - if(!$row['uid']) - { - $username_link = $username; - } - else - { - $username_link = build_profile_link($username, $row['uid'], "_blank"); - } - $mod_username = format_name(htmlspecialchars_uni($row['mod_username']), $row['mod_usergroup'], $row['mod_displaygroup']); - $mod_username_link = build_profile_link($mod_username, $row['mod_uid'], "_blank"); - $issued_date = my_date('relative', $row['dateline']); - $revoked_text = ''; - if($row['daterevoked'] > 0) - { - $revoked_date = my_date('relative', $row['daterevoked']); - $revoked_text = "
{$lang->revoked} {$revoked_date}"; - } - if($row['expires'] > 0) - { - $expire_date = my_date('relative', $row['expires']); - } - else - { - $expire_date = $lang->never; - } - $title = $row['title']; - if(empty($row['title'])) - { - $title = $row['custom_title']; - } - $title = htmlspecialchars_uni($title); - if($row['points'] > 0) - { - $points = '+'.$row['points']; - } - - $table->construct_cell($username_link); - $table->construct_cell("{$title} ({$points})"); - $table->construct_cell($issued_date, array("class" => "align_center")); - $table->construct_cell($expire_date.$revoked_text, array("class" => "align_center")); - $table->construct_cell($mod_username_link); - $table->construct_cell("{$lang->view}", array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_warning_logs, array("colspan" => "6")); - $table->construct_row(); - } - - $table->output($lang->warning_logs); - - // Do we need to construct the pagination? - if($total_warnings > $per_page) - { - echo draw_admin_pagination($view_page, $per_page, $total_warnings, $url)."
"; - } - - $sort_by = array( - 'expires' => $lang->expiry_date, - 'dateline' => $lang->issued_date, - 'username' => $lang->warned_user, - 'issuedby' => $lang->issued_by - ); - - $order_array = array( - 'asc' => $lang->asc, - 'desc' => $lang->desc - ); - - $form = new Form("index.php?module=tools-warninglog", "post"); - $form_container = new FormContainer($lang->filter_warning_logs); - $form_container->output_row($lang->filter_warned_user, "", $form->generate_text_box('filter[username]', $mybb->input['filter']['username'], array('id' => 'filter_username')), 'filter_username'); - $form_container->output_row($lang->filter_issued_by, "", $form->generate_text_box('filter[mod_username]', $mybb->input['filter']['mod_username'], array('id' => 'filter_mod_username')), 'filter_mod_username'); - $form_container->output_row($lang->filter_reason, "", $form->generate_text_box('filter[reason]', $mybb->input['filter']['reason'], array('id' => 'filter_reason')), 'filter_reason'); - $form_container->output_row($lang->sort_by, "", $form->generate_select_box('filter[sortby]', $sort_by, $mybb->input['filter']['sortby'], array('id' => 'filter_sortby'))." {$lang->in} ".$form->generate_select_box('filter[order]', $order_array, $order, array('id' => 'filter_order'))." {$lang->order}", 'filter_order'); - $form_container->output_row($lang->results_per_page, "", $form->generate_numeric_field('filter[per_page]', $per_page, array('id' => 'filter_per_page', 'min' => 1)), 'filter_per_page'); - - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->filter_warning_logs); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/user/admin_permissions.php b/html/forums/admin/modules/user/admin_permissions.php deleted file mode 100644 index a7c5380..0000000 --- a/html/forums/admin/modules/user/admin_permissions.php +++ /dev/null @@ -1,534 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->admin_permissions, "index.php?module=user-admin_permissions"); - -if(($mybb->input['action'] == "edit" && $mybb->input['uid'] == 0) || $mybb->input['action'] == "group" || !$mybb->input['action']) -{ - $sub_tabs['user_permissions'] = array( - 'title' => $lang->user_permissions, - 'link' => "index.php?module=user-admin_permissions", - 'description' => $lang->user_permissions_desc - ); - - $sub_tabs['group_permissions'] = array( - 'title' => $lang->group_permissions, - 'link' => "index.php?module=user-admin_permissions&action=group", - 'description' => $lang->group_permissions_desc - ); - - $sub_tabs['default_permissions'] = array( - 'title' => $lang->default_permissions, - 'link' => "index.php?module=user-admin_permissions&action=edit&uid=0", - 'description' => $lang->default_permissions_desc - ); -} - -$uid = $mybb->get_input('uid', MyBB::INPUT_INT); - -$plugins->run_hooks("admin_user_admin_permissions_begin"); - -if($mybb->input['action'] == "delete") -{ - if(is_super_admin($uid)) - { - flash_message($lang->error_super_admin, 'error'); - admin_redirect("index.php?module=user-admin_permissions"); - } - - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-admin_permissions"); - } - - if(!trim($mybb->input['uid'])) - { - flash_message($lang->error_delete_no_uid, 'error'); - admin_redirect("index.php?module=user-admin_permissions"); - } - - $query = $db->simple_select("adminoptions", "COUNT(uid) as adminoptions", "uid = '{$mybb->input['uid']}'"); - if($db->fetch_field($query, 'adminoptions') == 0) - { - flash_message($lang->error_delete_invalid_uid, 'error'); - admin_redirect("index.php?module=user-admin_permissions"); - } - - $plugins->run_hooks("admin_user_admin_permissions_delete"); - - if($mybb->request_method == "post") - { - $newperms = array( - "permissions" => '' - ); - - $plugins->run_hooks("admin_user_admin_permissions_delete_commit"); - - $db->update_query("adminoptions", $newperms, "uid = '{$uid}'"); - - // Log admin action - if($uid < 0) - { - $gid = abs($uid); - $query = $db->simple_select("usergroups", "title", "gid='{$gid}'"); - $group = $db->fetch_array($query); - log_admin_action($uid, $group['title']); - - } - elseif($uid == 0) - { - // Default - log_admin_action(0, $lang->default); - } - else - { - $user = get_user($uid); - log_admin_action($uid, $user['username']); - } - - flash_message($lang->success_perms_deleted, 'success'); - admin_redirect("index.php?module=user-admin_permissions"); - } - else - { - $page->output_confirm_action("index.php?module=user-admin_permissions&action=delete&uid={$mybb->input['uid']}", $lang->confirm_perms_deletion); - } -} - -if($mybb->input['action'] == "edit") -{ - if(is_super_admin($uid)) - { - flash_message($lang->error_super_admin, 'error'); - admin_redirect("index.php?module=user-admin_permissions"); - } - - $plugins->run_hooks("admin_user_admin_permissions_edit"); - - if($mybb->request_method == "post") - { - foreach($mybb->input['permissions'] as $module => $actions) - { - $no_access = 0; - foreach($actions as $action => $access) - { - if($access == 0) - { - ++$no_access; - } - } - // User can't access any actions in this module - just disallow it completely - if($no_access == count($actions)) - { - unset($mybb->input['permissions'][$module]); - } - } - - // Does an options row exist for this admin already? - $query = $db->simple_select("adminoptions", "COUNT(uid) AS existing_options", "uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"); - $existing_options = $db->fetch_field($query, "existing_options"); - if($existing_options > 0) - { - $db->update_query("adminoptions", array('permissions' => $db->escape_string(my_serialize($mybb->input['permissions']))), "uid = '".$mybb->get_input('uid', MyBB::INPUT_INT)."'"); - } - else - { - $insert_array = array( - "uid" => $mybb->get_input('uid', MyBB::INPUT_INT), - "permissions" => $db->escape_string(my_serialize($mybb->input['permissions'])), - "notes" => '', - "defaultviews" => '' - ); - $db->insert_query("adminoptions", $insert_array); - } - - $plugins->run_hooks("admin_user_admin_permissions_edit_commit"); - - // Log admin action - if($uid > 0) - { - // Users - $user = get_user($uid); - log_admin_action($uid, $user['username']); - } - elseif($uid < 0) - { - // Groups - $gid = abs($uid); - $query = $db->simple_select("usergroups", "title", "gid='{$gid}'"); - $group = $db->fetch_array($query); - log_admin_action($uid, $group['title']); - } - else - { - // Default - log_admin_action(0); - } - - flash_message($lang->admin_permissions_updated, 'success'); - admin_redirect("index.php?module=user-admin_permissions"); - } - - if($uid > 0) - { - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->query(" - SELECT u.uid, u.username, g.cancp, g.gid - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."usergroups g ON (((','|| u.additionalgroups|| ',' LIKE '%,'|| g.gid|| ',%') OR u.usergroup = g.gid)) - WHERE u.uid='$uid' - AND g.cancp=1 - LIMIT 1 - "); - break; - default: - $query = $db->query(" - SELECT u.uid, u.username, g.cancp, g.gid - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."usergroups g ON (((CONCAT(',', u.additionalgroups, ',') LIKE CONCAT('%,', g.gid, ',%')) OR u.usergroup = g.gid)) - WHERE u.uid='$uid' - AND g.cancp=1 - LIMIT 1 - "); - } - - $admin = $db->fetch_array($query); - $permission_data = get_admin_permissions($uid, $admin['gid']); - $title = htmlspecialchars_uni($admin['username']); - $page->add_breadcrumb_item($lang->user_permissions, "index.php?module=user-admin_permissions"); - } - elseif($uid < 0) - { - $gid = abs($uid); - $query = $db->simple_select("usergroups", "title", "gid='$gid'"); - $group = $db->fetch_array($query); - $permission_data = get_admin_permissions("", $gid); - $title = $group['title']; - $page->add_breadcrumb_item($lang->group_permissions, "index.php?module=user-admin_permissions&action=group"); - } - else - { - $query = $db->simple_select("adminoptions", "permissions", "uid='0'"); - $permission_data = my_unserialize($db->fetch_field($query, "permissions")); - $page->add_breadcrumb_item($lang->default_permissions); - $title = $lang->default; - } - - if($uid != 0) - { - $page->add_breadcrumb_item($lang->edit_permissions.": {$title}"); - } - - $page->output_header($lang->edit_permissions); - - if($uid != 0) - { - $sub_tabs['edit_permissions'] = array( - 'title' => $lang->edit_permissions, - 'link' => "index.php?module=user-admin_permissions&action=edit&uid={$uid}", - 'description' => $lang->edit_permissions_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_permissions'); - } - - $form = new Form("index.php?module=user-admin_permissions&action=edit", "post", "edit"); - - echo $form->generate_hidden_field("uid", $uid); - - // Fetch all of the modules we have - $modules_dir = MYBB_ADMIN_DIR."modules"; - $dir = opendir($modules_dir); - $modules = array(); - while(($module = readdir($dir)) !== false) - { - if(is_dir($modules_dir."/".$module) && !in_array($module, array(".", "..")) && file_exists($modules_dir."/".$module."/module_meta.php")) - { - require_once $modules_dir."/".$module."/module_meta.php"; - $meta_function = $module."_admin_permissions"; - - // Module has no permissions, skip it - if(function_exists($meta_function) && is_array($meta_function())) - { - $permission_modules[$module] = $meta_function(); - $modules[$permission_modules[$module]['disporder']][] = $module; - } - } - } - closedir($dir); - - ksort($modules); - foreach($modules as $disp_order => $mod) - { - if(!is_array($mod)) - { - continue; - } - - foreach($mod as $module) - { - $module_tabs[$module] = $permission_modules[$module]['name']; - } - } - $page->output_tab_control($module_tabs); - - foreach($permission_modules as $key => $module) - { - echo "
\n"; - $form_container = new FormContainer("{$module['name']}"); - foreach($module['permissions'] as $action => $title) - { - $form_container->output_row($title, "", $form->generate_yes_no_radio('permissions['.$key.']['.$action.']', (int)$permission_data[$key][$action], array('yes' => 1, 'no' => 0)), 'permissions['.$key.']['.$action.']'); - } - $form_container->end(); - echo "
\n"; - } - - $buttons[] = $form->generate_submit_button($lang->update_permissions); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "group") -{ - $plugins->run_hooks("admin_user_admin_permissions_group"); - - $page->add_breadcrumb_item($lang->group_permissions); - $page->output_header($lang->group_permissions); - - $page->output_nav_tabs($sub_tabs, 'group_permissions'); - - $table = new Table; - $table->construct_header($lang->group); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - // Get usergroups with ACP access - $query = $db->query(" - SELECT g.title, g.cancp, a.permissions, g.gid - FROM ".TABLE_PREFIX."usergroups g - LEFT JOIN ".TABLE_PREFIX."adminoptions a ON (a.uid = -g.gid) - WHERE g.cancp = 1 - ORDER BY g.title ASC - "); - while($group = $db->fetch_array($query)) - { - if($group['permissions'] != "") - { - $perm_type = "group"; - } - else - { - $perm_type = "default"; - } - $uid = -$group['gid']; - $table->construct_cell("
style}/images/icons/{$perm_type}.png\" title=\"{$lang->permissions_type_group}\" alt=\"{$perm_type}\" />
"); - - if($group['permissions'] != "") - { - $popup = new PopupMenu("groupperm_{$uid}", $lang->options); - $popup->add_item($lang->edit_permissions, "index.php?module=user-admin_permissions&action=edit&uid={$uid}"); - - // Check permissions for Revoke - $popup->add_item($lang->revoke_permissions, "index.php?module=user-admin_permissions&action=delete&uid={$uid}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, 'Are you sure you wish to revoke this group\'s permissions?')"); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - } - else - { - $table->construct_cell("{$lang->set_permissions}", array("class" => "align_center")); - } - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_group_perms, array("colspan" => "3")); - $table->construct_row(); - } - - $table->output($lang->group_permissions); - - echo << -
-{$lang->legend} -{$lang->using_custom_perms} {$lang->using_custom_perms}
-{$lang->using_default_perms} {$lang->using_default_perms}
-LEGEND; - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_user_admin_permissions_start"); - - $page->add_breadcrumb_item($lang->user_permissions); - $page->output_header($lang->user_permissions); - - $page->output_nav_tabs($sub_tabs, 'user_permissions'); - - $table = new Table; - $table->construct_header($lang->user); - $table->construct_header($lang->last_active, array("class" => "align_center", "width" => 200)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - // Get usergroups with ACP access - $usergroups = array(); - $query = $db->simple_select("usergroups", "*", "cancp = 1"); - while($usergroup = $db->fetch_array($query)) - { - $usergroups[$usergroup['gid']] = $usergroup; - } - - if(!empty($usergroups)) - { - // Get users whose primary or secondary usergroup has ACP access - $comma = $primary_group_list = $secondary_group_list = ''; - foreach($usergroups as $gid => $group_info) - { - $primary_group_list .= $comma.$gid; - switch($db->type) - { - case "pgsql": - case "sqlite": - $secondary_group_list .= " OR ','|| u.additionalgroups||',' LIKE '%,{$gid},%'"; - break; - default: - $secondary_group_list .= " OR CONCAT(',', u.additionalgroups,',') LIKE '%,{$gid},%'"; - } - - $comma = ','; - } - - $group_list = implode(',', array_keys($usergroups)); - $secondary_groups = ','.$group_list.','; - - // Get usergroups with ACP access - $query = $db->query(" - SELECT g.title, g.cancp, a.permissions, g.gid - FROM ".TABLE_PREFIX."usergroups g - LEFT JOIN ".TABLE_PREFIX."adminoptions a ON (a.uid = -g.gid) - WHERE g.cancp = 1 - ORDER BY g.title ASC - "); - while($group = $db->fetch_array($query)) - { - $group_permissions[$group['gid']] = $group['permissions']; - } - - $query = $db->query(" - SELECT u.uid, u.username, u.lastactive, u.usergroup, u.additionalgroups, a.permissions - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."adminoptions a ON (a.uid=u.uid) - WHERE u.usergroup IN ({$primary_group_list}) {$secondary_group_list} - ORDER BY u.username ASC - "); - while($admin = $db->fetch_array($query)) - { - if($admin['permissions'] != "") - { - $perm_type = "user"; - } - else - { - $groups = explode(",", $admin['additionalgroups'].",".$admin['usergroup']); - foreach($groups as $group) - { - if($group == "") continue; - if($group_permissions[$group] != "") - { - $perm_type = "group"; - break; - } - } - - if(!$group_permissions) - { - $perm_type = "default"; - } - } - - $usergroup_list = array(); - - // Build a list of group memberships that have access to the Admin CP - // Primary usergroup? - if($usergroups[$admin['usergroup']]['cancp'] == 1) - { - $usergroup_list[] = "".$usergroups[$admin['usergroup']]['title'].""; - } - - // Secondary usergroups? - $additional_groups = explode(',', $admin['additionalgroups']); - if(is_array($additional_groups)) - { - foreach($additional_groups as $gid) - { - if($usergroups[$gid]['cancp'] == 1) - { - $usergroup_list[] = $usergroups[$gid]['title']; - } - } - } - $usergroup_list = implode($lang->comma, $usergroup_list); - - $username = htmlspecialchars_uni($admin['username']); - $table->construct_cell("
style}/images/icons/{$perm_type}.png\" title=\"{$lang->perms_type_user}\" alt=\"{$perm_type}\" />
edit_user}\">{$username}
{$usergroup_list}
"); - - $table->construct_cell(my_date('relative', $admin['lastactive']), array("class" => "align_center")); - - $popup = new PopupMenu("adminperm_{$admin['uid']}", $lang->options); - if(!is_super_admin($admin['uid'])) - { - if($admin['permissions'] != "") - { - $popup->add_item($lang->edit_permissions, "index.php?module=user-admin_permissions&action=edit&uid={$admin['uid']}"); - $popup->add_item($lang->revoke_permissions, "index.php?module=user-admin_permissions&action=delete&uid={$admin['uid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_perms_deletion2}')"); - } - else - { - $popup->add_item($lang->set_permissions, "index.php?module=user-admin_permissions&action=edit&uid={$admin['uid']}"); - } - } - $popup->add_item($lang->view_log, "index.php?module=tools-adminlog&uid={$admin['uid']}"); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - $table->construct_row(); - } - } - - if(empty($usergroups) || $table->num_rows() == 0) - { - $table->construct_cell($lang->no_user_perms, array("colspan" => "3")); - $table->construct_row(); - } - - $table->output($lang->user_permissions); - - echo << -
-{$lang->legend} -{$lang->using_individual_perms} {$lang->using_individual_perms}
-{$lang->using_group_perms} {$lang->using_group_perms}
-{$lang->using_default_perms} {$lang->using_default_perms}
-LEGEND; - $page->output_footer(); -} - diff --git a/html/forums/admin/modules/user/awaiting_activation.php b/html/forums/admin/modules/user/awaiting_activation.php deleted file mode 100644 index 5432042..0000000 --- a/html/forums/admin/modules/user/awaiting_activation.php +++ /dev/null @@ -1,213 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->awaiting_activation, "index.php?module=user-awaiting_activation"); - -$sub_tabs['awaiting_activation'] = array( - 'title' => $lang->awaiting_activation, - 'link' => "index.php?module=user-awaiting_activation", - 'description' => $lang->awaiting_activation_desc -); - -$plugins->run_hooks("admin_user_awaiting_activation_begin"); - -if($mybb->input['action'] == "activate" && $mybb->request_method == "post") -{ - $plugins->run_hooks("admin_user_awaiting_activation_activate"); - - $mybb->input['user'] = array_map('intval', $mybb->input['user']); - $user_ids = implode(", ", $mybb->input['user']); - - if(empty($user_ids)) - { - flash_message($lang->no_users_selected, 'error'); - admin_redirect("index.php?module=user-awaiting_activation"); - } - - $num_activated = $num_deleted = 0; - $users_to_delete = array(); - if($mybb->input['delete']) // Delete selected user(s) - { - require_once MYBB_ROOT.'inc/datahandlers/user.php'; - $userhandler = new UserDataHandler('delete'); - - $query = $db->simple_select("users", "uid, usergroup", "uid IN ({$user_ids})"); - while($user = $db->fetch_array($query)) - { - if($user['usergroup'] == 5) - { - ++$num_deleted; - $users_to_delete[] = (int)$user['uid']; - } - } - - if(!empty($users_to_delete)) - { - $userhandler->delete_user($users_to_delete, 1); - } - - $plugins->run_hooks("admin_user_awaiting_activation_activate_delete_commit"); - - // Log admin action - log_admin_action('deleted', $num_deleted); - - flash_message($lang->success_users_deleted, 'success'); - admin_redirect("index.php?module=user-awaiting_activation"); - } - else // Activate selected user(s) - { - $query = $db->simple_select("users", "uid, username, email, usergroup, coppauser", "uid IN ({$user_ids})"); - while($user = $db->fetch_array($query)) - { - ++$num_activated; - if($user['coppauser']) - { - $updated_user = array( - "coppauser" => 0 - ); - } - else - { - $db->delete_query("awaitingactivation", "uid='{$user['uid']}'"); - } - - // Move out of awaiting activation if they're in it. - if($user['usergroup'] == 5) - { - $updated_user['usergroup'] = 2; - } - - $db->update_query("users", $updated_user, "uid='{$user['uid']}'"); - - $message = $lang->sprintf($lang->email_adminactivateaccount, $user['username'], $mybb->settings['bbname'], $mybb->settings['bburl']); my_mail($user['email'], $lang->sprintf($lang->emailsubject_activateaccount, $mybb->settings['bbname']), $message); - } - - $cache->update_awaitingactivation(); - - $plugins->run_hooks("admin_user_awaiting_activation_activate_commit"); - - // Log admin action - log_admin_action('activated', $num_activated); - - flash_message($lang->success_users_activated, 'success'); - admin_redirect("index.php?module=user-awaiting_activation"); - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_user_awaiting_activation_start"); - - $per_page = 20; - - if($mybb->input['page'] && $mybb->input['page'] > 1) - { - $mybb->input['page'] = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($mybb->input['page']*$per_page)-$per_page; - } - else - { - $mybb->input['page'] = 1; - $start = 0; - } - - $page->output_header($lang->manage_awaiting_activation); - - $page->output_nav_tabs($sub_tabs, 'awaiting_activation'); - - $form = new Form("index.php?module=user-awaiting_activation&action=activate", "post"); - - $table = new Table; - $table->construct_header($form->generate_check_box("allbox", 1, '', array('class' => 'checkall'))); - $table->construct_header($lang->username, array('width' => '20%')); - $table->construct_header($lang->registered, array('width' => '15%', 'class' => 'align_center')); - $table->construct_header($lang->last_active, array('width' => '15%', 'class' => 'align_center')); - $table->construct_header($lang->email, array('width' => '15%', 'class' => 'align_center')); - $table->construct_header($lang->ipaddress, array('width' => '10%', 'class' => 'align_center')); - $table->construct_header($lang->type, array('class' => 'align_center')); - - $query = $db->query(" - SELECT u.uid, u.username, u.regdate, u.regip, u.lastactive, u.email, u.coppauser, a.type AS reg_type, a.validated - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."awaitingactivation a ON (a.uid=u.uid) - WHERE u.usergroup='5' - ORDER BY u.regdate DESC - LIMIT {$start}, {$per_page} - "); - while($user = $db->fetch_array($query)) - { - $trow = alt_trow(); - $user['username'] = htmlspecialchars_uni($user['username']); - $user['profilelink'] = build_profile_link($user['username'], $user['uid'], "_blank"); - $user['email'] = htmlspecialchars_uni($user['email']); - $user['regdate'] = my_date('relative', $user['regdate']); - $user['lastactive'] = my_date('relative', $user['lastactive']); - - if($user['reg_type'] == 'r' || $user['reg_type'] == 'b' && $user['validated'] == 0) - { - $user['type'] = $lang->email_activation; - } - elseif($user['coppauser'] == 1) - { - $user['type'] = $lang->admin_activation_coppa; - } - else - { - $user['type'] = $lang->administrator_activation; - } - - if(empty($user['regip'])) - { - $user['regip'] = $lang->na; - } - else - { - $user['regip'] = my_inet_ntop($db->unescape_binary($user['regip'])); - } - - $table->construct_cell($form->generate_check_box("user[{$user['uid']}]", $user['uid'], '')); - $table->construct_cell($user['profilelink']); - $table->construct_cell($user['regdate'], array("class" => "align_center")); - $table->construct_cell($user['lastactive'], array("class" => "align_center")); - $table->construct_cell($user['email'], array("class" => "align_center")); - $table->construct_cell($user['regip'], array("class" => "align_center")); - $table->construct_cell($user['type'], array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_users_awaiting_activation, array('colspan' => 7)); - $table->construct_row(); - $table->output($lang->manage_awaiting_activation); - } - else - { - $table->output($lang->manage_awaiting_activation); - $buttons[] = $form->generate_submit_button($lang->activate_users, array('onclick' => "return confirm('{$lang->confirm_activate_users}');")); - $buttons[] = $form->generate_submit_button($lang->delete_users, array('name' => 'delete', 'onclick' => "return confirm('{$lang->confirm_delete_users}');")); - $form->output_submit_wrapper($buttons); - } - - $form->end(); - - $query = $db->simple_select("users", "COUNT(uid) AS users", "usergroup='5'"); - $total_rows = $db->fetch_field($query, "users"); - - echo "
".draw_admin_pagination($mybb->input['page'], $per_page, $total_rows, "index.php?module=user-awaiting_activation&page={page}"); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/user/banning.php b/html/forums/admin/modules/user/banning.php deleted file mode 100644 index 4d8e9d1..0000000 --- a/html/forums/admin/modules/user/banning.php +++ /dev/null @@ -1,606 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->banning, "index.php?module=user-banning"); - - -$sub_tabs['ips'] = array( - 'title' => $lang->banned_ips, - 'link' => "index.php?module=config-banning", -); - -$sub_tabs['bans'] = array( - 'title' => $lang->banned_accounts, - 'link' => "index.php?module=user-banning", - 'description' => $lang->banned_accounts_desc -); - -$sub_tabs['usernames'] = array( - 'title' => $lang->disallowed_usernames, - 'link' => "index.php?module=config-banning&type=usernames", -); - -$sub_tabs['emails'] = array( - 'title' => $lang->disallowed_email_addresses, - 'link' => "index.php?module=config-banning&type=emails", -); - -// Fetch banned groups -$query = $db->simple_select("usergroups", "gid,title", "isbannedgroup=1", array('order_by' => 'title')); -while($group = $db->fetch_array($query)) -{ - $banned_groups[$group['gid']] = $group['title']; -} - -// Fetch ban times -$ban_times = fetch_ban_times(); - -$plugins->run_hooks("admin_user_banning_begin"); - -if($mybb->input['action'] == "prune") -{ - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-banning"); - } - - $query = $db->simple_select("banned", "*", "uid='{$mybb->input['uid']}'"); - $ban = $db->fetch_array($query); - - if(!$ban['uid']) - { - flash_message($lang->error_invalid_ban, 'error'); - admin_redirect("index.php?module=user-banning"); - } - - $user = get_user($ban['uid']); - - if(is_super_admin($user['uid']) && ($mybb->user['uid'] != $user['uid'] && !is_super_admin($mybb->user['uid']))) - { - flash_message($lang->cannot_perform_action_super_admin_general, 'error'); - admin_redirect("index.php?module=user-banning"); - } - - $plugins->run_hooks("admin_user_banning_prune"); - - if($mybb->request_method == "post") - { - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation(); - - $query = $db->simple_select("threads", "tid", "uid='{$user['uid']}'"); - while($thread = $db->fetch_array($query)) - { - $moderation->delete_thread($thread['tid']); - } - - $query = $db->simple_select("posts", "pid", "uid='{$user['uid']}'"); - while($post = $db->fetch_array($query)) - { - $moderation->delete_post($post['pid']); - } - - $plugins->run_hooks("admin_user_banning_prune_commit"); - - $cache->update_reportedcontent(); - - // Log admin action - log_admin_action($user['uid'], htmlspecialchars_uni($user['username'])); - - flash_message($lang->success_pruned, 'success'); - admin_redirect("index.php?module=user-banning"); - } - else - { - $page->output_confirm_action("index.php?module=user-banning&action=prune&uid={$user['uid']}", $lang->confirm_prune); - } -} - -if($mybb->input['action'] == "lift") -{ - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-banning"); - } - - $query = $db->simple_select("banned", "*", "uid='{$mybb->input['uid']}'"); - $ban = $db->fetch_array($query); - - if(!$ban['uid']) - { - flash_message($lang->error_invalid_ban, 'error'); - admin_redirect("index.php?module=user-banning"); - } - - $user = get_user($ban['uid']); - - if(is_super_admin($user['uid']) && ($mybb->user['uid'] != $user['uid'] && !is_super_admin($mybb->user['uid']))) - { - flash_message($lang->cannot_perform_action_super_admin_general, 'error'); - admin_redirect("index.php?module=user-banning"); - } - - $plugins->run_hooks("admin_user_banning_lift"); - - if($mybb->request_method == "post") - { - $updated_group = array( - 'usergroup' => $ban['oldgroup'], - 'additionalgroups' => $ban['oldadditionalgroups'], - 'displaygroup' => $ban['olddisplaygroup'] - ); - $db->delete_query("banned", "uid='{$ban['uid']}'"); - - $plugins->run_hooks("admin_user_banning_lift_commit"); - - $db->update_query("users", $updated_group, "uid='{$ban['uid']}'"); - - $cache->update_banned(); - $cache->update_moderators(); - - // Log admin action - log_admin_action($ban['uid'], htmlspecialchars_uni($user['username'])); - - flash_message($lang->success_ban_lifted, 'success'); - admin_redirect("index.php?module=user-banning"); - } - else - { - $page->output_confirm_action("index.php?module=user-banning&action=lift&uid={$ban['uid']}", $lang->confirm_lift_ban); - } -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("banned", "*", "uid='{$mybb->input['uid']}'"); - $ban = $db->fetch_array($query); - - $user = get_user($ban['uid']); - - if(!$ban['uid']) - { - flash_message($lang->error_invalid_ban, 'error'); - admin_redirect("index.php?module=user-banning"); - } - - $plugins->run_hooks("admin_user_banning_edit"); - - if($mybb->request_method == "post") - { - if(!$ban['uid']) - { - $errors[] = $lang->error_invalid_username; - } - // Is the user we're trying to ban a super admin and we're not? - else if(is_super_admin($ban['uid']) && !is_super_admin($ban['uid'])) - { - $errors[] = $lang->error_no_perm_to_ban; - } - - if($ban['uid'] == $mybb->user['uid']) - { - $errors[] = $lang->error_ban_self; - } - - // No errors? Update - if(!$errors) - { - // Ban the user - if($mybb->input['bantime'] == '---') - { - $lifted = 0; - } - else - { - $lifted = ban_date2timestamp($mybb->input['bantime'], $ban['dateline']); - } - - $reason = my_substr($mybb->input['reason'], 0, 255); - - if(count($banned_groups) == 1) - { - $group = array_keys($banned_groups); - $mybb->input['usergroup'] = $group[0]; - } - - $update_array = array( - 'gid' => $mybb->get_input('usergroup', MyBB::INPUT_INT), - 'dateline' => TIME_NOW, - 'bantime' => $db->escape_string($mybb->input['bantime']), - 'lifted' => $db->escape_string($lifted), - 'reason' => $db->escape_string($reason) - ); - - $db->update_query('banned', $update_array, "uid='{$ban['uid']}'"); - - // Move the user to the banned group - $update_array = array( - 'usergroup' => $mybb->get_input('usergroup', MyBB::INPUT_INT), - 'displaygroup' => 0, - 'additionalgroups' => '', - ); - $db->update_query('users', $update_array, "uid = {$ban['uid']}"); - - $plugins->run_hooks("admin_user_banning_edit_commit"); - - $cache->update_banned(); - - // Log admin action - log_admin_action($ban['uid'], htmlspecialchars_uni($user['username'])); - - flash_message($lang->success_ban_updated, 'success'); - admin_redirect("index.php?module=user-banning"); - } - } - $page->add_breadcrumb_item($lang->edit_ban); - $page->output_header($lang->edit_ban); - - $sub_tabs = array(); - $sub_tabs['edit'] = array( - 'title' => $lang->edit_ban, - 'description' => $lang->edit_ban_desc - ); - $page->output_nav_tabs($sub_tabs, "edit"); - - $form = new Form("index.php?module=user-banning&action=edit&uid={$ban['uid']}", "post"); - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = array_merge($mybb->input, $ban); - } - - $form_container = new FormContainer($lang->edit_ban); - $form_container->output_row($lang->ban_username, "", htmlspecialchars_uni($user['username'])); - $form_container->output_row($lang->ban_reason, "", $form->generate_text_area('reason', $mybb->input['reason'], array('id' => 'reason', 'maxlength' => '255')), 'reason'); - if(count($banned_groups) > 1) - { - $form_container->output_row($lang->ban_group, $lang->ban_group_desc, $form->generate_select_box('usergroup', $banned_groups, $mybb->input['usergroup'], array('id' => 'usergroup')), 'usergroup'); - } - - if($mybb->input['bantime'] == 'perm' || $mybb->input['bantime'] == '' || $mybb->input['lifted'] == 'perm' ||$mybb->input['lifted'] == '') - { - $mybb->input['bantime'] = '---'; - $mybb->input['lifted'] = '---'; - } - - foreach($ban_times as $time => $period) - { - if($time != '---') - { - $friendly_time = my_date("D, jS M Y @ {$mybb->settings['timeformat']}", ban_date2timestamp($time)); - $period = "{$period} ({$friendly_time})"; - } - $length_list[$time] = $period; - } - $form_container->output_row($lang->ban_time, "", $form->generate_select_box('bantime', $length_list, $mybb->input['bantime'], array('id' => 'bantime')), 'bantime'); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->update_ban); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $where_sql_full = $where_sql = ''; - - $plugins->run_hooks("admin_user_banning_start"); - - if($mybb->request_method == "post") - { - $options = array( - 'fields' => array('username', 'usergroup', 'additionalgroups', 'displaygroup') - ); - - $user = get_user_by_username($mybb->input['username'], $options); - - // Are we searching a user? - if(isset($mybb->input['search'])) - { - $where_sql = 'uid=\''.(int)$user['uid'].'\''; - $where_sql_full = 'WHERE b.uid=\''.(int)$user['uid'].'\''; - } - else - { - if(!$user['uid']) - { - $errors[] = $lang->error_invalid_username; - } - // Is the user we're trying to ban a super admin and we're not? - else if(is_super_admin($user['uid']) && !is_super_admin($mybb->user['uid'])) - { - $errors[] = $lang->error_no_perm_to_ban; - } - else - { - $query = $db->simple_select("banned", "uid", "uid='{$user['uid']}'"); - if($db->fetch_field($query, "uid")) - { - $errors[] = $lang->error_already_banned; - } - - // Get PRIMARY usergroup information - $usergroups = $cache->read("usergroups"); - if(!empty($usergroups[$user['usergroup']]) && $usergroups[$user['usergroup']]['isbannedgroup'] == 1) - { - $errors[] = $lang->error_already_banned; - } - } - - if($user['uid'] == $mybb->user['uid']) - { - $errors[] = $lang->error_ban_self; - } - - // No errors? Insert - if(!$errors) - { - // Ban the user - if($mybb->input['bantime'] == '---') - { - $lifted = 0; - } - else - { - $lifted = ban_date2timestamp($mybb->input['bantime']); - } - - $reason = my_substr($mybb->input['reason'], 0, 255); - - if(count($banned_groups) == 1) - { - $group = array_keys($banned_groups); - $mybb->input['usergroup'] = $group[0]; - } - - $insert_array = array( - 'uid' => $user['uid'], - 'gid' => $mybb->get_input('usergroup', MyBB::INPUT_INT), - 'oldgroup' => $user['usergroup'], - 'oldadditionalgroups' => $user['additionalgroups'], - 'olddisplaygroup' => $user['displaygroup'], - 'admin' => (int)$mybb->user['uid'], - 'dateline' => TIME_NOW, - 'bantime' => $db->escape_string($mybb->input['bantime']), - 'lifted' => $db->escape_string($lifted), - 'reason' => $db->escape_string($reason) - ); - $db->insert_query('banned', $insert_array); - - // Move the user to the banned group - $update_array = array( - 'usergroup' => $mybb->get_input('usergroup', MyBB::INPUT_INT), - 'displaygroup' => 0, - 'additionalgroups' => '', - ); - - $db->delete_query("forumsubscriptions", "uid = '{$user['uid']}'"); - $db->delete_query("threadsubscriptions", "uid = '{$user['uid']}'"); - - $plugins->run_hooks("admin_user_banning_start_commit"); - - $db->update_query('users', $update_array, "uid = '{$user['uid']}'"); - - $cache->update_banned(); - - // Log admin action - log_admin_action($user['uid'], htmlspecialchars_uni($user['username']), $lifted); - - flash_message($lang->success_banned, 'success'); - admin_redirect("index.php?module=user-banning"); - } - } - } - - $page->output_header($lang->banned_accounts); - - $page->output_nav_tabs($sub_tabs, "bans"); - - $query = $db->simple_select("banned", "COUNT(*) AS ban_count", $where_sql); - $ban_count = $db->fetch_field($query, "ban_count"); - - $per_page = 20; - - if($mybb->input['page'] > 0) - { - $current_page = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($current_page-1)*$per_page; - $pages = $ban_count / $per_page; - $pages = ceil($pages); - if($current_page > $pages) - { - $start = 0; - $current_page = 1; - } - } - else - { - $start = 0; - $current_page = 1; - } - - $pagination = draw_admin_pagination($current_page, $per_page, $ban_count, "index.php?module=user-banning&page={page}"); - - $table = new Table; - $table->construct_header($lang->user); - $table->construct_header($lang->ban_lifts_on, array("class" => "align_center", "width" => 150)); - $table->construct_header($lang->time_left, array("class" => "align_center", "width" => 150)); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2, "width" => 200)); - $table->construct_header($lang->moderation, array("class" => "align_center", "colspan" => 1, "width" => 200)); - - // Fetch bans - $query = $db->query(" - SELECT b.*, a.username AS adminuser, u.username - FROM ".TABLE_PREFIX."banned b - LEFT JOIN ".TABLE_PREFIX."users u ON (b.uid=u.uid) - LEFT JOIN ".TABLE_PREFIX."users a ON (b.admin=a.uid) - {$where_sql_full} - ORDER BY dateline DESC - LIMIT {$start}, {$per_page} - "); - - // Get the banned users - while($ban = $db->fetch_array($query)) - { - $profile_link = build_profile_link(htmlspecialchars_uni($ban['username']), $ban['uid'], "_blank"); - $ban_date = my_date($mybb->settings['dateformat'], $ban['dateline']); - if($ban['lifted'] == 'perm' || $ban['lifted'] == '' || $ban['bantime'] == 'perm' || $ban['bantime'] == '---') - { - $ban_period = $lang->permenantly; - $time_remaining = $lifts_on = $lang->na; - } - else - { - $ban_period = $lang->for." ".$ban_times[$ban['bantime']]; - - $remaining = $ban['lifted']-TIME_NOW; - $time_remaining = nice_time($remaining, array('short' => 1, 'seconds' => false)).""; - - if($remaining < 3600) - { - $time_remaining = "{$time_remaining}"; - } - else if($remaining < 86400) - { - $time_remaining = "{$time_remaining}"; - } - else if($remaining < 604800) - { - $time_remaining = "{$time_remaining}"; - } - - $lifts_on = my_date($mybb->settings['dateformat'], $ban['lifted']); - } - - if(!$ban['adminuser']) - { - if($ban['admin'] == 0) - { - $ban['adminuser'] = $lang->mybb_engine; - } - else - { - $ban['adminuser'] = $ban['admin']; - } - } - - $table->construct_cell($lang->sprintf($lang->bannedby_x_on_x, $profile_link, htmlspecialchars_uni($ban['adminuser']), $ban_date, $ban_period)); - $table->construct_cell($lifts_on, array("class" => "align_center")); - $table->construct_cell($time_remaining, array("class" => "align_center")); - $table->construct_cell("{$lang->edit}", array("class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_lift_ban}');\">{$lang->lift}", array("class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_prune}');\">{$lang->prune_threads_and_posts}", array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_banned_users, array("colspan" => "6")); - $table->construct_row(); - } - $table->output($lang->banned_accounts); - echo $pagination; - - $form = new Form("index.php?module=user-banning", "post"); - if($errors) - { - $page->output_inline_error($errors); - } - - if($mybb->input['uid'] && !$mybb->input['username']) - { - $user = get_user($mybb->input['uid']); - $mybb->input['username'] = $user['username']; - } - - $form_container = new FormContainer($lang->ban_a_user); - $form_container->output_row($lang->ban_username, $lang->autocomplete_enabled, $form->generate_text_box('username', $mybb->input['username'], array('id' => 'username')), 'username'); - $form_container->output_row($lang->ban_reason, "", $form->generate_text_area('reason', $mybb->input['reason'], array('id' => 'reason', 'maxlength' => '255')), 'reason'); - if(count($banned_groups) > 1) - { - $form_container->output_row($lang->ban_group, $lang->add_ban_group_desc, $form->generate_select_box('usergroup', $banned_groups, $mybb->input['usergroup'], array('id' => 'usergroup')), 'usergroup'); - } - foreach($ban_times as $time => $period) - { - if($time != "---") - { - $friendly_time = my_date("D, jS M Y @ {$mybb->settings['timeformat']}", ban_date2timestamp($time)); - $period = "{$period} ({$friendly_time})"; - } - $length_list[$time] = $period; - } - $form_container->output_row($lang->ban_time, "", $form->generate_select_box('bantime', $length_list, $mybb->input['bantime'], array('id' => 'bantime')), 'bantime'); - - $form_container->end(); - - // Autocompletion for usernames - echo ' - - - '; - - $buttons[] = $form->generate_submit_button($lang->ban_user); - $buttons[] = $form->generate_submit_button($lang->search_for_a_user, array('name' => 'search')); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/user/group_promotions.php b/html/forums/admin/modules/user/group_promotions.php deleted file mode 100644 index ca150e2..0000000 --- a/html/forums/admin/modules/user/group_promotions.php +++ /dev/null @@ -1,769 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->user_group_promotions, "index.php?module=user-group_promotions"); - -$sub_tabs['usergroup_promotions'] = array( - 'title' => $lang->user_group_promotions, - 'link' => "index.php?module=user-group_promotions", - 'description' => $lang->user_group_promotions_desc -); - -$sub_tabs['add_promotion'] = array( - 'title' => $lang->add_new_promotion, - 'link' => "index.php?module=user-group_promotions&action=add", - 'description' => $lang->add_new_promotion_desc -); - -$sub_tabs['promotion_logs'] = array( - 'title' => $lang->view_promotion_logs, - 'link' => "index.php?module=user-group_promotions&action=logs", - 'description' => $lang->view_promotion_logs_desc -); - -$plugins->run_hooks("admin_user_group_promotions_begin"); - -if($mybb->input['action'] == "disable") -{ - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-group_promotions"); - } - - if(!trim($mybb->input['pid'])) - { - flash_message($lang->error_no_promo_id, 'error'); - admin_redirect("index.php?module=user-group_promotions"); - } - - $query = $db->simple_select("promotions", "*", "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - $promotion = $db->fetch_array($query); - - if(!$promotion['pid']) - { - flash_message($lang->error_invalid_promo_id, 'error'); - admin_redirect("index.php?module=user-group_promotions"); - } - - $plugins->run_hooks("admin_user_group_promotions_disable"); - - if($mybb->request_method == "post") - { - $update_promotion = array( - "enabled" => 0 - ); - - $plugins->run_hooks("admin_user_group_promotions_disable_commit"); - - $db->update_query("promotions", $update_promotion, "pid = '{$promotion['pid']}'"); - - // Log admin action - log_admin_action($promotion['pid'], $promotion['title']); - - flash_message($lang->success_promo_disabled, 'success'); - admin_redirect("index.php?module=user-group_promotions"); - } - else - { - $page->output_confirm_action("index.php?module=user-group_promotions&action=disable&pid={$promotion['pid']}", $lang->confirm_promo_disable); - } -} - -if($mybb->input['action'] == "delete") -{ - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-group_promotions"); - } - - if(!trim($mybb->input['pid'])) - { - flash_message($lang->error_no_promo_id, 'error'); - admin_redirect("index.php?module=user-group_promotions"); - } - - $query = $db->simple_select("promotions", "*", "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - $promotion = $db->fetch_array($query); - - if(!$promotion['pid']) - { - flash_message($lang->error_invalid_promo_id, 'error'); - admin_redirect("index.php?module=user-group_promotions"); - } - - $plugins->run_hooks("admin_user_group_promotions_delete"); - - if($mybb->request_method == "post") - { - $db->delete_query("promotions", "pid = '{$promotion['pid']}'"); - - $plugins->run_hooks("admin_user_group_promotions_delete_commit"); - - // Log admin action - log_admin_action($promotion['pid'], $promotion['title']); - - flash_message($lang->success_promo_deleted, 'success'); - admin_redirect("index.php?module=user-group_promotions"); - } - else - { - $page->output_confirm_action("index.php?module=user-group_promotions&action=delete&pid={$mybb->input['pid']}", $lang->confirm_promo_deletion); - } -} - -if($mybb->input['action'] == "enable") -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=user-group_promotions"); - } - - if(!trim($mybb->input['pid'])) - { - flash_message($lang->error_no_promo_id, 'error'); - admin_redirect("index.php?module=user-group_promotions"); - } - - $query = $db->simple_select("promotions", "*", "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - $promotion = $db->fetch_array($query); - - if(!$promotion['pid']) - { - flash_message($lang->error_invalid_promo_id, 'error'); - admin_redirect("index.php?module=user-group_promotions"); - } - - $plugins->run_hooks("admin_user_group_promotions_enable"); - - $update_promotion = array( - "enabled" => 1 - ); - - $plugins->run_hooks("admin_user_group_promotions_enable_commit"); - - $db->update_query("promotions", $update_promotion, "pid = '{$promotion['pid']}'"); - - // Log admin action - log_admin_action($promotion['pid'], $promotion['title']); - - flash_message($lang->success_promo_enabled, 'success'); - admin_redirect("index.php?module=user-group_promotions"); -} - -if($mybb->input['action'] == "edit") -{ - if(!trim($mybb->input['pid'])) - { - flash_message($lang->error_no_promo_id, 'error'); - admin_redirect("index.php?module=user-group_promotions"); - } - - $query = $db->simple_select("promotions", "*", "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - $promotion = $db->fetch_array($query); - - if(!$promotion) - { - flash_message($lang->error_invalid_promo_id, 'error'); - admin_redirect("index.php?module=user-group_promotions"); - } - - $plugins->run_hooks("admin_user_group_promotions_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_no_title; - } - - if(!trim($mybb->input['description'])) - { - $errors[] = $lang->error_no_desc; - } - - if(empty($mybb->input['requirements'])) - { - $errors[] = $lang->error_no_requirements; - } - - if(empty($mybb->input['originalusergroup'])) - { - $errors[] = $lang->error_no_orig_usergroup; - } - - if(!trim($mybb->input['newusergroup'])) - { - $errors[] = $lang->error_no_new_usergroup; - } - - if(!trim($mybb->input['usergroupchangetype'])) - { - $errors[] = $lang->error_no_usergroup_change_type; - } - - if(!$errors) - { - if(in_array('*', $mybb->input['originalusergroup'])) - { - $mybb->input['originalusergroup'] = '*'; - } - else - { - $mybb->input['originalusergroup'] = implode(',', array_map('intval', $mybb->input['originalusergroup'])); - } - - $allowed_operators = array('>', '>=', '=', '<=', '<'); - $operator_fields = array('posttype', 'threadtype', 'reputationtype', 'referralstype', 'warningstype'); - - foreach($operator_fields as $field) - { - if(!in_array($mybb->get_input($field), $allowed_operators)) - { - $mybb->input[$field] = '='; - } - } - - $allowed_times = array('hours', 'days', 'weeks', 'months', 'years'); - $time_fields = array('timeregisteredtype', 'timeonlinetype'); - - foreach($time_fields as $field) - { - if(!in_array($mybb->get_input($field), $allowed_times)) - { - $mybb->input[$field] = 'days'; - } - } - - $update_promotion = array( - "title" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "posts" => $mybb->get_input('postcount', MyBB::INPUT_INT), - "posttype" => $db->escape_string($mybb->input['posttype']), - "threads" => $mybb->get_input('threadcount', MyBB::INPUT_INT), - "threadtype" => $db->escape_string($mybb->input['threadtype']), - "registered" => $mybb->get_input('timeregistered', MyBB::INPUT_INT), - "registeredtype" => $db->escape_string($mybb->input['timeregisteredtype']), - "online" => $mybb->get_input('timeonline', MyBB::INPUT_INT), - "onlinetype" => $db->escape_string($mybb->input['timeonlinetype']), - "reputations" => $mybb->get_input('reputationcount', MyBB::INPUT_INT), - "reputationtype" => $db->escape_string($mybb->input['reputationtype']), - "referrals" => $mybb->get_input('referrals', MyBB::INPUT_INT), - "referralstype" => $db->escape_string($mybb->input['referralstype']), - "warnings" => $mybb->get_input('warnings', MyBB::INPUT_INT), - "warningstype" => $db->escape_string($mybb->input['warningstype']), - "requirements" => $db->escape_string(implode(",", $mybb->input['requirements'])), - "originalusergroup" => $db->escape_string($mybb->input['originalusergroup']), - "newusergroup" => $mybb->get_input('newusergroup', MyBB::INPUT_INT), - "usergrouptype" => $db->escape_string($mybb->input['usergroupchangetype']), - "enabled" => $mybb->get_input('enabled', MyBB::INPUT_INT), - "logging" => $mybb->get_input('logging', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_user_group_promotions_edit_commit"); - - $db->update_query("promotions", $update_promotion, "pid = '{$promotion['pid']}'"); - - // Log admin action - log_admin_action($promotion['pid'], $mybb->input['title']); - - flash_message($lang->success_promo_updated, 'success'); - admin_redirect("index.php?module=user-group_promotions"); - } - } - - $page->add_breadcrumb_item($lang->edit_promotion); - $page->output_header($lang->user_group_promotions." - ".$lang->edit_promotion); - - $sub_tabs = array(); - $sub_tabs['edit_promotion'] = array( - 'title' => $lang->edit_promotion, - 'link' => "index.php?module=user-group_promotions&action=edit", - 'description' => $lang->edit_promotion_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_promotion'); - $form = new Form("index.php?module=user-group_promotions&action=edit", "post", "edit"); - echo $form->generate_hidden_field("pid", $promotion['pid']); - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['title'] = $promotion['title']; - $mybb->input['description'] = $promotion['description']; - $mybb->input['requirements'] = explode(',', $promotion['requirements']); - $mybb->input['reputationcount'] = $promotion['reputations']; - $mybb->input['reputationtype'] = $promotion['reputationtype']; - $mybb->input['postcount'] = $promotion['posts']; - $mybb->input['posttype'] = $promotion['posttype']; - $mybb->input['threadcount'] = $promotion['threads']; - $mybb->input['threadtype'] = $promotion['threadtype']; - $mybb->input['referrals'] = $promotion['referrals']; - $mybb->input['referralstype'] = $promotion['referralstype']; - $mybb->input['warnings'] = $promotion['warnings']; - $mybb->input['warningstype'] = $promotion['warningstype']; - $mybb->input['timeregistered'] = $promotion['registered']; - $mybb->input['timeregisteredtype'] = $promotion['registeredtype']; - $mybb->input['timeonline'] = $promotion['online']; - $mybb->input['timeonlinetype'] = $promotion['onlinetype']; - $mybb->input['originalusergroup'] = explode(',', $promotion['originalusergroup']); - $mybb->input['usergroupchangetype'] = $promotion['usergrouptype']; - $mybb->input['newusergroup'] = $promotion['newusergroup']; - $mybb->input['enabled'] = $promotion['enabled']; - $mybb->input['logging'] = $promotion['logging']; - } - - $form_container = new FormContainer($lang->edit_promotion); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_desc." *", "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - - $options = array( - "postcount" => $lang->post_count, - "threadcount" => $lang->thread_count, - "reputation" => $lang->reputation, - "referrals" => $lang->referrals, - "warnings" => $lang->warning_points, - "timeregistered" => $lang->time_registered, - "timeonline" => $lang->time_online - ); - - $form_container->output_row($lang->promo_requirements." *", $lang->promo_requirements_desc, $form->generate_select_box('requirements[]', $options, $mybb->input['requirements'], array('id' => 'requirements', 'multiple' => true, 'size' => 5)), 'requirements'); - - $options_type = array( - ">" => $lang->greater_than, - ">=" => $lang->greater_than_or_equal_to, - "=" => $lang->equal_to, - "<=" => $lang->less_than_or_equal_to, - "<" => $lang->less_than - ); - - $form_container->output_row($lang->post_count, $lang->post_count_desc, $form->generate_numeric_field('postcount', $mybb->input['postcount'], array('id' => 'postcount', 'min' => 0))." ".$form->generate_select_box("posttype", $options_type, $mybb->input['posttype'], array('id' => 'posttype')), 'postcount'); - - $form_container->output_row($lang->thread_count, $lang->thread_count_desc, $form->generate_numeric_field('threadcount', $mybb->input['threadcount'], array('id' => 'threadcount', 'min' => 0))." ".$form->generate_select_box("threadtype", $options_type, $mybb->input['threadtype'], array('id' => 'threadtype')), 'threadcount'); - - $form_container->output_row($lang->reputation_count, $lang->reputation_count_desc, $form->generate_numeric_field('reputationcount', $mybb->input['reputationcount'], array('id' => 'reputationcount', 'min' => 0))." ".$form->generate_select_box("reputationtype", $options_type, $mybb->input['reputationtype'], array('id' => 'reputationtype')), 'reputationcount'); - - $options = array( - "hours" => $lang->hours, - "days" => $lang->days, - "weeks" => $lang->weeks, - "months" => $lang->months, - "years" => $lang->years - ); - - $form_container->output_row($lang->referral_count, $lang->referral_count_desc, $form->generate_numeric_field('referrals', $mybb->input['referrals'], array('id' => 'referrals', 'min' => 0))." ".$form->generate_select_box("referralstype", $options_type, $mybb->input['referralstype'], array('id' => 'referralstype')), 'referrals'); - - $form_container->output_row($lang->warning_points, $lang->warning_points_desc, $form->generate_numeric_field('warnings', $mybb->input['warnings'], array('id' => 'warnings', 'min' => 0))." ".$form->generate_select_box("warningstype", $options_type, $mybb->input['warningstype'], array('id' => 'warningstype')), 'warnings'); - - $form_container->output_row($lang->time_registered, $lang->time_registered_desc, $form->generate_numeric_field('timeregistered', $mybb->input['timeregistered'], array('id' => 'timeregistered', 'min' => 0))." ".$form->generate_select_box("timeregisteredtype", $options, $mybb->input['timeregisteredtype'], array('id' => 'timeregisteredtype')), 'timeregistered'); - - $form_container->output_row($lang->time_online, $lang->time_online_desc, $form->generate_numeric_field('timeonline', $mybb->input['timeonline'], array('id' => 'timeonline', 'min' => 0))." ".$form->generate_select_box("timeonlinetype", $options, $mybb->input['timeonlinetype'], array('id' => 'timeonlinetype')), 'timeonline'); - - $options = array(); - - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $options[(int)$usergroup['gid']] = $usergroup['title']; - } - - $form_container->output_row($lang->orig_user_group." *", $lang->orig_user_group_desc, $form->generate_select_box('originalusergroup[]', $options, $mybb->input['originalusergroup'], array('id' => 'originalusergroup', 'multiple' => true, 'size' => 5)), 'originalusergroup'); - - unset($options['*']); // Remove the all usergroups option - $form_container->output_row($lang->new_user_group." *", $lang->new_user_group_desc, $form->generate_select_box('newusergroup', $options, $mybb->input['newusergroup'], array('id' => 'newusergroup')), 'newusergroup'); - - $options = array( - 'primary' => $lang->primary_user_group, - 'secondary' => $lang->secondary_user_group - ); - - $form_container->output_row($lang->user_group_change_type." *", $lang->user_group_change_type_desc, $form->generate_select_box('usergroupchangetype', $options, $mybb->input['usergroupchangetype'], array('id' => 'usergroupchangetype')), 'usergroupchangetype'); - - $form_container->output_row($lang->enabled." *", "", $form->generate_yes_no_radio("enabled", $mybb->input['enabled'], true)); - - $form_container->output_row($lang->enable_logging." *", "", $form->generate_yes_no_radio("logging", $mybb->input['logging'], true)); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->update_promotion); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_user_group_promotions_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_no_title; - } - - if(!trim($mybb->input['description'])) - { - $errors[] = $lang->error_no_desc; - } - - if(empty($mybb->input['requirements'])) - { - $errors[] = $lang->error_no_requirements; - } - - if(empty($mybb->input['originalusergroup'])) - { - $errors[] = $lang->error_no_orig_usergroup; - } - - if(!trim($mybb->input['newusergroup'])) - { - $errors[] = $lang->error_no_new_usergroup; - } - - if(!trim($mybb->input['usergroupchangetype'])) - { - $errors[] = $lang->error_no_usergroup_change_type; - } - - if(!$errors) - { - if(in_array('*', $mybb->input['originalusergroup'])) - { - $mybb->input['originalusergroup'] = '*'; - } - else - { - $mybb->input['originalusergroup'] = implode(',', array_map('intval', $mybb->input['originalusergroup'])); - } - - $allowed_operators = array('>', '>=', '=', '<=', '<'); - $operator_fields = array('posttype', 'threadtype', 'reputationtype', 'referralstype', 'warningstype'); - - foreach($operator_fields as $field) - { - if(!in_array($mybb->get_input($field), $allowed_operators)) - { - $mybb->input[$field] = '='; - } - } - - $allowed_times = array('hours', 'days', 'weeks', 'months', 'years'); - $time_fields = array('timeregisteredtype', 'timeonlinetype'); - - foreach($time_fields as $field) - { - if(!in_array($mybb->get_input($field), $allowed_times)) - { - $mybb->input[$field] = 'days'; - } - } - - $new_promotion = array( - "title" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "posts" => $mybb->get_input('postcount', MyBB::INPUT_INT), - "posttype" => $db->escape_string($mybb->input['posttype']), - "threads" => $mybb->get_input('threadcount', MyBB::INPUT_INT), - "threadtype" => $db->escape_string($mybb->input['threadtype']), - "registered" => $mybb->get_input('timeregistered', MyBB::INPUT_INT), - "registeredtype" => $db->escape_string($mybb->input['timeregisteredtype']), - "online" => $mybb->get_input('timeonline', MyBB::INPUT_INT), - "onlinetype" => $db->escape_string($mybb->input['timeonlinetype']), - "reputations" => $mybb->get_input('reputationcount', MyBB::INPUT_INT), - "reputationtype" => $db->escape_string($mybb->input['reputationtype']), - "referrals" => $mybb->get_input('referrals', MyBB::INPUT_INT), - "referralstype" => $db->escape_string($mybb->input['referralstype']), - "warnings" => $mybb->get_input('warnings', MyBB::INPUT_INT), - "warningstype" => $db->escape_string($mybb->input['warningstype']), - "requirements" => $db->escape_string(implode(",", $mybb->input['requirements'])), - "originalusergroup" => $db->escape_string($mybb->input['originalusergroup']), - "usergrouptype" => $db->escape_string($mybb->input['usergroupchangetype']), - "newusergroup" => $mybb->get_input('newusergroup', MyBB::INPUT_INT), - "enabled" => $mybb->get_input('enabled', MyBB::INPUT_INT), - "logging" => $mybb->get_input('logging', MyBB::INPUT_INT) - ); - - $pid = $db->insert_query("promotions", $new_promotion); - - $plugins->run_hooks("admin_user_group_promotions_add_commit"); - - // Log admin action - log_admin_action($pid, $mybb->input['title']); - - flash_message($lang->success_promo_added, 'success'); - admin_redirect("index.php?module=user-group_promotions"); - } - } - $page->add_breadcrumb_item($lang->add_new_promotion); - $page->output_header($lang->user_group_promotions." - ".$lang->add_new_promotion); - - $sub_tabs['usergroup_promotions'] = array( - 'title' => $lang->user_group_promotions, - 'link' => "index.php?module=user-group_promotions" - ); - - $sub_tabs['add_promotion'] = array( - 'title' => $lang->add_new_promotion, - 'link' => "index.php?module=user-group_promotions&action=add", - 'description' => $lang->add_new_promotion_desc - ); - - $sub_tabs['promotion_logs'] = array( - 'title' => $lang->view_promotion_logs, - 'link' => "index.php?module=user-group_promotions&action=logs" - ); - - $page->output_nav_tabs($sub_tabs, 'add_promotion'); - $form = new Form("index.php?module=user-group_promotions&action=add", "post", "add"); - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input['reputationcount'] = '0'; - $mybb->input['referrals'] = '0'; - $mybb->input['warnings'] = '0'; - $mybb->input['postcount'] = '0'; - $mybb->input['threadcount'] = '0'; - $mybb->input['timeregistered'] = '0'; - $mybb->input['timeregisteredtype'] = 'days'; - $mybb->input['timeonline'] = '0'; - $mybb->input['timeonlinetype'] = 'days'; - $mybb->input['originalusergroup'] = '*'; - $mybb->input['newusergroup'] = '2'; - $mybb->input['enabled'] = '1'; - $mybb->input['logging'] = '1'; - } - $form_container = new FormContainer($lang->add_new_promotion); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_desc." *", "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - - $options = array( - "postcount" => $lang->post_count, - "threadcount" => $lang->thread_count, - "reputation" => $lang->reputation, - "referrals" => $lang->referrals, - "warnings" => $lang->warning_points, - "timeregistered" => $lang->time_registered, - "timeonline" => $lang->time_online - ); - - $form_container->output_row($lang->promo_requirements." *", $lang->promo_requirements_desc, $form->generate_select_box('requirements[]', $options, $mybb->input['requirements'], array('id' => 'requirements', 'multiple' => true, 'size' => 5)), 'requirements'); - - $options_type = array( - ">" => $lang->greater_than, - ">=" => $lang->greater_than_or_equal_to, - "=" => $lang->equal_to, - "<=" => $lang->less_than_or_equal_to, - "<" => $lang->less_than - ); - - $form_container->output_row($lang->post_count, $lang->post_count_desc, $form->generate_numeric_field('postcount', $mybb->input['postcount'], array('id' => 'postcount', 'min' => 0))." ".$form->generate_select_box("posttype", $options_type, $mybb->input['posttype'], array('id' => 'posttype')), 'postcount'); - - $form_container->output_row($lang->thread_count, $lang->thread_count_desc, $form->generate_numeric_field('threadcount', $mybb->input['threadcount'], array('id' => 'threadcount', 'min' => 0))." ".$form->generate_select_box("threadtype", $options_type, $mybb->input['threadtype'], array('id' => 'threadtype')), 'threadcount'); - - $form_container->output_row($lang->reputation_count, $lang->reputation_count_desc, $form->generate_numeric_field('reputationcount', $mybb->input['reputationcount'], array('id' => 'reputationcount', 'min' => 0))." ".$form->generate_select_box("reputationtype", $options_type, $mybb->input['reputationtype'], array('id' => 'reputationtype')), 'reputationcount'); - - $options = array( - "hours" => $lang->hours, - "days" => $lang->days, - "weeks" => $lang->weeks, - "months" => $lang->months, - "years" => $lang->years - ); - - $form_container->output_row($lang->referral_count, $lang->referral_count_desc, $form->generate_numeric_field('referrals', $mybb->input['referrals'], array('id' => 'referrals', 'min' => 0))." ".$form->generate_select_box("referralstype", $options_type, $mybb->input['referralstype'], array('id' => 'referralstype')), 'referrals'); - - $form_container->output_row($lang->warning_points, $lang->warning_points_desc, $form->generate_numeric_field('warnings', $mybb->input['warnings'], array('id' => 'warnings', 'min' => 0))." ".$form->generate_select_box("warningstype", $options_type, $mybb->input['warningstype'], array('id' => 'warningstype')), 'warnings'); - - $form_container->output_row($lang->time_registered, $lang->time_registered_desc, $form->generate_numeric_field('timeregistered', $mybb->input['timeregistered'], array('id' => 'timeregistered', 'min' => 0))." ".$form->generate_select_box("timeregisteredtype", $options, $mybb->input['timeregisteredtype'], array('id' => 'timeregisteredtype')), 'timeregistered'); - - $form_container->output_row($lang->time_online, $lang->time_online_desc, $form->generate_numeric_field('timeonline', $mybb->input['timeonline'], array('id' => 'timeonline', 'min' => 0))." ".$form->generate_select_box("timeonlinetype", $options, $mybb->input['timeonlinetype'], array('id' => 'timeonlinetype')), 'timeonline'); - $options = array(); - - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $options[(int)$usergroup['gid']] = $usergroup['title']; - } - - $form_container->output_row($lang->orig_user_group." *", $lang->orig_user_group_desc, $form->generate_select_box('originalusergroup[]', $options, $mybb->input['originalusergroup'], array('id' => 'originalusergroup', 'multiple' => true, 'size' => 5)), 'originalusergroup'); - - unset($options['*']); - $form_container->output_row($lang->new_user_group." *", $lang->new_user_group_desc, $form->generate_select_box('newusergroup', $options, $mybb->input['newusergroup'], array('id' => 'newusergroup')), 'newusergroup'); - - $options = array( - 'primary' => $lang->primary_user_group, - 'secondary' => $lang->secondary_user_group - ); - - $form_container->output_row($lang->user_group_change_type." *", $lang->user_group_change_type_desc, $form->generate_select_box('usergroupchangetype', $options, $mybb->input['usergroupchangetype'], array('id' => 'usergroupchangetype')), 'usergroupchangetype'); - - $form_container->output_row($lang->enabled." *", "", $form->generate_yes_no_radio("enabled", $mybb->input['enabled'], true)); - - $form_container->output_row($lang->enable_logging." *", "", $form->generate_yes_no_radio("logging", $mybb->input['logging'], true)); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->update_promotion); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "logs") -{ - $plugins->run_hooks("admin_user_group_promotions_logs"); - - if($mybb->get_input('page', MyBB::INPUT_INT) > 1) - { - $mybb->input['page'] = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($mybb->input['page']*20)-20; - } - else - { - $mybb->input['page'] = 1; - $start = 0; - } - - $page->add_breadcrumb_item($lang->promotion_logs); - $page->output_header($lang->user_group_promotions." - ".$lang->promotion_logs); - - $page->output_nav_tabs($sub_tabs, 'promotion_logs'); - - $table = new Table; - $table->construct_header($lang->promoted_user, array("class" => "align_center", "width" => '20%')); - $table->construct_header($lang->user_group_change_type, array("class" => "align_center", "width" => '20%')); - $table->construct_header($lang->orig_user_group, array("class" => "align_center", "width" => '20%')); - $table->construct_header($lang->new_user_group, array("class" => "align_center", "width" => '20%')); - $table->construct_header($lang->time_promoted, array("class" => "align_center", "width" => '20%')); - - $query = $db->query(" - SELECT pl.*,u.username - FROM ".TABLE_PREFIX."promotionlogs pl - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=pl.uid) - ORDER BY dateline DESC - LIMIT {$start}, 20 - "); - while($log = $db->fetch_array($query)) - { - $log['username'] = "".htmlspecialchars_uni($log['username']).""; - - if($log['type'] == "secondary" || (!empty($log['oldusergroup']) && strstr(",", $log['oldusergroup']))) - { - $log['oldusergroup'] = "".$lang->multiple_usergroups.""; - $log['newusergroup'] = htmlspecialchars_uni($groupscache[$log['newusergroup']]['title']); - } - else - { - $log['oldusergroup'] = htmlspecialchars_uni($groupscache[$log['oldusergroup']]['title']); - $log['newusergroup'] = htmlspecialchars_uni($groupscache[$log['newusergroup']]['title']); - } - - if($log['type'] == "secondary") - { - $log['type'] = $lang->secondary; - } - else - { - $log['type'] = $lang->primary; - } - - $log['dateline'] = date($mybb->settings['dateformat'], $log['dateline']).", ".date($mybb->settings['timeformat'], $log['dateline']); - $table->construct_cell($log['username']); - $table->construct_cell($log['type'], array('style' => 'text-align: center;')); - $table->construct_cell($log['oldusergroup'], array('style' => 'text-align: center;')); - $table->construct_cell($log['newusergroup'], array('style' => 'text-align: center;')); - $table->construct_cell($log['dateline'], array('style' => 'text-align: center;')); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_promotion_logs, array("colspan" => "5")); - $table->construct_row(); - } - - $table->output($lang->promotion_logs); - - $query = $db->simple_select("promotionlogs", "COUNT(plid) as promotionlogs"); - $total_rows = $db->fetch_field($query, "promotionlogs"); - - echo "
".draw_admin_pagination($mybb->input['page'], "20", $total_rows, "index.php?module=user-group_promotions&action=logs&page={page}"); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_user_group_promotions_start"); - - $page->output_header($lang->promotion_manager); - - $page->output_nav_tabs($sub_tabs, 'usergroup_promotions'); - - $table = new Table; - $table->construct_header($lang->promotion); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 150)); - - $query = $db->simple_select("promotions", "*", "", array("order_by" => "title", "order_dir" => "asc")); - while($promotion = $db->fetch_array($query)) - { - $promotion['title'] = htmlspecialchars_uni($promotion['title']); - $promotion['description'] = htmlspecialchars_uni($promotion['description']); - if($promotion['enabled'] == 1) - { - $icon = "style}/images/icons/bullet_on.png\" alt=\"({$lang->alt_enabled})\" title=\"{$lang->alt_enabled}\" style=\"vertical-align: middle;\" /> "; - } - else - { - $icon = "style}/images/icons/bullet_off.png\" alt=\"({$lang->alt_disabled})\" title=\"{$lang->alt_disabled}\" style=\"vertical-align: middle;\" /> "; - } - - $table->construct_cell("
{$icon}{$promotion['title']}
{$promotion['description']}
"); - - $popup = new PopupMenu("promotion_{$promotion['pid']}", $lang->options); - $popup->add_item($lang->edit_promotion, "index.php?module=user-group_promotions&action=edit&pid={$promotion['pid']}"); - if($promotion['enabled'] == 1) - { - $popup->add_item($lang->disable_promotion, "index.php?module=user-group_promotions&action=disable&pid={$promotion['pid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_promo_disable}')"); - } - else - { - $popup->add_item($lang->enable_promotion, "index.php?module=user-group_promotions&action=enable&pid={$promotion['pid']}&my_post_key={$mybb->post_code}"); - } - $popup->add_item($lang->delete_promotion, "index.php?module=user-group_promotions&action=delete&pid={$promotion['pid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_promo_deletion}')"); - $table->construct_cell($popup->fetch(), array("class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_promotions_set, array("colspan" => "2")); - $table->construct_row(); - } - - $table->output($lang->user_group_promotions); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/user/groups.php b/html/forums/admin/modules/user/groups.php deleted file mode 100644 index 1e57f62..0000000 --- a/html/forums/admin/modules/user/groups.php +++ /dev/null @@ -1,1546 +0,0 @@ - 0, - "canview" => 1, - "canviewthreads" => 1, - "canviewprofiles" => 1, - "candlattachments" => 1, - "canviewboardclosed" => 1, - "canpostthreads" => 1, - "canpostreplys" => 1, - "canpostattachments" => 1, - "canratethreads" => 1, - "modposts" => 0, - "modthreads" => 0, - "modattachments" => 0, - "mod_edit_posts" => 0, - "caneditposts" => 1, - "candeleteposts" => 1, - "candeletethreads" => 1, - "caneditattachments" => 1, - "canviewdeletionnotice" => 1, - "canpostpolls" => 1, - "canvotepolls" => 1, - "canundovotes" => 0, - "canusepms" => 1, - "cansendpms" => 1, - "cantrackpms" => 1, - "candenypmreceipts" => 1, - "pmquota" => 100, - "maxpmrecipients" => 5, - "cansendemail" => 1, - "cansendemailoverride" => 0, - "maxemails" => 4, - "emailfloodtime" => 5, - "canviewmemberlist" => 1, - "canviewcalendar" => 1, - "canaddevents" => 1, - "canbypasseventmod" => 0, - "canmoderateevents" => 0, - "canviewonline" => 1, - "canviewwolinvis" => 0, - "canviewonlineips" => 0, - "cancp" => 0, - "issupermod" => 0, - "cansearch" => 1, - "canusercp" => 1, - "canuploadavatars" => 1, - "canratemembers" => 1, - "canchangename" => 0, - "canbereported" => 0, - "canchangewebsite" => 1, - "showforumteam" => 0, - "usereputationsystem" => 1, - "cangivereputations" => 1, - "candeletereputations" => 1, - "reputationpower" => 1, - "maxreputationsday" => 5, - "maxreputationsperuser" => 0, - "maxreputationsperthread" => 0, - "candisplaygroup" => 0, - "attachquota" => 5000, - "cancustomtitle" => 0, - "canwarnusers" => 0, - "canreceivewarnings" => 1, - "maxwarningsday" => 0, - "canmodcp" => 0, - "showinbirthdaylist" => 0, - "canoverridepm" => 0, - "canusesig" => 0, - "canusesigxposts" => 0, - "signofollow" => 0, - "edittimelimit" => 0, - "maxposts" => 0, - "showmemberlist" => 1, - "canmanageannounce" => 0, - "canmanagemodqueue" => 0, - "canmanagereportedcontent" => 0, - "canviewmodlogs" => 0, - "caneditprofiles" => 0, - "canbanusers" => 0, - "canviewwarnlogs" => 0, - "canuseipsearch" => 0 -); - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->user_groups, "index.php?module=user-groups"); - -if($mybb->input['action'] == "add" || !$mybb->input['action']) -{ - $sub_tabs['manage_groups'] = array( - 'title' => $lang->manage_user_groups, - 'link' => "index.php?module=user-groups", - 'description' => $lang->manage_user_groups_desc - ); - $sub_tabs['add_group'] = array( - 'title' => $lang->add_user_group, - 'link' => "index.php?module=user-groups&action=add", - 'description' => $lang->add_user_group_desc - ); -} - -$plugins->run_hooks("admin_user_groups_begin"); - -if($mybb->input['action'] == "approve_join_request") -{ - $query = $db->simple_select("joinrequests", "*", "rid='".$mybb->input['rid']."'"); - $request = $db->fetch_array($query); - - if(!$request['rid']) - { - flash_message($lang->error_invalid_join_request, 'error'); - admin_redirect("index.php?module=user-groups"); - } - - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=user-groups&action=join_requests&gid={$request['gid']}"); - } - - $plugins->run_hooks("admin_user_groups_approve_join_request"); - - // Add the user to the group - join_usergroup($request['uid'], $request['gid']); - - // Delete the join request - $db->delete_query("joinrequests", "rid='{$request['rid']}'"); - - $plugins->run_hooks("admin_user_groups_approve_join_request_commit"); - - flash_message($lang->success_join_request_approved, "success"); - admin_redirect("index.php?module=user-groups&action=join_requests&gid={$request['gid']}"); -} - -if($mybb->input['action'] == "deny_join_request") -{ - $query = $db->simple_select("joinrequests", "*", "rid='".$mybb->input['rid']."'"); - $request = $db->fetch_array($query); - - if(!$request['rid']) - { - flash_message($lang->error_invalid_join_request, 'error'); - admin_redirect("index.php?module=user-groups"); - } - - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=user-groups&action=join_requests&gid={$request['gid']}"); - } - - $plugins->run_hooks("admin_user_groups_deny_join_request"); - - // Delete the join request - $db->delete_query("joinrequests", "rid='{$request['rid']}'"); - - $plugins->run_hooks("admin_user_groups_deny_join_request_commit"); - - flash_message($lang->success_join_request_denied, "success"); - admin_redirect("index.php?module=user-groups&action=join_requests&gid={$request['gid']}"); -} - -if($mybb->input['action'] == "join_requests") -{ - $query = $db->simple_select("usergroups", "*", "gid='".$mybb->get_input('gid', MyBB::INPUT_INT)."'"); - $group = $db->fetch_array($query); - - if(!$group['gid'] || $group['type'] != 4) - { - flash_message($lang->error_invalid_user_group, 'error'); - admin_redirect("index.php?module=user-groups"); - } - - $plugins->run_hooks("admin_user_groups_join_requests_start"); - - if($mybb->request_method == "post" && is_array($mybb->input['users'])) - { - $uid_in = implode(",", array_map('intval', $mybb->input['users'])); - - if(isset($mybb->input['approve'])) - { - foreach($mybb->input['users'] as $uid) - { - $uid = (int)$uid; - join_usergroup($uid, $group['gid']); - } - // Log admin action - log_admin_action("approve", htmlspecialchars_uni($group['title']), $group['gid']); - $message = $lang->success_selected_requests_approved; - } - else - { - // Log admin action - log_admin_action("deny", htmlspecialchars_uni($group['title']), $group['gid']); - $message = $lang->success_selected_requests_denied; - } - - $plugins->run_hooks("admin_user_groups_join_requests_commit"); - - // Go through and delete the join requests from the database - $db->delete_query("joinrequests", "uid IN ({$uid_in}) AND gid='{$group['gid']}'"); - - $plugins->run_hooks("admin_user_groups_join_requests_commit_end"); - - flash_message($message, 'success'); - admin_redirect("index.php?module=user-groups&action=join_requests&gid={$group['gid']}"); - } - - $page->add_breadcrumb_item($lang->join_requests_for.' '.htmlspecialchars_uni($group['title'])); - $page->output_header($lang->join_requests_for.' '.htmlspecialchars_uni($group['title'])); - - $sub_tabs = array(); - $sub_tabs['join_requests'] = array( - 'title' => $lang->group_join_requests, - 'link' => "index.php?module=user-groups&action=join_requests&gid={$group['gid']}", - 'description' => $lang->group_join_requests_desc - ); - - $page->output_nav_tabs($sub_tabs, 'join_requests'); - - $query = $db->simple_select("joinrequests", "COUNT(*) AS num_requests", "gid='{$group['gid']}'"); - $num_requests = $db->fetch_field($query, "num_requests"); - - $per_page = 20; - - if($mybb->input['page'] > 0) - { - $current_page = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($current_page-1)*$per_page; - $pages = $num_requests / $per_page; - $pages = ceil($pages); - if($current_page > $pages) - { - $start = 0; - $current_page = 1; - } - } - else - { - $start = 0; - $current_page = 1; - } - - // Do we need to construct the pagination? - $pagination = ''; - if($num_requests > $per_page) - { - $pagination = draw_admin_pagination($page, $per_page, $num_requests, "index.php?module=user-groups&action=join_requests&gid={$group['gid']}"); - echo $pagination; - } - - $form = new Form("index.php?module=user-groups&action=join_requests&gid={$group['gid']}", "post"); - $table = new Table; - $table->construct_header($form->generate_check_box("checkall", 1, "", array('class' => 'checkall')), array('width' => 1)); - $table->construct_header($lang->users); - $table->construct_header($lang->reason); - $table->construct_header($lang->date_requested, array("class" => 'align_center', "width" => 200)); - $table->construct_header($lang->controls, array("class" => "align_center", "width" => 200)); - - $query = $db->query(" - SELECT j.*, u.username - FROM ".TABLE_PREFIX."joinrequests j - INNER JOIN ".TABLE_PREFIX."users u ON (u.uid=j.uid) - WHERE j.gid='{$group['gid']}' - ORDER BY dateline ASC - LIMIT {$start}, {$per_page} - "); - - while($request = $db->fetch_array($query)) - { - $table->construct_cell($form->generate_check_box("users[]", $request['uid'], "")); - $table->construct_cell("".build_profile_link(htmlspecialchars_uni($request['username']), $request['uid'], "_blank").""); - $table->construct_cell(htmlspecialchars_uni($request['reason'])); - $table->construct_cell(my_date('relative', $request['dateline']), array('class' => 'align_center')); - - $popup = new PopupMenu("join_{$request['rid']}", $lang->options); - $popup->add_item($lang->approve, "index.php?module=user-groups&action=approve_join_request&rid={$request['rid']}&my_post_key={$mybb->post_code}"); - $popup->add_item($lang->deny, "index.php?module=user-groups&action=deny_join_request&rid={$request['rid']}&my_post_key={$mybb->post_code}"); - - $table->construct_cell($popup->fetch(), array('class' => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_join_requests, array("colspan" => 6)); - $table->construct_row(); - } - - $table->output($lang->join_requests_for.' '.htmlspecialchars_uni($group['title'])); - echo $pagination; - - $buttons[] = $form->generate_submit_button($lang->approve_selected_requests, array('name' => 'approve')); - $buttons[] = $form->generate_submit_button($lang->deny_selected_requests, array('name' => 'deny')); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} -if($mybb->input['action'] == "add_leader" && $mybb->request_method == "post") -{ - $query = $db->simple_select("usergroups", "*", "gid='".$mybb->get_input('gid', MyBB::INPUT_INT)."'"); - $group = $db->fetch_array($query); - - if(!$group['gid']) - { - flash_message($lang->error_invalid_user_group, 'error'); - admin_redirect("index.php?module=user-group"); - } - - $plugins->run_hooks("admin_user_groups_add_leader"); - - $user = get_user_by_username($mybb->input['username'], array('fields' => 'username')); - if(!$user['uid']) - { - $errors[] = $lang->error_invalid_username; - } - else - { - // Is this user already a leader of this group? - $query = $db->simple_select("groupleaders", "uid", "uid='{$user['uid']}' AND gid='{$group['gid']}'"); - $existing_leader = $db->fetch_field($query, "uid"); - if($existing_leader) - { - $errors[] = $lang->error_already_leader; - } - } - - // No errors, insert - if(!$errors) - { - $new_leader = array( - "gid" => $group['gid'], - "uid" => $user['uid'], - "canmanagemembers" => $mybb->get_input('canmanagemembers', MyBB::INPUT_INT), - "canmanagerequests" => $mybb->get_input('canmanagerequests', MyBB::INPUT_INT), - "caninvitemembers" => $mybb->get_input('caninvitemembers', MyBB::INPUT_INT) - ); - - $makeleadermember = $mybb->get_input('makeleadermember', MyBB::INPUT_INT); - if($makeleadermember == 1) - { - join_usergroup($user['uid'], $group['gid']); - } - - $plugins->run_hooks("admin_user_groups_add_leader_commit"); - - $db->insert_query("groupleaders", $new_leader); - - $cache->update_groupleaders(); - - // Log admin action - log_admin_action($user['uid'], htmlspecialchars_uni($user['username']), $group['gid'], htmlspecialchars_uni($group['title'])); - - $username = htmlspecialchars_uni($user['username']); - flash_message("{$username} ".$lang->success_user_made_leader, 'success'); - admin_redirect("index.php?module=user-groups&action=leaders&gid={$group['gid']}"); - } - else - { - // Errors, show leaders page - $mybb->input['action'] = "leaders"; - } -} - -// Show a listing of group leaders -if($mybb->input['action'] == "leaders") -{ - $query = $db->simple_select("usergroups", "*", "gid='".$mybb->get_input('gid', MyBB::INPUT_INT)."'"); - $group = $db->fetch_array($query); - - if(!$group['gid']) - { - flash_message($lang->error_invalid_user_group, 'error'); - admin_redirect("index.php?module=user-groups"); - } - - $plugins->run_hooks("admin_user_groups_leaders"); - - $page->add_breadcrumb_item($lang->group_leaders_for.' '.htmlspecialchars_uni($group['title'])); - $page->output_header($lang->group_leaders_for.' '.htmlspecialchars_uni($group['title'])); - - $sub_tabs = array(); - $sub_tabs['group_leaders'] = array( - 'title' => $lang->manage_group_leaders, - 'link' => "index.php?module=user-groups&action=leaders&gid={$group['gid']}", - 'description' => $lang->manage_group_leaders_desc - ); - - $page->output_nav_tabs($sub_tabs, 'group_leaders'); - - $table = new Table; - $table->construct_header($lang->user); - $table->construct_header($lang->can_manage_members, array("class" => 'align_center', "width" => 200)); - $table->construct_header($lang->can_manage_join_requests, array("class" => 'align_center', "width" => 200)); - $table->construct_header($lang->can_invite_members, array("class" => 'align_center', "width" => 200)); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2, "width" => 200)); - - $query = $db->query(" - SELECT g.*, u.username - FROM ".TABLE_PREFIX."groupleaders g - INNER JOIN ".TABLE_PREFIX."users u ON (u.uid=g.uid) - WHERE g.gid='{$group['gid']}' - ORDER BY u.username ASC - "); - while($leader = $db->fetch_array($query)) - { - $leader['username'] = htmlspecialchars_uni($leader['username']); - if($leader['canmanagemembers']) - { - $canmanagemembers = $lang->yes; - } - else - { - $canmanagemembers = $lang->no; - } - - if($leader['canmanagerequests']) - { - $canmanagerequests = $lang->yes; - } - else - { - $canmanagerequests = $lang->no; - } - - if($leader['caninvitemembers']) - { - $caninvitemembers = $lang->yes; - } - else - { - $caninvitemembers = $lang->no; - } - - $table->construct_cell("".build_profile_link($leader['username'], $leader['uid'], "_blank").""); - $table->construct_cell($canmanagemembers, array("class" => "align_center")); - $table->construct_cell($canmanagerequests, array("class" => "align_center")); - $table->construct_cell($caninvitemembers, array("class" => "align_center")); - $table->construct_cell("{$lang->edit}", array("width" => 100, "class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_group_leader_deletion}')\">{$lang->delete}", array("width" => 100, "class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_assigned_leaders, array("colspan" => 5)); - $table->construct_row(); - } - - $table->output($lang->group_leaders_for.' '.htmlspecialchars_uni($group['title'])); - - $form = new Form("index.php?module=user-groups&action=add_leader&gid={$group['gid']}", "post"); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = array_merge($mybb->input, array( - "canmanagemembers" => 1, - "canmanagerequests" => 1, - "caninvitemembers" => 1, - "makeleadermember" => 0 - ) - ); - } - - $form_container = new FormContainer($lang->add_group_leader.' '.htmlspecialchars_uni($group['title'])); - $form_container->output_row($lang->username." *", "", $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'username'); - $form_container->output_row($lang->can_manage_group_members, $lang->can_manage_group_members_desc, $form->generate_yes_no_radio('canmanagemembers', $mybb->input['canmanagemembers'])); - $form_container->output_row($lang->can_manage_group_join_requests, $lang->can_manage_group_join_requests_desc, $form->generate_yes_no_radio('canmanagerequests', $mybb->input['canmanagerequests'])); - $form_container->output_row($lang->can_invite_group_members, $lang->can_invite_group_members_desc, $form->generate_yes_no_radio('caninvitemembers', $mybb->input['caninvitemembers'])); - $form_container->output_row($lang->make_user_member, $lang->make_user_member_desc, $form->generate_yes_no_radio('makeleadermember', $mybb->input['makeleadermember'])); - $form_container->end(); - - // Autocompletion for usernames - echo ' - - - '; - - $buttons[] = $form->generate_submit_button($lang->save_group_leader); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete_leader") -{ - $query = $db->query(" - SELECT l.*, u.username - FROM ".TABLE_PREFIX."groupleaders l - INNER JOIN ".TABLE_PREFIX."users u ON (u.uid=l.uid) - WHERE l.lid='".$mybb->get_input('lid', MyBB::INPUT_INT)."'"); - $leader = $db->fetch_array($query); - - if(!$leader['lid']) - { - flash_message($lang->error_invalid_group_leader, 'error'); - admin_redirect("index.php?module=user-groups"); - } - - $query = $db->simple_select("usergroups", "*", "gid='{$leader['gid']}'"); - $group = $db->fetch_array($query); - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-groups"); - } - - $plugins->run_hooks("admin_user_groups_delete_leader"); - - if($mybb->request_method == "post") - { - $plugins->run_hooks("admin_user_groups_delete_leader_commit"); - - // Delete the leader - $db->delete_query("groupleaders", "lid='{$leader['lid']}'"); - - $plugins->run_hooks("admin_user_groups_delete_leader_commit_end"); - - $cache->update_groupleaders(); - - // Log admin action - log_admin_action($leader['uid'], htmlspecialchars_uni($leader['username']), $group['gid'], htmlspecialchars_uni($group['title'])); - - flash_message($lang->success_group_leader_deleted, 'success'); - admin_redirect("index.php?module=user-groups&action=leaders&gid={$group['gid']}"); - } - else - { - $page->output_confirm_action("index.php?module=user-groups&action=delete_leader&lid={$leader['lid']}", $lang->confirm_group_leader_deletion); - } -} - -if($mybb->input['action'] == "edit_leader") -{ - $query = $db->query(" - SELECT l.*, u.username - FROM ".TABLE_PREFIX."groupleaders l - INNER JOIN ".TABLE_PREFIX."users u ON (u.uid=l.uid) - WHERE l.lid='".$mybb->get_input('lid', MyBB::INPUT_INT)."' - "); - $leader = $db->fetch_array($query); - - if(!$leader['lid']) - { - flash_message($lang->error_invalid_group_leader, 'error'); - admin_redirect("index.php?module=user-groups"); - } - - $query = $db->simple_select("usergroups", "*", "gid='{$leader['gid']}'"); - $group = $db->fetch_array($query); - - $plugins->run_hooks("admin_user_groups_edit_leader"); - - if($mybb->request_method == "post") - { - $updated_leader = array( - "canmanagemembers" => $mybb->get_input('canmanagemembers', MyBB::INPUT_INT), - "canmanagerequests" => $mybb->get_input('canmanagerequests', MyBB::INPUT_INT), - "caninvitemembers" => $mybb->get_input('caninvitemembers', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_user_groups_edit_leader_commit"); - - $db->update_query("groupleaders", $updated_leader, "lid={$leader['lid']}"); - - $cache->update_groupleaders(); - - // Log admin action - log_admin_action($leader['uid'], htmlspecialchars_uni($leader['username']), $group['gid'], htmlspecialchars_uni($group['title'])); - - flash_message($lang->success_group_leader_updated, 'success'); - admin_redirect("index.php?module=user-groups&action=leaders&gid={$group['gid']}"); - } - - if(!$errors) - { - $mybb->input = array_merge($mybb->input, $leader); - } - - $page->add_breadcrumb_item($lang->group_leaders_for.' '.htmlspecialchars_uni($group['title']), "index.php?module=user-groups&action=leaders&gid={$group['gid']}"); - $leader['username'] = htmlspecialchars_uni($leader['username']); - $page->add_breadcrumb_item($lang->edit_leader." {$leader['username']}"); - - $page->output_header($lang->edit_group_leader); - - $sub_tabs = array(); - $sub_tabs['group_leaders'] = array( - 'title' => $lang->edit_group_leader, - 'link' => "index.php?module=user-groups&action=edit_leader&lid={$leader['lid']}", - 'description' => $lang->edit_group_leader_desc - ); - - $page->output_nav_tabs($sub_tabs, 'group_leaders'); - - $form = new Form("index.php?module=user-groups&action=edit_leader&lid={$leader['lid']}", "post"); - - $form_container = new FormContainer($lang->edit_group_leader); - $form_container->output_row($lang->username." *", "", $leader['username']); - - $form_container->output_row($lang->can_manage_group_members, $lang->can_manage_group_members_desc, $form->generate_yes_no_radio('canmanagemembers', $mybb->input['canmanagemembers'])); - $form_container->output_row($lang->can_manage_group_join_requests, $lang->can_manage_group_join_requests_desc, $form->generate_yes_no_radio('canmanagerequests', $mybb->input['canmanagerequests'])); - $form_container->output_row($lang->can_invite_group_members, $lang->can_invite_group_members_desc, $form->generate_yes_no_radio('caninvitemembers', $mybb->input['caninvitemembers'])); - $buttons[] = $form->generate_submit_button($lang->save_group_leader); - - $form_container->end(); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_user_groups_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(my_strpos($mybb->input['namestyle'], "{username}") === false) - { - $errors[] = $lang->error_missing_namestyle_username; - } - - if(!$errors) - { - if($mybb->input['stars'] < 1) - { - $mybb->input['stars'] = 0; - } - - if(!$mybb->input['starimage']) - { - $mybb->input['starimage'] = "images/star.png"; - } - - $new_usergroup = array( - "type" => 2, - "title" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "namestyle" => $db->escape_string($mybb->input['namestyle']), - "usertitle" => $db->escape_string($mybb->input['usertitle']), - "stars" => $mybb->get_input('stars', MyBB::INPUT_INT), - "starimage" => $db->escape_string($mybb->input['starimage']), - "disporder" => 0 - ); - - // Set default permissions - if($mybb->input['copyfrom'] == 0) - { - $new_usergroup = array_merge($new_usergroup, $usergroup_permissions); - } - // Copying permissions from another group - else - { - $query = $db->simple_select("usergroups", "*", "gid='".$mybb->get_input('copyfrom', MyBB::INPUT_INT)."'"); - $existing_usergroup = $db->fetch_array($query); - foreach(array_keys($usergroup_permissions) as $field) - { - $new_usergroup[$field] = $existing_usergroup[$field]; - } - } - - $plugins->run_hooks("admin_user_groups_add_commit"); - - $gid = $db->insert_query("usergroups", $new_usergroup); - - $plugins->run_hooks("admin_user_groups_add_commit_end"); - - // Are we copying permissions? If so, copy all forum permissions too - if($mybb->input['copyfrom'] > 0) - { - $query = $db->simple_select("forumpermissions", "*", "gid='".$mybb->get_input('copyfrom', MyBB::INPUT_INT)."'"); - while($forum_permission = $db->fetch_array($query)) - { - unset($forum_permission['pid']); - $forum_permission['gid'] = $gid; - $db->insert_query("forumpermissions", $forum_permission); - } - } - - // Update the caches - $cache->update_usergroups(); - $cache->update_forumpermissions(); - - // Log admin action - log_admin_action($gid, htmlspecialchars_uni($mybb->input['title'])); - - flash_message($lang->success_group_created, 'success'); - admin_redirect("index.php?module=user-groups&action=edit&gid={$gid}"); - } - } - - $page->add_breadcrumb_item($lang->add_user_group); - $page->output_header($lang->add_user_group); - - $page->output_nav_tabs($sub_tabs, 'add_group'); - $form = new Form("index.php?module=user-groups&action=add", "post"); - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = array_merge($mybb->input, array( - "namestyle" => "{username}" - ) - ); - } - - $form_container = new FormContainer($lang->add_user_group); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_description, "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->username_style, $lang->username_style_desc, $form->generate_text_box('namestyle', $mybb->input['namestyle'], array('id' => 'namestyle')), 'namestyle'); - $form_container->output_row($lang->user_title, $lang->user_title_desc, $form->generate_text_box('usertitle', $mybb->input['usertitle'], array('id' => 'usertitle')), 'usertitle'); - - $options[0] = $lang->do_not_copy_permissions; - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $options[$usergroup['gid']] = htmlspecialchars_uni($usergroup['title']); - } - $form_container->output_row($lang->copy_permissions_from, $lang->copy_permissions_from_desc, $form->generate_select_box('copyfrom', $options, $mybb->input['copyfrom'], array('id' => 'copyfrom')), 'copyfrom'); - - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->save_user_group); - $form->output_submit_wrapper($buttons); - - $form->end(); - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("usergroups", "*", "gid='".$mybb->get_input('gid', MyBB::INPUT_INT)."'"); - $usergroup = $db->fetch_array($query); - - if(!$usergroup['gid']) - { - flash_message($lang->error_invalid_user_group, 'error'); - admin_redirect("index.php?module=user-group"); - } - else - { - if(preg_match("#<((m[^a])|(b[^diloru>])|(s[^aemptu>]))(\s*[^>]*)>#si", $mybb->input['namestyle'])) - { - $errors[] = $lang->error_disallowed_namestyle_username; - $mybb->input['namestyle'] = $usergroup['namestyle']; - } - } - - $plugins->run_hooks("admin_user_groups_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(my_strpos($mybb->input['namestyle'], "{username}") === false) - { - $errors[] = $lang->error_missing_namestyle_username; - } - - if($mybb->input['moderate'] == 1 && $mybb->input['invite'] == 1) - { - $errors[] = $lang->error_cannot_have_both_types; - } - - if(!$errors) - { - if($mybb->input['joinable'] == 1) - { - if($mybb->input['moderate'] == 1) - { - $mybb->input['type'] = "4"; - } - elseif($mybb->input['invite'] == 1) - { - $mybb->input['type'] = "5"; - } - else - { - $mybb->input['type'] = "3"; - } - } - else - { - $mybb->input['type'] = "2"; - } - - if($usergroup['type'] == 1) - { - $mybb->input['type'] = 1; - } - - if($mybb->input['stars'] < 1) - { - $mybb->input['stars'] = 0; - } - - $updated_group = array( - "type" => $mybb->get_input('type', MyBB::INPUT_INT), - "title" => $db->escape_string($mybb->input['title']), - "description" => $db->escape_string($mybb->input['description']), - "namestyle" => $db->escape_string($mybb->input['namestyle']), - "usertitle" => $db->escape_string($mybb->input['usertitle']), - "stars" => $mybb->get_input('stars', MyBB::INPUT_INT), - "starimage" => $db->escape_string($mybb->input['starimage']), - "image" => $db->escape_string($mybb->input['image']), - "isbannedgroup" => $mybb->get_input('isbannedgroup', MyBB::INPUT_INT), - "canview" => $mybb->get_input('canview', MyBB::INPUT_INT), - "canviewthreads" => $mybb->get_input('canviewthreads', MyBB::INPUT_INT), - "canviewprofiles" => $mybb->get_input('canviewprofiles', MyBB::INPUT_INT), - "candlattachments" => $mybb->get_input('candlattachments', MyBB::INPUT_INT), - "canviewboardclosed" => $mybb->get_input('canviewboardclosed', MyBB::INPUT_INT), - "canpostthreads" => $mybb->get_input('canpostthreads', MyBB::INPUT_INT), - "canpostreplys" => $mybb->get_input('canpostreplys', MyBB::INPUT_INT), - "canpostattachments" => $mybb->get_input('canpostattachments', MyBB::INPUT_INT), - "canratethreads" => $mybb->get_input('canratethreads', MyBB::INPUT_INT), - "modposts" => $mybb->get_input('modposts', MyBB::INPUT_INT), - "modthreads" => $mybb->get_input('modthreads', MyBB::INPUT_INT), - "mod_edit_posts" => $mybb->get_input('mod_edit_posts', MyBB::INPUT_INT), - "modattachments" => $mybb->get_input('modattachments', MyBB::INPUT_INT), - "caneditposts" => $mybb->get_input('caneditposts', MyBB::INPUT_INT), - "candeleteposts" => $mybb->get_input('candeleteposts', MyBB::INPUT_INT), - "candeletethreads" => $mybb->get_input('candeletethreads', MyBB::INPUT_INT), - "caneditattachments" => $mybb->get_input('caneditattachments', MyBB::INPUT_INT), - "canviewdeletionnotice" => $mybb->get_input('canviewdeletionnotice', MyBB::INPUT_INT), - "canpostpolls" => $mybb->get_input('canpostpolls', MyBB::INPUT_INT), - "canvotepolls" => $mybb->get_input('canvotepolls', MyBB::INPUT_INT), - "canundovotes" => $mybb->get_input('canundovotes', MyBB::INPUT_INT), - "canusepms" => $mybb->get_input('canusepms', MyBB::INPUT_INT), - "cansendpms" => $mybb->get_input('cansendpms', MyBB::INPUT_INT), - "cantrackpms" => $mybb->get_input('cantrackpms', MyBB::INPUT_INT), - "candenypmreceipts" => $mybb->get_input('candenypmreceipts', MyBB::INPUT_INT), - "pmquota" => $mybb->get_input('pmquota', MyBB::INPUT_INT), - "maxpmrecipients" => $mybb->get_input('maxpmrecipients', MyBB::INPUT_INT), - "cansendemail" => $mybb->get_input('cansendemail', MyBB::INPUT_INT), - "cansendemailoverride" => $mybb->get_input('cansendemailoverride', MyBB::INPUT_INT), - "maxemails" => $mybb->get_input('maxemails', MyBB::INPUT_INT), - "emailfloodtime" => $mybb->get_input('emailfloodtime', MyBB::INPUT_INT), - "canviewmemberlist" => $mybb->get_input('canviewmemberlist', MyBB::INPUT_INT), - "canviewcalendar" => $mybb->get_input('canviewcalendar', MyBB::INPUT_INT), - "canaddevents" => $mybb->get_input('canaddevents', MyBB::INPUT_INT), - "canbypasseventmod" => $mybb->get_input('canbypasseventmod', MyBB::INPUT_INT), - "canmoderateevents" => $mybb->get_input('canmoderateevents', MyBB::INPUT_INT), - "canviewonline" => $mybb->get_input('canviewonline', MyBB::INPUT_INT), - "canviewwolinvis" => $mybb->get_input('canviewwolinvis', MyBB::INPUT_INT), - "canviewonlineips" => $mybb->get_input('canviewonlineips', MyBB::INPUT_INT), - "cancp" => $mybb->get_input('cancp', MyBB::INPUT_INT), - "issupermod" => $mybb->get_input('issupermod', MyBB::INPUT_INT), - "cansearch" => $mybb->get_input('cansearch', MyBB::INPUT_INT), - "canusercp" => $mybb->get_input('canusercp', MyBB::INPUT_INT), - "canuploadavatars" => $mybb->get_input('canuploadavatars', MyBB::INPUT_INT), - "canchangename" => $mybb->get_input('canchangename', MyBB::INPUT_INT), - "canbereported" => $mybb->get_input('canbereported', MyBB::INPUT_INT), - "canchangewebsite" => $mybb->get_input('canchangewebsite', MyBB::INPUT_INT), - "showforumteam" => $mybb->get_input('showforumteam', MyBB::INPUT_INT), - "usereputationsystem" => $mybb->get_input('usereputationsystem', MyBB::INPUT_INT), - "cangivereputations" => $mybb->get_input('cangivereputations', MyBB::INPUT_INT), - "candeletereputations" => $mybb->get_input('candeletereputations', MyBB::INPUT_INT), - "reputationpower" => $mybb->get_input('reputationpower', MyBB::INPUT_INT), - "maxreputationsday" => $mybb->get_input('maxreputationsday', MyBB::INPUT_INT), - "maxreputationsperuser" => $mybb->get_input('maxreputationsperuser', MyBB::INPUT_INT), - "maxreputationsperthread" => $mybb->get_input('maxreputationsperthread', MyBB::INPUT_INT), - "attachquota" => $mybb->get_input('attachquota', MyBB::INPUT_INT), - "cancustomtitle" => $mybb->get_input('cancustomtitle', MyBB::INPUT_INT), - "canwarnusers" => $mybb->get_input('canwarnusers', MyBB::INPUT_INT), - "canreceivewarnings" =>$mybb->get_input('canreceivewarnings', MyBB::INPUT_INT), - "maxwarningsday" => $mybb->get_input('maxwarningsday', MyBB::INPUT_INT), - "canmodcp" => $mybb->get_input('canmodcp', MyBB::INPUT_INT), - "showinbirthdaylist" => $mybb->get_input('showinbirthdaylist', MyBB::INPUT_INT), - "canoverridepm" => $mybb->get_input('canoverridepm', MyBB::INPUT_INT), - "canusesig" => $mybb->get_input('canusesig', MyBB::INPUT_INT), - "canusesigxposts" => $mybb->get_input('canusesigxposts', MyBB::INPUT_INT), - "signofollow" => $mybb->get_input('signofollow', MyBB::INPUT_INT), - "edittimelimit" => $mybb->get_input('edittimelimit', MyBB::INPUT_INT), - "maxposts" => $mybb->get_input('maxposts', MyBB::INPUT_INT), - "showmemberlist" => $mybb->get_input('showmemberlist', MyBB::INPUT_INT), - "canmanageannounce" => $mybb->get_input('canmanageannounce', MyBB::INPUT_INT), - "canmanagemodqueue" => $mybb->get_input('canmanagemodqueue', MyBB::INPUT_INT), - "canmanagereportedcontent" => $mybb->get_input('canmanagereportedcontent', MyBB::INPUT_INT), - "canviewmodlogs" => $mybb->get_input('canviewmodlogs', MyBB::INPUT_INT), - "caneditprofiles" => $mybb->get_input('caneditprofiles', MyBB::INPUT_INT), - "canbanusers" => $mybb->get_input('canbanusers', MyBB::INPUT_INT), - "canviewwarnlogs" => $mybb->get_input('canviewwarnlogs', MyBB::INPUT_INT), - "canuseipsearch" => $mybb->get_input('canuseipsearch', MyBB::INPUT_INT) - ); - - // Only update the candisplaygroup setting if not a default user group - if($usergroup['type'] != 1) - { - $updated_group['candisplaygroup'] = $mybb->get_input('candisplaygroup', MyBB::INPUT_INT); - } - - $plugins->run_hooks("admin_user_groups_edit_commit"); - - $db->update_query("usergroups", $updated_group, "gid='{$usergroup['gid']}'"); - - // Update the caches - $cache->update_usergroups(); - $cache->update_forumpermissions(); - - // Log admin action - log_admin_action($usergroup['gid'], htmlspecialchars_uni($mybb->input['title'])); - - flash_message($lang->success_group_updated, 'success'); - admin_redirect("index.php?module=user-groups"); - } - } - - $page->add_breadcrumb_item($lang->edit_user_group); - $page->output_header($lang->edit_user_group); - - $sub_tabs = array(); - $sub_tabs['edit_group'] = array( - 'title' => $lang->edit_user_group, - 'description' => $lang->edit_user_group_desc - ); - - $form = new Form("index.php?module=user-groups&action=edit&gid={$usergroup['gid']}", "post"); - - $page->output_nav_tabs($sub_tabs, 'edit_group'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - } - else - { - if($usergroup['type'] == "3") - { - $usergroup['joinable'] = 1; - $usergroup['moderate'] = 0; - $usergroup['invite'] = 0; - } - elseif($usergroup['type'] == "4") - { - $usergroup['joinable'] = 1; - $usergroup['moderate'] = 1; - $usergroup['invite'] = 0; - } - elseif($usergroup['type'] == "5") - { - $usergroup['joinable'] = 1; - $usergroup['moderate'] = 0; - $usergroup['invite'] = 1; - } - else - { - $usergroup['joinable'] = 0; - $usergroup['moderate'] = 0; - $usergroup['invite'] = 0; - } - $mybb->input = array_merge($mybb->input, $usergroup); - } - $tabs = array( - "general" => $lang->general, - "forums_posts" => $lang->forums_posts, - "users_permissions" => $lang->users_permissions, - "misc" => $lang->misc, - "modcp" => $lang->mod_cp - ); - $tabs = $plugins->run_hooks("admin_user_groups_edit_graph_tabs", $tabs); - $page->output_tab_control($tabs); - - echo "
"; - $form_container = new FormContainer($lang->general); - $form_container->output_row($lang->title." *", "", $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->short_description, "", $form->generate_text_box('description', $mybb->input['description'], array('id' => 'description')), 'description'); - $form_container->output_row($lang->username_style, $lang->username_style_desc, $form->generate_text_box('namestyle', $mybb->input['namestyle'], array('id' => 'namestyle')), 'namestyle'); - $form_container->output_row($lang->user_title, $lang->user_title_desc, $form->generate_text_box('usertitle', $mybb->input['usertitle'], array('id' => 'usertitle')), 'usertitle'); - - $stars = ""; - $stars .= "
".$form->generate_numeric_field('stars', $mybb->input['stars'], array('class' => 'field50', 'id' => 'stars', 'min' => 0))."".$form->generate_text_box('starimage', $mybb->input['starimage'], array('id' => 'starimage'))."
{$lang->stars}{$lang->star_image}
"; - $form_container->output_row($lang->user_stars, $lang->user_stars_desc, $stars, "stars"); - - $form_container->output_row($lang->group_image, $lang->group_image_desc, $form->generate_text_box('image', $mybb->input['image'], array('id' => 'image')), 'image'); - - $general_options = array(); - $general_options[] = $form->generate_check_box("showmemberlist", 1, $lang->member_list, array("checked" => $mybb->input['showmemberlist'])); - if($usergroup['gid'] != "1" && $usergroup['gid'] != "5") - { - $general_options[] = $form->generate_check_box("showforumteam", 1, $lang->forum_team, array("checked" => $mybb->input['showforumteam'])); - } - $general_options[] = $form->generate_check_box("isbannedgroup", 1, $lang->is_banned_group, array("checked" => $mybb->input['isbannedgroup'])); - - $form_container->output_row($lang->general_options, "", "
".implode("
", $general_options)."
"); - - if($usergroup['type'] != 1) - { - $public_options = array( - $form->generate_check_box("joinable", 1, $lang->user_joinable, array("checked" => $mybb->input['joinable'])), - $form->generate_check_box("moderate", 1, $lang->moderate_join_requests, array("checked" => $mybb->input['moderate'])), - $form->generate_check_box("invite", 1, $lang->invite_only, array("checked" => $mybb->input['invite'])), - $form->generate_check_box("candisplaygroup", 1, $lang->can_set_as_display_group, array("checked" => $mybb->input['candisplaygroup'])), - ); - $form_container->output_row($lang->publicly_joinable_options, "", "
".implode("
", $public_options)."
"); - } - - $admin_options = array( - $form->generate_check_box("issupermod", 1, $lang->is_super_mod, array("checked" => $mybb->input['issupermod'])), - $form->generate_check_box("canmodcp", 1, $lang->can_access_mod_cp, array("checked" => $mybb->input['canmodcp'])), - $form->generate_check_box("cancp", 1, $lang->can_access_admin_cp, array("checked" => $mybb->input['cancp'])) - ); - $form_container->output_row($lang->moderation_administration_options, "", "
".implode("
", $admin_options)."
"); - - $form_container->end(); - echo "
"; - - // - // FORUMS AND POSTS - // - echo "
"; - $form_container = new FormContainer($lang->forums_posts); - - $viewing_options = array( - $form->generate_check_box("canview", 1, $lang->can_view_board, array("checked" => $mybb->input['canview'])), - $form->generate_check_box("canviewthreads", 1, $lang->can_view_threads, array("checked" => $mybb->input['canviewthreads'])), - $form->generate_check_box("cansearch", 1, $lang->can_search_forums, array("checked" => $mybb->input['cansearch'])), - $form->generate_check_box("canviewprofiles", 1, $lang->can_view_profiles, array("checked" => $mybb->input['canviewprofiles'])), - $form->generate_check_box("candlattachments", 1, $lang->can_download_attachments, array("checked" => $mybb->input['candlattachments'])), - $form->generate_check_box("canviewboardclosed", 1, $lang->can_view_board_closed, array("checked" => $mybb->input['canviewboardclosed'])) - ); - $form_container->output_row($lang->viewing_options, "", "
".implode("
", $viewing_options)."
"); - - $posting_options = array( - $form->generate_check_box("canpostthreads", 1, $lang->can_post_threads, array("checked" => $mybb->input['canpostthreads'])), - $form->generate_check_box("canpostreplys", 1, $lang->can_post_replies, array("checked" => $mybb->input['canpostreplys'])), - $form->generate_check_box("canratethreads", 1, $lang->can_rate_threads, array("checked" => $mybb->input['canratethreads'])), - "{$lang->max_posts_per_day}
{$lang->max_posts_per_day_desc}
".$form->generate_numeric_field('maxposts', $mybb->input['maxposts'], array('id' => 'maxposts', 'class' => 'field50', 'min' => 0)) - ); - $form_container->output_row($lang->posting_rating_options, "", "
".implode("
", $posting_options)."
"); - - $moderator_options = array( - $form->generate_check_box("modposts", 1, $lang->mod_new_posts, array("checked" => $mybb->input['modposts'])), - $form->generate_check_box("modthreads", 1, $lang->mod_new_threads, array("checked" => $mybb->input['modthreads'])), - $form->generate_check_box("modattachments", 1, $lang->mod_new_attachments, array("checked" => $mybb->input['modattachments'])), - $form->generate_check_box("mod_edit_posts", 1, $lang->mod_after_edit, array("checked" => $mybb->input['mod_edit_posts'])) - ); - $form_container->output_row($lang->moderation_options, "", "
".implode("
", $moderator_options)."
"); - - $poll_options = array( - $form->generate_check_box("canpostpolls", 1, $lang->can_post_polls, array("checked" => $mybb->input['canpostpolls'])), - $form->generate_check_box("canvotepolls", 1, $lang->can_vote_polls, array("checked" => $mybb->input['canvotepolls'])), - $form->generate_check_box("canundovotes", 1, $lang->can_undo_votes, array("checked" => $mybb->input['canundovotes'])) - ); - $form_container->output_row($lang->poll_options, "", "
".implode("
", $poll_options)."
"); - - $attachment_options = array( - $form->generate_check_box("canpostattachments", 1, $lang->can_post_attachments, array("checked" => $mybb->input['canpostattachments'])), - "{$lang->attach_quota}
{$lang->attach_quota_desc}
".$form->generate_numeric_field('attachquota', $mybb->input['attachquota'], array('id' => 'attachquota', 'class' => 'field50', 'min' => 0)). "KB" - ); - $form_container->output_row($lang->attachment_options, "", "
".implode("
", $attachment_options)."
"); - - $editing_options = array( - $form->generate_check_box("caneditposts", 1, $lang->can_edit_posts, array("checked" => $mybb->input['caneditposts'])), - $form->generate_check_box("candeleteposts", 1, $lang->can_delete_posts, array("checked" => $mybb->input['candeleteposts'])), - $form->generate_check_box("candeletethreads", 1, $lang->can_delete_threads, array("checked" => $mybb->input['candeletethreads'])), - $form->generate_check_box("caneditattachments", 1, $lang->can_edit_attachments, array("checked" => $mybb->input['caneditattachments'])), - $form->generate_check_box("canviewdeletionnotice", 1, $lang->can_view_deletion_notices, array("checked" => $mybb->input['canviewdeletionnotice'])), - "{$lang->edit_time_limit}
{$lang->edit_time_limit_desc}
".$form->generate_numeric_field('edittimelimit', $mybb->input['edittimelimit'], array('id' => 'edittimelimit', 'class' => 'field50', 'min' => 0)) - ); - $form_container->output_row($lang->editing_deleting_options, "", "
".implode("
", $editing_options)."
"); - - $form_container->end(); - echo "
"; - - // - // USERS AND PERMISSIONS - // - echo "
"; - $form_container = new FormContainer($lang->users_permissions); - - $account_options = array( - $form->generate_check_box("canbereported", 1, $lang->can_be_reported, array("checked" => $mybb->input['canbereported'])), - $form->generate_check_box("canusercp", 1, $lang->can_access_usercp, array("checked" => $mybb->input['canusercp'])), - $form->generate_check_box("canchangename", 1, $lang->can_change_username, array("checked" => $mybb->input['canchangename'])), - $form->generate_check_box("cancustomtitle", 1, $lang->can_use_usertitles, array("checked" => $mybb->input['cancustomtitle'])), - $form->generate_check_box("canuploadavatars", 1, $lang->can_upload_avatars, array("checked" => $mybb->input['canuploadavatars'])), - $form->generate_check_box("canusesig", 1, $lang->can_use_signature, array("checked" => $mybb->input['canusesig'])), - $form->generate_check_box("signofollow", 1, $lang->uses_no_follow, array("checked" => $mybb->input['signofollow'])), - $form->generate_check_box("canchangewebsite", 1, $lang->can_change_website, array("checked" => $mybb->input['canchangewebsite'])), - "{$lang->required_posts}
{$lang->required_posts_desc}
".$form->generate_numeric_field('canusesigxposts', $mybb->input['canusesigxposts'], array('id' => 'canusesigxposts', 'class' => 'field50', 'min' => 0)) - ); - $form_container->output_row($lang->account_management, "", "
".implode("
", $account_options)."
"); - - $reputation_options = array( - $form->generate_check_box("usereputationsystem", 1, $lang->show_reputations, array("checked" => $mybb->input['usereputationsystem'])), - $form->generate_check_box("cangivereputations", 1, $lang->can_give_reputation, array("checked" => $mybb->input['cangivereputations'])), - $form->generate_check_box("candeletereputations", 1, $lang->can_delete_own_reputation, array("checked" => $mybb->input['candeletereputations'])), - "{$lang->points_to_award_take}
{$lang->points_to_award_take_desc}
".$form->generate_numeric_field('reputationpower', $mybb->input['reputationpower'], array('id' => 'reputationpower', 'class' => 'field50', 'min' => 0)), - "{$lang->max_reputations_perthread}
{$lang->max_reputations_perthread_desc}
".$form->generate_numeric_field('maxreputationsperthread', $mybb->input['maxreputationsperthread'], array('id' => 'maxreputationsperthread', 'class' => 'field50', 'min' => 0)), - "{$lang->max_reputations_peruser}
{$lang->max_reputations_peruser_desc}
".$form->generate_numeric_field('maxreputationsperuser', $mybb->input['maxreputationsperuser'], array('id' => 'maxreputationsperuser', 'class' => 'field50', 'min' => 0)), - "{$lang->max_reputations_daily}
{$lang->max_reputations_daily_desc}
".$form->generate_numeric_field('maxreputationsday', $mybb->input['maxreputationsday'], array('id' => 'maxreputationsday', 'class' => 'field50', 'min' => 0)) - ); - $form_container->output_row($lang->reputation_system, "", "
".implode("
", $reputation_options)."
"); - - $warning_options = array( - $form->generate_check_box("canwarnusers", 1, $lang->can_send_warnings, array("checked" => $mybb->input['canwarnusers'])), - $form->generate_check_box("canreceivewarnings", 1, $lang->can_receive_warnings, array("checked" => $mybb->input['canreceivewarnings'])), - "{$lang->warnings_per_day}
".$form->generate_numeric_field('maxwarningsday', $mybb->input['maxwarningsday'], array('id' => 'maxwarningsday', 'class' => 'field50')) - ); - $form_container->output_row($lang->warning_system, "", "
".implode("
", $warning_options)."
"); - - $pm_options = array( - $form->generate_check_box("canusepms", 1, $lang->can_use_pms, array("checked" => $mybb->input['canusepms'])), - $form->generate_check_box("cansendpms", 1, $lang->can_send_pms, array("checked" => $mybb->input['cansendpms'])), - $form->generate_check_box("canoverridepm", 1, $lang->can_override_pms, array("checked" => $mybb->input['canoverridepm'])), - $form->generate_check_box("cantrackpms", 1, $lang->can_track_pms, array("checked" => $mybb->input['cantrackpms'])), - $form->generate_check_box("candenypmreceipts", 1, $lang->can_deny_reciept, array("checked" => $mybb->input['candenypmreceipts'])), - "{$lang->message_quota}
{$lang->message_quota_desc}
".$form->generate_numeric_field('pmquota', $mybb->input['pmquota'], array('id' => 'pmquota', 'class' => 'field50', 'min' => 0)), - "{$lang->max_recipients}
{$lang->max_recipients_desc}
".$form->generate_numeric_field('maxpmrecipients', $mybb->input['maxpmrecipients'], array('id' => 'maxpmrecipients', 'class' => 'field50', 'min' => 0)) - ); - $form_container->output_row($lang->private_messaging, "", "
".implode("
", $pm_options)."
"); - - $form_container->end(); - echo "
"; - - // - // MISC - // - echo "
"; - $form_container = new FormContainer($lang->misc); - - $calendar_options = array( - $form->generate_check_box("canviewcalendar", 1, $lang->can_view_calendar, array("checked" => $mybb->input['canviewcalendar'])), - $form->generate_check_box("canaddevents", 1, $lang->can_post_events, array("checked" => $mybb->input['canaddevents'])), - $form->generate_check_box("canbypasseventmod", 1, $lang->can_bypass_event_moderation, array("checked" => $mybb->input['canbypasseventmod'])), - $form->generate_check_box("canmoderateevents", 1, $lang->can_moderate_events, array("checked" => $mybb->input['canmoderateevents'])) - ); - $form_container->output_row($lang->calendar, "", "
".implode("
", $calendar_options)."
"); - - $wol_options = array( - $form->generate_check_box("canviewonline", 1, $lang->can_view_whos_online, array("checked" => $mybb->input['canviewonline'])), - $form->generate_check_box("canviewwolinvis", 1, $lang->can_view_invisible, array("checked" => $mybb->input['canviewwolinvis'])), - $form->generate_check_box("canviewonlineips", 1, $lang->can_view_ips, array("checked" => $mybb->input['canviewonlineips'])) - ); - $form_container->output_row($lang->whos_online, "", "
".implode("
", $wol_options)."
"); - - $misc_options = array( - $form->generate_check_box("canviewmemberlist", 1, $lang->can_view_member_list, array("checked" => $mybb->input['canviewmemberlist'])), - $form->generate_check_box("showinbirthdaylist", 1, $lang->show_in_birthday_list, array("checked" => $mybb->input['showinbirthdaylist'])), - $form->generate_check_box("cansendemail", 1, $lang->can_email_users, array("checked" => $mybb->input['cansendemail'])), - $form->generate_check_box("cansendemailoverride", 1, $lang->can_email_users_override, array("checked" => $mybb->input['cansendemailoverride'])), - "{$lang->max_emails_per_day}
{$lang->max_emails_per_day_desc}
".$form->generate_numeric_field('maxemails', $mybb->input['maxemails'], array('id' => 'maxemails', 'class' => 'field50', 'min' => 0)), - "{$lang->email_flood_time}
{$lang->email_flood_time_desc}
".$form->generate_numeric_field('emailfloodtime', $mybb->input['emailfloodtime'], array('id' => 'emailfloodtime', 'class' => 'field50', 'min' => 0)) - ); - $form_container->output_row($lang->misc, "", "
".implode("
", $misc_options)."
"); - - $form_container->end(); - echo "
"; - - // - // MODERATOR CP - // - echo "
"; - $form_container = new FormContainer($lang->mod_cp); - - $forum_post_options = array( - $form->generate_check_box("canmanageannounce", 1, $lang->can_manage_announce, array("checked" => $mybb->input['canmanageannounce'])), - $form->generate_check_box("canmanagemodqueue", 1, $lang->can_manage_mod_queue, array("checked" => $mybb->input['canmanagemodqueue'])), - $form->generate_check_box("canmanagereportedcontent", 1, $lang->can_manage_reported_content, array("checked" => $mybb->input['canmanagereportedcontent'])), - $form->generate_check_box("canviewmodlogs", 1, $lang->can_view_mod_logs, array("checked" => $mybb->input['canviewmodlogs'])) - ); - $form_container->output_row($lang->forum_post_options, "", "
".implode("
", $forum_post_options)."
"); - - $user_options = array( - $form->generate_check_box("caneditprofiles", 1, $lang->can_edit_profiles, array("checked" => $mybb->input['caneditprofiles'])), - $form->generate_check_box("canbanusers", 1, $lang->can_ban_users, array("checked" => $mybb->input['canbanusers'])), - $form->generate_check_box("canviewwarnlogs", 1, $lang->can_view_warnlogs, array("checked" => $mybb->input['canviewwarnlogs'])), - $form->generate_check_box("canuseipsearch", 1, $lang->can_use_ipsearch, array("checked" => $mybb->input['canuseipsearch'])) - ); - $form_container->output_row($lang->user_options, "", "
".implode("
", $user_options)."
"); - - $form_container->end(); - echo "
"; - - $plugins->run_hooks("admin_user_groups_edit_graph"); - - $buttons[] = $form->generate_submit_button($lang->save_user_group); - $form->output_submit_wrapper($buttons); - - $form->end(); - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("usergroups", "*", "gid='".$mybb->get_input('gid', MyBB::INPUT_INT)."'"); - $usergroup = $db->fetch_array($query); - - if(!$usergroup['gid']) - { - flash_message($lang->error_invalid_user_group, 'error'); - admin_redirect("index.php?module=user-groups"); - } - if($usergroup['type'] == 1) - { - flash_message($lang->error_default_group_delete, 'error'); - admin_redirect("index.php?module=user-groups"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-groups"); - } - - $plugins->run_hooks("admin_user_groups_delete"); - - if($mybb->request_method == "post") - { - if($usergroup['isbannedgroup'] == 1) - { - // If banned group, move users to default banned group - $updated_users = array("usergroup" => 7); - } - else - { - // Move any users back to the registered group - $updated_users = array("usergroup" => 2); - } - - $db->update_query("users", $updated_users, "usergroup='{$usergroup['gid']}'"); - - $updated_users = array("displaygroup" => "usergroup"); - $plugins->run_hooks("admin_user_groups_delete_commit"); - - $db->update_query("users", $updated_users, "displaygroup='{$usergroup['gid']}'", "", true); // No quotes = displaygroup=usergroup - - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("users", "uid", "','||additionalgroups||',' LIKE '%,{$usergroup['gid']},%'"); - break; - default: - $query = $db->simple_select("users", "uid", "CONCAT(',',additionalgroups,',') LIKE '%,{$usergroup['gid']},%'"); - } - while($user = $db->fetch_array($query)) - { - leave_usergroup($user['uid'], $usergroup['gid']); - } - - $db->update_query("banned", array("gid" => 7), "gid='{$usergroup['gid']}'"); - $db->update_query("banned", array("oldgroup" => 2), "oldgroup='{$usergroup['gid']}'"); - $db->update_query("banned", array("olddisplaygroup" => "oldgroup"), "olddisplaygroup='{$usergroup['gid']}'", "", true); // No quotes = displaygroup=usergroup - - $db->delete_query("forumpermissions", "gid='{$usergroup['gid']}'"); - $db->delete_query("calendarpermissions", "gid='{$usergroup['gid']}'"); - $db->delete_query("joinrequests", "gid='{$usergroup['gid']}'"); - $db->delete_query("moderators", "id='{$usergroup['gid']}' AND isgroup='1'"); - $db->delete_query("groupleaders", "gid='{$usergroup['gid']}'"); - $db->delete_query("usergroups", "gid='{$usergroup['gid']}'"); - - $plugins->run_hooks("admin_user_groups_delete_commit_end"); - - $cache->update_groupleaders(); - $cache->update_moderators(); - $cache->update_usergroups(); - $cache->update_forumpermissions(); - $cache->update_banned(); - - // Log admin action - log_admin_action($usergroup['gid'], htmlspecialchars_uni($usergroup['title'])); - - flash_message($lang->success_group_deleted, 'success'); - admin_redirect("index.php?module=user-groups"); - } - else - { - $page->output_confirm_action("index.php?module=user-groups&action=delete&gid={$usergroup['gid']}", $lang->confirm_group_deletion); - } -} - -if($mybb->input['action'] == "disporder" && $mybb->request_method == "post") -{ - $plugins->run_hooks("admin_user_groups_disporder"); - - foreach($mybb->input['disporder'] as $gid=>$order) - { - $gid = (int)$gid; - $order = (int)$order; - if($gid != 0 && $order != 0) - { - $sql_array = array( - 'disporder' => $order, - ); - $db->update_query('usergroups', $sql_array, "gid = '{$gid}'"); - } - } - - // Log admin action - log_admin_action(); - - $plugins->run_hooks("admin_user_groups_disporder_commit"); - - flash_message($lang->success_group_disporders_updated, 'success'); - admin_redirect("index.php?module=user-groups"); -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_user_groups_start"); - - if($mybb->request_method == "post") - { - if(!empty($mybb->input['disporder'])) - { - foreach($mybb->input['disporder'] as $gid => $order) - { - $db->update_query("usergroups", array('disporder' => (int)$order), "gid='".(int)$gid."'"); - } - - $plugins->run_hooks("admin_user_groups_start_commit"); - - $cache->update_usergroups(); - - flash_message($lang->success_groups_disporder_updated, 'success'); - admin_redirect("index.php?module=user-groups"); - } - } - - $page->output_header($lang->manage_user_groups); - $page->output_nav_tabs($sub_tabs, 'manage_groups'); - - $form = new Form("index.php?module=user-groups", "post", "groups"); - - $query = $db->query(" - SELECT g.gid, COUNT(u.uid) AS users - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."usergroups g ON (g.gid=u.usergroup) - GROUP BY g.gid - "); - while($groupcount = $db->fetch_array($query)) - { - $primaryusers[$groupcount['gid']] = $groupcount['users']; - } - - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->query(" - SELECT g.gid, COUNT(u.uid) AS users - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."usergroups g ON (','|| u.additionalgroups|| ',' LIKE '%,'|| g.gid|| ',%') - WHERE g.gid != '0' AND g.gid is not NULL GROUP BY g.gid - "); - break; - default: - $query = $db->query(" - SELECT g.gid, COUNT(u.uid) AS users - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."usergroups g ON (CONCAT(',', u.additionalgroups, ',') LIKE CONCAT('%,', g.gid, ',%')) - WHERE g.gid != '0' AND g.gid is not NULL GROUP BY g.gid - "); - } - while($groupcount = $db->fetch_array($query)) - { - $secondaryusers[$groupcount['gid']] = $groupcount['users']; - } - - $query = $db->query(" - SELECT g.gid, COUNT(r.uid) AS users - FROM ".TABLE_PREFIX."joinrequests r - LEFT JOIN ".TABLE_PREFIX."usergroups g ON (g.gid=r.gid) - GROUP BY g.gid - "); - - $joinrequests = array(); - while($joinrequest = $db->fetch_array($query)) - { - $joinrequests[$joinrequest['gid']] = $joinrequest['users']; - } - - // Fetch group leaders - $leaders = array(); - $query = $db->query(" - SELECT u.username, u.uid, l.gid - FROM ".TABLE_PREFIX."groupleaders l - INNER JOIN ".TABLE_PREFIX."users u ON (u.uid=l.uid) - ORDER BY u.username ASC - "); - while($leader = $db->fetch_array($query)) - { - $leaders[$leader['gid']][] = build_profile_link(htmlspecialchars_uni($leader['username']), $leader['uid'], "_blank"); - } - - $form_container = new FormContainer($lang->user_groups); - $form_container->output_row_header($lang->group); - $form_container->output_row_header($lang->number_of_users, array("class" => "align_center", 'width' => '75')); - $form_container->output_row_header($lang->order, array("class" => "align_center", 'width' => '5%')); - $form_container->output_row_header($lang->controls, array("class" => "align_center")); - - $query = $db->simple_select("usergroups", "*", "", array('order_by' => 'disporder')); - while($usergroup = $db->fetch_array($query)) - { - if($usergroup['type'] > 1) - { - $icon = "\"{$lang-custom_user_group}\" style=\"vertical-align: middle;\" />"; - } - else - { - $icon = "\"{$lang-default_user_group}\" style=\"vertical-align: middle;\" />"; - } - - $leaders_list = ''; - if(isset($leaders[$usergroup['gid']])) - { - $leaders_list = "
{$lang->group_leaders}: ".implode($lang->comma, $leaders[$usergroup['gid']]); - } - - $join_requests = ''; - if($joinrequests[$usergroup['gid']] > 1 && $usergroup['type'] == 4) - { - $join_requests = " ({$joinrequests[$usergroup['gid']]} {$lang->outstanding_join_request})"; - } - else if($joinrequests[$usergroup['gid']] == 1 && $usergroup['type'] == 4) - { - $join_requests = " ({$joinrequests[$usergroup['gid']]} {$lang->outstanding_join_request})"; - } - - $form_container->output_cell("
{$icon}
".htmlspecialchars_uni($usergroup['title'])."{$join_requests}
".htmlspecialchars_uni($usergroup['description'])."{$leaders_list}
"); - - if(!$primaryusers[$usergroup['gid']]) - { - $primaryusers[$usergroup['gid']] = 0; - } - $numusers = $primaryusers[$usergroup['gid']]; - $numusers += $secondaryusers[$usergroup['gid']]; - - $form_container->output_cell(my_number_format($numusers), array("class" => "align_center")); - - if($usergroup['showforumteam'] == 1) - { - $form_container->output_cell("", array("class" => "align_center")); - } - else - { - $form_container->output_cell(" ", array("class" => "align_center")); - } - - $popup = new PopupMenu("usergroup_{$usergroup['gid']}", $lang->options); - $popup->add_item($lang->edit_group, "index.php?module=user-groups&action=edit&gid={$usergroup['gid']}"); - $popup->add_item($lang->list_users, "index.php?module=user-users&action=search&results=1&conditions[usergroup]={$usergroup['gid']}"); - if($joinrequests[$usergroup['gid']] > 0 && $usergroup['type'] == 4) - { - $popup->add_item($lang->join_requests, "index.php?module=user-groups&action=join_requests&gid={$usergroup['gid']}"); - } - $popup->add_item($lang->group_leaders, "index.php?module=user-groups&action=leaders&gid={$usergroup['gid']}"); - if($usergroup['type'] > 1) - { - $popup->add_item($lang->delete_group, "index.php?module=user-groups&action=delete&gid={$usergroup['gid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_group_deletion}')"); - } - $form_container->output_cell($popup->fetch(), array("class" => "align_center")); - $form_container->construct_row(); - } - - if($form_container->num_rows() == 0) - { - $form_container->output_cell($lang->no_groups, array('colspan' => 4)); - $form_container->construct_row(); - } - - $form_container->end(); - - $buttons = array(); - $buttons[] = $form->generate_submit_button($lang->update_groups_order); - $form->output_submit_wrapper($buttons); - - $form->end(); - - echo << -
-{$lang->legend} -{$lang->custom_user_group} {$lang->custom_user_group}
-{$lang->default_user_group} {$lang->default_user_group} -
-LEGEND; - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/user/index.html b/html/forums/admin/modules/user/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/modules/user/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/modules/user/mass_mail.php b/html/forums/admin/modules/user/mass_mail.php deleted file mode 100644 index c607bbb..0000000 --- a/html/forums/admin/modules/user/mass_mail.php +++ /dev/null @@ -1,1668 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -require_once MYBB_ROOT."/inc/functions_massmail.php"; - -$page->add_breadcrumb_item($lang->mass_mail, "index.php?module=user-mass_mail"); - -if($mybb->input['action'] == "send" || $mybb->input['action'] == "archive" || !$mybb->input['action']) -{ - $sub_tabs['mail_queue'] = array( - 'title' => $lang->mass_mail_queue, - 'link' => 'index.php?module=user-mass_mail', - 'description' => $lang->mass_mail_queue_desc - ); - - $sub_tabs['send_mass_mail'] = array( - 'title' => $lang->create_mass_mail, - 'link' => 'index.php?module=user-mass_mail&action=send', - 'description' => $lang->create_mass_mail_desc - ); - - $sub_tabs['archive'] = array( - 'title' => $lang->mass_mail_archive, - 'link' => 'index.php?module=user-mass_mail&action=archive', - 'description' => $lang->mass_mail_archive_desc - ); -} - -$plugins->run_hooks("admin_user_mass_email"); - -if($mybb->input['action'] == "edit") -{ - $page->add_breadcrumb_item($lang->edit_mass_mail); - - $query = $db->simple_select("massemails", "*", "mid='".$mybb->get_input('mid', MyBB::INPUT_INT)."'"); - $email = $db->fetch_array($query); - if(!$email['mid']) - { - flash_message($lang->error_invalid_mid, 'error'); - admin_redirect("index.php?module=user-mass_mail"); - } - - $plugins->run_hooks("admin_user_mass_email_edit_start"); - - if($email['conditions'] != '') - { - $email['conditions'] = my_unserialize($email['conditions']); - } - - $sub_tabs['edit_mass_mail'] = array( - 'title' => $lang->edit_mass_mail, - 'link' => 'index.php?module=user-mass_mail&action=edit&mid='.$email['mid'], - 'description' => $lang->edit_mass_mail_desc - ); - - $replacement_fields = array( - "{username}" => $lang->username, - "{email}" => $lang->email_addr, - "{bbname}" => $lang->board_name, - "{bburl}" => $lang->board_url - ); - - $html_personalisation = $text_personalisation = "\n"; - $text_personalisation = substr($text_personalisation, 0, -2)."');\n// -->\n"; - - $localized_time_offset = (float)$mybb->user['timezone']*3600 + $mybb->user['dst']*3600; - - // All done here - if($mybb->request_method == "post") - { - // Sending this message now - if($mybb->input['delivery_type'] == "now") - { - $delivery_date = TIME_NOW; - } - // Delivering in the future - else - { - if(stristr($mybb->input['deliverytime_time'], "pm")) - { - $mybb->input['deliveryhour'] += 12; - } - - $exploded = explode(':', $mybb->input['endtime_time']); - $mybb->input['deliveryhour'] = (int)$exploded[0]; - - $exploded = explode(' ', $exploded[1]); - $mybb->input['deliveryminute'] = (int)$exploded[0]; - - $delivery_date = gmmktime($mybb->input['deliveryhour'], $mybb->input['deliveryminute'], 0, $mybb->input['endtime_month'], $mybb->input['endtime_day'], $mybb->input['endtime_year']) - $localized_time_offset; - if($delivery_date <= TIME_NOW) - { - $errors[] = $lang->error_only_in_future; - } - } - - // Need to perform the search to fetch the number of users we're emailing - $member_query = build_mass_mail_query($mybb->input['conditions']); - $query = $db->simple_select("users u", "COUNT(uid) AS num", $member_query); - $num = $db->fetch_field($query, "num"); - - if($num == 0) - { - $errors[] = $lang->error_no_users; - } - - if(!trim($mybb->input['subject'])) - { - $errors[] = $lang->error_missing_subject; - } - - if($mybb->input['type'] == 1) - { - if(!$mybb->input['message']) - { - $errors[] = $lang->error_missing_message; - } - } - else - { - if($mybb->input['format'] == 2 && $mybb->input['automatic_text'] == 0 && !$mybb->input['message']) - { - $errors[] = $lang->error_missing_plain_text; - } - - if(($mybb->input['format'] == 1 || $mybb->input['format'] == 2) && !$mybb->input['htmlmessage']) - { - $errors[] = $lang->error_missing_html; - } - else if($mybb->input['format'] == 0 && !$mybb->input['message']) - { - $errors[] = $lang->error_missing_plain_text; - } - } - - if(!$errors) - { - // Sending via a PM - if($mybb->input['type'] == 1) - { - $mybb->input['format'] = 0; - $mybb->input['htmlmessage'] = ''; - } - // Sending via email - else - { - // Do we need to generate a text based version? - if($mybb->input['format'] == 2 && $mybb->input['automatic_text']) - { - $mybb->input['message'] = create_text_message($mybb->input['htmlmessage']); - } - else if($mybb->input['format'] == 1) - { - $mybb->input['message'] = ''; - } - else if($mybb->input['format'] == 0) - { - $mybb->input['htmlmessage'] = ''; - } - } - - // Mark as queued for delivery - $updated_email = array( - "status" => 1, - "senddate" => $delivery_date, - "totalcount" => $num, - "conditions" => $db->escape_string(my_serialize($mybb->input['conditions'])), - "message" => $db->escape_string($mybb->input['message']), - "subject" => $db->escape_string($mybb->input['subject']), - "htmlmessage" => $db->escape_string($mybb->input['htmlmessage']), - "format" => $mybb->get_input('format', MyBB::INPUT_INT), - "type" => $mybb->get_input('type', MyBB::INPUT_INT), - "perpage" => $mybb->get_input('perpage', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_user_mass_email_edit_commit"); - - $db->update_query("massemails", $updated_email, "mid='{$email['mid']}'"); - - flash_message($lang->success_mass_mail_saved, 'success'); - admin_redirect("index.php?module=user-mass_mail"); - } - } - - $page->output_header($lang->edit_mass_mail); - - $page->output_nav_tabs($sub_tabs, 'edit_mass_mail'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - $input = $mybb->input; - } - else - { - $input = $email; - - if($email['senddate'] != 0) - { - if($email['senddate'] <= TIME_NOW) - { - $input['delivery_type'] = "now"; - $delivery_type_checked['now'] = " checked=\"checked\""; - } - else - { - // correct date by timezone and dst - $offset = - $input['delivery_type'] = "future"; - $time = gmdate("d-n-Y", $email['senddate'] + $localized_time_offset); - $time = explode('-', $time); - $input['deliverymonth'] = (int)$time[1]; - $input['deliveryday'] = (int)$time[0]; - $input['deliveryyear'] = (int)$time[2]; - $input['endtime_time'] = gmdate($mybb->settings['timeformat'], $email['senddate'] + $localized_time_offset); - $delivery_type_checked['future'] = " checked=\"checked\""; - } - } - else - { - $input['delivery_type'] = "now"; - $delivery_type_checked['now'] = " checked=\"checked\""; - } - } - - if(!$input['endtime_time']) - { - $input['endtime_time'] = gmdate($mybb->settings['timeformat'], TIME_NOW + $localized_time_offset); - } - - if(!$input['deliveryyear']) - { - $enddateyear = gmdate('Y', TIME_NOW + $localized_time_offset); - } - else - { - $enddateyear = (int)$input['deliveryyear']; - } - - if(!$input['deliverymonth']) - { - $input['enddatemonth'] = gmdate('n', TIME_NOW + $localized_time_offset); - } - else - { - $input['enddatemonth'] = (int)$input['deliverymonth']; - } - - if(!$input['deliveryday']) - { - $input['enddateday'] = gmdate('j', TIME_NOW + $localized_time_offset); - } - else - { - $input['enddateday'] = (int)$input['deliveryday']; - } - - $form = new Form("index.php?module=user-mass_mail&action=edit", "post"); - echo $form->generate_hidden_field("mid", $email['mid']); - - $mid_add = ''; - if($email['mid']) - { - $mid_add = "&mid={$email['mid']}"; - } - - $form_container = new FormContainer("{$lang->edit_mass_mail}: {$lang->message_settings}"); - - $form_container->output_row("{$lang->subject}: *", $lang->subject_desc, $form->generate_text_box('subject', $input['subject'], array('id' => 'subject')), 'subject'); - - if($input['type'] == 0) - { - $type_email_checked = true; - $type_pm_checked = false; - } - else if($input['type'] == 1) - { - $type_email_checked = false; - $type_pm_checked = true; - } - - $type_options = array( - $form->generate_radio_button("type", 0, $lang->send_via_email, array("id" => "type_email", "checked" => $type_email_checked)), - $form->generate_radio_button("type", 1, $lang->send_via_pm, array("id" => "type_pm", "checked" => $type_pm_checked)) - ); - $form_container->output_row("{$lang->message_type}: *", "", implode("
", $type_options)); - - $monthnames = array( - "offset", - $lang->january, - $lang->february, - $lang->march, - $lang->april, - $lang->may, - $lang->june, - $lang->july, - $lang->august, - $lang->september, - $lang->october, - $lang->november, - $lang->december, - ); - - $enddatemonth = ""; - foreach($monthnames as $key => $month) - { - if($month == "offset") - { - continue; - } - - if($key == $input['enddatemonth']) - { - $enddatemonth .= "\n"; - } - else - { - $enddatemonth .= "\n"; - } - } - - $enddateday = ""; - - // Construct option list for days - for($i = 1; $i <= 31; ++$i) - { - if($i == $input['enddateday']) - { - $enddateday .= "\n"; - } - else - { - $enddateday .= "\n"; - } - } - - $actions = " -
-
- -
-
- - - - -
\n   \n\n   \n\n - {$lang->time} ".$form->generate_text_box('endtime_time', $input['endtime_time'], array('id' => 'endtime_time', 'style' => 'width: 60px;'))."
-
-
- "; - $form_container->output_row("{$lang->delivery_date}: *", $lang->delivery_date_desc, $actions); - - $form_container->output_row("{$lang->per_page}: *", $lang->per_page_desc, $form->generate_numeric_field('perpage', $input['perpage'], array('id' => 'perpage', 'min' => 1)), 'perpage'); - - $format_options = array( - 0 => $lang->plain_text_only, - 1 => $lang->html_only, - 2 => $lang->html_and_plain_text - ); - - $form_container->output_row("{$lang->message_format}: *", "", $form->generate_select_box('format', $format_options, $input['format'], array('id' => 'format')), 'format', null, array("id" => "format_container")); - - $form_container->end(); - - if($input['format'] == 2) - { - if($input['automatic_text'] && !$email['mid']) - { - $automatic_text_check = true; - $text_display = 'display: none'; - $automatic_display = 'display: none;'; - } - } - else if($input['format'] == 1 && $input['type'] != 1) - { - $text_display = 'display: none;'; - } - else if($input['format'] == 0 || $input['type'] == 1) - { - $html_display = 'display: none'; - } - - echo "
"; - $form_container = new FormContainer("{$lang->edit_mass_mail}: {$lang->define_html_message}"); - $form_container->output_row("{$lang->define_html_message_desc}:", $html_personalisation, $form->generate_text_area('htmlmessage', $input['htmlmessage'], array('id' => 'htmlmessage', 'rows' => 15, 'cols '=> 70, 'style' => 'width: 95%'))."
".$form->generate_check_box('automatic_text', 1, $lang->auto_gen_plain_text, array('checked' => $automatic_text_check, "id" => "automatic_text"))."
"); - $form_container->end(); - echo "
"; - - echo "
"; - $form_container = new FormContainer("{$lang->edit_mass_mail}: {$lang->define_text_version}"); - $form_container->output_row("{$lang->define_text_version_desc}:", $text_personalisation, $form->generate_text_area('message', $input['message'], array('id' => 'message', 'rows' => 15, 'cols '=> 70, 'style' => 'width: 95%'))); - $form_container->end(); - echo "
"; - - echo " - "; - - $form_container = new FormContainer("{$lang->edit_mass_mail}: {$lang->define_the_recipients}"); - - $form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', htmlspecialchars_uni($input['conditions']['username']), array('id' => 'username')), 'username'); - $form_container->output_row($lang->email_addr_contains, "", $form->generate_text_box('conditions[email]', $input['conditions']['email'], array('id' => 'email')), 'email'); - - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - - $options = array(); - while($usergroup = $db->fetch_array($query)) - { - $options[$usergroup['gid']] = $usergroup['title']; - } - - $form_container->output_row($lang->members_of, $lang->additional_user_groups_desc, $form->generate_select_box('conditions[usergroup][]', $options, $input['conditions']['usergroup'], array('id' => 'usergroups', 'multiple' => true, 'size' => 5)), 'usergroups'); - - $greater_options = array( - "greater_than" => $lang->greater_than, - "is_exactly" => $lang->is_exactly, - "less_than" => $lang->less_than - ); - $form_container->output_row($lang->post_count_is, "", $form->generate_select_box('conditions[postnum_dir]', $greater_options, $input['conditions']['postnum_dir'], array('id' => 'postnum_dir'))." ".$form->generate_numeric_field('conditions[postnum]', $input['conditions']['postnum'], array('id' => 'postnum', 'min' => 0)), 'postnum'); - - $more_options = array( - "more_than" => $lang->more_than, - "less_than" => $lang->less_than - ); - - $date_options = array( - "hours" => $lang->hours, - "days" => $lang->days, - "weeks" => $lang->weeks, - "months" => $lang->months, - "years" => $lang->years - ); - $form_container->output_row($lang->user_registered, "", $form->generate_select_box('conditions[regdate_dir]', $more_options, $input['conditions']['regdate_dir'], array('id' => 'regdate_dir'))." ".$form->generate_numeric_field('conditions[regdate]', $input['conditions']['regdate'], array('id' => 'regdate', 'min' => 0))." ".$form->generate_select_box('conditions[regdate_date]', $date_options, $input['conditions']['regdate_date'], array('id' => 'regdate_date'))." {$lang->ago}", 'regdate'); - - $form_container->output_row($lang->user_last_active, "", $form->generate_select_box('conditions[lastactive_dir]', $more_options, $input['conditions']['lastactive_dir'], array('id' => 'lastactive_dir'))." ".$form->generate_numeric_field('conditions[lastactive]', $input['conditions']['lastactive'], array('id' => 'lastactive', 'min' => 0))." ".$form->generate_select_box('conditions[lastactive_date]', $date_options, $input['conditions']['lastactive_date'], array('id' => 'lastactive_date'))." {$lang->ago}", 'lastactive'); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_mass_mail); - $form->output_submit_wrapper($buttons); - - $form->end(); - $page->output_footer(); -} - -if($mybb->input['action'] == "send") -{ - $page->add_breadcrumb_item($lang->send_mass_mail); - - if($mybb->input['step']) - { - $query = $db->simple_select("massemails", "*", "status=0 and mid='".$mybb->get_input('mid', MyBB::INPUT_INT)."'"); - $email = $db->fetch_array($query); - if(!$email['mid'] && $mybb->input['step'] != 1) - { - flash_message($lang->error_invalid_mid, 'error'); - admin_redirect("index.php?module=user-mass_mail"); - } - } - - $replacement_fields = array( - "{username}" => $lang->username, - "{email}" => $lang->email_addr, - "{bbname}" => $lang->board_name, - "{bburl}" => $lang->board_url - ); - - $html_personalisation = $text_personalisation = "\n"; - $text_personalisation = substr($text_personalisation, 0, -2)."');\n// -->\n"; - - $plugins->run_hooks("admin_user_mass_email_send_start"); - - $localized_time_offset = (float)$mybb->user['timezone']*3600 + $mybb->user['dst']*3600; - - if($mybb->input['step'] == 4) - { - // All done here - if($mybb->request_method == "post") - { - // Sending this message now - if($mybb->input['delivery_type'] == "now") - { - $delivery_date = TIME_NOW; - } - // Delivering in the future - else - { - if(stristr($mybb->input['deliverytime_time'], "pm")) - { - $mybb->input['deliveryhour'] += 12; - } - - $exploded = explode(':', $mybb->input['endtime_time']); - $mybb->input['deliveryhour'] = (int)$exploded[0]; - - $exploded = explode(' ', $exploded[1]); - $mybb->input['deliveryminute'] = (int)$exploded[0]; - - $delivery_date = gmmktime($mybb->input['deliveryhour'], $mybb->input['deliveryminute'], 0, $mybb->input['endtime_month'], $mybb->input['endtime_day'], $mybb->input['endtime_year'])- $localized_time_offset; - if($delivery_date <= TIME_NOW) - { - $errors[] = $lang->error_only_in_future; - } - } - - if(!$errors) - { - // Mark as queued for delivery - $updated_email = array( - "status" => 1, - "senddate" => $delivery_date - ); - - $plugins->run_hooks("admin_user_mass_email_send_finalize_commit"); - - $db->update_query("massemails", $updated_email, "mid='{$email['mid']}'"); - - flash_message($lang->success_mass_mail_saved, 'success'); - admin_redirect("index.php?module=user-mass_mail"); - } - } - - // Show summary of the mass email we've just been creating and allow the user to specify the delivery date - $page->output_header("{$lang->send_mass_mail}: {$lang->step_four}"); - - $page->output_nav_tabs($sub_tabs, 'send_mass_mail'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - $input = $mybb->input; - } - else - { - $input = array(); - if($email['senddate'] != 0) - { - if($email['senddate'] <= TIME_NOW) - { - $input['delivery_type'] = "now"; - $delivery_type_checked['now'] = " checked=\"checked\""; - } - else - { - $input['delivery_type'] = "future"; - $time = gmdate("d-n-Y", $email['senddate'] + $localized_time_offset); - $time = explode('-', $time); - $input['deliverymonth'] = (int)$time[1]; - $input['deliveryday'] = (int)$time[0]; - $input['deliveryyear'] = (int)$time[2]; - $input['endtime_time'] = gmdate($mybb->settings['timeformat'], $email['senddate'] + $localized_time_offset); - $delivery_type_checked['future'] = " checked=\"checked\""; - } - } - else - { - $input['delivery_type'] = "now"; - $delivery_type_checked['now'] = " checked=\"checked\""; - } - } - - $table = new Table; - $table->construct_cell("{$lang->delivery_method}:", array('width' => '25%')); - if($email['type'] == 1) - { - $delivery_type = $lang->private_message; - } - else if($email['type'] == 0) - { - $delivery_type = $lang->email; - } - $table->construct_cell($delivery_type); - $table->construct_row(); - - $table->construct_cell("{$lang->subject}:"); - $table->construct_cell(htmlspecialchars_uni($email['subject'])); - $table->construct_row(); - - $table->construct_cell("{$lang->message}:"); - $format_preview = ''; - if($email['format'] == 0 || $email['format'] == 2) - { - $format_preview .= "{$lang->text_based} - {$lang->preview}"; - } - if($email['format'] == 2) - { - $format_preview .= " {$lang->and}
"; - } - if($email['format'] == 1 || $email['format'] == 2) - { - $format_preview.= "{$lang->html_based} - {$lang->preview}"; - } - $table->construct_cell($format_preview); - $table->construct_row(); - - // Recipient counts & details - $table->construct_cell("{$lang->total_recipients}:"); - $table->construct_cell(my_number_format($email['totalcount'])." - {$lang->change_recipient_conds}"); - $table->construct_row(); - - $table->output("{$lang->send_mass_mail}: {$lang->step_four} - {$lang->review_message}"); - - if(!$input['endtime_time']) - { - $input['endtime_time'] = gmdate($mybb->settings['timeformat'], TIME_NOW + $localized_time_offset); - } - - if(!$input['deliveryyear']) - { - $enddateyear = gmdate('Y', TIME_NOW + $localized_time_offset); - } - else - { - $enddateyear = (int)$input['deliveryyear']; - } - - if(!$input['deliverymonth']) - { - $input['enddatemonth'] = gmdate('n', TIME_NOW + $localized_time_offset); - } - else - { - $input['enddatemonth'] = (int)$input['deliverymonth']; - } - - if(!$input['deliveryday']) - { - $input['enddateday'] = gmdate('j', TIME_NOW + $localized_time_offset); - } - else - { - $input['enddateday'] = (int)$input['deliveryday']; - } - - $monthnames = array( - "offset", - $lang->january, - $lang->february, - $lang->march, - $lang->april, - $lang->may, - $lang->june, - $lang->july, - $lang->august, - $lang->september, - $lang->october, - $lang->november, - $lang->december, - ); - - $enddatemonth = ""; - foreach($monthnames as $key => $month) - { - if($month == "offset") - { - continue; - } - - if($key == $input['enddatemonth']) - { - $enddatemonth .= "\n"; - } - else - { - $enddatemonth .= "\n"; - } - } - - $enddateday = ""; - - // Construct option list for days - for($i = 1; $i <= 31; ++$i) - { - if($i == $input['enddateday']) - { - $enddateday .= "\n"; - } - else - { - $enddateday .= "\n"; - } - } - - $form = new Form("index.php?module=user-mass_mail&action=send&step=4&mid={$email['mid']}", "post"); - $form_container = new FormContainer("{$lang->send_mass_mail}: {$lang->step_four} - {$lang->define_delivery_date}"); - - $actions = " -
-
- -
-
- - - - -
\n   \n\n   \n\n - {$lang->time} ".$form->generate_text_box('endtime_time', $input['endtime_time'], array('id' => 'endtime_time', 'style' => 'width: 60px;'))."
-
-
- "; - $form_container->output_row("{$lang->delivery_date}: *", $lang->delivery_date_desc, $actions); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->schedule_for_delivery); - $form->output_submit_wrapper($buttons); - - $form->end(); - $page->output_footer(); - } - elseif($mybb->input['step'] == 3) - { - // Define the recipients/conditions - if($mybb->request_method == "post") - { - // Need to perform the search to fetch the number of users we're emailing - $member_query = build_mass_mail_query($mybb->input['conditions']); - $query = $db->simple_select("users u", "COUNT(uid) AS num", $member_query); - $num = $db->fetch_field($query, "num"); - - if($num == 0) - { - $errors[] = $lang->error_no_users; - } - // Got one or more results - else - { - $updated_email = array( - "totalcount" => $num, - "conditions" => $db->escape_string(my_serialize($mybb->input['conditions'])) - ); - - $plugins->run_hooks("admin_user_mass_email_send_define_commit"); - - $db->update_query("massemails", $updated_email, "mid='{$email['mid']}'"); - - // Take the user to the next step - admin_redirect("index.php?module=user-mass_mail&action=send&step=4&mid={$email['mid']}"); - } - } - - $page->output_header("{$lang->send_mass_mail}: {$lang->step_three}"); - - $form = new Form("index.php?module=user-mass_mail&action=send&step=3&mid={$email['mid']}", "post"); - $page->output_nav_tabs($sub_tabs, 'send_mass_mail'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - $input = $mybb->input; - } - else - { - if($email['conditions'] != '') - { - $input = array( - "conditions" => my_unserialize($email['conditions']) - ); - } - else - { - $input = array(); - } - } - - $options = array( - 'username', 'email', 'postnum_dir', 'postnum', 'regdate', 'regdate_date', 'regdate_dir', 'lastactive', 'lastactive_date', 'lastactive_dir' - ); - - foreach($options as $option) - { - if(!isset($input['conditions'][$option])) - { - $input['conditions'][$option] = ''; - } - } - if(!isset($input['conditions']['usergroup']) || !is_array($input['conditions']['usergroup'])) - { - $input['conditions']['usergroup'] = array(); - } - - $form_container = new FormContainer("{$lang->send_mass_mail}: {$lang->step_three} - {$lang->define_the_recipients}"); - - $form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', htmlspecialchars_uni($input['conditions']['username']), array('id' => 'username')), 'username'); - $form_container->output_row($lang->email_addr_contains, "", $form->generate_text_box('conditions[email]', $input['conditions']['email'], array('id' => 'email')), 'email'); - - $options = array(); - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $options[$usergroup['gid']] = $usergroup['title']; - } - - $form_container->output_row($lang->members_of, $lang->additional_user_groups_desc, $form->generate_select_box('conditions[usergroup][]', $options, $input['conditions']['usergroup'], array('id' => 'usergroups', 'multiple' => true, 'size' => 5)), 'usergroups'); - - $greater_options = array( - "greater_than" => $lang->greater_than, - "is_exactly" => $lang->is_exactly, - "less_than" => $lang->less_than - ); - $form_container->output_row($lang->post_count_is, "", $form->generate_select_box('conditions[postnum_dir]', $greater_options, $input['conditions']['postnum_dir'], array('id' => 'postnum_dir'))." ".$form->generate_numeric_field('conditions[postnum]', $input['conditions']['postnum'], array('id' => 'postnum', 'min' => 0)), 'postnum'); - - $more_options = array( - "more_than" => $lang->more_than, - "less_than" => $lang->less_than - ); - - $date_options = array( - "hours" => $lang->hours, - "days" => $lang->days, - "weeks" => $lang->weeks, - "months" => $lang->months, - "years" => $lang->years - ); - $form_container->output_row($lang->user_registered, "", $form->generate_select_box('conditions[regdate_dir]', $more_options, $input['conditions']['regdate_dir'], array('id' => 'regdate_dir'))." ".$form->generate_numeric_field('conditions[regdate]', $input['conditions']['regdate'], array('id' => 'regdate', 'min' => 0))." ".$form->generate_select_box('conditions[regdate_date]', $date_options, $input['conditions']['regdate_date'], array('id' => 'regdate_date'))." {$lang->ago}", 'regdate'); - - $form_container->output_row($lang->user_last_active, "", $form->generate_select_box('conditions[lastactive_dir]', $more_options, $input['conditions']['lastactive_dir'], array('id' => 'lastactive_dir'))." ".$form->generate_numeric_field('conditions[lastactive]', $input['conditions']['lastactive'], array('id' => 'lastactive', 'min' => 0))." ".$form->generate_select_box('conditions[lastactive_date]', $date_options, $input['conditions']['lastactive_date'], array('id' => 'lastactive_date'))." {$lang->ago}", 'lastactive'); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->next_step); - $form->output_submit_wrapper($buttons); - - $form->end(); - $page->output_footer(); - } - // Reviewing the automatic text based version of the message. - elseif($mybb->input['step'] == 2) - { - // Update text based version - if($mybb->request_method == "post") - { - if(!trim($mybb->input['message'])) - { - $errors[] = $lang->error_missing_plain_text; - } - else - { - $updated_email = array( - "message" => $db->escape_string($mybb->input['message']) - ); - - $plugins->run_hooks("admin_user_mass_email_send_review_commit"); - - $db->update_query("massemails", $updated_email, "mid='{$email['mid']}'"); - - // Take the user to the next step - admin_redirect("index.php?module=user-mass_mail&action=send&step=3&mid={$email['mid']}"); - } - } - - $page->output_header("{$lang->send_mass_mail}: {$lang->step_two}"); - - $form = new Form("index.php?module=user-mass_mail&action=send&step=2&mid={$email['mid']}", "post"); - $page->output_nav_tabs($sub_tabs, 'send_mass_mail'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer("{$lang->send_mass_mail}: {$lang->step_two} - {$lang->review_text_version}"); - $form_container->output_row("{$lang->review_text_version_desc}:", $text_personalisation, $form->generate_text_area('message', $email['message'], array('id' => 'message', 'rows' => 15, 'cols '=> 70, 'style' => 'width: 95%'))); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->next_step); - $form->output_submit_wrapper($buttons); - - $form->end(); - $page->output_footer(); - } - elseif(!$mybb->input['step'] || $mybb->input['step'] == 1) - { - if($mybb->request_method == "post") - { - if(!trim($mybb->input['subject'])) - { - $errors[] = $lang->error_missing_subject; - } - - if($mybb->input['type'] == 1) - { - if(!$mybb->input['message']) - { - $errors[] = $lang->error_missing_message; - } - } - else - { - if($mybb->input['format'] == 2 && $mybb->input['automatic_text'] == 0 && !$mybb->input['message']) - { - $errors[] = $lang->error_missing_plain_text; - } - - if(($mybb->input['format'] == 1 || $mybb->input['format'] == 2) && !$mybb->input['htmlmessage']) - { - $errors[] = $lang->error_missing_html; - } - else if($mybb->input['format'] == 0 && !$mybb->input['message']) - { - $errors[] = $lang->error_missing_plain_text; - } - } - - // No errors, insert away - if(!$errors) - { - if(!$new_email['mid']) - { - // Sending via a PM - if($mybb->input['type'] == 1) - { - $mybb->input['format'] = 0; - $mybb->input['htmlmessage'] = ''; - } - // Sending via email - else - { - // Do we need to generate a text based version? - if($mybb->input['format'] == 2 && $mybb->input['automatic_text']) - { - $mybb->input['message'] = create_text_message($mybb->input['htmlmessage']); - } - else if($mybb->input['format'] == 1) - { - $mybb->input['message'] = ''; - } - else if($mybb->input['format'] == 0) - { - $mybb->input['htmlmessage'] = ''; - } - } - - $new_email = array( - "uid" => $mybb->user['uid'], - "subject" => $db->escape_string($mybb->input['subject']), - "message" => $db->escape_string($mybb->input['message']), - "htmlmessage" => $db->escape_string($mybb->input['htmlmessage']), - "format" => $mybb->get_input('format', MyBB::INPUT_INT), - "type" => $mybb->get_input('type', MyBB::INPUT_INT), - "dateline" => TIME_NOW, - "senddate" => 0, - "status" => 0, - "sentcount" => 0, - "totalcount" => 0, - "conditions" => "", - "perpage" => $mybb->get_input('perpage', MyBB::INPUT_INT) - ); - - $mid = $db->insert_query("massemails", $new_email); - - $plugins->run_hooks("admin_user_mass_email_send_insert_commit"); - } - // Updating an existing one - else - { - $updated_email = array( - "subject" => $db->escape_string($mybb->input['subject']), - "message" => $db->escape_string($mybb->input['message']), - "htmlmessage" => $db->escape_string($mybb->input['htmlmessage']), - "format" => $mybb->get_input('format', MyBB::INPUT_INT), - "type" => $mybb->get_input('type', MyBB::INPUT_INT), - "perpage" => $mybb->get_input('perpage', MyBB::INPUT_INT) - ); - - $plugins->run_hooks("admin_user_mass_email_send_update_commit"); - - $db->update_query("massemails", $updated_email, "mid='{$email['mid']}'"); - $mid = $email['mid']; - } - - if($mybb->input['format'] == 2 && $mybb->input['automatic_text'] == 1) - { - $next = 2; - } - else - { - $next = 3; - } - admin_redirect("index.php?module=user-mass_mail&action=send&step={$next}&mid={$mid}"); - } - } - - $page->output_header("{$lang->send_mass_mail}: {$lang->step_one}"); - - $mid_add = ''; - if($email['mid']) - { - $mid_add = "&mid={$email['mid']}"; - } - - $form = new Form("index.php?module=user-mass_mail&action=send{$mid_add}", "post"); - $page->output_nav_tabs($sub_tabs, 'send_mass_mail'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - $input = $mybb->input; - } - else if(!$email) - { - $input = array( - "type" => 0, - "format" => 2, - "automatic_text" => 1, - "perpage" => 50, - ); - } - else - { - $input = $email; - } - - $form_container = new FormContainer("{$lang->send_mass_mail}: {$lang->step_one} - {$lang->message_settings}"); - - $form_container->output_row("{$lang->subject}: *", $lang->subject_desc, $form->generate_text_box('subject', $input['subject'], array('id' => 'subject')), 'subject'); - - if($mybb->input['type'] == 0) - { - $type_email_checked = true; - $type_pm_checked = false; - } - else if($mybb->input['type'] == 1) - { - $type_email_checked = false; - $type_pm_checked = true; - } - - $type_options = array( - $form->generate_radio_button("type", 0, $lang->send_via_email, array("id" => "type_email", "checked" => $type_email_checked)), - $form->generate_radio_button("type", 1, $lang->send_via_pm, array("id" => "type_pm", "checked" => $type_pm_checked)) - ); - $form_container->output_row("{$lang->message_type}:", "", implode("
", $type_options)); - - $format_options = array( - 0 => $lang->plain_text_only, - 1 => $lang->html_only, - 2 => $lang->html_and_plain_text - ); - - $form_container->output_row("{$lang->message_format}:", "", $form->generate_select_box('format', $format_options, $input['format'], array('id' => 'format')), 'format', null, array("id" => "format_container")); - - $form_container->output_row("{$lang->per_page}: *", $lang->per_page_desc, $form->generate_numeric_field('perpage', $input['perpage'], array('id' => 'perpage', 'min' => 1)), 'perpage'); - - $form_container->end(); - - if($mybb->input['format'] == 2) - { - if($mybb->input['automatic_text'] && !$email['mid']) - { - $automatic_text_check = true; - $text_display = 'display: none'; - $automatic_display = 'display: none;'; - } - } - else if($mybb->input['format'] == 1 && $mybb->input['type'] != 1) - { - $text_display = 'display: none;'; - } - else if($mybb->input['format'] == 0 || $mybb->input['type'] == 1) - { - $html_display = 'display: none'; - } - - echo "
"; - $form_container = new FormContainer("{$lang->send_mass_mail}: {$lang->step_one} - {$lang->define_html_message}"); - $form_container->output_row("{$lang->define_html_message_desc}:", $html_personalisation, $form->generate_text_area('htmlmessage', $input['htmlmessage'], array('id' => 'htmlmessage', 'rows' => 15, 'cols '=> 70, 'style' => 'width: 95%'))."
".$form->generate_check_box('automatic_text', 1, $lang->auto_gen_plain_text, array('checked' => $automatic_text_check, "id" => "automatic_text"))."
"); - $form_container->end(); - echo "
"; - - echo "
"; - $form_container = new FormContainer("{$lang->send_mass_mail}: {$lang->step_one} - {$lang->define_text_version}"); - $form_container->output_row("{$lang->define_text_version_desc}:", $text_personalisation, $form->generate_text_area('message', $input['message'], array('id' => 'message', 'rows' => 15, 'cols '=> 70, 'style' => 'width: 95%'))); - $form_container->end(); - echo "
"; - - echo " - "; - - $buttons[] = $form->generate_submit_button($lang->next_step); - $form->output_submit_wrapper($buttons); - - $form->end(); - $page->output_footer(); - } - - $plugins->run_hooks("admin_user_mass_email_preview_end"); -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("massemails", "*", "mid='".$mybb->get_input('mid', MyBB::INPUT_INT)."'"); - $mass_email = $db->fetch_array($query); - - if(!$mass_email['mid']) - { - flash_message($lang->error_delete_invalid_mid, 'error'); - admin_redirect("index.php?module=user-mass_mail"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-mass_mail"); - } - - $plugins->run_hooks("admin_user_mass_email_delete_start"); - - if($mybb->request_method == "post") - { - $db->delete_query("massemails", "mid='{$mass_email['mid']}'"); - - $plugins->run_hooks("admin_user_mass_email_delete_commit"); - - // Log admin action - log_admin_action($mass_email['mid'], $mass_email['subject']); - - if($mybb->input['archive'] == 1) - { - flash_message($lang->success_mass_mail_deleted, 'success'); - admin_redirect("index.php?module=user-mass_mail&action=archive"); - } - else - { - flash_message($lang->success_mass_mail_deleted, 'success'); - admin_redirect("index.php?module=user-mass_mail"); - } - } - else - { - if($mybb->input['archive'] == 1) - { - $page->output_confirm_action("index.php?module=user-mass_mail&action=delete&mid={$mass_email['mid']}&archive=1", $lang->mass_mail_deletion_confirmation); - } - else - { - $page->output_confirm_action("index.php?module=user-mass_mail&action=delete&mid={$mass_email['mid']}", $lang->mass_mail_deletion_confirmation); - } - } -} - -if($mybb->input['action'] == "preview") -{ - $query = $db->simple_select("massemails", "*", "mid='".$mybb->get_input('mid', MyBB::INPUT_INT)."'"); - $mass_email = $db->fetch_array($query); - - if(!$mass_email['mid']) - { - flash_message($lang->error_invalid_mid, 'error'); - admin_redirect("index.php?module=user-mass_mail"); - } - - $plugins->run_hooks("admin_user_mass_email_preview_start"); - - echo ''; - exit; -} - -if($mybb->input['action'] == "resend") -{ - // Copy and resend an email - $query = $db->simple_select("massemails", "*", "mid='".$mybb->get_input('mid', MyBB::INPUT_INT)."'"); - $mass_email = $db->fetch_array($query); - - if(!$mass_email['mid']) - { - flash_message($lang->error_invalid_mid, 'error'); - admin_redirect("index.php?module=user-mass_mail"); - } - - $plugins->run_hooks("admin_user_mass_email_resend_start"); - - // Need to perform the search to fetch the number of users we're emailing - $member_query = build_mass_mail_query(my_unserialize($mass_email['conditions'])); - $query = $db->simple_select("users u", "COUNT(uid) AS num", $member_query); - $total_recipients = $db->fetch_field($query, "num"); - - // Create the new email based off the old one. - $new_email = array( - "uid" => $mass_email['uid'], - "subject" => $db->escape_string($mass_email['subject']), - "message" => $db->escape_string($mass_email['message']), - "htmlmessage" => $db->escape_string($mass_email['htmlmessage']), - "type" => $db->escape_string($mass_email['type']), - "format" => $db->escape_string($mass_email['format']), - "dateline" => TIME_NOW, - "senddate" => '0', - "status" => 0, - "sentcount" => 0, - "totalcount" => $total_recipients, - "conditions" => $db->escape_string($mass_email['conditions']), - "perpage" => $mass_email['perpage'] - ); - - $mid = $db->insert_query("massemails", $new_email); - - $plugins->run_hooks("admin_user_mass_email_resend_end"); - - // Redirect the user to the summary page so they can select when to deliver this message - flash_message($lang->success_mass_mail_resent, 'success'); - admin_redirect("index.php?module=user-mass_mail&action=send&step=4&mid={$mid}"); - exit; -} - -if($mybb->input['action'] == "cancel") -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=user-users"); - } - - // Cancel the delivery of a mass-email. - $query = $db->simple_select("massemails", "*", "mid='".$mybb->get_input('mid', MyBB::INPUT_INT)."'"); - $mass_email = $db->fetch_array($query); - - if(!$mass_email['mid']) - { - flash_message($lang->error_invalid_mid, 'error'); - admin_redirect("index.php?module=user-mass_mail"); - } - - $updated_email = array( - 'status' => 4 - ); - - $plugins->run_hooks("admin_user_mass_email_cancel"); - - $db->update_query("massemails", $updated_email, "mid='{$mass_email['mid']}'"); - - flash_message($lang->success_mass_mail_canceled, 'success'); - admin_redirect("index.php?module=user-mass_mail"); - exit; -} - -if($mybb->input['action'] == "archive") -{ - // View a list of archived email messages - $page->output_header($lang->mass_mail_archive); - - $plugins->run_hooks("admin_user_mass_email_archive_start"); - - $page->output_nav_tabs($sub_tabs, 'archive'); - - $table = new Table; - $table->construct_header($lang->subject); - $table->construct_header($lang->status, array('width' => '130', 'class' => 'align_center')); - $table->construct_header($lang->delivery_date, array('width' => '130', 'class' => 'align_center')); - $table->construct_header($lang->recipients, array('width' => '130', 'class' => 'align_center')); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2, "width" => 200)); - - $query = $db->simple_select("massemails", "*", "status NOT IN (0, 1, 2)", array('order_by' => 'senddate')); - while($email = $db->fetch_array($query)) - { - $email['subject'] = htmlspecialchars_uni($email['subject']); - if($email['senddate'] < TIME_NOW) - { - $table->construct_cell("{$email['subject']}"); - } - if($email['status'] == 3) - { - $status = $lang->delivered; - } - else if($email['status'] == 4) - { - $status = $lang->canceled; - } - $table->construct_cell($status, array("class" => "align_center")); - - $delivery_date = my_date($mybb->settings['dateformat'], $email['senddate']); - - $table->construct_cell($delivery_date, array("class" => "align_center")); - $table->construct_cell(my_number_format($email['totalcount']), array("class" => "align_center")); - - $table->construct_cell("{$lang->resend}", array("width" => 100, "class" => "align_center")); - $table->construct_cell("post_code}&archive=1\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->mass_mail_deletion_confirmation}')\">{$lang->delete}", array("width" => 100, "class" => "align_center")); - - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_archived_messages, array('colspan' => 6)); - $table->construct_row(); - $no_results = true; - } - - $plugins->run_hooks("admin_user_mass_email_archive_end"); - - $table->output($lang->mass_mail_archive); - - $page->output_footer(); -} - -if(!$mybb->input['action']) -{ - $page->output_header($lang->mass_mail_queue); - - $plugins->run_hooks("admin_user_mass_email_start"); - - $page->output_nav_tabs($sub_tabs, 'mail_queue'); - - $table = new Table; - $table->construct_header($lang->subject); - $table->construct_header($lang->status, array('width' => '130', 'class' => 'align_center')); - $table->construct_header($lang->delivery_date, array('width' => '130', 'class' => 'align_center')); - $table->construct_header($lang->recipients, array('width' => '130', 'class' => 'align_center')); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2, "width" => 200)); - - $query = $db->simple_select("massemails", "*", "status IN (0, 1, 2)", array('order_by' => 'senddate')); - while($email = $db->fetch_array($query)) - { - $email['subject'] = htmlspecialchars_uni($email['subject']); - if(TIME_NOW >= $email['senddate'] && $email['status'] > 1) - { - $table->construct_cell("{$email['subject']}"); - } - else - { - $table->construct_cell("{$email['subject']}"); - } - if($email['status'] == 0) - { - $status = $lang->draft; - } - else if($email['status'] == 1) - { - $status = $lang->queued; - } - else if($email['status'] == 2) - { - $progress = ceil($email['sentcount']/$email['totalcount']*100); - if($progress > 100) - { - $progress = 100; - } - $status = "{$lang->delivering} ({$progress}%)"; - } - $table->construct_cell($status, array("class" => "align_center")); - - if($email['status'] != 0) - { - $delivery_date = my_date($mybb->settings['dateformat'], $email['senddate']); - } - else - { - $delivery_date = $lang->na; - } - - $table->construct_cell($delivery_date, array("class" => "align_center")); - $table->construct_cell(my_number_format($email['totalcount']), array("class" => "align_center")); - if(TIME_NOW >= $email['senddate'] && $email['status'] > 1) - { - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->mass_mail_cancel_confirmation}')\">{$lang->cancel}", array("width" => 100, "colspan" => 2, "class" => "align_center")); - } - else - { - $table->construct_cell("{$lang->edit}", array("width" => 100, "class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->mass_mail_deletion_confirmation}')\">{$lang->delete}", array("width" => 100, "class" => "align_center")); - } - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_unsent_messages, array('colspan' => 6)); - $table->construct_row(); - $no_results = true; - } - - $plugins->run_hooks("admin_user_mass_email_end"); - - $table->output($lang->mass_mail_queue); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/user/module_meta.php b/html/forums/admin/modules/user/module_meta.php deleted file mode 100644 index a7b1707..0000000 --- a/html/forums/admin/modules/user/module_meta.php +++ /dev/null @@ -1,97 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -/** - * @return bool true - */ -function user_meta() -{ - global $page, $lang, $plugins; - - $sub_menu = array(); - $sub_menu['10'] = array("id" => "users", "title" => $lang->users, "link" => "index.php?module=user-users"); - $sub_menu['20'] = array("id" => "awaiting_activation", "title" => $lang->awaiting_activation, "link" => "index.php?module=user-awaiting_activation"); - $sub_menu['30'] = array("id" => "groups", "title" => $lang->groups, "link" => "index.php?module=user-groups"); - $sub_menu['40'] = array("id" => "titles", "title" => $lang->user_titles, "link" => "index.php?module=user-titles"); - $sub_menu['50'] = array("id" => "banning", "title" => $lang->banning, "link" => "index.php?module=user-banning"); - $sub_menu['60'] = array("id" => "admin_permissions", "title" => $lang->admin_permissions, "link" => "index.php?module=user-admin_permissions"); - $sub_menu['70'] = array("id" => "mass_mail", "title" => $lang->mass_mail, "link" => "index.php?module=user-mass_mail"); - $sub_menu['80'] = array("id" => "group_promotions", "title" => $lang->group_promotions, "link" => "index.php?module=user-group_promotions"); - - $sub_menu = $plugins->run_hooks("admin_user_menu", $sub_menu); - - $page->add_menu_item($lang->users_and_groups, "user", "index.php?module=user", 30, $sub_menu); - return true; -} - -/** - * @param string $action - * - * @return string - */ -function user_action_handler($action) -{ - global $page, $lang, $plugins; - - $page->active_module = "user"; - - $actions = array( - 'awaiting_activation' => array('active' => 'awaiting_activation', 'file' => 'awaiting_activation.php'), - 'group_promotions' => array('active' => 'group_promotions', 'file' => 'group_promotions.php'), - 'admin_permissions' => array('active' => 'admin_permissions', 'file' => 'admin_permissions.php'), - 'titles' => array('active' => 'titles', 'file' => 'titles.php'), - 'banning' => array('active' => 'banning', 'file' => 'banning.php'), - 'groups' => array('active' => 'groups', 'file' => 'groups.php'), - 'mass_mail' => array('active' => 'mass_mail', 'file' => 'mass_mail.php'), - 'users' => array('active' => 'users', 'file' => 'users.php') - ); - - $actions = $plugins->run_hooks("admin_user_action_handler", $actions); - - if(isset($actions[$action])) - { - $page->active_action = $actions[$action]['active']; - return $actions[$action]['file']; - } - else - { - $page->active_action = "users"; - return "users.php"; - } -} - -/** - * @return array - */ -function user_admin_permissions() -{ - global $lang, $plugins; - - $admin_permissions = array( - "users" => $lang->can_manage_users, - "awaiting_activation" => $lang->can_manage_awaiting_activation, - "groups" => $lang->can_manage_user_groups, - "titles" => $lang->can_manage_user_titles, - "banning" => $lang->can_manage_user_bans, - "admin_permissions" => $lang->can_manage_admin_permissions, - "mass_mail" => $lang->can_send_mass_mail, - "group_promotions" => $lang->can_manage_group_promotions - ); - - $admin_permissions = $plugins->run_hooks("admin_user_permissions", $admin_permissions); - - return array("name" => $lang->users_and_groups, "permissions" => $admin_permissions, "disporder" => 30); -} diff --git a/html/forums/admin/modules/user/titles.php b/html/forums/admin/modules/user/titles.php deleted file mode 100644 index d33e789..0000000 --- a/html/forums/admin/modules/user/titles.php +++ /dev/null @@ -1,280 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -$page->add_breadcrumb_item($lang->user_titles, "index.php?module=user-titles"); - -if($mybb->input['action'] == "add" || !$mybb->input['action']) -{ - $sub_tabs['manage_titles'] = array( - 'title' => $lang->user_titles, - 'link' => "index.php?module=user-titles", - 'description' => $lang->user_titles_desc - ); - $sub_tabs['add_title'] = array( - 'title' => $lang->add_new_user_title, - 'link' => "index.php?module=user-titles&action=add", - 'description' => $lang->add_new_user_title_desc - ); -} - -$plugins->run_hooks("admin_user_titles_begin"); - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_user_titles_add"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(!isset($mybb->input['posts'])) - { - $errors[] = $lang->error_missing_posts; - } - - $query = $db->simple_select("usertitles", "utid", "posts= '".$mybb->get_input('posts', MyBB::INPUT_INT)."'"); - if($db->num_rows($query)) - { - $errors[] = $lang->error_cannot_have_same_posts; - } - - if(!$errors) - { - $new_title = array( - "title" => $db->escape_string($mybb->input['title']), - "posts" => $mybb->get_input('posts', MyBB::INPUT_INT), - "stars" => $mybb->get_input('stars', MyBB::INPUT_INT), - "starimage" => $db->escape_string($mybb->input['starimage']) - ); - - $utid = $db->insert_query("usertitles", $new_title); - - $plugins->run_hooks("admin_user_titles_add_commit"); - - $cache->update_usertitles(); - - // Log admin action - log_admin_action($utid, htmlspecialchars_uni($mybb->input['title']), $mybb->input['posts']); - - flash_message($lang->success_user_title_created, 'success'); - admin_redirect("index.php?module=user-titles"); - } - } - else - { - $mybb->input = array_merge($mybb->input, array( - 'stars' => '1', - 'starimage' => '{theme}/star.png', - ) - ); - } - - $page->add_breadcrumb_item($lang->add_new_user_title); - $page->output_header($lang->user_titles." - ".$lang->add_new_user_title); - - $page->output_nav_tabs($sub_tabs, 'add_title'); - $form = new Form("index.php?module=user-titles&action=add", "post"); - - - if($errors) - { - $page->output_inline_error($errors); - } - - $form_container = new FormContainer($lang->add_new_user_title); - $form_container->output_row($lang->title_to_assign."*", $lang->title_to_assign_desc, $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->minimum_posts, $lang->minimum_posts_desc, $form->generate_numeric_field('posts', $mybb->input['posts'], array('id' => 'posts', 'min' => 0)), 'posts'); - $form_container->output_row($lang->number_of_stars, $lang->number_of_stars_desc, $form->generate_numeric_field('stars', $mybb->input['stars'], array('id' => 'stars', 'min' => 0)), 'stars'); - $form_container->output_row($lang->star_image, $lang->star_image_desc, $form->generate_text_box('starimage', $mybb->input['starimage'], array('id' => 'starimage')), 'starimage'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_user_title); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $query = $db->simple_select("usertitles", "*", "utid='".$mybb->get_input('utid', MyBB::INPUT_INT)."'"); - $usertitle = $db->fetch_array($query); - - if(!$usertitle['utid']) - { - flash_message($lang->error_invalid_user_title, 'error'); - admin_redirect("index.php?module=user-titles"); - } - - $plugins->run_hooks("admin_user_titles_edit"); - - if($mybb->request_method == "post") - { - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - if(!isset($mybb->input['posts'])) - { - $errors[] = $lang->error_missing_posts; - } - - $query = $db->simple_select("usertitles", "utid", "posts= '".$mybb->get_input('posts', MyBB::INPUT_INT)."' AND utid!= '".$mybb->get_input('utid', MyBB::INPUT_INT)."'"); - if($db->num_rows($query)) - { - $errors[] = $lang->error_cannot_have_same_posts; - } - - if(!$errors) - { - $updated_title = array( - "title" => $db->escape_string($mybb->input['title']), - "posts" => $mybb->get_input('posts', MyBB::INPUT_INT), - "stars" => $mybb->get_input('stars', MyBB::INPUT_INT), - "starimage" => $db->escape_string($mybb->input['starimage']) - ); - - $plugins->run_hooks("admin_user_titles_edit_commit"); - - $db->update_query("usertitles", $updated_title, "utid='{$usertitle['utid']}'"); - - $cache->update_usertitles(); - - // Log admin action - log_admin_action($usertitle['utid'], htmlspecialchars_uni($mybb->input['title']), $mybb->input['posts']); - - flash_message($lang->success_user_title_updated, 'success'); - admin_redirect("index.php?module=user-titles"); - } - } - - $page->add_breadcrumb_item($lang->edit_user_title); - $page->output_header($lang->user_titles." - ".$lang->edit_user_title); - - $sub_tabs['edit_title'] = array( - 'title' => $lang->edit_user_title, - 'link' => "index.php?module=user-titles&action=edit&utid=".$usertitle['utid'], - 'description' => $lang->edit_user_title_desc - ); - - $page->output_nav_tabs($sub_tabs, 'edit_title'); - $form = new Form("index.php?module=user-titles&action=edit&utid={$usertitle['utid']}", "post"); - - - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = array_merge($mybb->input, $usertitle); - } - - $form_container = new FormContainer($lang->edit_user_title); - $form_container->output_row($lang->title_to_assign."*", $lang->title_to_assign_desc, $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title'); - $form_container->output_row($lang->minimum_posts, $lang->minimum_posts_desc, $form->generate_numeric_field('posts', $mybb->input['posts'], array('id' => 'posts', 'min' => 0)), 'posts'); - $form_container->output_row($lang->number_of_stars, $lang->number_of_stars_desc, $form->generate_numeric_field('stars', $mybb->input['stars'], array('id' => 'stars', 'min' => 0)), 'stars'); - $form_container->output_row($lang->star_image, $lang->star_image_desc, $form->generate_text_box('starimage', $mybb->input['starimage'], array('id' => 'starimage')), 'starimage'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->save_user_title); - - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); - -} - -if($mybb->input['action'] == "delete") -{ - $query = $db->simple_select("usertitles", "*", "utid='".$mybb->get_input('utid', MyBB::INPUT_INT)."'"); - $usertitle = $db->fetch_array($query); - - if(!$usertitle['utid']) - { - flash_message($lang->error_invalid_user_title, 'error'); - admin_redirect("index.php?module=user-titles"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-titles"); - } - - $plugins->run_hooks("admin_user_titles_delete"); - - if($mybb->request_method == "post") - { - $db->delete_query("usertitles", "utid='{$usertitle['utid']}'"); - - $plugins->run_hooks("admin_user_titles_delete_commit"); - - $cache->update_usertitles(); - - // Log admin action - log_admin_action($usertitle['utid'], htmlspecialchars_uni($usertitle['title']), $usertitle['posts']); - - flash_message($lang->success_user_title_deleted, 'success'); - admin_redirect("index.php?module=user-titles"); - } - else - { - $page->output_confirm_action("index.php?module=user-titles&action=delete&utid={$usertitle['utid']}", $lang->user_title_deletion_confirmation); - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_user_titles_start"); - - $page->output_header($lang->manage_user_titles); - - $page->output_nav_tabs($sub_tabs, 'manage_titles'); - - $table = new Table; - $table->construct_header($lang->user_title); - $table->construct_header($lang->minimum_posts, array('width' => '130', 'class' => 'align_center')); - $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2, "width" => 200)); - - $query = $db->simple_select("usertitles", "*", "", array('order_by' => 'posts')); - while($usertitle = $db->fetch_array($query)) - { - $usertitle['title'] = htmlspecialchars_uni($usertitle['title']); - $table->construct_cell("{$usertitle['title']}"); - $table->construct_cell($usertitle['posts'], array("class" => "align_center")); - $table->construct_cell("{$lang->edit}", array("width" => 100, "class" => "align_center")); - $table->construct_cell("post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->user_title_deletion_confirmation}')\">{$lang->delete}", array("width" => 100, "class" => "align_center")); - $table->construct_row(); - } - - if($table->num_rows() == 0) - { - $table->construct_cell($lang->no_user_titles, array('colspan' => 4)); - $table->construct_row(); - $no_results = true; - } - - $table->output($lang->manage_user_titles); - - $page->output_footer(); -} diff --git a/html/forums/admin/modules/user/users.php b/html/forums/admin/modules/user/users.php deleted file mode 100644 index bb64038..0000000 --- a/html/forums/admin/modules/user/users.php +++ /dev/null @@ -1,4319 +0,0 @@ -
Please make sure IN_MYBB is defined."); -} - -require_once MYBB_ROOT."inc/functions_upload.php"; - -$page->add_breadcrumb_item($lang->users, "index.php?module=user-users"); - -if($mybb->input['action'] == "add" || $mybb->input['action'] == "merge" || $mybb->input['action'] == "search" || !$mybb->input['action']) -{ - $sub_tabs['browse_users'] = array( - 'title' => $lang->browse_users, - 'link' => "index.php?module=user-users", - 'description' => $lang->browse_users_desc - ); - - $sub_tabs['find_users'] = array( - 'title' => $lang->find_users, - 'link' => "index.php?module=user-users&action=search", - 'description' => $lang->find_users_desc - ); - - $sub_tabs['create_user'] = array( - 'title' => $lang->create_user, - 'link' => "index.php?module=user-users&action=add", - 'description' => $lang->create_user_desc - ); - - $sub_tabs['merge_users'] = array( - 'title' => $lang->merge_users, - 'link' => "index.php?module=user-users&action=merge", - 'description' => $lang->merge_users_desc - ); -} - -$user_view_fields = array( - "avatar" => array( - "title" => $lang->avatar, - "width" => "24", - "align" => "" - ), - - "username" => array( - "title" => $lang->username, - "width" => "", - "align" => "" - ), - - "email" => array( - "title" => $lang->email, - "width" => "", - "align" => "center" - ), - - "usergroup" => array( - "title" => $lang->primary_group, - "width" => "", - "align" => "center" - ), - - "additionalgroups" => array( - "title" => $lang->additional_groups, - "width" => "", - "align" => "center" - ), - - "regdate" => array( - "title" => $lang->registered, - "width" => "", - "align" => "center" - ), - - "lastactive" => array( - "title" => $lang->last_active, - "width" => "", - "align" => "center" - ), - - "postnum" => array( - "title" => $lang->post_count, - "width" => "", - "align" => "center" - ), - - "threadnum" => array( - "title" => $lang->thread_count, - "width" => "", - "align" => "center" - ), - - "reputation" => array( - "title" => $lang->reputation, - "width" => "", - "align" => "center" - ), - - "warninglevel" => array( - "title" => $lang->warning_level, - "width" => "", - "align" => "center" - ), - - "regip" => array( - "title" => $lang->registration_ip, - "width" => "", - "align" => "center" - ), - - "lastip" => array( - "title" => $lang->last_known_ip, - "width" => "", - "align" => "center" - ), - - "controls" => array( - "title" => $lang->controls, - "width" => "", - "align" => "center" - ) -); - -$sort_options = array( - "username" => $lang->username, - "regdate" => $lang->registration_date, - "lastactive" => $lang->last_active, - "numposts" => $lang->post_count, - "reputation" => $lang->reputation, - "warninglevel" => $lang->warning_level -); - -$plugins->run_hooks("admin_user_users_begin"); - -// Initialise the views manager for user based views -require MYBB_ADMIN_DIR."inc/functions_view_manager.php"; -if($mybb->input['action'] == "views") -{ - view_manager("index.php?module=user-users", "user", $user_view_fields, $sort_options, "user_search_conditions"); -} - -if($mybb->input['action'] == 'iplookup') -{ - $mybb->input['ipaddress'] = $mybb->get_input('ipaddress'); - $lang->ipaddress_misc_info = $lang->sprintf($lang->ipaddress_misc_info, htmlspecialchars_uni($mybb->input['ipaddress'])); - $ipaddress_location = $lang->na; - $ipaddress_host_name = $lang->na; - $modcp_ipsearch_misc_info = ''; - if(!strstr($mybb->input['ipaddress'], "*")) - { - // Return GeoIP information if it is available to us - if(function_exists('geoip_record_by_name')) - { - $ip_record = @geoip_record_by_name($mybb->input['ipaddress']); - if($ip_record) - { - $ipaddress_location = htmlspecialchars_uni(utf8_encode($ip_record['country_name'])); - if($ip_record['city']) - { - $ipaddress_location .= $lang->comma.htmlspecialchars_uni(utf8_encode($ip_record['city'])); - } - } - } - - $ipaddress_host_name = htmlspecialchars_uni(@gethostbyaddr($mybb->input['ipaddress'])); - - // gethostbyaddr returns the same ip on failure - if($ipaddress_host_name == $mybb->input['ipaddress']) - { - $ipaddress_host_name = $lang->na; - } - } - - ?> - -input['action'] == "activate_user") -{ - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=user-users"); - } - - $user = get_user($mybb->input['uid']); - - // Does the user not exist? - if(!$user['uid'] || $user['usergroup'] != 5) - { - flash_message($lang->error_invalid_user, 'error'); - admin_redirect("index.php?module=user-users"); - } - - $plugins->run_hooks("admin_user_users_coppa_activate"); - - $updated_user['usergroup'] = $user['usergroup']; - - // Update - if($user['coppauser']) - { - $updated_user = array( - "coppauser" => 0 - ); - } - else - { - $db->delete_query("awaitingactivation", "uid='{$user['uid']}'"); - } - - // Move out of awaiting activation if they're in it. - if($user['usergroup'] == 5) - { - $updated_user['usergroup'] = 2; - } - - $plugins->run_hooks("admin_user_users_coppa_activate_commit"); - - $db->update_query("users", $updated_user, "uid='{$user['uid']}'"); - - $cache->update_awaitingactivation(); - - $message = $lang->sprintf($lang->email_adminactivateaccount, $user['username'], $mybb->settings['bbname'], $mybb->settings['bburl']); - my_mail($user['email'], $lang->sprintf($lang->emailsubject_activateaccount, $mybb->settings['bbname']), $message); - - // Log admin action - log_admin_action($user['uid'], htmlspecialchars_uni($user['username'])); - - if($mybb->input['from'] == "home") - { - if($user['coppauser']) - { - $message = $lang->success_coppa_activated; - } - else - { - $message = $lang->success_activated; - } - - update_admin_session('flash_message2', array('message' => $message, 'type' => 'success')); - } - else - { - if($user['coppauser']) - { - flash_message($lang->success_coppa_activated, 'success'); - } - else - { - flash_message($lang->success_activated, 'success'); - } - } - - if($admin_session['data']['last_users_url']) - { - $url = $admin_session['data']['last_users_url']; - update_admin_session('last_users_url', ''); - - if($mybb->input['from'] == "home") - { - update_admin_session('from', 'home'); - } - } - else - { - $url = "index.php?module=user-users&action=edit&uid={$user['uid']}"; - } - - $plugins->run_hooks("admin_user_users_coppa_end"); - - admin_redirect($url); -} - -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("admin_user_users_add"); - - if($mybb->request_method == "post") - { - // Determine the usergroup stuff - if(is_array($mybb->input['additionalgroups'])) - { - foreach($mybb->input['additionalgroups'] as $key => $gid) - { - if($gid == $mybb->input['usergroup']) - { - unset($mybb->input['additionalgroups'][$key]); - } - } - $additionalgroups = implode(",", $mybb->input['additionalgroups']); - } - else - { - $additionalgroups = ''; - } - - // Set up user handler. - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler('insert'); - - // Set the data for the new user. - $new_user = array( - "uid" => $mybb->input['uid'], - "username" => $mybb->input['username'], - "password" => $mybb->input['password'], - "password2" => $mybb->input['confirm_password'], - "email" => $mybb->input['email'], - "email2" => $mybb->input['email'], - "usergroup" => $mybb->input['usergroup'], - "additionalgroups" => $additionalgroups, - "displaygroup" => $mybb->input['displaygroup'], - "profile_fields" => $mybb->input['profile_fields'], - "profile_fields_editable" => true, - ); - - // Set the data of the user in the datahandler. - $userhandler->set_data($new_user); - $errors = ''; - - // Validate the user and get any errors that might have occurred. - if(!$userhandler->validate_user()) - { - $errors = $userhandler->get_friendly_errors(); - } - else - { - $user_info = $userhandler->insert_user(); - - $plugins->run_hooks("admin_user_users_add_commit"); - - // Log admin action - log_admin_action($user_info['uid'], htmlspecialchars_uni($user_info['username'])); - - flash_message($lang->success_user_created, 'success'); - admin_redirect("index.php?module=user-users&action=edit&uid={$user_info['uid']}"); - } - } - - // Fetch custom profile fields - only need required profile fields here - $query = $db->simple_select("profilefields", "*", "required=1", array('order_by' => 'disporder')); - - $profile_fields = array(); - while($profile_field = $db->fetch_array($query)) - { - $profile_fields['required'][] = $profile_field; - } - - $page->add_breadcrumb_item($lang->create_user); - $page->output_header($lang->create_user); - - $form = new Form("index.php?module=user-users&action=add", "post"); - - $page->output_nav_tabs($sub_tabs, 'create_user'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - } - else - { - $mybb->input = array_merge($mybb->input, array('usergroup' => 2)); - } - - $form_container = new FormContainer($lang->required_profile_info); - $form_container->output_row($lang->username." *", "", $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'username'); - $form_container->output_row($lang->password." *", "", $form->generate_password_box('password', $mybb->input['password'], array('id' => 'password', 'autocomplete' => 'off')), 'password'); - $form_container->output_row($lang->confirm_password." *", "", $form->generate_password_box('confirm_password', $mybb->input['confirm_password'], array('id' => 'confirm_new_password')), 'confirm_new_password'); - $form_container->output_row($lang->email_address." *", "", $form->generate_text_box('email', $mybb->input['email'], array('id' => 'email')), 'email'); - - $display_group_options[0] = $lang->use_primary_user_group; - $options = array(); - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $options[$usergroup['gid']] = htmlspecialchars_uni($usergroup['title']); - $display_group_options[$usergroup['gid']] = htmlspecialchars_uni($usergroup['title']); - } - - $form_container->output_row($lang->primary_user_group." *", "", $form->generate_select_box('usergroup', $options, $mybb->input['usergroup'], array('id' => 'usergroup')), 'usergroup'); - $form_container->output_row($lang->additional_user_groups, $lang->additional_user_groups_desc, $form->generate_select_box('additionalgroups[]', $options, $mybb->input['additionalgroups'], array('id' => 'additionalgroups', 'multiple' => true, 'size' => 5)), 'additionalgroups'); - $form_container->output_row($lang->display_user_group." *", "", $form->generate_select_box('displaygroup', $display_group_options, $mybb->input['displaygroup'], array('id' => 'displaygroup')), 'displaygroup'); - - // Output custom profile fields - required - output_custom_profile_fields($profile_fields['required'], $mybb->input['profile_fields'], $form_container, $form); - - $form_container->end(); - $buttons[] = $form->generate_submit_button($lang->save_user); - $form->output_submit_wrapper($buttons); - - $form->end(); - $page->output_footer(); -} - -if($mybb->input['action'] == "edit") -{ - $user = get_user($mybb->input['uid']); - - // Does the user not exist? - if(!$user['uid']) - { - flash_message($lang->error_invalid_user, 'error'); - admin_redirect("index.php?module=user-users"); - } - - $plugins->run_hooks("admin_user_users_edit"); - - if($mybb->request_method == "post") - { - $plugins->run_hooks("admin_user_users_edit_start"); - if(is_super_admin($mybb->input['uid']) && $mybb->user['uid'] != $mybb->input['uid'] && !is_super_admin($mybb->user['uid'])) - { - flash_message($lang->error_no_perms_super_admin, 'error'); - admin_redirect("index.php?module=user-users"); - } - - // Determine the usergroup stuff - if(is_array($mybb->input['additionalgroups'])) - { - foreach($mybb->input['additionalgroups'] as $key => $gid) - { - if($gid == $mybb->input['usergroup']) - { - unset($mybb->input['additionalgroups'][$key]); - } - } - $additionalgroups = implode(",", $mybb->input['additionalgroups']); - } - else - { - $additionalgroups = ''; - } - - $returndate = ""; - if(!empty($mybb->input['away_day'])) - { - $awaydate = TIME_NOW; - // If the user has indicated that they will return on a specific day, but not month or year, assume it is current month and year - if(!$mybb->input['away_month']) - { - $mybb->input['away_month'] = my_date('n', $awaydate); - } - if(!$mybb->input['away_year']) - { - $mybb->input['away_year'] = my_date('Y', $awaydate); - } - - $return_month = (int)substr($mybb->input['away_month'], 0, 2); - $return_day = (int)substr($mybb->input['away_day'], 0, 2); - $return_year = min($mybb->get_input('away_year', MyBB::INPUT_INT), 9999); - - // Check if return date is after the away date. - $returntimestamp = gmmktime(0, 0, 0, $return_month, $return_day, $return_year); - $awaytimestamp = gmmktime(0, 0, 0, my_date('n', $awaydate), my_date('j', $awaydate), my_date('Y', $awaydate)); - if($return_year < my_date('Y', $awaydate) || ($returntimestamp < $awaytimestamp && $return_year == my_date('Y', $awaydate))) - { - $away_in_past = true; - } - - $returndate = "{$return_day}-{$return_month}-{$return_year}"; - } - - // Set up user handler. - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler('update'); - - // Set the data for the new user. - $updated_user = array( - "uid" => $mybb->input['uid'], - "username" => $mybb->input['username'], - "email" => $mybb->input['email'], - "email2" => $mybb->input['email'], - "usergroup" => $mybb->input['usergroup'], - "additionalgroups" => $additionalgroups, - "displaygroup" => $mybb->input['displaygroup'], - "postnum" => $mybb->input['postnum'], - "threadnum" => $mybb->input['threadnum'], - "usertitle" => $mybb->input['usertitle'], - "timezone" => $mybb->input['timezone'], - "language" => $mybb->input['language'], - "profile_fields" => $mybb->input['profile_fields'], - "profile_fields_editable" => true, - "website" => $mybb->input['website'], - "icq" => $mybb->input['icq'], - "aim" => $mybb->input['aim'], - "yahoo" => $mybb->input['yahoo'], - "skype" => $mybb->input['skype'], - "google" => $mybb->input['google'], - "birthday" => array( - "day" => $mybb->input['bday1'], - "month" => $mybb->input['bday2'], - "year" => $mybb->input['bday3'] - ), - "style" => $mybb->input['style'], - "signature" => $mybb->input['signature'], - "dateformat" => $mybb->get_input('dateformat', MyBB::INPUT_INT), - "timeformat" => $mybb->get_input('timeformat', MyBB::INPUT_INT), - "usernotes" => $mybb->input['usernotes'], - "away" => array( - "away" => $mybb->input['away'], - "date" => TIME_NOW, - "returndate" => $returndate, - "awayreason" => $mybb->input['awayreason'] - ) - ); - - if($user['usergroup'] == 5 && $mybb->input['usergroup'] != 5) - { - if($user['coppauser'] == 1) - { - $updated_user['coppa_user'] = 0; - } - } - if($mybb->input['new_password']) - { - $updated_user['password'] = $mybb->input['new_password']; - $updated_user['password2'] = $mybb->input['confirm_new_password']; - } - - $updated_user['options'] = array( - "allownotices" => $mybb->input['allownotices'], - "hideemail" => $mybb->input['hideemail'], - "subscriptionmethod" => $mybb->input['subscriptionmethod'], - "invisible" => $mybb->input['invisible'], - "dstcorrection" => $mybb->input['dstcorrection'], - "threadmode" => $mybb->input['threadmode'], - "classicpostbit" => $mybb->input['classicpostbit'], - "showimages" => $mybb->input['showimages'], - "showvideos" => $mybb->input['showvideos'], - "showsigs" => $mybb->input['showsigs'], - "showavatars" => $mybb->input['showavatars'], - "showquickreply" => $mybb->input['showquickreply'], - "receivepms" => $mybb->input['receivepms'], - "receivefrombuddy" => $mybb->input['receivefrombuddy'], - "pmnotice" => $mybb->input['pmnotice'], - "daysprune" => $mybb->input['daysprune'], - "showcodebuttons" => $mybb->input['showcodebuttons'], - "sourceeditor" => $mybb->input['sourceeditor'], - "pmnotify" => $mybb->input['pmnotify'], - "buddyrequestspm" => $mybb->input['buddyrequestspm'], - "buddyrequestsauto" => $mybb->input['buddyrequestsauto'], - "showredirect" => $mybb->input['showredirect'] - ); - - if($mybb->settings['usertppoptions']) - { - $updated_user['options']['tpp'] = $mybb->get_input('tpp', MyBB::INPUT_INT); - } - - if($mybb->settings['userpppoptions']) - { - $updated_user['options']['ppp'] = $mybb->get_input('ppp', MyBB::INPUT_INT); - } - - // Set the data of the user in the datahandler. - $userhandler->set_data($updated_user); - $errors = ''; - - // Validate the user and get any errors that might have occurred. - if(!$userhandler->validate_user()) - { - $errors = $userhandler->get_friendly_errors(); - } - else - { - // Are we removing an avatar from this user? - if($mybb->input['remove_avatar']) - { - $extra_user_updates = array( - "avatar" => "", - "avatardimensions" => "", - "avatartype" => "" - ); - remove_avatars($user['uid']); - } - - // Are we uploading a new avatar? - if($_FILES['avatar_upload']['name']) - { - $avatar = upload_avatar($_FILES['avatar_upload'], $user['uid']); - if($avatar['error']) - { - $errors = array($avatar['error']); - } - else - { - if($avatar['width'] > 0 && $avatar['height'] > 0) - { - $avatar_dimensions = $avatar['width']."|".$avatar['height']; - } - $extra_user_updates = array( - "avatar" => $avatar['avatar'].'?dateline='.TIME_NOW, - "avatardimensions" => $avatar_dimensions, - "avatartype" => "upload" - ); - } - } - // Are we setting a new avatar from a URL? - else if($mybb->input['avatar_url'] && $mybb->input['avatar_url'] != $user['avatar']) - { - if(!$mybb->settings['allowremoteavatars']) - { - $errors = array($lang->error_remote_avatar_not_allowed); - } - else - { - if(filter_var($mybb->input['avatar_url'], FILTER_VALIDATE_EMAIL) !== false) - { - // Gravatar - $email = md5(strtolower(trim($mybb->input['avatar_url']))); - - $s = ''; - if(!$mybb->settings['maxavatardims']) - { - $mybb->settings['maxavatardims'] = '100x100'; // Hard limit of 100 if there are no limits - } - - // Because Gravatars are square, hijack the width - list($maxwidth, $maxheight) = explode("x", my_strtolower($mybb->settings['maxavatardims'])); - - $s = "?s={$maxwidth}"; - $maxheight = (int)$maxwidth; - - $extra_user_updates = array( - "avatar" => "https://www.gravatar.com/avatar/{$email}{$s}", - "avatardimensions" => "{$maxheight}|{$maxheight}", - "avatartype" => "gravatar" - ); - } - else - { - $mybb->input['avatar_url'] = preg_replace("#script:#i", "", $mybb->input['avatar_url']); - $ext = get_extension($mybb->input['avatar_url']); - - // Copy the avatar to the local server (work around remote URL access disabled for getimagesize) - $file = fetch_remote_file($mybb->input['avatar_url']); - if(!$file) - { - $avatar_error = $lang->error_invalidavatarurl; - } - else - { - $tmp_name = "../".$mybb->settings['avataruploadpath']."/remote_".md5(random_str()); - $fp = @fopen($tmp_name, "wb"); - if(!$fp) - { - $avatar_error = $lang->error_invalidavatarurl; - } - else - { - fwrite($fp, $file); - fclose($fp); - list($width, $height, $type) = @getimagesize($tmp_name); - @unlink($tmp_name); - echo $type; - if(!$type) - { - $avatar_error = $lang->error_invalidavatarurl; - } - } - } - - if(empty($avatar_error)) - { - if($width && $height && $mybb->settings['maxavatardims'] != "") - { - list($maxwidth, $maxheight) = explode("x", my_strtolower($mybb->settings['maxavatardims'])); - if(($maxwidth && $width > $maxwidth) || ($maxheight && $height > $maxheight)) - { - $lang->error_avatartoobig = $lang->sprintf($lang->error_avatartoobig, $maxwidth, $maxheight); - $avatar_error = $lang->error_avatartoobig; - } - } - } - - if(empty($avatar_error)) - { - if($width > 0 && $height > 0) - { - $avatar_dimensions = (int)$width."|".(int)$height; - } - $extra_user_updates = array( - "avatar" => $db->escape_string($mybb->input['avatar_url'].'?dateline='.TIME_NOW), - "avatardimensions" => $avatar_dimensions, - "avatartype" => "remote" - ); - remove_avatars($user['uid']); - } - else - { - $errors = array($avatar_error); - } - } - } - } - - // Moderator "Options" (suspend signature, suspend/moderate posting) - $moderator_options = array( - 1 => array( - "action" => "suspendsignature", // The moderator action we're performing - "period" => "action_period", // The time period we've selected from the dropdown box - "time" => "action_time", // The time we've entered - "update_field" => "suspendsignature", // The field in the database to update if true - "update_length" => "suspendsigtime" // The length of suspension field in the database - ), - 2 => array( - "action" => "moderateposting", - "period" => "modpost_period", - "time" => "modpost_time", - "update_field" => "moderateposts", - "update_length" => "moderationtime" - ), - 3 => array( - "action" => "suspendposting", - "period" => "suspost_period", - "time" => "suspost_time", - "update_field" => "suspendposting", - "update_length" => "suspensiontime" - ) - ); - - require_once MYBB_ROOT."inc/functions_warnings.php"; - foreach($moderator_options as $option) - { - if(!$mybb->input[$option['action']]) - { - if($user[$option['update_field']] == 1) - { - // We're revoking the suspension - $extra_user_updates[$option['update_field']] = 0; - $extra_user_updates[$option['update_length']] = 0; - } - - // Skip this option if we haven't selected it - continue; - } - - if($mybb->input[$option['action']]) - { - if((int)$mybb->input[$option['time']] == 0 && $mybb->input[$option['period']] != "never" && $user[$option['update_field']] != 1) - { - // User has selected a type of ban, but not entered a valid time frame - $string = $option['action']."_error"; - $errors[] = $lang->$string; - } - - if(!is_array($errors)) - { - $suspend_length = fetch_time_length((int)$mybb->input[$option['time']], $mybb->input[$option['period']]); - - if($user[$option['update_field']] == 1 && ($mybb->input[$option['time']] || $mybb->input[$option['period']] == "never")) - { - // We already have a suspension, but entered a new time - if($suspend_length == "-1") - { - // Permanent ban on action - $extra_user_updates[$option['update_length']] = 0; - } - elseif($suspend_length && $suspend_length != "-1") - { - // Temporary ban on action - $extra_user_updates[$option['update_length']] = TIME_NOW + $suspend_length; - } - } - elseif(!$user[$option['update_field']]) - { - // New suspension for this user... bad user! - $extra_user_updates[$option['update_field']] = 1; - if($suspend_length == "-1") - { - $extra_user_updates[$option['update_length']] = 0; - } - else - { - $extra_user_updates[$option['update_length']] = TIME_NOW + $suspend_length; - } - } - } - } - } - - if($extra_user_updates['moderateposts'] && $extra_user_updates['suspendposting']) - { - $errors[] = $lang->suspendmoderate_error; - } - - if(isset($away_in_past)) - { - $errors[] = $lang->error_acp_return_date_past; - } - - if(!$errors) - { - $user_info = $userhandler->update_user(); - - $plugins->run_hooks("admin_user_users_edit_commit_start"); - - $db->update_query("users", $extra_user_updates, "uid='{$user['uid']}'"); - - // if we're updating the user's signature preferences, do so now - if($mybb->input['update_posts'] == 'enable' || $mybb->input['update_posts'] == 'disable') - { - $update_signature = array( - 'includesig' => ($mybb->input['update_posts'] == 'enable' ? 1 : 0) - ); - $db->update_query("posts", $update_signature, "uid='{$user['uid']}'"); - } - - $plugins->run_hooks("admin_user_users_edit_commit"); - - if($user['usergroup'] == 5 && $mybb->input['usergroup'] != 5) - { - $cache->update_awaitingactivation(); - } - - // Log admin action - log_admin_action($user['uid'], htmlspecialchars_uni($mybb->input['username'])); - - flash_message($lang->success_user_updated, 'success'); - admin_redirect("index.php?module=user-users"); - } - $plugins->run_hooks("admin_user_users_edit_end"); - } - } - - if(!$errors) - { - $user['usertitle'] = htmlspecialchars_decode($user['usertitle']); - $mybb->input = array_merge($mybb->input, $user); - - $options = array( - 'bday1', 'bday2', 'bday3', - 'new_password', 'confirm_new_password', - 'action_time', 'action_period', - 'modpost_period', 'moderateposting', 'modpost_time', 'suspost_period', 'suspost_time' - ); - - foreach($options as $option) - { - if(!isset($input_user[$option])) - { - $mybb->input[$option] = ''; - } - } - - // We need to fetch this users profile field values - $query = $db->simple_select("userfields", "*", "ufid='{$user['uid']}'"); - $mybb->input['profile_fields'] = $db->fetch_array($query); - } - - if($mybb->input['bday1'] || $mybb->input['bday2'] || $mybb->input['bday3']) - { - $mybb->input['bday'][0] = $mybb->input['bday1']; - $mybb->input['bday'][1] = $mybb->input['bday2']; - $mybb->input['bday'][2] = $mybb->get_input('bday3', MyBB::INPUT_INT); - } - else - { - $mybb->input['bday'] = array(0, 0, ''); - - if($user['birthday']) - { - $mybb->input['bday'] = explode('-', $user['birthday']); - } - } - - if($mybb->input['away_day'] || $mybb->input['away_month'] || $mybb->input['away_year']) - { - $mybb->input['away_year'] = $mybb->get_input('away_year', MyBB::INPUT_INT); - } - else - { - $mybb->input['away_day'] = 0; - $mybb->input['away_month'] = 0; - $mybb->input['away_year'] = ''; - - if($user['returndate']) - { - list($mybb->input['away_day'], $mybb->input['away_month'], $mybb->input['away_year']) = explode('-', $user['returndate']); - } - } - - // Fetch custom profile fields - $query = $db->simple_select("profilefields", "*", "", array('order_by' => 'disporder')); - - $profile_fields = array(); - while($profile_field = $db->fetch_array($query)) - { - if($profile_field['required'] == 1) - { - $profile_fields['required'][] = $profile_field; - } - else - { - $profile_fields['optional'][] = $profile_field; - } - } - - $page->add_breadcrumb_item($lang->edit_user.": ".htmlspecialchars_uni($user['username'])); - - $page->extra_header .= << - - - -EOF; - $page->output_header($lang->edit_user); - - $sub_tabs['edit_user'] = array( - 'title' => $lang->edit_user, - 'description' => $lang->edit_user_desc - ); - - $form = new Form("index.php?module=user-users&action=edit&uid={$user['uid']}", "post", "", 1); - - $page->output_nav_tabs($sub_tabs, 'edit_user'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - } - - // Is this user a COPPA user? We show a warning & activate link - if($user['coppauser']) - { - echo $lang->sprintf($lang->warning_coppa_user, $user['uid']); - } - - $tabs = array( - "overview" => $lang->overview, - "profile" => $lang->profile, - "settings" => $lang->account_settings, - "signature" => $lang->signature, - "avatar" => $lang->avatar, - "modoptions" => $lang->mod_options - ); - $tabs = $plugins->run_hooks("admin_user_users_edit_graph_tabs", $tabs); - $page->output_tab_control($tabs); - - // - // OVERVIEW - // - echo "
\n"; - $table = new Table; - $table->construct_header($lang->avatar, array('class' => 'align_center')); - $table->construct_header($lang->general_account_stats, array('colspan' => '2', 'class' => 'align_center')); - - // Avatar - $avatar_dimensions = explode("|", $user['avatardimensions']); - if($user['avatar'] && (my_strpos($user['avatar'], '://') === false || $mybb->settings['allowremoteavatars'])) - { - if($user['avatardimensions']) - { - require_once MYBB_ROOT."inc/functions_image.php"; - list($width, $height) = explode("|", $user['avatardimensions']); - $scaled_dimensions = scale_image($width, $height, 120, 120); - } - else - { - $scaled_dimensions = array( - "width" => 120, - "height" => 120 - ); - } - if(!my_validate_url($user['avatar'])) - { - $user['avatar'] = "../{$user['avatar']}\n"; - } - } - else - { - if(my_validate_url($mybb->settings['useravatar'])) - { - $user['avatar'] = str_replace('{theme}', 'images', $mybb->settings['useravatar']); - } - else - { - $user['avatar'] = "../".str_replace('{theme}', 'images', $mybb->settings['useravatar']); - } - $scaled_dimensions = array( - "width" => 120, - "height" => 120 - ); - } - $avatar_top = ceil((126-$scaled_dimensions['height'])/2); - if($user['lastactive']) - { - $last_active = my_date('relative', $user['lastactive']); - } - else - { - $last_active = $lang->never; - } - $reg_date = my_date('relative', $user['regdate']); - if($user['dst'] == 1) - { - $timezone = (float)$user['timezone']+1; - } - else - { - $timezone = (float)$user['timezone']; - } - $local_date = gmdate($mybb->settings['dateformat'], TIME_NOW + ($timezone * 3600)); - $local_time = gmdate($mybb->settings['timeformat'], TIME_NOW + ($timezone * 3600)); - - $localtime = $lang->sprintf($lang->local_time_format, $local_date, $local_time); - $days_registered = (TIME_NOW - $user['regdate']) / (24*3600); - $posts_per_day = 0; - if($days_registered > 0) - { - $posts_per_day = round($user['postnum'] / $days_registered, 2); - if($posts_per_day > $user['postnum']) - { - $posts_per_day = $user['postnum']; - } - } - $posts_per_day = my_number_format($posts_per_day); - - $stats = $cache->read("stats"); - $posts = $stats['numposts']; - if($posts == 0) - { - $percent_posts = "0"; - } - else - { - $percent_posts = round($user['postnum']*100/$posts, 2); - } - - $user_permissions = user_permissions($user['uid']); - - // Fetch the reputation for this user - if($user_permissions['usereputationsystem'] == 1 && $mybb->settings['enablereputation'] == 1) - { - $reputation = get_reputation($user['reputation']); - } - else - { - $reputation = "-"; - } - - if($mybb->settings['enablewarningsystem'] != 0 && $user_permissions['canreceivewarnings'] != 0) - { - if($mybb->settings['maxwarningpoints'] < 1) - { - $mybb->settings['maxwarningpoints'] = 10; - } - - $warning_level = round($user['warningpoints']/$mybb->settings['maxwarningpoints']*100); - if($warning_level > 100) - { - $warning_level = 100; - } - $warning_level = get_colored_warning_level($warning_level); - } - - $age = $lang->na; - if($user['birthday']) - { - $age = get_age($user['birthday']); - } - - $postnum = my_number_format($user['postnum']); - - $table->construct_cell("
\"\"
", array('rowspan' => 6, 'width' => 1)); - $table->construct_cell("{$lang->email_address}: ".htmlspecialchars_uni($user['email']).""); - $table->construct_cell("{$lang->last_active}: {$last_active}"); - $table->construct_row(); - $table->construct_cell("{$lang->registration_date}: {$reg_date}"); - $table->construct_cell("{$lang->local_time}: {$localtime}"); - $table->construct_row(); - $table->construct_cell("{$lang->posts}: {$postnum}"); - $table->construct_cell("{$lang->age}: {$age}"); - $table->construct_row(); - $table->construct_cell("{$lang->posts_per_day}: {$posts_per_day}"); - $table->construct_cell("{$lang->reputation}: {$reputation}"); - $table->construct_row(); - $table->construct_cell("{$lang->percent_of_total_posts}: {$percent_posts}"); - $table->construct_cell("{$lang->warning_level}: {$warning_level}"); - $table->construct_row(); - $table->construct_cell("{$lang->registration_ip}: ".my_inet_ntop($db->unescape_binary($user['regip']))); - $table->construct_cell("{$lang->last_known_ip}: ".my_inet_ntop($db->unescape_binary($user['lastip']))); - $table->construct_row(); - - $username = htmlspecialchars_uni($user['username']); - $table->output("{$lang->user_overview}: {$username}"); - $plugins->run_hooks("admin_user_users_edit_overview"); - echo "
\n"; - - // - // PROFILE - // - echo "
\n"; - - $form_container = new FormContainer($lang->required_profile_info.": ".htmlspecialchars_uni($user['username'])); - $form_container->output_row($lang->username." *", "", $form->generate_text_box('username', $mybb->input['username'], array('id' => 'username')), 'username'); - $form_container->output_row($lang->new_password, $lang->new_password_desc, $form->generate_password_box('new_password', $mybb->input['new_password'], array('id' => 'new_password', 'autocomplete' => 'off')), 'new_password'); - $form_container->output_row($lang->confirm_new_password, $lang->new_password_desc, $form->generate_password_box('confirm_new_password', $mybb->input['confirm_new_password'], array('id' => 'confirm_new_password')), 'confirm_new_password'); - $form_container->output_row($lang->email_address." *", "", $form->generate_text_box('email', $mybb->input['email'], array('id' => 'email')), 'email'); - - $display_group_options[0] = $lang->use_primary_user_group; - $options = array(); - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $options[$usergroup['gid']] = htmlspecialchars_uni($usergroup['title']); - $display_group_options[$usergroup['gid']] = htmlspecialchars_uni($usergroup['title']); - } - - if(!is_array($mybb->input['additionalgroups'])) - { - $mybb->input['additionalgroups'] = explode(',', $mybb->input['additionalgroups']); - } - - $form_container->output_row($lang->primary_user_group." *", "", $form->generate_select_box('usergroup', $options, $mybb->input['usergroup'], array('id' => 'usergroup')), 'usergroup'); - $form_container->output_row($lang->additional_user_groups, $lang->additional_user_groups_desc, $form->generate_select_box('additionalgroups[]', $options, $mybb->input['additionalgroups'], array('id' => 'additionalgroups', 'multiple' => true, 'size' => 5)), 'additionalgroups'); - $form_container->output_row($lang->display_user_group." *", "", $form->generate_select_box('displaygroup', $display_group_options, $mybb->input['displaygroup'], array('id' => 'displaygroup')), 'displaygroup'); - $form_container->output_row($lang->post_count." *", "", $form->generate_numeric_field('postnum', $mybb->input['postnum'], array('id' => 'postnum', 'min' => 0)), 'postnum'); - $form_container->output_row($lang->thread_count." *", "", $form->generate_numeric_field('threadnum', $mybb->input['threadnum'], array('id' => 'threadnum', 'min' => 0)), 'threadnum'); - - // Output custom profile fields - required - if(!isset($profile_fields['required'])) - { - $profile_fields['required'] = array(); - } - output_custom_profile_fields($profile_fields['required'], $mybb->input['profile_fields'], $form_container, $form); - - $form_container->end(); - - $form_container = new FormContainer($lang->optional_profile_info.': '.htmlspecialchars_uni($user['username'])); - $form_container->output_row($lang->custom_user_title, $lang->custom_user_title_desc, $form->generate_text_box('usertitle', $mybb->input['usertitle'], array('id' => 'usertitle')), 'usertitle'); - $form_container->output_row($lang->website, "", $form->generate_text_box('website', $mybb->input['website'], array('id' => 'website')), 'website'); - $form_container->output_row($lang->icq_number, "", $form->generate_numeric_field('icq', $mybb->input['icq'], array('id' => 'icq', 'min' => 0)), 'icq'); - $form_container->output_row($lang->aim_handle, "", $form->generate_text_box('aim', $mybb->input['aim'], array('id' => 'aim')), 'aim'); - $form_container->output_row($lang->yahoo_messanger_handle, "", $form->generate_text_box('yahoo', $mybb->input['yahoo'], array('id' => 'yahoo')), 'yahoo'); - $form_container->output_row($lang->skype_handle, "", $form->generate_text_box('skype', $mybb->input['skype'], array('id' => 'skype')), 'skype'); - $form_container->output_row($lang->google_handle, "", $form->generate_text_box('google', $mybb->input['google'], array('id' => 'google')), 'google'); - - // Birthday - $birthday_days = array(0 => ''); - for($i = 1; $i <= 31; $i++) - { - $birthday_days[$i] = $i; - } - - $birthday_months = array( - 0 => '', - 1 => $lang->january, - 2 => $lang->february, - 3 => $lang->march, - 4 => $lang->april, - 5 => $lang->may, - 6 => $lang->june, - 7 => $lang->july, - 8 => $lang->august, - 9 => $lang->september, - 10 => $lang->october, - 11 => $lang->november, - 12 => $lang->december - ); - - $birthday_row = $form->generate_select_box('bday1', $birthday_days, $mybb->input['bday'][0], array('id' => 'bday_day')); - $birthday_row .= ' '.$form->generate_select_box('bday2', $birthday_months, $mybb->input['bday'][1], array('id' => 'bday_month')); - $birthday_row .= ' '.$form->generate_numeric_field('bday3', $mybb->input['bday'][2], array('id' => 'bday_year', 'style' => 'width: 4em;', 'min' => 0)); - - $form_container->output_row($lang->birthday, "", $birthday_row, 'birthday'); - - // Output custom profile fields - optional - output_custom_profile_fields($profile_fields['optional'], $mybb->input['profile_fields'], $form_container, $form); - - $form_container->end(); - - - if($mybb->settings['allowaway'] != 0) - { - $form_container = new FormContainer($lang->away_information.': '.htmlspecialchars_uni($user['username'])); - $awaycheck = array(false, true); - if($mybb->input['away'] == 1) - { - $awaycheck = array(true, false); - } - $form_container->output_row($lang->away_status, $lang->away_status_desc, $form->generate_radio_button('away', 1, $lang->im_away, array('id' => 'away', "checked" => $awaycheck[0]))." ".$form->generate_radio_button('away', 0, $lang->im_here, array('id' => 'away2', "checked" => $awaycheck[1])), 'away'); - $form_container->output_row($lang->away_reason, $lang->away_reason_desc, $form->generate_text_box('awayreason', $mybb->input['awayreason'], array('id' => 'awayreason')), 'awayreason'); - - //Return date (we can use the arrays from birthday) - $return_row = $form->generate_select_box('away_day', $birthday_days, $mybb->input['away_day'], array('id' => 'away_day')); - $return_row .= ' '.$form->generate_select_box('away_month', $birthday_months, $mybb->input['away_month'], array('id' => 'away_month')); - $return_row .= ' '.$form->generate_numeric_field('away_year', $mybb->input['away_year'], array('id' => 'away_year', 'style' => 'width: 4em;', 'min' => 0)); - - $form_container->output_row($lang->return_date, $lang->return_date_desc, $return_row, 'away_date'); - - $form_container->end(); - } - - $plugins->run_hooks("admin_user_users_edit_profile"); - echo "
\n"; - - // - // ACCOUNT SETTINGS - // - - // Plugin hook note - we should add hooks in above each output_row for the below so users can add their own options to each group :> - - echo "
\n"; - $form_container = new FormContainer($lang->account_settings.': '.htmlspecialchars_uni($user['username'])); - $login_options = array( - $form->generate_check_box("invisible", 1, $lang->hide_from_whos_online, array("checked" => $mybb->input['invisible'])), - ); - $form_container->output_row($lang->login_cookies_privacy, "", "
".implode("
", $login_options)."
"); - - if($mybb->input['pmnotice'] > 1) - { - $mybb->input['pmnotice'] = 1; - } - - $messaging_options = array( - $form->generate_check_box("allownotices", 1, $lang->recieve_admin_emails, array("checked" => $mybb->input['allownotices'])), - $form->generate_check_box("hideemail", 1, $lang->hide_email_from_others, array("checked" => $mybb->input['hideemail'])), - $form->generate_check_box("receivepms", 1, $lang->recieve_pms_from_others, array("checked" => $mybb->input['receivepms'])), - $form->generate_check_box("receivefrombuddy", 1, $lang->recieve_pms_from_buddy, array("checked" => $mybb->input['receivefrombuddy'])), - $form->generate_check_box("pmnotice", 1, $lang->alert_new_pms, array("checked" => $mybb->input['pmnotice'])), - $form->generate_check_box("pmnotify", 1, $lang->email_notify_new_pms, array("checked" => $mybb->input['pmnotify'])), - $form->generate_check_box("buddyrequestspm", 1, $lang->buddy_requests_pm, array("checked" => $mybb->input['buddyrequestspm'])), - $form->generate_check_box("buddyrequestsauto", 1, $lang->buddy_requests_auto, array("checked" => $mybb->input['buddyrequestsauto'])), - "
".$form->generate_select_box("subscriptionmethod", array($lang->do_not_subscribe, $lang->no_email_notification, $lang->instant_email_notification), $mybb->input['subscriptionmethod'], array('id' => 'subscriptionmethod')) - ); - $form_container->output_row($lang->messaging_and_notification, "", "
".implode("
", $messaging_options)."
"); - - $date_format_options = array($lang->use_default); - foreach($date_formats as $key => $format) - { - $date_format_options[$key] = my_date($format, TIME_NOW, "", 0); - } - - $time_format_options = array($lang->use_default); - foreach($time_formats as $key => $format) - { - $time_format_options[$key] = my_date($format, TIME_NOW, "", 0); - } - - $date_options = array( - "
".$form->generate_select_box("dateformat", $date_format_options, $mybb->input['dateformat'], array('id' => 'dateformat')), - "
".$form->generate_select_box("timeformat", $time_format_options, $mybb->input['timeformat'], array('id' => 'timeformat')), - "
".build_timezone_select("timezone", $mybb->input['timezone']), - "
".$form->generate_select_box("dstcorrection", array(2 => $lang->automatically_detect, 1 => $lang->always_use_dst_correction, 0 => $lang->never_use_dst_correction), $mybb->input['dstcorrection'], array('id' => 'dstcorrection')) - ); - $form_container->output_row($lang->date_and_time_options, "", "
".implode("
", $date_options)."
"); - - - $tpp_options = array($lang->use_default); - if($mybb->settings['usertppoptions']) - { - $explodedtpp = explode(",", $mybb->settings['usertppoptions']); - if(is_array($explodedtpp)) - { - foreach($explodedtpp as $tpp) - { - if($tpp <= 0) continue; - $tpp_options[$tpp] = $tpp; - } - } - } - - $thread_age_options = array( - 0 => $lang->use_default, - 1 => $lang->show_threads_last_day, - 5 => $lang->show_threads_last_5_days, - 10 => $lang->show_threads_last_10_days, - 20 => $lang->show_threads_last_20_days, - 50 => $lang->show_threads_last_50_days, - 75 => $lang->show_threads_last_75_days, - 100 => $lang->show_threads_last_100_days, - 365 => $lang->show_threads_last_year, - 9999 => $lang->show_all_threads - ); - - $forum_options = array( - "
".$form->generate_select_box("tpp", $tpp_options, $mybb->input['tpp'], array('id' => 'tpp')), - "
".$form->generate_select_box("daysprune", $thread_age_options, $mybb->input['daysprune'], array('id' => 'daysprune')) - ); - $form_container->output_row($lang->forum_display_options, "", "
".implode("
", $forum_options)."
"); - - $ppp_options = array($lang->use_default); - if($mybb->settings['userpppoptions']) - { - $explodedppp = explode(",", $mybb->settings['userpppoptions']); - if(is_array($explodedppp)) - { - foreach($explodedppp as $ppp) - { - if($ppp <= 0) continue; - $ppp_options[$ppp] = $ppp; - } - } - } - - $thread_options = array( - $form->generate_check_box("classicpostbit", 1, $lang->show_classic_postbit, array("checked" => $mybb->input['classicpostbit'])), - $form->generate_check_box("showimages", 1, $lang->display_images, array("checked" => $mybb->input['showimages'])), - $form->generate_check_box("showvideos", 1, $lang->display_videos, array("checked" => $mybb->input['showvideos'])), - $form->generate_check_box("showsigs", 1, $lang->display_users_sigs, array("checked" => $mybb->input['showsigs'])), - $form->generate_check_box("showavatars", 1, $lang->display_users_avatars, array("checked" => $mybb->input['showavatars'])), - $form->generate_check_box("showquickreply", 1, $lang->show_quick_reply, array("checked" => $mybb->input['showquickreply'])), - "
".$form->generate_select_box("ppp", $ppp_options, $mybb->input['ppp'], array('id' => 'ppp')), - "
".$form->generate_select_box("threadmode", array("" => $lang->use_default, "linear" => $lang->linear_mode, "threaded" => $lang->threaded_mode), $mybb->input['threadmode'], array('id' => 'threadmode')) - ); - $form_container->output_row($lang->thread_view_options, "", "
".implode("
", $thread_options)."
"); - - $languages = array_merge(array('' => $lang->use_default), $lang->get_languages()); - - $other_options = array( - $form->generate_check_box("showredirect", 1, $lang->show_redirect, array("checked" => $mybb->input['showredirect'])), - $form->generate_check_box("showcodebuttons", "1", $lang->show_code_buttons, array("checked" => $mybb->input['showcodebuttons'])), - $form->generate_check_box("sourceeditor", "1", $lang->source_editor, array("checked" => $mybb->input['sourceeditor'])), - "
".build_theme_select("style", $mybb->input['style'], 0, "", true, false, true), - "
".$form->generate_select_box("language", $languages, $mybb->input['language'], array('id' => 'language')) - ); - $form_container->output_row($lang->other_options, "", "
".implode("
", $other_options)."
"); - - $form_container->end(); - $plugins->run_hooks("admin_user_users_edit_settings"); - echo "
\n"; - - // - // SIGNATURE EDITOR - // - $signature_editor = $form->generate_text_area("signature", $mybb->input['signature'], array('id' => 'signature', 'rows' => 15, 'cols' => '70', 'style' => 'height: 250px; width: 95%')); - $sig_smilies = $lang->off; - if($mybb->settings['sigsmilies'] == 1) - { - $sig_smilies = $lang->on; - } - $sig_mycode = $lang->off; - if($mybb->settings['sigmycode'] == 1) - { - $sig_mycode = $lang->on; - $signature_editor .= build_mycode_inserter("signature"); - } - $sig_html = $lang->off; - if($mybb->settings['sightml'] == 1) - { - $sig_html = $lang->on; - } - $sig_imgcode = $lang->off; - if($mybb->settings['sigimgcode'] == 1) - { - $sig_imgcode = $lang->on; - } - echo "
\n"; - $form_container = new FormContainer($lang->signature.': '.htmlspecialchars_uni($user['username'])); - $form_container->output_row($lang->signature, $lang->sprintf($lang->signature_desc, $sig_mycode, $sig_smilies, $sig_imgcode, $sig_html), $signature_editor, 'signature'); - - $periods = array( - "hours" => $lang->expire_hours, - "days" => $lang->expire_days, - "weeks" => $lang->expire_weeks, - "months" => $lang->expire_months, - "never" => $lang->expire_permanent - ); - - // Are we already suspending the signature? - if($mybb->input['suspendsignature']) - { - $sig_checked = 1; - - // Display how much time is left on the ban for the user to extend it - if($user['suspendsigtime'] == "0") - { - // Permanent - $lang->suspend_expire_info = $lang->suspend_sig_perm; - } - else - { - // There's a limit to the suspension! - $remaining = $user['suspendsigtime']-TIME_NOW; - $expired = nice_time($remaining, array('seconds' => false)); - - $color = 'inherit'; - if($remaining < 3600) - { - $color = 'red'; - } - elseif($remaining < 86400) - { - $color = 'maroon'; - } - elseif($remaining < 604800) - { - $color = 'green'; - } - - $lang->suspend_expire_info = $lang->sprintf($lang->suspend_expire_info, $expired, $color); - } - $user_suspend_info = ' - - '.$lang->suspend_expire_info.'
'.$lang->suspend_sig_extend.' - '; - } - else - { - $sig_checked = 0; - $user_suspend_info = ''; - } - - $actions = ' - - -
-
'.$form->generate_check_box("suspendsignature", 1, $lang->suspend_sig_box, array('checked' => $sig_checked, 'onclick' => 'toggleAction();')).'
-
- '.$user_suspend_info.' - - - - -
'.$lang->expire_length.''.$form->generate_numeric_field('action_time', $mybb->input['action_time'], array('style' => 'width: 3em;', 'min' => 0)).' '.$form->generate_select_box('action_period', $periods, $mybb->input['action_period']).'
-
-
- - '; - - $form_container->output_row($lang->suspend_sig, $lang->suspend_sig_info, $actions); - - $signature_options = array( - $form->generate_radio_button("update_posts", "enable", $lang->enable_sig_in_all_posts, array("checked" => 0)), - $form->generate_radio_button("update_posts", "disable", $lang->disable_sig_in_all_posts, array("checked" => 0)), - $form->generate_radio_button("update_posts", "no", $lang->do_nothing, array("checked" => 1)) - ); - - $form_container->output_row($lang->signature_preferences, "", implode("
", $signature_options)); - - $form_container->end(); - $plugins->run_hooks("admin_user_users_edit_signatur"); - echo "
\n"; - - // - // AVATAR MANAGER - // - echo "
\n"; - $table = new Table; - $table->construct_header($lang->current_avatar, array('colspan' => 2)); - - $table->construct_cell("
\"\"
", array('width' => 1)); - - $avatar_url = ''; - if($user['avatartype'] == "upload" || stristr($user['avatar'], $mybb->settings['avataruploadpath'])) - { - $current_avatar_msg = "
{$lang->user_current_using_uploaded_avatar}"; - } - elseif($user['avatartype'] == "remote" || my_validate_url($user['avatar'])) - { - $current_avatar_msg = "
{$lang->user_current_using_remote_avatar}"; - $avatar_url = $user['avatar']; - } - - if($errors) - { - $avatar_url = htmlspecialchars_uni($mybb->input['avatar_url']); - } - - if($mybb->settings['maxavatardims'] != "") - { - list($max_width, $max_height) = explode("x", my_strtolower($mybb->settings['maxavatardims'])); - $max_size = "
{$lang->max_dimensions_are} {$max_width}x{$max_height}"; - } - - if($mybb->settings['avatarsize']) - { - $maximum_size = get_friendly_size($mybb->settings['avatarsize']*1024); - $max_size .= "
{$lang->avatar_max_size} {$maximum_size}"; - } - - if($user['avatar']) - { - $remove_avatar = "

".$form->generate_check_box("remove_avatar", 1, "{$lang->remove_avatar}"); - } - - $table->construct_cell($lang->avatar_desc."{$remove_avatar}
{$max_size}"); - $table->construct_row(); - - $table->output($lang->avatar.': '.htmlspecialchars_uni($user['username'])); - - // Custom avatar - if($mybb->settings['avatarresizing'] == "auto") - { - $auto_resize = $lang->avatar_auto_resize; - } - else if($mybb->settings['avatarresizing'] == "user") - { - $auto_resize = " "; - } - $form_container = new FormContainer($lang->specify_custom_avatar); - $form_container->output_row($lang->upload_avatar, $auto_resize, $form->generate_file_upload_box('avatar_upload', array('id' => 'avatar_upload')), 'avatar_upload'); - if($mybb->settings['allowremoteavatars']) - { - $form_container->output_row($lang->or_specify_avatar_url, "", $form->generate_text_box('avatar_url', $avatar_url, array('id' => 'avatar_url')), 'avatar_url'); - } - $form_container->end(); - $plugins->run_hooks("admin_user_users_edit_avatar"); - echo "
\n"; - - // - // MODERATOR OPTIONS - // - $periods = array( - "hours" => $lang->expire_hours, - "days" => $lang->expire_days, - "weeks" => $lang->expire_weeks, - "months" => $lang->expire_months, - "never" => $lang->expire_permanent - ); - - echo "
\n"; - $form_container = new FormContainer($lang->mod_options.': '.htmlspecialchars_uni($user['username'])); - $form_container->output_row($lang->user_notes, '', $form->generate_text_area('usernotes', $mybb->input['usernotes'], array('id' => 'usernotes')), 'usernotes'); - - // Mod posts - // Generate check box - $modpost_options = $form->generate_select_box('modpost_period', $periods, $mybb->input['modpost_period'], array('id' => 'modpost_period')); - - // Do we have any existing suspensions here? - $existing_info = ''; - if($user['moderateposts'] || ($mybb->input['moderateposting'] && !empty($errors))) - { - $mybb->input['moderateposting'] = 1; - if($user['moderationtime'] != 0) - { - $remaining = $user['moderationtime']-TIME_NOW; - $expired = nice_time($remaining, array('seconds' => false)); - - $color = 'inherit'; - if($remaining < 3600) - { - $color = 'red'; - } - elseif($remaining < 86400) - { - $color = 'maroon'; - } - elseif($remaining < 604800) - { - $color = 'green'; - } - - $existing_info = $lang->sprintf($lang->moderate_length, $expired, $color); - } - else - { - $existing_info = $lang->moderated_perm; - } - } - - $modpost_div = '
'.$existing_info.''.$lang->moderate_for.' '.$form->generate_numeric_field("modpost_time", $mybb->input['modpost_time'], array('style' => 'width: 3em;', 'min' => 0)).' '.$modpost_options.'
'; - $lang->moderate_posts_info = $lang->sprintf($lang->moderate_posts_info, htmlspecialchars_uni($user['username'])); - $form_container->output_row($form->generate_check_box("moderateposting", 1, $lang->moderate_posts, array("id" => "moderateposting", "onclick" => "toggleBox('modpost');", "checked" => $mybb->input['moderateposting'])), $lang->moderate_posts_info, $modpost_div); - - // Suspend posts - // Generate check box - $suspost_options = $form->generate_select_box('suspost_period', $periods, $mybb->input['suspost_period'], array('id' => 'suspost_period')); - - // Do we have any existing suspensions here? - if($user['suspendposting'] || ($mybb->input['suspendposting'] && !empty($errors))) - { - $mybb->input['suspendposting'] = 1; - - if($user['suspensiontime'] == 0 || $mybb->input['suspost_period'] == "never") - { - $existing_info = $lang->suspended_perm; - } - else - { - $remaining = $user['suspensiontime']-TIME_NOW; - $suspost_date = nice_time($remaining, array('seconds' => false)); - - $color = 'inherit'; - if($remaining < 3600) - { - $color = 'red'; - } - elseif($remaining < 86400) - { - $color = 'maroon'; - } - elseif($remaining < 604800) - { - $color = 'green'; - } - - $existing_info = $lang->sprintf($lang->suspend_length, $suspost_date, $color); - } - } - - $suspost_div = '
'.$existing_info.''.$lang->suspend_for.' '.$form->generate_numeric_field("suspost_time", $mybb->input['suspost_time'], array('style' => 'width: 3em;', 'min' => 0)).' '.$suspost_options.'
'; - $lang->suspend_posts_info = $lang->sprintf($lang->suspend_posts_info, htmlspecialchars_uni($user['username'])); - $form_container->output_row($form->generate_check_box("suspendposting", 1, $lang->suspend_posts, array("id" => "suspendposting", "onclick" => "toggleBox('suspost');", "checked" => $mybb->input['suspendposting'])), $lang->suspend_posts_info, $suspost_div); - - - $form_container->end(); - $plugins->run_hooks("admin_user_users_edit_moderator_options"); - echo "
\n"; - - $plugins->run_hooks("admin_user_users_edit_graph"); - - $buttons[] = $form->generate_submit_button($lang->save_user); - $form->output_submit_wrapper($buttons); - - $form->end(); - - echo ''; - - $page->output_footer(); -} - -if($mybb->input['action'] == "delete") -{ - $user = get_user($mybb->input['uid']); - - // Does the user not exist? - if(!$user['uid']) - { - flash_message($lang->error_invalid_user, 'error'); - admin_redirect("index.php?module=user-users"); - } - - if(is_super_admin($mybb->input['uid']) && $mybb->user['uid'] != $mybb->input['uid'] && !is_super_admin($mybb->user['uid'])) - { - flash_message($lang->error_no_perms_super_admin, 'error'); - admin_redirect("index.php?module=user-users"); - } - - // User clicked no - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-users"); - } - - $plugins->run_hooks("admin_user_users_delete"); - - if($mybb->request_method == "post") - { - $plugins->run_hooks("admin_user_users_delete_commit"); - - // Set up user handler. - require_once MYBB_ROOT.'inc/datahandlers/user.php'; - $userhandler = new UserDataHandler('delete'); - - // Delete the user - if(!$userhandler->delete_user($user['uid'])) - { - flash_message($lang->error_cannot_delete_user, 'error'); - admin_redirect("index.php?module=user-users"); - } - - $cache->update_awaitingactivation(); - - $plugins->run_hooks("admin_user_users_delete_commit_end"); - - log_admin_action($user['uid'], htmlspecialchars_uni($user['username'])); - - flash_message($lang->success_user_deleted, 'success'); - admin_redirect("index.php?module=user-users"); - } - else - { - $page->output_confirm_action("index.php?module=user-users&action=delete&uid={$user['uid']}", $lang->user_deletion_confirmation); - } -} - -if($mybb->input['action'] == "referrers") -{ - $page->add_breadcrumb_item($lang->show_referrers); - $page->output_header($lang->show_referrers); - - $sub_tabs['referrers'] = array( - 'title' => $lang->show_referrers, - 'link' => "index.php?module=user-users&action=referrers&uid={$mybb->input['uid']}", - 'description' => $lang->show_referrers_desc - ); - - $plugins->run_hooks("admin_user_users_referrers"); - - $page->output_nav_tabs($sub_tabs, 'referrers'); - - // Fetch default admin view - $default_view = fetch_default_view("user"); - if(!$default_view) - { - $default_view = "0"; - } - $query = $db->simple_select("adminviews", "*", "type='user' AND (vid='{$default_view}' OR uid=0)", array("order_by" => "uid", "order_dir" => "desc")); - $admin_view = $db->fetch_array($query); - - if($mybb->input['type']) - { - $admin_view['view_type'] = $mybb->input['type']; - } - - $admin_view['conditions'] = my_unserialize($admin_view['conditions']); - $admin_view['conditions']['referrer'] = $mybb->input['uid']; - - $view = build_users_view($admin_view); - - // No referred users - if(!$view) - { - $table = new Table; - $table->construct_cell($lang->error_no_referred_users); - $table->construct_row(); - $table->output($lang->show_referrers); - } - else - { - echo $view; - } - - $page->output_footer(); -} - -if($mybb->input['action'] == "ipaddresses") -{ - $page->add_breadcrumb_item($lang->ip_addresses); - $page->output_header($lang->ip_addresses); - - $sub_tabs['ipaddresses'] = array( - 'title' => $lang->show_ip_addresses, - 'link' => "index.php?module=user-users&action=ipaddresses&uid={$mybb->input['uid']}", - 'description' => $lang->show_ip_addresses_desc - ); - - $plugins->run_hooks("admin_user_users_ipaddresses"); - - $page->output_nav_tabs($sub_tabs, 'ipaddresses'); - - $query = $db->simple_select("users", "uid, regip, username, lastip", "uid='{$mybb->input['uid']}'", array('limit' => 1)); - $user = $db->fetch_array($query); - - // Log admin action - log_admin_action($user['uid'], htmlspecialchars_uni($user['username'])); - - $table = new Table; - - $table->construct_header($lang->ip_address); - $table->construct_header($lang->controls, array('width' => 200, 'class' => "align_center")); - - if(empty($user['lastip'])) - { - $user['lastip'] = $lang->unknown; - $controls = ''; - } - else - { - $user['lastip'] = my_inet_ntop($db->unescape_binary($user['lastip'])); - $popup = new PopupMenu("user_last", $lang->options); - $popup->add_item($lang->show_users_regged_with_ip, - "index.php?module=user-users&action=search&results=1&conditions=".urlencode(my_serialize(array("regip" => $user['lastip'])))); - $popup->add_item($lang->show_users_posted_with_ip, "index.php?module=user-users&results=1&action=search&conditions=".urlencode(my_serialize(array("postip" => $user['lastip'])))); - $popup->add_item($lang->info_on_ip, "index.php?module=user-users&action=iplookup&ipaddress={$user['lastip']}", "MyBB.popupWindow('index.php?module=user-users&action=iplookup&ipaddress={$user['lastip']}', null, true); return false;"); - $popup->add_item($lang->ban_ip, "index.php?module=config-banning&filter={$user['lastip']}"); - $controls = $popup->fetch(); - } - $table->construct_cell("{$lang->last_known_ip}: ".$user['lastip']); - $table->construct_cell($controls, array('class' => "align_center")); - $table->construct_row(); - - if(empty($user['regip'])) - { - $user['regip'] = $lang->unknown; - $controls = ''; - } - else - { - $user['regip'] = my_inet_ntop($db->unescape_binary($user['regip'])); - $popup = new PopupMenu("user_reg", $lang->options); - $popup->add_item($lang->show_users_regged_with_ip, "index.php?module=user-users&results=1&action=search&conditions=".urlencode(my_serialize(array("regip" => $user['regip'])))); - $popup->add_item($lang->show_users_posted_with_ip, "index.php?module=user-users&results=1&action=search&conditions=".urlencode(my_serialize(array("postip" => $user['regip'])))); - $popup->add_item($lang->info_on_ip, "index.php?module=user-users&action=iplookup&ipaddress={$user['regip']}", "MyBB.popupWindow('index.php?module=user-users&action=iplookup&ipaddress={$user['regip']}', null, true); return false;"); - $popup->add_item($lang->ban_ip, "index.php?module=config-banning&filter={$user['regip']}"); - $controls = $popup->fetch(); - } - $table->construct_cell("{$lang->registration_ip}: ".$user['regip']); - $table->construct_cell($controls, array('class' => "align_center")); - $table->construct_row(); - - $counter = 0; - - $query = $db->simple_select("posts", "DISTINCT ipaddress", "uid='{$mybb->input['uid']}'"); - while($ip = $db->fetch_array($query)) - { - ++$counter; - $ip['ipaddress'] = my_inet_ntop($db->unescape_binary($ip['ipaddress'])); - $popup = new PopupMenu("id_{$counter}", $lang->options); - $popup->add_item($lang->show_users_regged_with_ip, "index.php?module=user-users&results=1&action=search&conditions=".urlencode(my_serialize(array("regip" => $ip['ipaddress'])))); - $popup->add_item($lang->show_users_posted_with_ip, "index.php?module=user-users&results=1&action=search&conditions=".urlencode(my_serialize(array("postip" => $ip['ipaddress'])))); - $popup->add_item($lang->info_on_ip, "index.php?module=user-users&action=iplookup&ipaddress={$ip['ipaddress']}", "MyBB.popupWindow('index.php?module=user-users&action=iplookup&ipaddress={$ip['ipaddress']}', null, true); return false;"); - $popup->add_item($lang->ban_ip, "index.php?module=config-banning&filter={$ip['ipaddress']}"); - $controls = $popup->fetch(); - - $table->construct_cell($ip['ipaddress']); - $table->construct_cell($controls, array('class' => "align_center")); - $table->construct_row(); - } - - $table->output($lang->ip_address_for.' '.htmlspecialchars_uni($user['username'])); - - $page->output_footer(); -} - -if($mybb->input['action'] == "merge") -{ - $plugins->run_hooks("admin_user_users_merge"); - - if($mybb->request_method == "post") - { - $source_user = get_user_by_username($mybb->input['source_username'], array('fields' => '*')); - if(!$source_user['uid']) - { - $errors[] = $lang->error_invalid_user_source; - } - - $destination_user = get_user_by_username($mybb->input['destination_username'], array('fields' => '*')); - if(!$destination_user['uid']) - { - $errors[] = $lang->error_invalid_user_destination; - } - - // If we're not a super admin and we're merging a source super admin or a destination super admin then dissallow this action - if(!is_super_admin($mybb->user['uid']) && (is_super_admin($source_user['uid']) || is_super_admin($destination_user['uid']))) - { - flash_message($lang->error_no_perms_super_admin, 'error'); - admin_redirect("index.php?module=user-users"); - } - - if($source_user['uid'] == $destination_user['uid']) - { - $errors[] = $lang->error_cannot_merge_same_account; - } - - if(empty($errors)) - { - // Begin to merge the accounts - $uid_update = array( - "uid" => $destination_user['uid'] - ); - $query = $db->simple_select("adminoptions", "uid", "uid='{$destination_user['uid']}'"); - $existing_admin_options = $db->fetch_field($query, "uid"); - - // Only carry over admin options/permissions if we don't already have them - if(!$existing_admin_options) - { - $db->update_query("adminoptions", $uid_update, "uid='{$source_user['uid']}'"); - } - - $db->update_query("adminlog", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("announcements", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("events", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("threadsubscriptions", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("forumsubscriptions", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("joinrequests", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("moderatorlog", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("pollvotes", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("posts", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("privatemessages", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("reportedcontent", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("threads", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("warnings", $uid_update, "uid='{$source_user['uid']}'"); - $db->update_query("warnings", array("revokedby" => $destination_user['uid']), "revokedby='{$source_user['uid']}'"); - $db->update_query("warnings", array("issuedby" => $destination_user['uid']), "issuedby='{$source_user['uid']}'"); - - // Thread ratings - merge_thread_ratings($source_user['uid'], $destination_user['uid']); - - // Banning - $db->update_query("banned", array('admin' => $destination_user['uid']), "admin = '{$source_user['uid']}'"); - - // Merging Reputation - // First, let's change all the details over to our new user... - $db->update_query("reputation", array("adduid" => $destination_user['uid']), "adduid = '".$source_user['uid']."'"); - $db->update_query("reputation", array("uid" => $destination_user['uid']), "uid = '".$source_user['uid']."'"); - - // Now that all the repuation is merged, figure out what to do with this user's comments... - $options = array( - "order_by" => "uid", - "order_dir" => "ASC" - ); - - $to_remove = array(); - $query = $db->simple_select("reputation", "*", "adduid = '".$destination_user['uid']."'"); - while($rep = $db->fetch_array($query)) - { - if($rep['pid'] == 0 && $mybb->settings['multirep'] == 0 && $last_result['uid'] == $rep['uid']) - { - // Multiple reputation is disallowed, and this isn't a post, so let's remove this comment - $to_remove[] = $rep['rid']; - } - - // Remove comments or posts liked by "me" - if($last_result['uid'] == $destination_user['uid'] || $rep['uid'] == $destination_user['uid']) - { - if(!in_array($rep['rid'], $to_remove)) - { - $to_remove[] = $rep['rid']; - continue; - } - } - - $last_result = array( - "rid" => $rep['rid'], - "uid" => $rep['uid'] - ); - } - - // Remove any reputations we've selected to remove... - if(!empty($to_remove)) - { - $imp = implode(",", $to_remove); - $db->delete_query("reputation", "rid IN (".$imp.")"); - } - - // Calculate the new reputation for this user... - $query = $db->simple_select("reputation", "SUM(reputation) as total_rep", "uid='{$destination_user['uid']}'"); - $total_reputation = $db->fetch_field($query, "total_rep"); - - $db->update_query("users", array('reputation' => (int)$total_reputation), "uid='{$destination_user['uid']}'"); - - // Calculate warning points - $query = $db->query(" - SELECT SUM(points) as warn_lev - FROM ".TABLE_PREFIX."warnings - WHERE uid='{$source_user['uid']}' AND expired='0' - "); - $original_warn_level = $db->fetch_field($query, "warn_lev"); - - $query = $db->query(" - SELECT SUM(points) as warn_lev - FROM ".TABLE_PREFIX."warnings - WHERE uid='{$destination_user['uid']}' AND expired='0' - "); - $new_warn_level = $db->fetch_field($query, "warn_lev"); - $db->update_query("users", array("warningpoints" => (int)$original_warn_level + $new_warn_level), "uid='{$destination_user['uid']}'"); - - // Additional updates for non-uid fields - $last_poster = array( - "lastposteruid" => $destination_user['uid'], - "lastposter" => $db->escape_string($destination_user['username']) - ); - $db->update_query("forums", $last_poster, "lastposteruid='{$source_user['uid']}'"); - $db->update_query("threads", $last_poster, "lastposteruid='{$source_user['uid']}'"); - $edit_uid = array( - "edituid" => $destination_user['uid'] - ); - $db->update_query("posts", $edit_uid, "edituid='{$source_user['uid']}'"); - - $from_uid = array( - "fromid" => $destination_user['uid'] - ); - $db->update_query("privatemessages", $from_uid, "fromid='{$source_user['uid']}'"); - $to_uid = array( - "toid" => $destination_user['uid'] - ); - $db->update_query("privatemessages", $to_uid, "toid='{$source_user['uid']}'"); - - // Buddy/ignore lists - $destination_buddies = explode(',', $destination_user['buddylist']); - $source_buddies = explode(',', $source_user['buddylist']); - $buddies = array_unique(array_merge($source_buddies, $destination_buddies)); - // Make sure the new buddy list doesn't contain either users - $buddies_array = array_diff($buddies, array($destination_user['uid'], $source_user['uid'])); - - $destination_ignored = explode(',', $destination_user['ignorelist']); - $source_ignored = explode(',', $destination_user['ignorelist']); - $ignored = array_unique(array_merge($source_ignored, $destination_ignored)); - // ... and the same for the new ignore list - $ignored_array = array_diff($ignored, array($destination_user['uid'], $source_user['uid'])); - - // Remove any ignored users from the buddy list - $buddies = array_diff($buddies_array, $ignored_array); - // implode the arrays so we get a nice neat list for each - $buddies = trim(implode(',', $buddies), ','); - $ignored = trim(implode(',', $ignored_array), ','); - - $lists = array( - "buddylist" => $buddies, - "ignorelist" => $ignored - ); - $db->update_query("users", $lists, "uid='{$destination_user['uid']}'"); - - // Get a list of forums where post count doesn't apply - $fids = array(); - $query = $db->simple_select("forums", "fid", "usepostcounts=0"); - while($fid = $db->fetch_field($query, "fid")) - { - $fids[] = $fid; - } - - $fids_not_in = ''; - if(!empty($fids)) - { - $fids_not_in = "AND fid NOT IN(".implode(',', $fids).")"; - } - - // Update user post count - $query = $db->simple_select("posts", "COUNT(*) AS postnum", "uid='".$destination_user['uid']."' {$fids_not_in}"); - $num = $db->fetch_array($query); - $updated_count = array( - "postnum" => $num['postnum'] - ); - $db->update_query("users", $updated_count, "uid='{$destination_user['uid']}'"); - - // Update user thread count - $query = $db->simple_select("threads", "COUNT(*) AS threadnum", "uid='".$destination_user['uid']."' {$fids_not_in}"); - $num = $db->fetch_array($query); - $updated_count = array( - "threadnum" => $num['threadnum'] - ); - $db->update_query("users", $updated_count, "uid='{$destination_user['uid']}'"); - - // Use the earliest registration date - if($destination_user['regdate'] > $source_user['regdate']) - { - $db->update_query("users", array('regdate' => $source_user['regdate']), "uid='{$destination_user['uid']}'"); - } - - $plugins->run_hooks("admin_user_users_merge_commit"); - - // Set up user handler. - require_once MYBB_ROOT.'inc/datahandlers/user.php'; - $userhandler = new UserDataHandler('delete'); - - // Delete the old user - $userhandler->delete_user($source_user['uid']); - - $cache->update_awaitingactivation(); - - // Log admin action - log_admin_action($source_user['uid'], htmlspecialchars_uni($source_user['username']), $destination_user['uid'], htmlspecialchars_uni($destination_user['username'])); - - // Redirect! - $username = htmlspecialchars_uni($source_user['username']); - $destination_username = htmlspecialchars_uni($destination_user['username']); - flash_message("{$username} {$lang->success_merged} {$destination_username}", "success"); - admin_redirect("index.php?module=user-users"); - exit; - } - } - - $page->add_breadcrumb_item($lang->merge_users); - $page->output_header($lang->merge_users); - - $page->output_nav_tabs($sub_tabs, 'merge_users'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=user-users&action=merge", "post"); - - $form_container = new FormContainer($lang->merge_users); - $form_container->output_row($lang->source_account." *", $lang->source_account_desc, $form->generate_text_box('source_username', $mybb->input['source_username'], array('id' => 'source_username')), 'source_username'); - $form_container->output_row($lang->destination_account." *", $lang->destination_account_desc, $form->generate_text_box('destination_username', $mybb->input['destination_username'], array('id' => 'destination_username')), 'destination_username'); - $form_container->end(); - - // Autocompletion for usernames - echo ' - - - '; - - $buttons[] = $form->generate_submit_button($lang->merge_user_accounts); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "search") -{ - $plugins->run_hooks("admin_user_users_search"); - - if($mybb->request_method == "post" || $mybb->input['results'] == 1) - { - // Build view options from incoming search options - if($mybb->input['vid']) - { - $query = $db->simple_select("adminviews", "*", "vid='".$mybb->get_input('vid', MyBB::INPUT_INT)."'"); - $admin_view = $db->fetch_array($query); - // View does not exist or this view is private and does not belong to the current user - if(!$admin_view['vid'] || ($admin_view['visibility'] == 1 && $admin_view['uid'] != $mybb->user['uid'])) - { - unset($admin_view); - } - } - - if($mybb->input['search_id'] && $admin_session['data']['user_views'][$mybb->input['search_id']]) - { - $admin_view = $admin_session['data']['user_views'][$mybb->input['search_id']]; - unset($admin_view['extra_sql']); - } - else - { - // Don't have a view? Fetch the default - if(!$admin_view['vid']) - { - $default_view = fetch_default_view("user"); - if(!$default_view) - { - $default_view = "0"; - } - $query = $db->simple_select("adminviews", "*", "type='user' AND (vid='{$default_view}' OR uid=0)", array("order_by" => "uid", "order_dir" => "desc")); - $admin_view = $db->fetch_array($query); - } - } - - // Override specific parts of the view - unset($admin_view['vid']); - - if($mybb->input['type']) - { - $admin_view['view_type'] = $mybb->input['type']; - } - - if($mybb->input['conditions']) - { - $admin_view['conditions'] = $mybb->input['conditions']; - } - - if($mybb->input['sortby']) - { - $admin_view['sortby'] = $mybb->input['sortby']; - } - - if($mybb->get_input('perpage', MyBB::INPUT_INT)) - { - $admin_view['perpage'] = $mybb->input['perpage']; - } - - if($mybb->input['order']) - { - $admin_view['sortorder'] = $mybb->input['order']; - } - - if($mybb->input['displayas']) - { - $admin_view['view_type'] = $mybb->input['displayas']; - } - - if($mybb->input['profile_fields']) - { - $admin_view['custom_profile_fields'] = $mybb->input['profile_fields']; - } - - $plugins->run_hooks("admin_user_users_search_commit"); - - $results = build_users_view($admin_view); - - if($results) - { - $page->output_header($lang->find_users); - echo ""; - $page->output_nav_tabs($sub_tabs, 'find_users'); - echo $results; - $page->output_footer(); - } - else - { - if($mybb->input['from'] == "home") - { - flash_message($lang->error_no_users_found, 'error'); - admin_redirect("index.php"); - exit; - } - else - { - $errors[] = $lang->error_no_users_found; - } - } - } - - $page->add_breadcrumb_item($lang->find_users); - $page->output_header($lang->find_users); - - $page->output_nav_tabs($sub_tabs, 'find_users'); - - // If we have any error messages, show them - if($errors) - { - $page->output_inline_error($errors); - } - - if(!$mybb->input['displayas']) - { - $mybb->input['displayas'] = "card"; - } - - $form = new Form("index.php?module=user-users&action=search", "post"); - - user_search_conditions($mybb->input, $form); - - $form_container = new FormContainer($lang->display_options); - $sort_directions = array( - "asc" => $lang->ascending, - "desc" => $lang->descending - ); - $form_container->output_row($lang->sort_results_by, "", $form->generate_select_box('sortby', $sort_options, $mybb->input['sortby'], array('id' => 'sortby'))." {$lang->in} ".$form->generate_select_box('order', $sort_directions, $mybb->input['order'], array('id' => 'order')), 'sortby'); - $form_container->output_row($lang->results_per_page, "", $form->generate_numeric_field('perpage', $mybb->input['perpage'], array('id' => 'perpage', 'min' => 1)), 'perpage'); - $form_container->output_row($lang->display_results_as, "", $form->generate_radio_button('displayas', 'table', $lang->table, array('checked' => ($mybb->input['displayas'] != "card" ? true : false)))."
".$form->generate_radio_button('displayas', 'card', $lang->business_card, array('checked' => ($mybb->input['displayas'] == "card" ? true : false)))); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->find_users); - $form->output_submit_wrapper($buttons); - $form->end(); - - $page->output_footer(); -} - -if($mybb->input['action'] == "inline_edit") -{ - $plugins->run_hooks("admin_user_users_inline"); - - if($mybb->input['vid'] || $mybb->cookies['acp_view']) - { - // We have a custom view - if(!$mybb->cookies['acp_view']) - { - // Set a cookie - my_setcookie("acp_view", $mybb->input['vid'], 60); - } - elseif($mybb->cookies['acp_view']) - { - // We already have a cookie, so let's use it... - $mybb->input['vid'] = $mybb->cookies['acp_view']; - } - - $vid_url = "&vid=".$mybb->input['vid']; - } - - // First, collect the user IDs that we're performing the moderation on - $ids = explode("|", $mybb->cookies['inlinemod_useracp']); - foreach($ids as $id) - { - if($id != '') - { - $selected[] = (int)$id; - } - } - - // Verify incoming POST request - if(!verify_post_check($mybb->input['my_post_key'])) - { - flash_message($lang->invalid_post_verify_key2, 'error'); - admin_redirect("index.php?module=user-user"); - } - $sub_tabs['manage_users'] = array( - "title" => $lang->manage_users, - "link" => "./", - "description" => $lang->manage_users_desc - ); - $page->add_breadcrumb_item($lang->manage_users); - - if(!is_array($selected)) - { - // Not selected any users, show error - flash_message($lang->error_inline_no_users_selected, 'error'); - admin_redirect("index.php?module=user-users".$vid_url); - } - - switch($mybb->input['inline_action']) - { - case 'multiactivate': - // Run through the activating users, so that users already registered (but have been selected) aren't affected - if(is_array($selected)) - { - $sql_array = implode(",", $selected); - $query = $db->simple_select("users", "uid, username, email", "usergroup = '5' AND uid IN (".$sql_array.")"); - $user_mail_data = array(); - while($user = $db->fetch_array($query)) - { - $to_update[] = $user['uid']; - $user_mail_data[] = array('username' => $user['username'], 'email' => $user['email']); - } - } - - if(is_array($to_update)) - { - $sql_array = implode(",", $to_update); - $db->write_query("UPDATE ".TABLE_PREFIX."users SET usergroup = '2' WHERE uid IN (".$sql_array.")"); - - $cache->update_awaitingactivation(); - - // send activation mail - foreach($user_mail_data as $mail_data) - { - $message = $lang->sprintf($lang->email_adminactivateaccount, $mail_data['username'], $mybb->settings['bbname'], $mybb->settings['bburl']); - my_mail($mail_data['email'], $lang->sprintf($lang->emailsubject_activateaccount, $mybb->settings['bbname']), $message); - } - - // Action complete, grab stats and show success message - redirect user - $to_update_count = count($to_update); - $lang->inline_activated = $lang->sprintf($lang->inline_activated, my_number_format($to_update_count)); - - if($to_update_count != count($selected)) - { - // The update count is different to how many we selected! - $not_updated_count = count($selected) - $to_update_count; - $lang->inline_activated_more = $lang->sprintf($lang->inline_activated_more, my_number_format($not_updated_count)); - $lang->inline_activated = $lang->inline_activated."
".$lang->inline_activated_more; // Add these stats to the message - } - - $mybb->input['action'] = "inline_activated"; // Force a change to the action so we can add it to the adminlog - log_admin_action($to_update_count); // Add to adminlog - my_unsetcookie("inlinemod_useracp"); // Unset the cookie, so that the users aren't still selected when we're redirected - - flash_message($lang->inline_activated, 'success'); - admin_redirect("index.php?module=user-users".$vid_url); - } - else - { - // Nothing was updated, show an error - flash_message($lang->inline_activated_failed, 'error'); - admin_redirect("index.php?module=user-users".$vid_url); - } - break; - case 'multilift': - // Get the users that are banned, and check that they have been selected - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-users".$vid_url); // User clicked on 'No' - } - - if($mybb->request_method == "post") - { - $sql_array = implode(",", $selected); - $query = $db->simple_select("banned", "*", "uid IN (".$sql_array.")"); - $to_be_unbanned = $db->num_rows($query); - while($ban = $db->fetch_array($query)) - { - $updated_group = array( - "usergroup" => $ban['oldgroup'], - "additionalgroups" => $ban['oldadditionalgroups'], - "displaygroup" => $ban['olddisplaygroup'] - ); - $db->update_query("users", $updated_group, "uid = '".$ban['uid']."'"); - $db->delete_query("banned", "uid = '".$ban['uid']."'"); - } - - $cache->update_banned(); - $cache->update_moderators(); - - $mybb->input['action'] = "inline_lift"; - log_admin_action($to_be_unbanned); - my_unsetcookie("inlinemod_useracp"); - - $lang->success_ban_lifted = $lang->sprintf($lang->success_ban_lifted, my_number_format($to_be_unbanned)); - flash_message($lang->success_ban_lifted, 'success'); - admin_redirect("index.php?module=user-users".$vid_url); - } - else - { - $page->output_confirm_action("index.php?module=user-users&action=inline_edit&inline_action=multilift", $lang->confirm_multilift); - } - - break; - case 'multiban': - if($mybb->input['processed'] == 1) - { - // We've posted ban information! - // Build an array of users to ban, =D - $sql_array = implode(",", $selected); - // Build a cache array for this users that have been banned already - $query = $db->simple_select("banned", "uid", "uid IN (".$sql_array.")"); - while($user = $db->fetch_array($query)) - { - $bannedcache[] = "u_".$user['uid']; - } - - // Collect the users - $query = $db->simple_select("users", "uid, username, usergroup, additionalgroups, displaygroup", "uid IN (".$sql_array.")"); - - if($mybb->input['bantime'] == '---') - { - $lifted = 0; - } - else - { - $lifted = ban_date2timestamp($mybb->input['bantime']); - } - - $reason = my_substr($mybb->input['reason'], 0, 255); - - $banned_count = 0; - while($user = $db->fetch_array($query)) - { - if($user['uid'] == $mybb->user['uid'] || is_super_admin($user['uid'])) - { - // We remove ourselves and Super Admins from the mix - continue; - } - - if(is_array($bannedcache) && in_array("u_".$user['uid'], $bannedcache)) - { - // User already has a ban, update it! - $update_array = array( - "admin" => (int)$mybb->user['uid'], - "dateline" => TIME_NOW, - "bantime" => $db->escape_string($mybb->input['bantime']), - "lifted" => $db->escape_string($lifted), - "reason" => $db->escape_string($reason) - ); - $db->update_query("banned", $update_array, "uid = '".$user['uid']."'"); - } - else - { - // Not currently banned - insert the ban - $insert_array = array( - 'uid' => $user['uid'], - 'gid' => $mybb->get_input('usergroup', MyBB::INPUT_INT), - 'oldgroup' => $user['usergroup'], - 'oldadditionalgroups' => $user['additionalgroups'], - 'olddisplaygroup' => $user['displaygroup'], - 'admin' => (int)$mybb->user['uid'], - 'dateline' => TIME_NOW, - 'bantime' => $db->escape_string($mybb->input['bantime']), - 'lifted' => $db->escape_string($lifted), - 'reason' => $db->escape_string($reason) - ); - $db->insert_query('banned', $insert_array); - } - - // Moved the user to the 'Banned' Group - $update_array = array( - 'usergroup' => 7, - 'displaygroup' => 0, - 'additionalgroups' => '', - ); - $db->update_query('users', $update_array, "uid = '{$user['uid']}'"); - - $db->delete_query("forumsubscriptions", "uid = '{$user['uid']}'"); - $db->delete_query("threadsubscriptions", "uid = '{$user['uid']}'"); - - $cache->update_banned(); - ++$banned_count; - } - $mybb->input['action'] = "inline_banned"; - log_admin_action($banned_count, $lifted); - my_unsetcookie("inlinemod_useracp"); // Remove the cookie of selected users as we've finished with them - - $lang->users_banned = $lang->sprintf($lang->users_banned, $banned_count); - flash_message($lang->users_banned, 'success'); - admin_redirect("index.php?module=user-users".$vid_url); - } - - $page->output_header($lang->manage_users); - $page->output_nav_tabs($sub_tabs, 'manage_users'); - - // Provide the user with a warning of what they're about to do - $table = new Table; - $lang->mass_ban_info = $lang->sprintf($lang->mass_ban_info, count($selected)); - $table->construct_cell($lang->mass_ban_info); - $table->construct_row(); - $table->output($lang->important); - - // If there's any errors, display inline - if($errors) - { - $page->output_inline_error($errors); - } - - $form = new Form("index.php?module=user-users", "post"); - echo $form->generate_hidden_field('action', 'inline_edit'); - echo $form->generate_hidden_field('inline_action', 'multiban'); - echo $form->generate_hidden_field('processed', '1'); - - $form_container = new FormContainer(''.$lang->mass_ban); - $form_container->output_row($lang->ban_reason, "", $form->generate_text_area('reason', $mybb->input['reason'], array('id' => 'reason', 'maxlength' => '255')), 'reason'); - $ban_times = fetch_ban_times(); - foreach($ban_times as $time => $period) - { - if($time != '---') - { - $friendly_time = my_date("D, jS M Y @ {$mybb->settings['timeformat']}", ban_date2timestamp($time)); - $period = "{$period} ({$friendly_time})"; - } - $length_list[$time] = $period; - } - $form_container->output_row($lang->ban_time, "", $form->generate_select_box('bantime', $length_list, $mybb->input['bantime'], array('id' => 'bantime')), 'bantime'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->ban_users); - $form->output_submit_wrapper($buttons); - $form->end(); - $page->output_footer(); - break; - case 'multidelete': - if($mybb->input['no']) - { - admin_redirect("index.php?module=user-users".$vid_url); // User clicked on 'No - } - else - { - if($mybb->input['processed'] == 1) - { - // Set up user handler. - require_once MYBB_ROOT.'inc/datahandlers/user.php'; - $userhandler = new UserDataHandler('delete'); - - // Delete users - $deleted = $userhandler->delete_user($selected); - $to_be_deleted = $deleted['deleted_users']; // Get the correct number of deleted users - - // Update forum stats, remove the cookie and redirect the user - my_unsetcookie("inlinemod_useracp"); - $mybb->input['action'] = "inline_delete"; - log_admin_action($to_be_deleted); - - $lang->users_deleted = $lang->sprintf($lang->users_deleted, $to_be_deleted); - - $cache->update_awaitingactivation(); - - flash_message($lang->users_deleted, 'success'); - admin_redirect("index.php?module=user-users".$vid_url); - } - - $to_be_deleted = count($selected); - $lang->confirm_multidelete = $lang->sprintf($lang->confirm_multidelete, my_number_format($to_be_deleted)); - $page->output_confirm_action("index.php?module=user-users&action=inline_edit&inline_action=multidelete&my_post_key={$mybb->post_code}&processed=1", $lang->confirm_multidelete); - } - break; - case 'multiprune': - if($mybb->input['processed'] == 1) - { - if(($mybb->input['day'] || $mybb->input['month'] || $mybb->input['year']) && $mybb->input['set']) - { - $errors[] = $lang->multi_selected_dates; - } - - $day = $mybb->get_input('day', MyBB::INPUT_INT); - $month = $mybb->get_input('month', MyBB::INPUT_INT); - $year = $mybb->get_input('year', MyBB::INPUT_INT); - - // Selected a date - check if the date the user entered is valid - if($mybb->input['day'] || $mybb->input['month'] || $mybb->input['year']) - { - // Is the date sort of valid? - if($day < 1 || $day > 31 || $month < 1 || $month > 12 || ($month == 2 && $day > 29)) - { - $errors[] = $lang->incorrect_date; - } - - // Check the month - $months = get_bdays($year); - if($day > $months[$month-1]) - { - $errors[] = $lang->incorrect_date; - } - - // Check the year - if($year != 0 && ($year < (date("Y")-100)) || $year > date("Y")) - { - $errors[] = $lang->incorrect_date; - } - - if(!$errors) - { - // No errors, so let's continue and set the date to delete from - $date = mktime(date('H'), date('i'), date('s'), $month, $day, $year); // Generate a unix time stamp - } - } - elseif($mybb->input['set'] > 0) - { - // Set options - // For this purpose, 1 month = 31 days - $base_time = 24 * 60 * 60; - - switch($mybb->input['set']) - { - case '1': - $threshold = $base_time * 31; // 1 month = 31 days, in the standard terms - break; - case '2': - $threshold = $base_time * 93; // 3 months = 31 days * 3 - break; - case '3': - $threshold = $base_time * 183; // 6 months = 365 days / 2 - break; - case '4': - $threshold = $base_time * 365; // 1 year = 365 days - break; - case '5': - $threshold = $base_time * 548; // 18 months = 365 + 183 - break; - case '6': - $threshold = $base_time * 730; // 2 years = 365 * 2 - break; - } - - if(!$threshold) - { - // An option was entered that isn't in the dropdown box - $errors[] = $lang->no_set_option; - } - else - { - $date = TIME_NOW - $threshold; - } - } - else - { - $errors[] = $lang->no_prune_option; - } - - if(!$errors) - { - $sql_array = implode(",", $selected); - $prune_array = array(); - $query = $db->simple_select("users", "uid", "uid IN (".$sql_array.")"); - while($user = $db->fetch_array($query)) - { - // Protect Super Admins - if(is_super_admin($user['uid']) && !is_super_admin($mybb->user['uid'])) - { - continue; - } - - $return_array = delete_user_posts($user['uid'], $date); // Delete user posts, and grab a list of threads to delete - if($return_array && is_array($return_array)) - { - $prune_array = array_merge_recursive($prune_array, $return_array); - } - } - - // No posts were found for the user, return error - if(!is_array($prune_array) || count($prune_array) == 0) - { - flash_message($lang->prune_fail, 'error'); - admin_redirect("index.php?module=user-users".$vid_url); - } - - // Require the rebuild functions - require_once MYBB_ROOT.'/inc/functions.php'; - require_once MYBB_ROOT.'/inc/functions_rebuild.php'; - - // We've finished deleting user's posts, so let's delete the threads - if(is_array($prune_array['to_delete']) && count($prune_array['to_delete']) > 0) - { - foreach($prune_array['to_delete'] as $tid) - { - $db->delete_query("threads", "tid='$tid'"); - $db->delete_query("threads", "closed='moved|$tid'"); - $db->delete_query("threadsubscriptions", "tid='$tid'"); - $db->delete_query("polls", "tid='$tid'"); - $db->delete_query("threadsread", "tid='$tid'"); - $db->delete_query("threadratings", "tid='$tid'"); - } - } - - // After deleting threads, rebuild the thread counters for the affected threads - if(is_array($prune_array['thread_update']) && count($prune_array['thread_update']) > 0) - { - $sql_array = implode(",", $prune_array['thread_update']); - $query = $db->simple_select("threads", "tid", "tid IN (".$sql_array.")", array('order_by' => 'tid', 'order_dir' => 'asc')); - while($thread = $db->fetch_array($query)) - { - rebuild_thread_counters($thread['tid']); - } - } - - // After updating thread counters, update the affected forum counters - if(is_array($prune_array['forum_update']) && count($prune_array['forum_update']) > 0) - { - $sql_array = implode(",", $prune_array['forum_update']); - $query = $db->simple_select("forums", "fid", "fid IN (".$sql_array.")", array('order_by' => 'fid', 'order_dir' => 'asc')); - while($forum = $db->fetch_array($query)) - { - // Because we have a recursive array merge, check to see if there isn't a duplicated forum to update - if($looped_forum == $forum['fid']) - { - continue; - } - $looped_forum = $forum['fid']; - rebuild_forum_counters($forum['fid']); - } - } - - //log_admin_action(); - my_unsetcookie("inlinemod_useracp"); // We've got our users, remove the cookie - flash_message($lang->prune_complete, 'success'); - admin_redirect("index.php?module=user-users".$vid_url); - } - } - - $page->output_header($lang->manage_users); - $page->output_nav_tabs($sub_tabs, 'manage_users'); - - // Display a table warning - $table = new Table; - $lang->mass_prune_info = $lang->sprintf($lang->mass_prune_info, count($selected)); - $table->construct_cell($lang->mass_prune_info); - $table->construct_row(); - $table->output($lang->important); - - if($errors) - { - $page->output_inline_error($errors); - } - - // Display the prune options - $form = new Form("index.php?module=user-users", "post"); - echo $form->generate_hidden_field('action', 'inline_edit'); - echo $form->generate_hidden_field('inline_action', 'multiprune'); - echo $form->generate_hidden_field('processed', '1'); - - $form_container = new FormContainer($lang->mass_prune_posts); - - // Generate a list of days (1 - 31) - $day_options = array(); - $day_options[] = " "; - for($i = 1; $i <= 31; ++$i) - { - $day_options[] = $i; - } - - // Generate a list of months (1 - 12) - $month_options = array(); - $month_options[] = " "; - for($i = 1; $i <= 12; ++$i) - { - $string = "month_{$i}"; - $month_options[] = $lang->$string; - } - $date_box = $form->generate_select_box('day', $day_options, $mybb->input['day']); - $month_box = $form->generate_select_box('month', $month_options, $mybb->input['month']); - $year_box = $form->generate_numeric_field('year', $mybb->input['year'], array('id' => 'year', 'style' => 'width: 50px;', 'min' => 0)); - - $prune_select = $date_box.$month_box.$year_box; - $form_container->output_row($lang->manual_date, "", $prune_select, 'date'); - - // Generate the set date box - $set_options = array(); - $set_options[] = $lang->set_an_option; - for($i = 1; $i <= 6; ++$i) - { - $string = "option_{$i}"; - $set_options[] = $lang->$string; - } - - $form_container->output_row($lang->relative_date, "", $lang->delete_posts." ".$form->generate_select_box('set', $set_options, $mybb->input['set']), 'set'); - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->prune_posts); - $form->output_submit_wrapper($buttons); - $form->end(); - $page->output_footer(); - break; - case 'multiusergroup': - if($mybb->input['processed'] == 1) - { - // Determine additional usergroups - if(is_array($mybb->input['additionalgroups'])) - { - foreach($mybb->input['additionalgroups'] as $key => $gid) - { - if($gid == $mybb->input['usergroup']) - { - unset($mybb->input['additionalgroups'][$key]); - } - } - - $additionalgroups = implode(",", array_map('intval', $mybb->input['additionalgroups'])); - } - else - { - $additionalgroups = ''; - } - - // Create an update array - $update_array = array( - "usergroup" => $mybb->get_input('usergroup', MyBB::INPUT_INT), - "additionalgroups" => $additionalgroups, - "displaygroup" => $mybb->get_input('displaygroup', MyBB::INPUT_INT) - ); - - // Do the usergroup update for all those selected - // If the a selected user is a super admin, don't update that user - foreach($selected as $user) - { - if(!is_super_admin($user)) - { - $users_to_update[] = $user; - } - } - - $to_update_count = count($users_to_update); - if($to_update_count > 0 && is_array($users_to_update)) - { - // Update the users in the database - $sql = implode(",", $users_to_update); - $db->update_query("users", $update_array, "uid IN (".$sql.")"); - - // Redirect the admin... - $mybb->input['action'] = "inline_usergroup"; - log_admin_action($to_update_count); - my_unsetcookie("inlinemod_useracp"); - flash_message($lang->success_mass_usergroups, 'success'); - admin_redirect("index.php?module=user-users".$vid_url); - } - else - { - // They tried to edit super admins! Uh-oh! - $errors[] = $lang->no_usergroup_changed; - } - } - - $page->output_header($lang->manage_users); - $page->output_nav_tabs($sub_tabs, 'manage_users'); - - // Display a table warning - $table = new Table; - $lang->usergroup_info = $lang->sprintf($lang->usergroup_info, count($selected)); - $table->construct_cell($lang->usergroup_info); - $table->construct_row(); - $table->output($lang->important); - - if($errors) - { - $page->output_inline_error($errors); - } - - // Display the usergroup options - $form = new Form("index.php?module=user-users", "post"); - echo $form->generate_hidden_field('action', 'inline_edit'); - echo $form->generate_hidden_field('inline_action', 'multiusergroup'); - echo $form->generate_hidden_field('processed', '1'); - - $form_container = new FormContainer($lang->mass_usergroups); - - // Usergroups - $display_group_options[0] = $lang->use_primary_user_group; - $options = array(); - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $options[$usergroup['gid']] = htmlspecialchars_uni($usergroup['title']); - $display_group_options[$usergroup['gid']] = htmlspecialchars_uni($usergroup['title']); - } - - if(!is_array($mybb->input['additionalgroups'])) - { - $mybb->input['additionalgroups'] = explode(',', $mybb->input['additionalgroups']); - } - - $form_container->output_row($lang->primary_user_group, "", $form->generate_select_box('usergroup', $options, $mybb->input['usergroup'], array('id' => 'usergroup')), 'usergroup'); - $form_container->output_row($lang->additional_user_groups, $lang->additional_user_groups_desc, $form->generate_select_box('additionalgroups[]', $options, $mybb->input['additionalgroups'], array('id' => 'additionalgroups', 'multiple' => true, 'size' => 5)), 'additionalgroups'); - $form_container->output_row($lang->display_user_group, "", $form->generate_select_box('displaygroup', $display_group_options, $mybb->input['displaygroup'], array('id' => 'displaygroup')), 'displaygroup'); - - $form_container->end(); - - $buttons[] = $form->generate_submit_button($lang->alter_usergroups); - $form->output_submit_wrapper($buttons); - $form->end(); - $page->output_footer(); - break; - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("admin_user_users_start"); - - $page->output_header($lang->browse_users); - echo ""; - - $page->output_nav_tabs($sub_tabs, 'browse_users'); - - if(isset($mybb->input['search_id']) && $admin_session['data']['user_views'][$mybb->input['search_id']]) - { - $admin_view = $admin_session['data']['user_views'][$mybb->input['search_id']]; - unset($admin_view['extra_sql']); - } - else - { - // Showing a specific view - if(isset($mybb->input['vid'])) - { - $query = $db->simple_select("adminviews", "*", "vid='".$mybb->get_input('vid', MyBB::INPUT_INT)."'"); - $admin_view = $db->fetch_array($query); - // View does not exist or this view is private and does not belong to the current user - if(!$admin_view['vid'] || ($admin_view['visibility'] == 1 && $admin_view['uid'] != $mybb->user['uid'])) - { - unset($admin_view); - } - } - - // Don't have a view? Fetch the default - if(!isset($admin_view)) - { - $default_view = fetch_default_view("user"); - if(!$default_view) - { - $default_view = "0"; - } - $query = $db->simple_select("adminviews", "*", "type='user' AND (vid='{$default_view}' OR uid=0)", array("order_by" => "uid", "order_dir" => "desc")); - $admin_view = $db->fetch_array($query); - } - } - - // Fetch a list of all of the views for this user - $popup = new PopupMenu("views", $lang->views); - - $query = $db->simple_select("adminviews", "*", "type='user' AND (visibility=2 OR uid={$mybb->user['uid']})", array("order_by" => "title")); - while($view = $db->fetch_array($query)) - { - $popup->add_item(htmlspecialchars_uni($view['title']), "index.php?module=user-users&vid={$view['vid']}"); - } - $popup->add_item("{$lang->manage_views}", "index.php?module=user-users&action=views"); - $admin_view['popup'] = $popup->fetch(); - - if(isset($mybb->input['type'])) - { - $admin_view['view_type'] = $mybb->input['type']; - } - - $results = build_users_view($admin_view); - - if(!$results) - { - // If we came from the home page and clicked on the "Activate Users" link, send them back to here - if($admin_session['data']['from'] == "home") - { - flash_message($admin_session['data']['flash_message2']['message'], $admin_session['data']['flash_message2']['type']); - update_admin_session('flash_message2', ''); - update_admin_session('from', ''); - admin_redirect("index.php"); - exit; - } - else - { - $errors[] = $lang->error_no_users_found; - } - } - - // If we have any error messages, show them - if($errors) - { - if($inline != true) - { - echo "
{$admin_view['popup']}

\n"; - } - $page->output_inline_error($errors); - } - - echo $results; - - $page->output_footer(); -} - -/** - * @param array $view - * - * @return string - */ -function build_users_view($view) -{ - global $mybb, $db, $cache, $lang, $user_view_fields, $page; - - if($view['view_type'] != 'card') - { - $view['view_type'] = 'table'; - } - - $view_title = ''; - if($view['title']) - { - $title_string = "view_title_{$view['vid']}"; - - if($lang->$title_string) - { - $view['title'] = $lang->$title_string; - } - - $view_title .= " (".htmlspecialchars_uni($view['title']).")"; - } - - // Build the URL to this view - if(!isset($view['url'])) - { - $view['url'] = "index.php?module=user-users"; - } - if(!is_array($view['conditions'])) - { - $view['conditions'] = my_unserialize($view['conditions']); - } - if(!is_array($view['fields'])) - { - $view['fields'] = my_unserialize($view['fields']); - } - if(!is_array($view['custom_profile_fields'])) - { - $view['custom_profile_fields'] = my_unserialize($view['custom_profile_fields']); - } - if(isset($mybb->input['username'])) - { - $view['conditions']['username'] = $mybb->input['username']; - $view['url'] .= "&username=".urlencode(htmlspecialchars_uni($mybb->input['username'])); - } - if($view['vid']) - { - $view['url'] .= "&vid={$view['vid']}"; - } - else - { - // If this is a custom view we need to save everything ready to pass it on from page to page - global $admin_session; - if(!$mybb->input['search_id']) - { - $search_id = md5(random_str()); - $admin_session['data']['user_views'][$search_id] = $view; - update_admin_session('user_views', $admin_session['data']['user_views']); - $mybb->input['search_id'] = $search_id; - } - $view['url'] .= "&search_id=".htmlspecialchars_uni($mybb->input['search_id']); - } - - if(!isset($admin_session['data']['last_users_view']) || $admin_session['data']['last_users_view'] != str_replace("&", "&", $view['url'])) - { - update_admin_session('last_users_url', str_replace("&", "&", $view['url'])); - } - - if(isset($view['conditions']['referrer'])){ - $view['url'] .= "&action=referrers&uid=".htmlspecialchars_uni($view['conditions']['referrer']); - } - - // Do we not have any views? - if(empty($view)) - { - return false; - } - - $table = new Table; - - // Build header for table based view - if($view['view_type'] != "card") - { - foreach($view['fields'] as $field) - { - if(!$user_view_fields[$field]) - { - continue; - } - $view_field = $user_view_fields[$field]; - $field_options = array(); - if($view_field['width']) - { - $field_options['width'] = $view_field['width']; - } - if($view_field['align']) - { - $field_options['class'] = "align_".$view_field['align']; - } - $table->construct_header($view_field['title'], $field_options); - } - $table->construct_header(""); // Create a header for the "select" boxes - } - - $search_sql = '1=1'; - - // Build the search SQL for users - - // List of valid LIKE search fields - $user_like_fields = array("username", "email", "website", "icq", "aim", "yahoo", "skype", "google", "signature", "usertitle"); - foreach($user_like_fields as $search_field) - { - if(!empty($view['conditions'][$search_field]) && !$view['conditions'][$search_field.'_blank']) - { - $search_sql .= " AND u.{$search_field} LIKE '%".$db->escape_string_like($view['conditions'][$search_field])."%'"; - } - else if(!empty($view['conditions'][$search_field.'_blank'])) - { - $search_sql .= " AND u.{$search_field} != ''"; - } - } - - // EXACT matching fields - $user_exact_fields = array("referrer"); - foreach($user_exact_fields as $search_field) - { - if(!empty($view['conditions'][$search_field])) - { - $search_sql .= " AND u.{$search_field}='".$db->escape_string($view['conditions'][$search_field])."'"; - } - } - - // LESS THAN or GREATER THAN - $direction_fields = array("postnum", "threadnum"); - foreach($direction_fields as $search_field) - { - $direction_field = $search_field."_dir"; - if(isset($view['conditions'][$search_field]) && ($view['conditions'][$search_field] || $view['conditions'][$search_field] === '0') && $view['conditions'][$direction_field]) - { - switch($view['conditions'][$direction_field]) - { - case "greater_than": - $direction = ">"; - break; - case "less_than": - $direction = "<"; - break; - default: - $direction = "="; - } - $search_sql .= " AND u.{$search_field}{$direction}'".$db->escape_string($view['conditions'][$search_field])."'"; - } - } - - // Registration searching - $reg_fields = array("regdate"); - foreach($reg_fields as $search_field) - { - if(!empty($view['conditions'][$search_field]) && (int)$view['conditions'][$search_field]) - { - $threshold = TIME_NOW - ((int)$view['conditions'][$search_field] * 24 * 60 * 60); - - $search_sql .= " AND u.{$search_field} >= '{$threshold}'"; - } - } - - // IP searching - $ip_fields = array("regip", "lastip"); - foreach($ip_fields as $search_field) - { - if(!empty($view['conditions'][$search_field])) - { - $ip_range = fetch_ip_range($view['conditions'][$search_field]); - if(!is_array($ip_range)) - { - $ip_sql = "{$search_field}=".$db->escape_binary($ip_range); - } - else - { - $ip_sql = "{$search_field} BETWEEN ".$db->escape_binary($ip_range[0])." AND ".$db->escape_binary($ip_range[1]); - } - $search_sql .= " AND {$ip_sql}"; - } - } - - // Post IP searching - if(!empty($view['conditions']['postip'])) - { - $ip_range = fetch_ip_range($view['conditions']['postip']); - if(!is_array($ip_range)) - { - $ip_sql = "ipaddress=".$db->escape_binary($ip_range); - } - else - { - $ip_sql = "ipaddress BETWEEN ".$db->escape_binary($ip_range[0])." AND ".$db->escape_binary($ip_range[1]); - } - $ip_uids = array(0); - $query = $db->simple_select("posts", "uid", $ip_sql); - while($uid = $db->fetch_field($query, "uid")) - { - $ip_uids[] = $uid; - } - $search_sql .= " AND u.uid IN(".implode(',', $ip_uids).")"; - unset($ip_uids); - } - - // Custom Profile Field searching - if($view['custom_profile_fields']) - { - $userfield_sql = '1=1'; - foreach($view['custom_profile_fields'] as $column => $input) - { - if(is_array($input)) - { - foreach($input as $value => $text) - { - if($value == $column) - { - $value = $text; - } - - if($value == $lang->na) - { - continue; - } - - if(strpos($column, '_blank') !== false) - { - $column = str_replace('_blank', '', $column); - $userfield_sql .= ' AND '.$db->escape_string($column)." != ''"; - } - else - { - $userfield_sql .= ' AND '.$db->escape_string($column)."='".$db->escape_string($value)."'"; - } - } - } - else if(!empty($input)) - { - if($input == $lang->na) - { - continue; - } - - if(strpos($column, '_blank') !== false) - { - $column = str_replace('_blank', '', $column); - $userfield_sql .= ' AND '.$db->escape_string($column)." != ''"; - } - else - { - $userfield_sql .= ' AND '.$db->escape_string($column)." LIKE '%".$db->escape_string_like($input)."%'"; - } - } - } - - if($userfield_sql != '1=1') - { - $userfield_uids = array(0); - $query = $db->simple_select("userfields", "ufid", $userfield_sql); - while($userfield = $db->fetch_array($query)) - { - $userfield_uids[] = $userfield['ufid']; - } - $search_sql .= " AND u.uid IN(".implode(',', $userfield_uids).")"; - unset($userfield_uids); - } - } - - // Usergroup based searching - if(isset($view['conditions']['usergroup'])) - { - if(!is_array($view['conditions']['usergroup'])) - { - $view['conditions']['usergroup'] = array($view['conditions']['usergroup']); - } - - foreach($view['conditions']['usergroup'] as $usergroup) - { - $usergroup = (int)$usergroup; - - if(!$usergroup) - { - continue; - } - - $additional_sql = ''; - - switch($db->type) - { - case "pgsql": - case "sqlite": - $additional_sql .= " OR ','||additionalgroups||',' LIKE '%,{$usergroup},%'"; - break; - default: - $additional_sql .= "OR CONCAT(',',additionalgroups,',') LIKE '%,{$usergroup},%'"; - } - } - - $search_sql .= " AND (u.usergroup IN (".implode(",", array_map('intval', $view['conditions']['usergroup'])).") {$additional_sql})"; - } - - // COPPA users only? - if(isset($view['conditions']['coppa'])) - { - $search_sql .= " AND u.coppauser=1 AND u.usergroup=5"; - } - - // Extra SQL? - if(isset($view['extra_sql'])) - { - $search_sql .= $view['extra_sql']; - } - - // Lets fetch out how many results we have - $query = $db->query(" - SELECT COUNT(u.uid) AS num_results - FROM ".TABLE_PREFIX."users u - WHERE {$search_sql} - "); - $num_results = $db->fetch_field($query, "num_results"); - - // No matching results then return false - if(!$num_results) - { - return false; - } - // Generate the list of results - else - { - if(!$view['perpage']) - { - $view['perpage'] = 20; - } - $view['perpage'] = (int)$view['perpage']; - - // Establish which page we're viewing and the starting index for querying - if(!isset($mybb->input['page'])) - { - $mybb->input['page'] = 1; - } - else - { - $mybb->input['page'] = $mybb->get_input('page', MyBB::INPUT_INT); - } - - if($mybb->input['page']) - { - $start = ($mybb->input['page'] - 1) * $view['perpage']; - } - else - { - $start = 0; - $mybb->input['page'] = 1; - } - - $from_bit = ""; - if(isset($mybb->input['from']) && $mybb->input['from'] == "home") - { - $from_bit = "&from=home"; - } - - switch($view['sortby']) - { - case "regdate": - case "lastactive": - case "postnum": - case "reputation": - $view['sortby'] = $db->escape_string($view['sortby']); - break; - case "numposts": - $view['sortby'] = "postnum"; - break; - case "numthreads": - $view['sortby'] = "threadnum"; - break; - case "warninglevel": - $view['sortby'] = "warningpoints"; - break; - default: - $view['sortby'] = "username"; - } - - if($view['sortorder'] != "desc") - { - $view['sortorder'] = "asc"; - } - - $usergroups = $cache->read("usergroups"); - - // Fetch matching users - $query = $db->query(" - SELECT u.* - FROM ".TABLE_PREFIX."users u - WHERE {$search_sql} - ORDER BY {$view['sortby']} {$view['sortorder']} - LIMIT {$start}, {$view['perpage']} - "); - $users = ''; - while($user = $db->fetch_array($query)) - { - $comma = $groups_list = ''; - $user['username'] = htmlspecialchars_uni($user['username']); - $user['view']['username'] = "".format_name($user['username'], $user['usergroup'], $user['displaygroup']).""; - $user['view']['usergroup'] = htmlspecialchars_uni($usergroups[$user['usergroup']]['title']); - if($user['additionalgroups']) - { - $additional_groups = explode(",", $user['additionalgroups']); - - foreach($additional_groups as $group) - { - $groups_list .= $comma.htmlspecialchars_uni($usergroups[$group]['title']); - $comma = $lang->comma; - } - } - if(!$groups_list) - { - $groups_list = $lang->none; - } - $user['view']['additionalgroups'] = "{$groups_list}"; - $user['view']['email'] = "".htmlspecialchars_uni($user['email']).""; - $user['view']['regdate'] = my_date('relative', $user['regdate']); - $user['view']['lastactive'] = my_date('relative', $user['lastactive']); - - // Build popup menu - $popup = new PopupMenu("user_{$user['uid']}", $lang->options); - $popup->add_item($lang->view_profile, $mybb->settings['bburl'].'/'.get_profile_link($user['uid'])); - $popup->add_item($lang->edit_profile_and_settings, "index.php?module=user-users&action=edit&uid={$user['uid']}"); - - // Banning options... is this user banned? - if($usergroups[$user['usergroup']]['isbannedgroup'] == 1) - { - // Yes, so do we want to edit the ban or pardon his crime? - $popup->add_item($lang->edit_ban, "index.php?module=user-banning&uid={$user['uid']}#username"); - $popup->add_item($lang->lift_ban, "index.php?module=user-banning&action=lift&uid={$user['uid']}&my_post_key={$mybb->post_code}"); - } - else - { - // Not banned... but soon maybe! - $popup->add_item($lang->ban_user, "index.php?module=user-banning&uid={$user['uid']}#username"); - } - - if($user['usergroup'] == 5) - { - if($user['coppauser']) - { - $popup->add_item($lang->approve_coppa_user, "index.php?module=user-users&action=activate_user&uid={$user['uid']}&my_post_key={$mybb->post_code}{$from_bit}"); - } - else - { - $popup->add_item($lang->approve_user, "index.php?module=user-users&action=activate_user&uid={$user['uid']}&my_post_key={$mybb->post_code}{$from_bit}"); - } - } - - $popup->add_item($lang->delete_user, "index.php?module=user-users&action=delete&uid={$user['uid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->user_deletion_confirmation}')"); - $popup->add_item($lang->show_referred_users, "index.php?module=user-users&action=referrers&uid={$user['uid']}"); - $popup->add_item($lang->show_ip_addresses, "index.php?module=user-users&action=ipaddresses&uid={$user['uid']}"); - $popup->add_item($lang->show_attachments, "index.php?module=forum-attachments&results=1&username=".urlencode($user['username'])); - $user['view']['controls'] = $popup->fetch(); - - // Fetch the reputation for this user - if($usergroups[$user['usergroup']]['usereputationsystem'] == 1 && $mybb->settings['enablereputation'] == 1) - { - $user['view']['reputation'] = get_reputation($user['reputation']); - } - else - { - $reputation = "-"; - } - - if($mybb->settings['enablewarningsystem'] != 0 && $usergroups[$user['usergroup']]['canreceivewarnings'] != 0) - { - if($mybb->settings['maxwarningpoints'] < 1) - { - $mybb->settings['maxwarningpoints'] = 10; - } - - $warning_level = round($user['warningpoints']/$mybb->settings['maxwarningpoints']*100); - if($warning_level > 100) - { - $warning_level = 100; - } - $user['view']['warninglevel'] = get_colored_warning_level($warning_level); - } - - if($user['avatar'] && !my_validate_url($user['avatar'])) - { - $user['avatar'] = "../{$user['avatar']}"; - } - if($view['view_type'] == "card") - { - $scaled_avatar = fetch_scaled_avatar($user, 80, 80); - } - else - { - $scaled_avatar = fetch_scaled_avatar($user, 34, 34); - } - if(!$user['avatar'] || (my_strpos($user['avatar'], '://') !== false && !$mybb->settings['allowremoteavatars'])) - { - if(my_validate_url($mybb->settings['useravatar'])) - { - $user['avatar'] = str_replace('{theme}', 'images', $mybb->settings['useravatar']); - } - else - { - $user['avatar'] = "../".str_replace('{theme}', 'images', $mybb->settings['useravatar']); - } - } - $user['view']['avatar'] = "\"\""; - - // Convert IP's to readable - $user['regip'] = my_inet_ntop($db->unescape_binary($user['regip'])); - $user['lastip'] = my_inet_ntop($db->unescape_binary($user['lastip'])); - - if($view['view_type'] == "card") - { - $users .= build_user_view_card($user, $view, $i); - } - else - { - build_user_view_table($user, $view, $table); - } - } - - // If card view, we need to output the results - if($view['view_type'] == "card") - { - $table->construct_cell($users); - $table->construct_row(); - } - } - - if(!isset($view['table_id'])) - { - $view['table_id'] = "users_list"; - } - - $switch_view = "
"; - $switch_url = $view['url']; - if($mybb->input['page'] > 0) - { - $switch_url .= "&page=".$mybb->get_input('page', MyBB::INPUT_INT); - } - if($view['view_type'] != "card") - { - $switch_view .= "{$lang->table_view} | {$lang->card_view}"; - } - else - { - $switch_view .= "{$lang->table_view} | {$lang->card_view}"; - } - $switch_view .= "
"; - - // Do we need to construct the pagination? - if($num_results > $view['perpage']) - { - $view_type = htmlspecialchars_uni($view['view_type']); - $pagination = draw_admin_pagination($mybb->input['page'], $view['perpage'], $num_results, $view['url']."&type={$view_type}"); - $search_class = "float_right"; - $search_style = ""; - } - else - { - $search_class = ''; - $search_style = "text-align: right;"; - } - - $search_action = $view['url']; - // stop &username= in the query string - if($view_upos = strpos($search_action, '&username=')) - { - $search_action = substr($search_action, 0, $view_upos); - } - $search_action = str_replace("&", "&", $search_action); - $search = new Form(htmlspecialchars_uni($search_action), 'post', 'search_form', 0, '', true); - $built_view = $search->construct_return; - $built_view .= "
"; - $built_view .= $search->generate_hidden_field('action', 'search')."\n"; - if(isset($view['conditions']['username'])) - { - $default_class = ''; - $value = $view['conditions']['username']; - } - else - { - $default_class = "search_default"; - $value = $lang->search_for_user; - } - $built_view .= $search->generate_text_box('username', htmlspecialchars_uni($value), array('id' => 'search_keywords', 'class' => "{$default_class} field150 field_small"))."\n"; - $built_view .= "search}\" />\n"; - if($view['popup']) - { - $built_view .= "
{$view['popup']}
\n"; - } - $built_view .= "\n"; - $built_view .= "
\n"; - - // Autocompletion for usernames - // TODO Select2 - - $built_view .= $search->end(); - - if(isset($pagination)) - { - $built_view .= $pagination; - } - if($view['view_type'] != "card") - { - $checkbox = ''; - } - else - { - $checkbox = " "; - } - $built_view .= $table->construct_html("{$switch_view}
{$checkbox}{$lang->users}{$view_title}
", 1, "", $view['table_id']); - if(isset($pagination)) - { - $built_view .= $pagination; - } - - $built_view .= ' - -
- - -
'.$lang->inline_edit.' - -  - -
-
-
-'; - - return $built_view; -} - -/** - * @param array $user - * @param array $view - * @param int $i - * - * @return string - */ -function build_user_view_card($user, $view, &$i) -{ - global $user_view_fields; - - ++$i; - if($i == 3) - { - $i = 1; - } - - // Loop through fields user wants to show - foreach($view['fields'] as $field) - { - if(!$user_view_fields[$field]) - { - continue; - } - - $view_field = $user_view_fields[$field]; - - // Special conditions for avatar - if($field == "avatar") - { - $avatar = $user['view']['avatar']; - } - else if($field == "controls") - { - $controls = $user['view']['controls']; - } - // Otherwise, just user data - else if($field != "username") - { - if(isset($user['view'][$field])) - { - $value = $user['view'][$field]; - } - else - { - $value = $user[$field]; - } - - if($field == "postnum") - { - $value = my_number_format($value); - } - - $user_details[] = "{$view_field['title']}: {$value}"; - } - - } - // Floated to the left or right? - if($i == 1) - { - $float = "left"; - } - else - { - $float = "right"; - } - - // And build the final card - $card = "
\n"; - $card .= " {$user['view']['username']}\n"; - if($avatar) - { - $card .= "
{$avatar}
\n"; - } - if($user_details) - { - $card .= "
".implode("
", $user_details)."
\n"; - } - if($controls) - { - $card .= "
{$controls}
\n"; - } - $card .= "
"; - return $card; - -} - -/** - * @param array $user - * @param array $view - * @param DefaultTable $table - */ -function build_user_view_table($user, $view, &$table) -{ - global $user_view_fields; - - foreach($view['fields'] as $field) - { - if(!$user_view_fields[$field]) - { - continue; - } - $view_field = $user_view_fields[$field]; - $field_options = array(); - if($view_field['align']) - { - $field_options['class'] = "align_".$view_field['align']; - } - if($user['view'][$field]) - { - $value = $user['view'][$field]; - } - else - { - $value = $user[$field]; - } - - if($field == "postnum") - { - $value = my_number_format($user[$field]); - } - $table->construct_cell($value, $field_options); - } - - $table->construct_cell(""); - - $table->construct_row(); -} - -/** - * @param array $user - * @param int $max_width - * @param int $max_height - * - * @return array - */ -function fetch_scaled_avatar($user, $max_width=80, $max_height=80) -{ - $scaled_dimensions = array( - "width" => $max_width, - "height" => $max_height, - ); - - global $mybb; - - if($user['avatar'] && (my_strpos($user['avatar'], '://') === false || $mybb->settings['allowremoteavatars'])) - { - if($user['avatardimensions']) - { - require_once MYBB_ROOT."inc/functions_image.php"; - list($width, $height) = explode("|", $user['avatardimensions']); - $scaled_dimensions = scale_image($width, $height, $max_width, $max_height); - } - } - - return array("width" => $scaled_dimensions['width'], "height" => $scaled_dimensions['height']); -} - -/** - * @param array $fields - * @param array $values - * @param DefaultFormContainer $form_container - * @param DefaultForm $form - * @param bool $search - */ -function output_custom_profile_fields($fields, $values, &$form_container, &$form, $search=false) -{ - global $lang; - - if(!is_array($fields)) - { - return; - } - foreach($fields as $profile_field) - { - $profile_field['name'] = htmlspecialchars_uni($profile_field['name']); - $profile_field['description'] = htmlspecialchars_uni($profile_field['description']); - list($type, $options) = explode("\n", $profile_field['type'], 2); - $type = trim($type); - $field_name = "fid{$profile_field['fid']}"; - - switch($type) - { - case "multiselect": - if(!is_array($values[$field_name])) - { - $user_options = explode("\n", $values[$field_name]); - } - else - { - $user_options = $values[$field_name]; - } - - $selected_options = array(); - foreach($user_options as $val) - { - $selected_options[$val] = htmlspecialchars_uni($val); - } - - $select_options = explode("\n", $options); - $options = array(); - if($search == true) - { - $select_options[''] = $lang->na; - } - - foreach($select_options as $val) - { - $val = htmlspecialchars_uni(trim($val)); - $options[$val] = $val; - } - if(!$profile_field['length']) - { - $profile_field['length'] = 3; - } - $code = $form->generate_select_box("profile_fields[{$field_name}][]", $options, $selected_options, array('id' => "profile_field_{$field_name}", 'multiple' => true, 'size' => $profile_field['length'])); - break; - case "select": - $select_options = array(); - if($search == true) - { - $select_options[''] = $lang->na; - } - $select_options += explode("\n", $options); - $options = array(); - foreach($select_options as $val) - { - $val = htmlspecialchars_uni(trim($val)); - $options[$val] = $val; - } - if(!$profile_field['length']) - { - $profile_field['length'] = 1; - } - if($search == true) - { - $code = $form->generate_select_box("profile_fields[{$field_name}][{$field_name}]", $options, htmlspecialchars_uni($values[$field_name]), array('id' => "profile_field_{$field_name}", 'size' => $profile_field['length'])); - } - else - { - $code = $form->generate_select_box("profile_fields[{$field_name}]", $options, htmlspecialchars_uni($values[$field_name]), array('id' => "profile_field_{$field_name}", 'size' => $profile_field['length'])); - } - break; - case "radio": - $radio_options = array(); - if($search == true) - { - $radio_options[''] = $lang->na; - } - $radio_options += explode("\n", $options); - $code = ''; - foreach($radio_options as $val) - { - $val = trim($val); - $code .= $form->generate_radio_button("profile_fields[{$field_name}]", $val, htmlspecialchars_uni($val), array('id' => "profile_field_{$field_name}", 'checked' => ($val == $values[$field_name] ? true : false)))."
"; - } - break; - case "checkbox": - if(!is_array($values[$field_name])) - { - $user_options = explode("\n", $values[$field_name]); - } - else - { - $user_options = $values[$field_name]; - } - foreach($user_options as $val) - { - $selected_options[$val] = $val; - } - $select_options = array(); - if($search == true) - { - $select_options[''] = $lang->na; - } - $select_options += explode("\n", $options); - $code = ''; - foreach($select_options as $val) - { - $val = trim($val); - $code .= $form->generate_check_box("profile_fields[{$field_name}][]", $val, htmlspecialchars_uni($val), array('id' => "profile_field_{$field_name}", 'checked' => ($val == $selected_options[$val] ? true : false)))."
"; - } - break; - case "textarea": - $extra = ''; - if(isset($mybb->input['action']) && $mybb->input['action'] == "search") - { - $extra = " {$lang->or} ".$form->generate_check_box("profile_fields[{$field_name}_blank]", 1, $lang->is_not_blank, array('id' => "{$field_name}_blank", 'checked' => $values[$field_name.'_blank'])); - } - - $code = $form->generate_text_area("profile_fields[{$field_name}]", $values[$field_name], array('id' => "profile_field_{$field_name}", 'rows' => 6, 'cols' => 50)).$extra; - break; - default: - $extra = ''; - if(isset($mybb->input['action']) && $mybb->input['action'] == "search") - { - $extra = " {$lang->or} ".$form->generate_check_box("profile_fields[{$field_name}_blank]", 1, $lang->is_not_blank, array('id' => "{$field_name}_blank", 'checked' => $values[$field_name.'_blank'])); - } - - $code = $form->generate_text_box("profile_fields[{$field_name}]", $values[$field_name], array('id' => "profile_field_{$field_name}", 'maxlength' => $profile_field['maxlength'], 'length' => $profile_field['length'])).$extra; - break; - } - - $form_container->output_row($profile_field['name'], $profile_field['description'], $code, "", array('id' => "profile_field_{$field_name}")); - $code = $user_options = $selected_options = $radio_options = $val = $options = ''; - } -} - -/** - * @param array $input - * @param DefaultForm $form - */ -function user_search_conditions($input=array(), &$form) -{ - global $mybb, $db, $lang; - - if(!$input) - { - $input = $mybb->input; - } - - if(!is_array($input['conditions'])) - { - $input['conditions'] = my_unserialize($input['conditions']); - } - - if(!is_array($input['profile_fields'])) - { - $input['profile_fields'] = my_unserialize($input['profile_fields']); - } - - if(!is_array($input['fields'])) - { - $input['fields'] = my_unserialize($input['fields']); - } - - $form_container = new FormContainer($lang->find_users_where); - $form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', htmlspecialchars_uni($input['conditions']['username']), array('id' => 'username')), 'username'); - $form_container->output_row($lang->email_address_contains, "", $form->generate_text_box('conditions[email]', $input['conditions']['email'], array('id' => 'email')), 'email'); - - $options = array(); - $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $options[$usergroup['gid']] = htmlspecialchars_uni($usergroup['title']); - } - - $form_container->output_row($lang->is_member_of_groups, $lang->additional_user_groups_desc, $form->generate_select_box('conditions[usergroup][]', $options, $input['conditions']['usergroup'], array('id' => 'usergroups', 'multiple' => true, 'size' => 5)), 'usergroups'); - - $form_container->output_row($lang->website_contains, "", $form->generate_text_box('conditions[website]', $input['conditions']['website'], array('id' => 'website'))." {$lang->or} ".$form->generate_check_box('conditions[website_blank]', 1, $lang->is_not_blank, array('id' => 'website_blank', 'checked' => $input['conditions']['website_blank'])), 'website'); - $form_container->output_row($lang->icq_number_contains, "", $form->generate_text_box('conditions[icq]', $input['conditions']['icq'], array('id' => 'icq'))." {$lang->or} ".$form->generate_check_box('conditions[icq_blank]', 1, $lang->is_not_blank, array('id' => 'icq_blank', 'checked' => $input['conditions']['icq_blank'])), 'icq'); - $form_container->output_row($lang->aim_handle_contains, "", $form->generate_text_box('conditions[aim]', $input['conditions']['aim'], array('id' => 'aim'))." {$lang->or} ".$form->generate_check_box('conditions[aim_blank]', 1, $lang->is_not_blank, array('id' => 'aim_blank', 'checked' => $input['conditions']['aim_blank'])), 'aim'); - $form_container->output_row($lang->yahoo_contains, "", $form->generate_text_box('conditions[yahoo]', $input['conditions']['yahoo'], array('id' => 'yahoo'))." {$lang->or} ".$form->generate_check_box('conditions[yahoo_blank]', 1, $lang->is_not_blank, array('id' => 'yahoo_blank', 'checked' => $input['conditions']['yahoo_blank'])), 'yahoo'); - $form_container->output_row($lang->skype_contains, "", $form->generate_text_box('conditions[skype]', $input['conditions']['skype'], array('id' => 'skype'))." {$lang->or} ".$form->generate_check_box('conditions[skype_blank]', 1, $lang->is_not_blank, array('id' => 'skype_blank', 'checked' => $input['conditions']['skype_blank'])), 'skype'); - $form_container->output_row($lang->google_contains, "", $form->generate_text_box('conditions[google]', $input['conditions']['google'], array('id' => 'google'))." {$lang->or} ".$form->generate_check_box('conditions[google_blank]', 1, $lang->is_not_blank, array('id' => 'google_blank', 'checked' => $input['conditions']['google_blank'])), 'google'); - $form_container->output_row($lang->signature_contains, "", $form->generate_text_box('conditions[signature]', $input['conditions']['signature'], array('id' => 'signature'))." {$lang->or} ".$form->generate_check_box('conditions[signature_blank]', 1, $lang->is_not_blank, array('id' => 'signature_blank', 'checked' => $input['conditions']['signature_blank'])), 'signature'); - $form_container->output_row($lang->user_title_contains, "", $form->generate_text_box('conditions[usertitle]', $input['conditions']['usertitle'], array('id' => 'usertitle'))." {$lang->or} ".$form->generate_check_box('conditions[usertitle_blank]', 1, $lang->is_not_blank, array('id' => 'usertitle_blank', 'checked' => $input['conditions']['usertitle_blank'])), 'usertitle'); - $greater_options = array( - "greater_than" => $lang->greater_than, - "is_exactly" => $lang->is_exactly, - "less_than" => $lang->less_than - ); - $form_container->output_row($lang->post_count_is, "", $form->generate_select_box('conditions[postnum_dir]', $greater_options, $input['conditions']['postnum_dir'], array('id' => 'numposts_dir'))." ".$form->generate_text_box('conditions[postnum]', $input['conditions']['postnum'], array('id' => 'numposts')), 'numposts'); - $form_container->output_row($lang->thread_count_is, "", $form->generate_select_box('conditions[threadnum_dir]', $greater_options, $input['conditions']['threadnum_dir'], array('id' => 'numthreads_dir'))." ".$form->generate_text_box('conditions[threadnum]', $input['conditions']['threadnum'], array('id' => 'numthreads')), 'numthreads'); - - $form_container->output_row($lang->reg_in_x_days, '', $form->generate_text_box('conditions[regdate]', $input['conditions']['regdate'], array('id' => 'regdate')).' '.$lang->days, 'regdate'); - $form_container->output_row($lang->reg_ip_matches, $lang->wildcard, $form->generate_text_box('conditions[regip]', $input['conditions']['regip'], array('id' => 'regip')), 'regip'); - $form_container->output_row($lang->last_known_ip, $lang->wildcard, $form->generate_text_box('conditions[lastip]', $input['conditions']['lastip'], array('id' => 'lastip')), 'lastip'); - $form_container->output_row($lang->posted_with_ip, $lang->wildcard, $form->generate_text_box('conditions[postip]', $input['conditions']['postip'], array('id' => 'postip')), 'postip'); - - $form_container->end(); - - // Custom profile fields go here - $form_container = new FormContainer($lang->custom_profile_fields_match); - - // Fetch custom profile fields - $query = $db->simple_select("profilefields", "*", "", array('order_by' => 'disporder')); - - $profile_fields = array(); - while($profile_field = $db->fetch_array($query)) - { - if($profile_field['required'] == 1) - { - $profile_fields['required'][] = $profile_field; - } - else - { - $profile_fields['optional'][] = $profile_field; - } - } - - output_custom_profile_fields($profile_fields['required'], $input['profile_fields'], $form_container, $form, true); - output_custom_profile_fields($profile_fields['optional'], $input['profile_fields'], $form_container, $form, true); - - $form_container->end(); - - // Autocompletion for usernames - echo ' - - -'; -} - -/** - * @param int $source_uid - * @param int $destination_uid - */ -function merge_thread_ratings($source_uid, $destination_uid) -{ - global $db; - - $source_ratings = $dest_threads = $delete_list = $decrement_list = array(); - - // Get all thread ratings from both accounts - $query = $db->simple_select('threadratings', 'tid, uid, rid, rating', "uid IN ({$destination_uid}, {$source_uid})"); - while($rating = $db->fetch_array($query)) - { - if($rating['uid'] == $destination_uid) - { - $dest_threads[] = $rating['tid']; - } - else - { - $source_ratings[] = $rating; - } - } - - // If there are duplicates, mark them for deletion - foreach($source_ratings as $rating) - { - if(in_array($rating['tid'], $dest_threads)) - { - $delete_list[] = $rating['rid']; - $decrement_list[$rating['tid']][] = (int) $rating['rating']; - } - } - - // Attribute all of the source user's ratings to the destination user - $db->update_query("threadratings", array("uid" => $destination_uid), "uid='{$source_uid}'"); - - // Remove ratings previously given to recently acquired threads - $query = $db->query(" - SELECT tr.rid, tr.rating, t.tid - FROM {$db->table_prefix}threadratings tr - LEFT JOIN {$db->table_prefix}threads t ON (t.tid=tr.tid) - WHERE tr.uid='{$destination_uid}' AND tr.uid=t.uid - "); - while($rating = $db->fetch_array($query)) - { - $delete_list[] = $rating['rid']; - $decrement_list[$rating['tid']][] = (int) $rating['rating']; - } - - // Delete the duplicate/disallowed ratings - if(!empty($delete_list)) - { - $imp = implode(',', $delete_list); - $db->delete_query('threadratings', "rid IN ({$imp})"); - } - - // Correct the thread rating counters - if(!empty($decrement_list)) - { - foreach($decrement_list as $tid => $ratings) - { - $db->update_query('threads', array('numratings' => 'numratings-'.count($ratings), 'totalratings' => 'totalratings-'.array_sum($ratings)), "tid='{$tid}'", 1, true); - } - } -} diff --git a/html/forums/admin/styles/default/config.css b/html/forums/admin/styles/default/config.css deleted file mode 100644 index 421013c..0000000 --- a/html/forums/admin/styles/default/config.css +++ /dev/null @@ -1,77 +0,0 @@ -/* language editor issue icons */ -.langeditor_ok { - width: 16px; - height: 16px; - display: inline-block; - margin: 1px; - background: url(images/icons/tick.png) no-repeat; -} - -.langeditor_nothingtocompare { - width: 16px; - height: 16px; - display: inline-block; - margin: 1px; - background: url(images/icons/no_change.png) no-repeat; -} - -.langeditor_warning { - width: 16px; - height: 16px; - display: inline-block; - margin: 1px; - background: url(images/icons/warning.png) no-repeat; -} - -/* language editor file list rows */ -.langeditor_editwithfile, -.langeditor_phrases, -.langeditor_editfile, -.langeditor_issues, -.langeditor_edit { - font-weight: bold; - text-align: center; -} - -.langeditor_editwithfile, -.langeditor_editfile { - text-align: left; -} - -.langeditor_edit, -.langeditor_phrases { - font-weight: normal; -} - -/* language editor edit mode textareas */ -.langeditor_textarea_issue { - border: 1px solid red; -} - -.langeditor_textarea_editwith { - background: #E0E0E0; -} -.langeditor_textarea_edit, -.langeditor_textarea_editwith { - width: 98%; - padding: 4px; -} - -/* language editor main page */ -.langeditor_info_name { - font-weight: bold; -} - -.langeditor_info_author { - font-size: x-small; -} - -.langeditor_rtl { - direction: rtl; - unicode-bidi: bidi-override; -} - -.langeditor_ltr { - direction: ltr; - unicode-bidi: bidi-override; -} diff --git a/html/forums/admin/styles/default/forum.css b/html/forums/admin/styles/default/forum.css deleted file mode 100644 index 38d2c3f..0000000 --- a/html/forums/admin/styles/default/forum.css +++ /dev/null @@ -1,76 +0,0 @@ -/* Moderation Queue */ -.modqueue_message { - overflow: auto; - max-height: 250px; -} - -.modqueue_controls { - width: 270px; - float: right; - text-align: center; - border: 1px solid #ccc; - background: #fff; - padding: 6px; - font-weight: bold; -} - -.modqueue_controls label { - margin-right: 8px; -} - -.label_radio_ignore, .label_radio_delete, .label_radio_approve { - font-weight: bold; -} - -.modqueue_meta { - color: #444; - font-size: 95%; - margin-bottom: 8px; -} - -.modqueue_mass { - list-style: none; - margin: 0; - width: 150px; - padding: 0; -} - -.modqueue_mass li { - margin-bottom: 4px; - padding: 0; -} - -.modqueue_mass li a { - display: block; - padding: 4px; - border: 1px solid transparent; -} - -.modqueue_mass li a:hover { - background: #efefef; - border: 1px solid #ccc; - text-decoration: none; -} - -.forum_settings_bit { - margin-bottom: 8px; -} - -.forum_settings_bit input { - vertical-align: middle; - margin-right: 8px; -} - -.forum_settings_bit select, -.forum_settings_bit input.text_input, -.forum_settings_bit textarea { - margin-top: 8px; -} - -.forum_settings_bit label { - font-weight: normal; -} - -.forum_settings_bit small { - padding-left: 25px; -} \ No newline at end of file diff --git a/html/forums/admin/styles/default/home.css b/html/forums/admin/styles/default/home.css deleted file mode 100644 index e84dc60..0000000 --- a/html/forums/admin/styles/default/home.css +++ /dev/null @@ -1,15 +0,0 @@ -#left_menu div.left_menu_box ul.online_admins li a { - background: url('images/icons/user.png') no-repeat 15px 4px; - padding-left: 37px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -#left_menu div.left_menu_box ul.online_admins li.mobile_user a { - background: url('images/icons/mobile_user.png') no-repeat 15px 4px; - padding-left: 37px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} \ No newline at end of file diff --git a/html/forums/admin/styles/default/images/close.png b/html/forums/admin/styles/default/images/close.png deleted file mode 100644 index 6ca5558..0000000 Binary files a/html/forums/admin/styles/default/images/close.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/bullet_off.png b/html/forums/admin/styles/default/images/icons/bullet_off.png deleted file mode 100644 index b68d1b1..0000000 Binary files a/html/forums/admin/styles/default/images/icons/bullet_off.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/bullet_on.png b/html/forums/admin/styles/default/images/icons/bullet_on.png deleted file mode 100644 index 6a97d23..0000000 Binary files a/html/forums/admin/styles/default/images/icons/bullet_on.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/cross.png b/html/forums/admin/styles/default/images/icons/cross.png deleted file mode 100644 index ba0bce7..0000000 Binary files a/html/forums/admin/styles/default/images/icons/cross.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/custom.png b/html/forums/admin/styles/default/images/icons/custom.png deleted file mode 100644 index 8f49806..0000000 Binary files a/html/forums/admin/styles/default/images/icons/custom.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/decrease.png b/html/forums/admin/styles/default/images/icons/decrease.png deleted file mode 100644 index 88ba157..0000000 Binary files a/html/forums/admin/styles/default/images/icons/decrease.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/default.png b/html/forums/admin/styles/default/images/icons/default.png deleted file mode 100644 index 4f3e27d..0000000 Binary files a/html/forums/admin/styles/default/images/icons/default.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/delete.png b/html/forums/admin/styles/default/images/icons/delete.png deleted file mode 100644 index e07ffcf..0000000 Binary files a/html/forums/admin/styles/default/images/icons/delete.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/error.png b/html/forums/admin/styles/default/images/icons/error.png deleted file mode 100644 index c18dbc3..0000000 Binary files a/html/forums/admin/styles/default/images/icons/error.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/find.png b/html/forums/admin/styles/default/images/icons/find.png deleted file mode 100644 index c3385a9..0000000 Binary files a/html/forums/admin/styles/default/images/icons/find.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/group.png b/html/forums/admin/styles/default/images/icons/group.png deleted file mode 100644 index 1de25e0..0000000 Binary files a/html/forums/admin/styles/default/images/icons/group.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/increase.png b/html/forums/admin/styles/default/images/icons/increase.png deleted file mode 100644 index 6d5fe1c..0000000 Binary files a/html/forums/admin/styles/default/images/icons/increase.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/index.html b/html/forums/admin/styles/default/images/icons/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/styles/default/images/icons/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/styles/default/images/icons/logout.png b/html/forums/admin/styles/default/images/icons/logout.png deleted file mode 100644 index 2f86a30..0000000 Binary files a/html/forums/admin/styles/default/images/icons/logout.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/maillogs_contact.png b/html/forums/admin/styles/default/images/icons/maillogs_contact.png deleted file mode 100644 index dce3aa7..0000000 Binary files a/html/forums/admin/styles/default/images/icons/maillogs_contact.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/maillogs_thread.png b/html/forums/admin/styles/default/images/icons/maillogs_thread.png deleted file mode 100644 index db8a6db..0000000 Binary files a/html/forums/admin/styles/default/images/icons/maillogs_thread.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/maillogs_user.png b/html/forums/admin/styles/default/images/icons/maillogs_user.png deleted file mode 100644 index dd82fa6..0000000 Binary files a/html/forums/admin/styles/default/images/icons/maillogs_user.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/make_default.png b/html/forums/admin/styles/default/images/icons/make_default.png deleted file mode 100644 index 2f86a30..0000000 Binary files a/html/forums/admin/styles/default/images/icons/make_default.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/mobile_user.png b/html/forums/admin/styles/default/images/icons/mobile_user.png deleted file mode 100644 index ba828df..0000000 Binary files a/html/forums/admin/styles/default/images/icons/mobile_user.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/no_change.png b/html/forums/admin/styles/default/images/icons/no_change.png deleted file mode 100644 index 1fd4e36..0000000 Binary files a/html/forums/admin/styles/default/images/icons/no_change.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/run_task.png b/html/forums/admin/styles/default/images/icons/run_task.png deleted file mode 100644 index 3262eae..0000000 Binary files a/html/forums/admin/styles/default/images/icons/run_task.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/search.png b/html/forums/admin/styles/default/images/icons/search.png deleted file mode 100644 index ffdcf7b..0000000 Binary files a/html/forums/admin/styles/default/images/icons/search.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/success.png b/html/forums/admin/styles/default/images/icons/success.png deleted file mode 100644 index 0402a48..0000000 Binary files a/html/forums/admin/styles/default/images/icons/success.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/tick.png b/html/forums/admin/styles/default/images/icons/tick.png deleted file mode 100644 index be250ec..0000000 Binary files a/html/forums/admin/styles/default/images/icons/tick.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/user.png b/html/forums/admin/styles/default/images/icons/user.png deleted file mode 100644 index dd82fa6..0000000 Binary files a/html/forums/admin/styles/default/images/icons/user.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/warning.png b/html/forums/admin/styles/default/images/icons/warning.png deleted file mode 100644 index d4be20a..0000000 Binary files a/html/forums/admin/styles/default/images/icons/warning.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/icons/world.png b/html/forums/admin/styles/default/images/icons/world.png deleted file mode 100644 index 8d6f1ec..0000000 Binary files a/html/forums/admin/styles/default/images/icons/world.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/index.html b/html/forums/admin/styles/default/images/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/styles/default/images/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/styles/default/images/login_logo.png b/html/forums/admin/styles/default/images/login_logo.png deleted file mode 100644 index 04ac676..0000000 Binary files a/html/forums/admin/styles/default/images/login_logo.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/logo.png b/html/forums/admin/styles/default/images/logo.png deleted file mode 100644 index 61efd58..0000000 Binary files a/html/forums/admin/styles/default/images/logo.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/spinner.gif b/html/forums/admin/styles/default/images/spinner.gif deleted file mode 100644 index 529e72f..0000000 Binary files a/html/forums/admin/styles/default/images/spinner.gif and /dev/null differ diff --git a/html/forums/admin/styles/default/images/spinner_big.gif b/html/forums/admin/styles/default/images/spinner_big.gif deleted file mode 100644 index 3bfd6e2..0000000 Binary files a/html/forums/admin/styles/default/images/spinner_big.gif and /dev/null differ diff --git a/html/forums/admin/styles/default/images/submit_bg.png b/html/forums/admin/styles/default/images/submit_bg.png deleted file mode 100644 index 688062e..0000000 Binary files a/html/forums/admin/styles/default/images/submit_bg.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/tcat.png b/html/forums/admin/styles/default/images/tcat.png deleted file mode 100644 index 1d07e08..0000000 Binary files a/html/forums/admin/styles/default/images/tcat.png and /dev/null differ diff --git a/html/forums/admin/styles/default/images/thead.png b/html/forums/admin/styles/default/images/thead.png deleted file mode 100644 index 648f582..0000000 Binary files a/html/forums/admin/styles/default/images/thead.png and /dev/null differ diff --git a/html/forums/admin/styles/default/index.html b/html/forums/admin/styles/default/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/styles/default/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/admin/styles/default/login.css b/html/forums/admin/styles/default/login.css deleted file mode 100644 index 7ac5cdc..0000000 --- a/html/forums/admin/styles/default/login.css +++ /dev/null @@ -1,191 +0,0 @@ -/* MyBB Admin CP - * - * Login CSS - */ - -body { - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - font-size: 12px; - background: #fff; - color: #000000; - margin: 0; -} - -a { - color: #0072BC; - text-decoration: none; -} - -a:hover { - color: #0072BC; - text-decoration: underline; -} - -.invisible { - display: none; -} - -#container { - width: 410px; - margin: 100px auto; -} - -#logo h1 { - height: 82px; - background: transparent url(images/login_logo.png) bottom left no-repeat; - margin: 10px; - padding: 0; -} - -#header h1 a { - float: left; - height: 82px; - width: 410px; -} - -#content { - border: 1px solid #ccc; - background: #fff; - padding: 1px; - border-radius: 6px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; -} - -p, form { - padding: 0 10px 10px 10px; -} - -form { - padding-bottom: 0; -} - -p { - margin-bottom: 0; -} - -form p { - padding: 0 0 10px 0; -} - -h2 { - background: #02426c url(images/thead.png) repeat-x top left; - border-bottom: 1px solid #263c30; - color:#fff; - margin: 0; - padding: 8px; - font-size: 14px; - border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - -webkit-border-radius: 5px 5px 0 0; -} - -input.text_input { - border: 1px solid #aaa; - width: 255px; - padding: 4px; - font-size: 13px; - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - outline: 0; -} - -input.text_input:focus { - border: 1px solid #777; -} - -#message { - margin: 10px 10px 0 10px; - padding: 10px; - font-weight: bold; - background: #efefef; - border: 1px solid #ccc; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -#message.error { - border: 1px solid #FC6; - background: #FFC; - color: #C00; -} - -#message.success { - border: #080 1px solid; - background-color: #E8FCDC; - color: #080; -} - -form .label { - margin-bottom: 3px; - width: 112px; - clear: left; - float: left; - padding: 15px 0 0 8px; - border-top: 1px solid #ddd; -} - -form label { - font-weight: bold; -} - -.form_container .field { - float: left; - padding: 8px 0; - border-top: 1px solid #ddd; -} - -p.submit { - clear: both; - background: #efefef; - border-top: 1px solid #ddd; - padding: 8px 10px; - margin: 8px -10px 0; - text-align: right; - border-radius: 0 0 5px 5px; - -moz-border-radius: 0 0 5px 5px; - -webkit-border-radius: 0 0 5px 5px; -} - -p.submit input { - border: 1px solid #999; - padding: 4px 7px; - background: #e3e3e3 url(images/submit_bg.png) repeat-x top; - color: #444; - font-weight: bold; - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - margin-right: 3px; - font-size: 1.1em; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -p.submit input:hover { - border: 1px solid #666; - cursor: pointer; -} - -.forgot_password { - float: left; - padding-top: 8px; - font-size: 11px; -} - -.forgot_password a { - color: #555; -} - -.alert { - padding: 5px 10px; - border: #FC6 1px solid; - background-color: #ffc; - color: #900; - font-style: normal; - font-weight: bold; - padding-left: 10px; - display: block; -} \ No newline at end of file diff --git a/html/forums/admin/styles/default/main.css b/html/forums/admin/styles/default/main.css deleted file mode 100644 index bc24b75..0000000 --- a/html/forums/admin/styles/default/main.css +++ /dev/null @@ -1,1262 +0,0 @@ -/* MyBB Admin CP - * - * Main CSS - */ - -body, td { - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - font-size: 12px; - color: #333; - margin: 0; - margin-bottom: 20px; -} - -body { - overflow-y: scroll; -} - -a { - color: #0072BC; - text-decoration: none; -} - -a:hover { - color: #0072BC; - text-decoration: underline; -} - -.invisible { - display: none; -} - -#container { - background: #fff; -} - -#logo { - background: url(images/logo.png) 15px 15px no-repeat; - border-bottom: 1px solid #263C30; - height: 90px; -} - -#logo h1 { - display: none; -} - -#welcome { - position: absolute; - right: 20px; - top: 60px; - color: #999; - height: 20px; - font-size: 90%; -} - -#welcome a, -#welcome a:link, -#welcome a:visited -{ - color: #666; - min-height: 16px; -} - -#welcome .logout { - margin-left: 4px; - padding: 0 18px 2px 0; - background: url(images/icons/logout.png) no-repeat top right; -} - -#welcome .forum { - margin-left: 4px; - padding: 1px 0 2px 20px; - background: url(images/icons/world.png) no-repeat top left; -} - -#welcome .username { - margin-left: 4px; - padding: 0 0 2px 18px; - background: url(images/icons/user.png) no-repeat top left; -} - -/* Menu */ - -#menu ul { - margin: 0; - padding: 5px 5px 0; - list-style: none; - background: #0F0F0F url(images/tcat.png) repeat-x; - border-top: 1px solid #444; - border-bottom: 1px solid #000; -} - -#menu li { - font-size: 12px; - display: inline-block; - margin: 0 8px 0 8px; - padding: 0; - list-style: none; -} - -#menu a { - font-weight: bold; - float: left; - padding: 7px; - text-decoration: none; - color: #ddd; -} - -#menu a:hover { - color: #fff; -} - -#menu li a.active { - padding: 7px 11px 10px; - margin-bottom: -5px; - background: #fff; - border-radius: 5px 5px 0 0; - color: #222; - font-size: 1.1em; -} - -#page { - clear: both; - background: #fff; -} - -/* Main Content */ - -#content { - padding: 10px 15px; - margin: 0; - margin-left: 200px; -} - -#content p { - line-height: 150%; -} - -#content h2 { - font-family: 'Lucida Grande', 'Trebuchet MS', Verdana, Sans-Serif; - font-size: 170%; - letter-spacing: -1px; - font-weight: bold; - color: #666; - margin: 0 0 5px 0; -} - -#content h3 { - border-bottom: 1px solid #ccc; - font-size: 16px; - margin: 10px 0 7px 0; -} - -#content h4 { - font-size: 14px; - margin: 10px 0 -10px 0; -} - -/* Left Menu */ - -#page { - background: #fff; -} - -#left_menu { - width: 200px; - color: #333; - padding: 0; - margin: 0; - float: left; - font-size: 11px; -} - -#left_menu div.left_menu_box { - background: #fff; - list-style: none; - margin: 10px 10px 30px 10px; - padding: 0; -} - -#left_menu div.left_menu_box div.title { - font-weight: bold; - border-bottom: 1px solid #ccc; - padding-bottom: 5px; - font-size: 1.1em; -} - -#left_menu div.left_menu_box ul.menu { - padding: 0; - margin: 0; - list-style: none; -} - -#left_menu div.left_menu_box ul.menu li a { - display: block; - padding: 6px; - border-bottom: 1px solid #ddd; -} - -#left_menu div.left_menu_box ul.menu li a:hover { - text-decoration: none; - background-color: #f5f5f5; -} - -#left_menu div.left_menu_box ul.menu li.active a { - font-weight: bold; - font-size: 120%; - color: #000; -} -/* Fix IE. Hide from IE Mac \*/ -* html #left_menu li a, * html #left_menu li { - height: 1%; -} -/* End */ - - -/* Tables */ - -.border_wrapper { - margin: 0; - padding: 1px; - margin-bottom: 14px; - border: 1px solid #ccc; - border-radius: 6px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; -} - -* html .border_wrapper { - height: 1px; -} - -.border_wrapper div.title { - background: #0066a2 url(images/thead.png) top left repeat-x; - color: #ffffff; - border-bottom: 1px solid #263c30; - padding: 8px; - font-weight: bold; - text-align: left; - font-size: 120%; - border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - -webkit-border-radius: 5px 5px 0 0; -} - -.border_wrapper div.title a { - color: #fff; - text-decoration: none; -} - -.border_wrapper div.title a:hover { - text-decoration: underline; -} - -table.general { - width: 100%; -} - -table.general td { - border-top: 1px solid #fafafa; - border-bottom: 1px solid #ccc; - border-right: 1px solid #ccc; - border-left: 1px solid #fafafa; -} - -table.general tr td:last-child { - border-right: 0; -} - -table.general tr td:first-child { - border-left: 0; -} - -table.general tr:last-child td { - border-bottom: 0; -} - -table.bottom_cell_border td { - border-right: 0; - border-left: 0; -} - -table.general td { - background: #f5f5f5; - padding: 6px; -/* vertical-align: top; */ -} - -table.general th { - background: #0f0f0f url(images/tcat.png) repeat-x; - color: #fff; - border-top: 1px solid #444; - border-bottom: 1px solid #000; - padding: 8px; - font-size: 96%; - font-weight: bold; - text-align: left; -} - -table.general th a, table.general th { - color: #fff; - text-decoration: none; -} - -table.general .alt_row td { - background: #f1f1f1; -} - -table.general tr:last-child td:first-child { - border-bottom-left-radius: 5px; - -moz-border-radius-bottomleft: 5px; - -webkit-border-bottom-left-radius: 5px; -} - -table.general tr:last-child td:last-child { - border-bottom-right-radius: 5px; - -moz-border-radius-bottomright: 5px; - -webkit-border-bottom-right-radius: 5px; -} - -.tfixed { - table-layout: fixed; - word-wrap: break-word; - width: 100%; -} - -/* Page Footer */ -#footer { - clear: both; - border-top: 1px solid #ccc; - background: #eee; - border-bottom: 1px solid #ccc; -} - -#footer p { - padding: 12px; - color: #666; - margin: 0; - font-size: 11px; -} - -#footer .generation { - float: right; -} - -#footer a:link, #footer a:visited { - color: #666666; - font-weight: bold; -} -#footer a:hover, #footer a:active { - color: #444444; - font-weight: bold; - text-decoration: underline; -} -/* Popup Menus */ - -.popup_button { - color: #444; - text-align: right; - border: 1px solid #999; - padding: 3px 6px; - background: #e3e3e3 url(images/submit_bg.png) repeat-x top; - font-weight: bold; - margin-top: 3px; - margin-bottom: 3px; - margin-left: 3px; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -a.popup_button:link, -a.popup_button:visited, -a.popup_button:active, -a.popup_button:hover { - text-decoration: none; - color: #444; -} - -a.popup_button:active, -a.popup_button:hover { - text-decoration: none; - color: #444; - border: 1px solid #666; -} - -.popup_menu { - margin: 1px 0 0 1px; - background: #fff; - border: 1px solid #ccc; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -.popup_menu .popup_item_container { - margin: 1px; - text-align: left; -} - -.popup_menu .popup_item { - display: block; - padding: 5px; - text-decoration: none; - white-space: nowrap; - background: #efefef; - color: #333; -} - -.popup_menu .popup_item_container:first-child .popup_item { - border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - -webkit-border-radius: 3px 3px 0 0; -} - -.popup_menu .popup_item_container:last-child .popup_item { - border-radius: 0 0 3px 3px; - -moz-border-radius: 0 0 3px 3px; - -webkit-border-radius: 0 0 3px 3px; -} - -.popup_menu a.popup_item:hover { - text-decoration: none; - background: #666; - color: #fff; -} - -.transparent, .transparent td { - background: transparent; -} - -.breadcrumb { - margin-bottom: 10px; - font-size: 96%; - color: #aaa; -} - -.breadcrumb a { - color: #666; -} - -.breadcrumb a:hover, -.breadcrumb a:active { - color: #444; - text-decoration: none; -} - -.breadcrumb .active { - font-weight: bold; - color: #222; -} - -.inline_message { - background: #FFF6BF; - border-top: 2px solid #FFD324; - border-bottom: 2px solid #FFD324; - text-align: center; - margin: 10px auto; - padding: 5px 20px; -} - -.notice { - background: #EFEFEF; - border-top: 2px solid #CCC; - border-bottom: 2px solid #CCC; - text-align: center; - margin: 10px auto; - padding: 5px 20px; -} - -table.individual_cell_border { - border-style: collapse; -} - -table.cell_border_bottom td { - border: 1px solid #CCC; - border-style: collapse; - border-spacing: 1px; -} - -/* Forms */ - -form { - border: 0; - margin: 0; -} - -form div.form_container, fieldset { - background: #efefef; - border: 1px solid #ccc; - padding: 2px 7px 5px; - margin-bottom: 10px; -} - -fieldset { - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -.form_row { - margin: 5px 0; -} - -legend { - font-weight: bold; -} - -.form_container label { - font-weight: bold; -} - -.form_container .description, small { - font-size: 11px; - color: #444; -} - -input.text_input { - border: 1px solid #aaa; - width: 300px; - padding: 4px; - font-size: 13px; - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - outline: 0; -} - -textarea { - border: 1px solid #aaa; - padding: 4px; - width: 400px; - font-size: 12px; - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - outline: 0; -} - -textarea[disabled=disabled] { - border: 1px solid #ccc; - padding: 4px; - color: #666; - font-size: 12px; - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -select { - border: 1px solid #aaa; - padding: 4px; - font-size: 12px; - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - outline: 0; -} - -textarea:focus, input.text_input:focus, select:focus { - border-color: #777; -} - -input.inline_submit { - font-weight: bold; -} - -form p.legend { - margin-bottom: 10px; -} - -form p.legend em { - color: #C00; font-style: normal; -} - -.form_container label em, fieldset label em { - font-style: normal; - color: #C00; -} - -input.submit_button { - border: 1px solid #999; - padding: 4px 7px; - background: #e3e3e3 url(images/submit_bg.png) repeat-x top; - color: #444; - font-weight: bold; - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - margin-right: 3px; - font-size: 1.1em; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - outline: 0; -} - -input.submit_button:hover { - border: 1px solid #666; - cursor: pointer; -} - -.form_button_wrapper { - margin-top: 5px; - text-align: center; - border: 1px solid #ccc; - background: #efefef; - padding: 3px; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -.confirm_action { - margin: 10px 0; - padding: 10px; - font-weight: bold; - border: 1px solid #FC6; - background: #FFC; - color: #C00; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -.confirm_action p { - margin: 0; -} - -input.button_yes, -input.button_yes:hover { - background: #D6ECA6; - border: 1px solid #8DC93E; - padding: 4px 6px; - font-weight: bold; - margin-right: 3px; -} - -input.button_no, -input.button_no:hover { - background: #ECA6D6; - border: 1px solid #C93E8D; - padding: 4px 6px; - font-weight: bold; -} - -.label_radio_yes, .label_radio_on, .label_radio_no, .label_radio_off { - padding: 4px 6px; - margin-right: 5px; - margin-top: 5px; - display: block; - width: 60px; - float: left; -} - -.label_radio_yes, .label_radio_on { - background: #D6ECA6; - border: 1px solid #8DC93E; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -.label_radio_no, .label_radio_off { - background: #ECA6D6; - border: 1px solid #C93E8D; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -input.radio_input { - vertical-align: middle; - margin: 0; - margin-right: 9px; -} - -#flash_message { - margin: 10px 0; - padding: 10px 10px 10px 32px; - font-weight: bold; - background: #efefef; - border: 1px solid #ccc; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -#flash_message.error { - border: 1px solid #FC6; - background: #FFC url('images/icons/error.png') no-repeat 10px 8px; - color: #C00; -} - -#flash_message.success { - border: #080 1px solid; - color: #080; - background: #E8FCDC url('images/icons/success.png') no-repeat 10px 8px; -} - -.alert { - margin: 10px 0; - padding: 10px 10px 10px 32px; - border: #FC6 1px solid; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - background: #ffc url('images/icons/warning.png') no-repeat 10px 8px; - color: #C00; - font-style: normal; - font-weight: bold; - display: block; -} - -div.error, div.success { - margin: 10px 0; - padding: 10px; -} - -div.error { - border: #FC6 1px solid; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - background: #ffc; -} - -div.success { - border: #080 1px solid; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - background: #E8FCDC; -} - -div.error p, div.success p { - margin: 0; - color: #000; - font-weight: normal; -} - -div.error p em, div.success p em { - font-style: normal; - font-weight: bold; - padding-left: 24px; - display: block; -} - -div.error p em { - color: #C00; - background: url('images/icons/error.png') no-repeat; -} - -div.success p em { - color: #080; - background: url('images/icons/success.png') no-repeat; -} - -div.success ul, div.error.ul { - margin-left: 24px; -} - -.nav_tabs { - margin-bottom: 10px; -} -.nav_tabs ul { - list-style: none; - padding: 0; - margin: 0 0 0 10px; - height: 32px; -} - -.nav_tabs li { - float: left; - padding-right: 5px; -} - -.nav_tabs li.right { - float: right; - padding-left: 5px; - padding-right: 0; -} - -.nav_tabs li a { - float: left; - border-bottom: 0; - display: block; - font-family: 'Lucida Grande', 'Trebuchet MS', Verdana, Sans-Serif; - font-size: 140%; - letter-spacing: -1px; - color: #888; - padding: 5px 8px 3px; - height: 24px; -} - -.nav_tabs li a:hover { - color: #666; - text-decoration: none; -} - -.nav_tabs li.active a { - color: #555; - font-size: 150%; - font-weight: bold; - padding-top: 5px; - border-bottom: 3px solid #555; -} - -.nav_tabs .tab_description { - background: #f3f3f3; - padding: 10px; - border: 1px solid #ddd; - border-top: 3px solid #bbb; - color: #555; - font-size: 95%; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -* html .nav_tabs .tab_description { - margin-left: 3px; -} -*.align_center, table.general th.align_center, input.align_center { - text-align: center; -} - -.float_right { - float: right; -} - -.float_left { - float: left; -} - -a img { - border: 0; -} - -option { - padding-right: 10px; -} - -ul.tabs { - width: 100%; - margin: 10px 0 0 10px; - padding: 0; - list-style: none; - height: 27px; -} - -ul.tabs li { - float: left; - margin: 0; - padding: 0; - list-style: none; -} - -ul.tabs a { - float: left; - padding: 6px 10px; - text-decoration: none; - color: #888; - border: 0; - margin: 0 5px; -} - -ul.tabs a:hover { - color: #666; -} - -ul.tabs li a.active { - color: #fff; - font-size: 100%; - text-align: left; - font-weight: bold; - color: #333; - border: 1px solid #ddd; - border-bottom: 1px solid #ccc; - margin-top: -1px; - background: #f5f5f5; - border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - -webkit-border-radius: 5px 5px 0 0; -} - -.editor { - background: #f1f1f1; - border: 1px solid #ccc; -} - -.editor_control_bar { - background: #fff; - border: 1px solid #0f5c8e; -} - -.toolbar_normal { - background: #f0f0f0; - border: 1px solid #f0f0f0; -} - -.toolbar_hover { - background: #c1d2ee; - border: 1px solid #5296f7; -} - -.toolbar_clicked { - background: #e1F2fe; - border: 1px solid #5296f7; -} - -.user_avatar { - height: 80px; - width: 80px; - background: #fff; - border: 1px solid #ccc; - float: left; - clear: left; - margin-right: 5px; - text-align: center; -} - -.user_avatar img { - vertical-align: middle; -} - -.user_details { - float: left; - margin-left: 5px; - line-height: 1.7; -} - -.pagination { - font-size: 11px; - margin-bottom: 10px; - margin-top: 10px; -} - -.pagination .pages { - font-weight: bold; -} - -.pagination .pagination_current, .pagination a { - padding: 2px 6px; - margin-bottom: 3px; -} - -.pagination a { - background: #f3f3f3; - border: 1px solid #ddd; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -.pagination .pagination_current { - background: #fff; - border: 1px solid #fff; - font-weight: bold; - font-size: 110%; -} - -.pagination a:hover { - background: #ddd; - text-decoration: none; - border: 1px solid #999; -} - -.view_fields .enabled, .view_fields .disabled { - width: 200px; - float: left; -} - -.view_fields .disabled { - margin-left: 20px; -} - -.view_fields .fields_title { - font-weight: bold; - font-size: 120%; -} - -.view_fields ul, .view_fields li { - list-style: none; - padding: 0; - margin: 0; -} - -.view_fields ul { - overflow: auto; // Scroll fix for Opera - overflow-y: auto; - overflow-x: hidden; - margin-top: 4px; -} - -.view_fields li { - -moz-border-radius: 3px; - padding: 4px; - background: #666; - color: #fff; - font-size: 11px; - margin-bottom: 2px; - margin-right: 5px; -} - -.quick_perm_fields .enabled, .quick_perm_fields .disabled { - width: 49%; - float: left; -} - -.quick_perm_fields .enabled { - border-right: 5px solid #666; -} - -.quick_perm_fields .disabled { - float: right; - margin-left: 0px; -} - -.quick_perm_fields .fields_title { - font-weight: bold; - font-size: 120%; -} - -.quick_perm_fields ul, .quick_perm_fields li { - list-style: none; - padding: 3px; - margin: 0; -} - -.quick_perm_fields ul { - overflow: auto; // Scroll fix for Opera - overflow-y: auto; - overflow-x: hidden; - height: 120px; - margin-top: 4px; -} - -.quick_perm_fields li { - border-radius: 3px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - padding: 4px; - background: #666; - color: #fff; - font-size: 11px; - margin-bottom: 2px; - margin-right: 10px; -} - -input.field50 { - width: 50px; -} -input.field150 { - width: 150px; -} - -input.field_small { - font-size: 13px; - padding: 3px; -} - -input.search_default { - text-align: center; - color: #aaa; - padding: 3px; -} - -input.image_button { - margin-left: 5px; - vertical-align: bottom; -} - -input.search_button { - background: #fff url(images/icons/search.png) no-repeat; - background-position: 4px 7px; - border: 0px; - padding: 4px; - padding-left: 23px; - font-size: 14px; - font-family: 'Lucida Grande', 'Trebuchet MS', Verdana, Sans-Serif; - color: #6F6F6F; - font-weight: bold; - height: 30px; -} - -.smalltext { - font-size: 11px; -} - -.inline_element { - font-weight: normal !important; -} - -.inline_selected { - background-color: #FFFBD9; -} - -/* Templates Differential page */ -.differential { - background: #FFF; - margin: 10px auto; - padding: 10px; - overflow: scroll; - height: 400px; - width: 980px; - border: 1px solid #ccc; -} - -/** jGrowl Start **/ - -/** Special IE6 Style Positioning **/ -.ie6 { - position: absolute; -} - -.ie6.top-right { - right: auto; - bottom: auto; - left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); - top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); -} - -.ie6.top-left { - left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); - top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); -} - -.ie6.bottom-right { - left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); - top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); -} - -.ie6.bottom-left { - left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); - top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); -} - -.ie6.center { - left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); - top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); - width: 100%; -} - - -/** jGrowl Styling **/ -.jGrowl { - z-index: 9999; - color: #fff; - font-size: 12px; - position: fixed; -} - -.jGrowl.top-left { - left: 0px; - top: 0px; -} - -.jGrowl.top-right { - right: 0px; - top: 0px; -} - -.jGrowl.bottom-left { - left: 0px; - bottom: 0px; -} - -.jGrowl.bottom-right { - right: 0px; - bottom: 0px; -} - -.jGrowl.center { - top: 0px; - width: 50%; - left: 25%; -} - -/** Cross Browser Styling **/ -.center .jGrowl-notification, .center .jGrowl-closer { - margin-left: auto; - margin-right: auto; -} - -.jGrowl .jGrowl-notification, .jGrowl .jGrowl-closer { - background-color: transparent; - opacity: .85; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=85); - zoom: 1; - width: 235px; - padding: 10px; - margin-top: 5px; - margin-bottom: 5px; - font-family: Tahoma, Arial, Helvetica, sans-serif; - font-size: 1em; - text-align: left; - display: none; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; -} - -.jGrowl .jGrowl-notification { - min-height: 40px; -} - -.jGrowl .jGrowl-notification, -.jGrowl .jGrowl-closer { - margin: 10px; -} - -.jGrowl .jGrowl-notification .jGrowl-header { - font-weight: bold; - font-size: .85em; -} - -.jGrowl .jGrowl-notification .jGrowl-close { - z-index: 99; - float: right; - font-weight: bold; - font-size: 1em; - cursor: pointer; -} - -.jGrowl .jGrowl-closer { - padding-top: 4px; - padding-bottom: 4px; - cursor: pointer; - font-size: .9em; - font-weight: bold; - text-align: center; -} - -.jGrowl .jGrowl-notification.jgrowl_success { - background: lightgreen; - border: 1px solid lightgreen; - color: #333; -} - -.jGrowl .jGrowl-notification.jgrowl_error { - background: red; - border: 1px solid red; - color: #333; -} - -.jGrowl .jGrowl-notification.jgrowl_process, .jGrowl .jGrowl-closer { - background: yellow; - border: 1px solid yellow; - color: #333; -} - -/** Hide jGrowl when printing **/ -@media print { - .jGrowl { - display: none; - } -} - -/** jGrowl End **/ diff --git a/html/forums/admin/styles/default/modal.css b/html/forums/admin/styles/default/modal.css deleted file mode 100644 index 7695f30..0000000 --- a/html/forums/admin/styles/default/modal.css +++ /dev/null @@ -1,45 +0,0 @@ - -.modal { - display: none; - width: 400px; - text-align: left; - background: #fff; - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - -o-border-radius: 8px; - -ms-border-radius: 8px; - border-radius: 8px; - -webkit-box-shadow: 0 0 10px #000; - -moz-box-shadow: 0 0 10px #000; - -o-box-shadow: 0 0 10px #000; - -ms-box-shadow: 0 0 10px #000; - box-shadow: 0 0 10px #000; -} - -.modal a.close-modal { - position: absolute; - top: -12.5px; - right: -12.5px; - display: block; - width: 30px; - height: 30px; - text-indent: -9999px; - background: url(images/close.png) no-repeat 0 0; -} - -.modal-spinner { - display: none; - width: 64px; - height: 64px; - position: fixed; - top: 50%; - left: 50%; - margin-right: -32px; - margin-top: -32px; - background: url(images/spinner.gif) #111 no-repeat center center; - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - -o-border-radius: 8px; - -ms-border-radius: 8px; - border-radius: 8px; -} diff --git a/html/forums/admin/styles/default/popup.css b/html/forums/admin/styles/default/popup.css deleted file mode 100644 index f1e9506..0000000 --- a/html/forums/admin/styles/default/popup.css +++ /dev/null @@ -1,32 +0,0 @@ -body { - background: #f7f7f7; - padding: 5px; -} - -#popup_container { - background: #fff; - padding: 5px; -} - -#content { - margin: 0; - padding: 0; -} - -.popup_title { - font-family: 'Lucida Grande', 'Trebuchet MS', Verdana, Sans-Serif; - font-size: 170%; - letter-spacing: -1px; - font-weight: bold; - color: #666; - margin: 0 0 5px 0; - border-bottom: 2px solid #999; -} - -.close_link { - float: right; - font-size: 13px; - margin-top: 7px; - font-weight: normal; - letter-spacing: normal; -} \ No newline at end of file diff --git a/html/forums/admin/styles/default/style.css b/html/forums/admin/styles/default/style.css deleted file mode 100644 index 751470f..0000000 --- a/html/forums/admin/styles/default/style.css +++ /dev/null @@ -1,42 +0,0 @@ -#templatebox { - position: absolute; - top: 40px; - left: 0; - width: 100%; - z-index: 100; - text-align: center; - line-height: 0; -} - -#fader{ - position: absolute; - top: 0; - left: 0; - z-index: 90; - width: 100%; - height: 500px; - background-color: #000; - filter:alpha(opacity=60); - -moz-opacity: 0.6; - opacity: 0.6; -} - -#outerContainer { - position: relative; - background-color: #fff; - width: 70%; - height: 300px; - margin: 0 auto; -} - -ins, del { - color: #000; - padding: 2px; - line-height: 1.5em; - text-decoration: none; - background: #dfd; -} - -del { - background: #fdd; -} \ No newline at end of file diff --git a/html/forums/admin/styles/default/style.php b/html/forums/admin/styles/default/style.php deleted file mode 100644 index 40b1086..0000000 --- a/html/forums/admin/styles/default/style.php +++ /dev/null @@ -1,82 +0,0 @@ -{$title}"; - * } - * } - * - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

Please make sure IN_MYBB is defined."); -} - -class Page extends DefaultPage -{ - function _generate_breadcrumb() - { - if(!is_array($this->_breadcrumb_trail)) - { - return false; - } - $trail = ""; - foreach($this->_breadcrumb_trail as $key => $crumb) - { - if($this->_breadcrumb_trail[$key+1]) - { - $trail .= "".$crumb['name'].""; - if($this->_breadcrumb_trail[$key+2]) - { - $trail .= " » "; - } - } - else - { - $trail .= " » ".$crumb['name'].""; - } - } - return $trail; - } -} - -class SidebarItem extends DefaultSidebarItem -{ -} - -class PopupMenu extends DefaultPopupMenu -{ -} - -class Table extends DefaultTable -{ -} - -class Form extends DefaultForm -{ -} - -class FormContainer extends DefaultFormContainer -{ -} diff --git a/html/forums/admin/styles/default/user.css b/html/forums/admin/styles/default/user.css deleted file mode 100644 index 07c947d..0000000 --- a/html/forums/admin/styles/default/user.css +++ /dev/null @@ -1,57 +0,0 @@ -.user_settings_bit { - margin-bottom: 8px; -} - -.user_settings_bit input { - vertical-align: middle; - margin-right: 8px; -} - -.user_settings_bit select { - margin-top: 8px; -} - -.user_settings_bit label { - font-weight: normal; -} - -.group_settings_bit { - margin-bottom: 8px; -} - -.group_settings_bit input { - vertical-align: middle; - margin-right: 8px; -} - -.group_settings_bit select, -.group_settings_bit input.text_input, -.group_settings_bit textarea { - margin-top: 8px; -} - -.group_settings_bit label { - font-weight: normal; -} - -.group_settings_bit small { - padding-left: 25px; -} - -.group_settings_bit small.input { - padding-left: 0; -} -#tab_general td td { - border: 0; - padding: 0 4px; -} - -.view_fields #fields_enabled, .view_fields #fields_disabled { - min-height: 300px; -} - -#fields_enabled li, #fields_disabled li { - border-radius: 3px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; -} \ No newline at end of file diff --git a/html/forums/admin/styles/index.html b/html/forums/admin/styles/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/admin/styles/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/announcements.php b/html/forums/announcements.php deleted file mode 100644 index da6adcd..0000000 --- a/html/forums/announcements.php +++ /dev/null @@ -1,126 +0,0 @@ -load("announcements"); - -$aid = $mybb->get_input('aid', MyBB::INPUT_INT); - -// Get announcement fid -$query = $db->simple_select("announcements", "fid", "aid='$aid'"); -$announcement = $db->fetch_array($query); - -$plugins->run_hooks("announcements_start"); - -if(!$announcement) -{ - error($lang->error_invalidannouncement); -} - -// Get forum info -$fid = $announcement['fid']; -if($fid > 0) -{ - $forum = get_forum($fid); - - if(!$forum) - { - error($lang->error_invalidforum); - } - - // Make navigation - build_forum_breadcrumb($forum['fid']); - - // Permissions - $forumpermissions = forum_permissions($forum['fid']); - - if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0) - { - error_no_permission(); - } - - // Check if this forum is password protected and we have a valid password - check_forum_password($forum['fid']); -} -add_breadcrumb($lang->nav_announcements); - -$archive_url = build_archive_link("announcement", $aid); - -// Get announcement info -$time = TIME_NOW; - -$query = $db->query(" - SELECT u.*, u.username AS userusername, a.*, f.* - FROM ".TABLE_PREFIX."announcements a - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=a.uid) - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - WHERE a.startdate<='$time' AND (a.enddate>='$time' OR a.enddate='0') AND a.aid='$aid' -"); - -$announcementarray = $db->fetch_array($query); - -if(!$announcementarray) -{ - error($lang->error_invalidannouncement); -} - -// Gather usergroup data from the cache -// Field => Array Key -$data_key = array( - 'title' => 'grouptitle', - 'usertitle' => 'groupusertitle', - 'stars' => 'groupstars', - 'starimage' => 'groupstarimage', - 'image' => 'groupimage', - 'namestyle' => 'namestyle', - 'usereputationsystem' => 'usereputationsystem' -); - -foreach($data_key as $field => $key) -{ - $announcementarray[$key] = $groupscache[$announcementarray['usergroup']][$field]; -} - -$announcementarray['dateline'] = $announcementarray['startdate']; -$announcementarray['userusername'] = $announcementarray['username']; -$announcement = build_postbit($announcementarray, 3); -$announcementarray['subject'] = $parser->parse_badwords($announcementarray['subject']); -$lang->forum_announcement = $lang->sprintf($lang->forum_announcement, htmlspecialchars_uni($announcementarray['subject'])); - -if($announcementarray['startdate'] > $mybb->user['lastvisit']) -{ - $setcookie = true; - if(isset($mybb->cookies['mybb']['announcements']) && is_scalar($mybb->cookies['mybb']['announcements'])) - { - $cookie = my_unserialize(stripslashes($mybb->cookies['mybb']['announcements'])); - - if(isset($cookie[$announcementarray['aid']])) - { - $setcookie = false; - } - } - - if($setcookie) - { - my_set_array_cookie('announcements', $announcementarray['aid'], $announcementarray['startdate'], -1); - } -} - -$plugins->run_hooks("announcements_end"); - -eval("\$forumannouncement = \"".$templates->get("announcement")."\";"); -output_page($forumannouncement); diff --git a/html/forums/archive/global.php b/html/forums/archive/global.php deleted file mode 100644 index 2f6c09a..0000000 --- a/html/forums/archive/global.php +++ /dev/null @@ -1,229 +0,0 @@ -read("usergroups"); -if(!is_array($groupscache)) -{ - $cache->update_usergroups(); - $groupscache = $cache->read("usergroups"); -} -$fpermissioncache = $cache->read("forumpermissions"); - -// Send headers before anything else. -send_page_headers(); - -// If the installer has not been removed and no lock exists, die. -if(is_dir(MYBB_ROOT."install") && !file_exists(MYBB_ROOT."install/lock")) -{ - echo "Please remove the install directory from your server, or create a file called 'lock' in the install directory. Until you do so, your board will remain unaccessable"; - exit; -} - -// If the server OS is not Windows and not Apache or the PHP is running as a CGI or we have defined ARCHIVE_QUERY_STRINGS, use query strings - DIRECTORY_SEPARATOR checks if running windows -//if((DIRECTORY_SEPARATOR != '\\' && stripos($_SERVER['SERVER_SOFTWARE'], 'apache') == false) || stripos(SAPI_NAME, 'cgi') !== false || defined("ARCHIVE_QUERY_STRINGS")) -// http://dev.mybb.com/issues/1489 - remove automatic detection and rely on users to set the right option here -if($mybb->settings['seourls_archive'] == 1) -{ - if($_SERVER['REQUEST_URI']) - { - $url = $_SERVER['REQUEST_URI']; - } - elseif($_SERVER['REDIRECT_URL']) - { - $url = $_SERVER['REDIRECT_URL']; - } - elseif($_SERVER['PATH_INFO']) - { - $url = $_SERVER['PATH_INFO']; - } - else - { - $url = $_SERVER['PHP_SELF']; - } - $base_url = $mybb->settings['bburl']."/archive/index.php/"; - $endpart = my_substr(strrchr($url, "/"), 1); -} -else -{ - $url = $_SERVER['QUERY_STRING']; - $base_url = $mybb->settings['bburl']."/archive/index.php?"; - $endpart = $url; -} - -$action = "index"; - -// This seems to work the same as the block below except without the css bugs O_o -$archiveurl = $mybb->settings['bburl'].'/archive'; - -if($endpart != "index.php") -{ - $endpart = str_replace(".html", "", $endpart); - $todo = explode("-", $endpart, 3); - if($todo[0]) - { - $action = $action2 = $todo[0]; - } - if(!empty($todo[2])) - { - $page = (int)$todo[2]; - } - else - { - $page = 1; - } - if(!empty($todo[1])) - { - $id = (int)$todo[1]; - } - else - { - $id = 0; - } - - // Get the thread, announcement or forum information. - if($action == "announcement") - { - $time = TIME_NOW; - $query = $db->query(" - SELECT a.*, u.username - FROM ".TABLE_PREFIX."announcements a - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=a.uid) - WHERE a.aid='{$id}' AND startdate < '{$time}' AND (enddate > '{$time}' OR enddate = 0) - "); - $announcement = $db->fetch_array($query); - if(!$announcement['aid']) - { - $action = "404"; - } - } - elseif($action == "thread") - { - $query = $db->simple_select("threads", "*", "tid='{$id}' AND closed NOT LIKE 'moved|%'"); - $thread = $db->fetch_array($query); - if(!$thread['tid']) - { - $action = "404"; - } - } - elseif($action == "forum") - { - $query = $db->simple_select("forums", "*", "fid='{$id}' AND active!=0 AND password=''"); - $forum = $db->fetch_array($query); - if(!$forum['fid']) - { - $action = "404"; - } - } - elseif($action != 'index') - { - $action = "404"; - } -} - -// Define the full MyBB version location of this page. -if($action == "thread") -{ - define('MYBB_LOCATION', get_thread_link($id)); -} -elseif($action == "forum") -{ - define('MYBB_LOCATION', get_forum_link($id)); -} -elseif($action == "announcement") -{ - define('MYBB_LOCATION', get_announcement_link($id)); -} -else -{ - define('MYBB_LOCATION', INDEX_URL); -} - -// Initialise session -$session = new session; -$session->init(); - -if(!$mybb->settings['bblanguage']) -{ - $mybb->settings['bblanguage'] = "english"; -} -$lang->set_language($mybb->settings['bblanguage']); - -// Load global language phrases -$lang->load("global"); -$lang->load("messages"); -$lang->load("archive"); - -// Draw up the basic part of our naviagation -$navbits[0]['name'] = $mybb->settings['bbname_orig']; -$navbits[0]['url'] = $mybb->settings['bburl']."/archive/index.php"; - -// Check banned ip addresses -if(is_banned_ip($session->ipaddress)) -{ - archive_error($lang->error_banned); -} - -// If our board is closed.. -if($mybb->settings['boardclosed'] == 1) -{ - if($mybb->usergroup['canviewboardclosed'] != 1) - { - if(!$mybb->settings['boardclosed_reason']) - { - $mybb->settings['boardclosed_reason'] = $lang->boardclosed_reason; - } - - $lang->error_boardclosed .= "
".$mybb->settings['boardclosed_reason']."
"; - archive_error($lang->error_boardclosed); - } -} - -// Do we require users to login? -if($mybb->settings['forcelogin'] == 1) -{ - if($mybb->user['uid'] == 0) - { - archive_error($lang->error_mustlogin); - } -} - -// Load Limiting - DIRECTORY_SEPARATOR checks if running windows -if(DIRECTORY_SEPARATOR != '\\') -{ - if($uptime = @exec('uptime')) - { - preg_match("/averages?: ([0-9\.]+),[\s]+([0-9\.]+),[\s]+([0-9\.]+)/", $uptime, $regs); - $load = $regs[1]; - if($mybb->usergroup['cancp'] != 1 && $load > $mybb->settings['load'] && $mybb->settings['load'] > 0) - { - archive_error($lang->error_loadlimit); - } - } -} - -if($mybb->usergroup['canview'] == 0) -{ - archive_error_no_permission(); -} diff --git a/html/forums/archive/index.php b/html/forums/archive/index.php deleted file mode 100644 index e1b44fb..0000000 --- a/html/forums/archive/index.php +++ /dev/null @@ -1,524 +0,0 @@ -load("index"); - -$plugins->run_hooks("archive_start"); - -switch($action) -{ - // Display an announcement. - case "announcement": - // Fetch the forum this thread is in - if($announcement['fid'] != -1) - { - $forum = get_forum($announcement['fid']); - if(!$forum['fid'] || $forum['password'] != '') - { - archive_error($lang->error_invalidforum); - } - - // Check if we have permission to view this thread - $forumpermissions = forum_permissions($forum['fid']); - if($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1) - { - archive_error_no_permission(); - } - - check_forum_password_archive($forum['fid']); - } - - $announcement['subject'] = htmlspecialchars_uni($parser->parse_badwords($announcement['subject'])); - - $parser_options = array( - "allow_html" => $announcement['allowhtml'], - "allow_mycode" => $announcement['allowmycode'], - "allow_smilies" => $announcement['allowsmilies'], - "allow_imgcode" => 1, - "allow_videocode" => 1, - "me_username" => $announcement['username'], - "filter_badwords" => 1 - ); - - $announcement['message'] = $parser->parse_message($announcement['message'], $parser_options); - - $profile_link = build_profile_link(htmlspecialchars_uni($announcement['username']), $announcement['uid']); - - // Build the navigation - add_breadcrumb($announcement['subject']); - archive_header($announcement['subject'], $announcement['subject'], $mybb->settings['bburl']."/announcements.php?aid={$id}"); - - // Format announcement contents. - $announcement['startdate'] = my_date('relative', $announcement['startdate']); - - $plugins->run_hooks("archive_announcement_start"); - - echo "
\n
\n

{$announcement['subject']} - {$profile_link}

"; - echo "
{$announcement['startdate']}
\n
\n
{$announcement['message']}
\n
\n"; - - $plugins->run_hooks("archive_announcement_end"); - - archive_footer(); - break; - - // Display a thread. - case "thread": - $thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); - - // Fetch the forum this thread is in - $forum = get_forum($thread['fid']); - if(!$forum['fid'] || $forum['password'] != '') - { - archive_error($lang->error_invalidforum); - } - - // Check if we have permission to view this thread - $forumpermissions = forum_permissions($forum['fid']); - if($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1) - { - archive_error_no_permission(); - } - - if($thread['visible'] != 1) - { - if(is_moderator($forum['fid'], "canviewunapprove")) - { - archive_error($lang->sprintf($lang->error_unapproved_thread, $mybb->settings['bburl']."/".get_thread_link($thread['tid'], $page))); - } - else - { - archive_error($lang->error_invalidthread); - } - } - - if(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] == 1 && $thread['uid'] != $mybb->user['uid']) - { - archive_error_no_permission(); - } - - check_forum_password_archive($forum['fid']); - - // Build the navigation - build_forum_breadcrumb($forum['fid'], 1); - add_breadcrumb($thread['subject']); - - archive_header($thread['subject'], $thread['subject'], $mybb->settings['bburl']."/".get_thread_link($thread['tid'], $page)); - - $plugins->run_hooks("archive_thread_start"); - - // Paginate this thread - if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) - { - $mybb->settings['postsperpage'] = 20; - } - $perpage = $mybb->settings['postsperpage']; - $postcount = (int)$thread['replies']+1; - $pages = ceil($postcount/$perpage); - - if($page > $pages) - { - $page = 1; - } - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $pids = array(); - // Fetch list of post IDs to be shown - $query = $db->simple_select("posts", "pid", "tid='{$id}' AND visible='1'", array('order_by' => 'dateline', 'limit_start' => $start, 'limit' => $perpage)); - while($post = $db->fetch_array($query)) - { - $pids[$post['pid']] = $post['pid']; - } - - if(empty($pids)) - { - archive_error($lang->error_invalidthread); - } - - archive_multipage($postcount, $perpage, $page, "{$base_url}thread-$id"); - - $pids = implode(",", $pids); - - if($pids && $mybb->settings['enableattachments'] == 1) - { - // Build attachments cache - $query = $db->simple_select("attachments", "*", "pid IN ({$pids})"); - while($attachment = $db->fetch_array($query)) - { - $acache[$attachment['pid']][$attachment['aid']] = $attachment; - } - } - - // Start fetching the posts - $query = $db->query(" - SELECT u.*, u.username AS userusername, p.* - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.pid IN ({$pids}) - ORDER BY p.dateline - "); - while($post = $db->fetch_array($query)) - { - $post['date'] = my_date('relative', $post['dateline']); - if($post['userusername']) - { - $post['username'] = $post['userusername']; - } - - // Parse the message - $parser_options = array( - "allow_html" => $forum['allowhtml'], - "allow_mycode" => $forum['allowmycode'], - "allow_smilies" => $forum['allowsmilies'], - "allow_imgcode" => $forum['allowimgcode'], - "allow_videocode" => $forum['allowvideocode'], - "me_username" => $post['username'], - "filter_badwords" => 1 - ); - if($post['smilieoff'] == 1) - { - $parser_options['allow_smilies'] = 0; - } - - $post['message'] = $parser->parse_message($post['message'], $parser_options); - - // Is there an attachment in this post? - if($mybb->settings['enableattachments'] == 1 && isset($acache[$post['pid']]) && is_array($acache[$post['pid']])) - { - foreach($acache[$post['pid']] as $aid => $attachment) - { - $post['message'] = str_replace("[attachment={$attachment['aid']}]", "[settings['bburl']."/attachment.php?aid={$attachment['aid']}\">attachment={$attachment['aid']}]", $post['message']); - } - } - - // Damn thats a lot of parsing, now to determine which username to show.. - if($post['userusername']) - { - $post['username'] = $post['userusername']; - } - $post['username'] = build_profile_link(htmlspecialchars_uni($post['username']), $post['uid']); - - $plugins->run_hooks("archive_thread_post"); - - // Finally show the post - echo "
\n
\n

{$post['username']}

"; - echo "
{$post['date']}
\n
\n
{$post['message']}
\n
\n"; - } - archive_multipage($postcount, $perpage, $page, "{$base_url}thread-$id"); - - $plugins->run_hooks("archive_thread_end"); - - archive_footer(); - break; - - // Display a category or a forum. - case "forum": - // Check if we have permission to view this forum - $forumpermissions = forum_permissions($forum['fid']); - if($forumpermissions['canview'] != 1) - { - archive_error_no_permission(); - } - - check_forum_password_archive($forum['fid']); - - $useronly = ""; - if(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] == 1) - { - $useronly = "AND uid={$mybb->user['uid']}"; - } - - // Paginate this forum - $query = $db->simple_select("threads", "COUNT(tid) AS threads", "fid='{$id}' AND visible='1' {$useronly}"); - $threadcount = $db->fetch_field($query, "threads"); - - // Build the navigation - build_forum_breadcrumb($forum['fid'], 1); - - // No threads and not a category? Error! - if($forum['type'] != 'c') - { - if($forumpermissions['canviewthreads'] != 1) - { - archive_header(strip_tags($forum['name']), $forum['name'], $mybb->settings['bburl']."/".get_forum_link($id, $page).""); - archive_error($lang->error_nopermission); - } - - if($threadcount < 1 && $forumpermissions['canviewthreads'] == 1) - { - archive_header(strip_tags($forum['name']), $forum['name'], $mybb->settings['bburl']."/".get_forum_link($id, $page).""); - archive_error($lang->error_nothreads); - } - } - - // Build the archive header. - archive_header(strip_tags($forum['name']), $forum['name'], $mybb->settings['bburl']."/".get_forum_link($id, $page), 1); - - $plugins->run_hooks("archive_forum_start"); - - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - $perpage = $mybb->settings['threadsperpage']; - $pages = ceil($threadcount/$perpage); - if($page > $pages) - { - $page = 1; - } - - if($page > 0) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - // Decide what type of listing to show. - if($forum['type'] == 'f') - { - echo "
\n

{$forum['name']}

\n"; - } - elseif($forum['type'] == 'c') - { - echo "
\n

{$forum['name']}

\n"; - } - - // Show subforums. - $query = $db->simple_select("forums", "COUNT(fid) AS subforums", "pid='{$id}'"); - $subforumcount = $db->fetch_field($query, "subforums"); - if($subforumcount > 0) - { - echo "
\n"; - echo "

{$lang->subforums}

\n"; - echo "
    \n"; - $forums = build_archive_forumbits($forum['fid']); - echo $forums; - echo "
\n
\n"; - } - - archive_multipage($threadcount, $perpage, $page, "{$base_url}forum-$id"); - - // Get the announcements if the forum is not a category. - if($forum['type'] == 'f') - { - $sql = build_parent_list($forum['fid'], "fid", "OR", $forum['parentlist']); - $time = TIME_NOW; - $query = $db->simple_select("announcements", "*", "startdate < '{$time}' AND (enddate > '{$time}' OR enddate=0) AND ({$sql} OR fid='-1')"); - if($db->num_rows($query) > 0) - { - echo "
\n"; - echo "

{$lang->forumbit_announcements}

"; - echo "
    \n"; - while($announcement = $db->fetch_array($query)) - { - $announcement['subject'] = $parser->parse_badwords($announcement['subject']); - echo "
  1. ".htmlspecialchars_uni($announcement['subject'])."
  2. "; - } - echo "
\n
\n"; - } - - } - - // Get the stickies if the forum is not a category. - if($forum['type'] == 'f') - { - $options = array( - 'order_by' => 'sticky, lastpost', - 'order_dir' => 'desc', - 'limit_start' => $start, - 'limit' => $perpage - ); - $query = $db->simple_select("threads", "*", "fid='{$id}' AND visible='1' AND sticky='1' AND closed NOT LIKE 'moved|%' {$useronly}", $options); - if($db->num_rows($query) > 0) - { - echo "
\n"; - echo "

{$lang->forumbit_stickies}

"; - echo "
    \n"; - while($sticky = $db->fetch_array($query)) - { - $sticky['subject'] = htmlspecialchars_uni($parser->parse_badwords($sticky['subject'])); - if($sticky['replies'] != 1) - { - $lang_reply_text = $lang->archive_replies; - } - else - { - $lang_reply_text = $lang->archive_reply; - } - - $plugins->run_hooks("archive_forum_thread"); - - $sticky['replies'] = my_number_format($sticky['replies']); - - echo "
  1. {$sticky['subject']}"; - echo " ({$sticky['replies']} {$lang_reply_text})
  2. "; - } - echo "
\n
\n"; - } - } - - // Get the threads if the forum is not a category. - if($forum['type'] == 'f') - { - $options = array( - 'order_by' => 'sticky, lastpost', - 'order_dir' => 'desc', - 'limit_start' => $start, - 'limit' => $perpage - ); - $query = $db->simple_select("threads", "*", "fid='{$id}' AND visible='1' AND sticky='0' AND closed NOT LIKE 'moved|%' {$useronly}", $options); - if($db->num_rows($query) > 0) - { - echo "
\n"; - echo "

{$lang->forumbit_threads}

"; - echo "
    \n"; - while($thread = $db->fetch_array($query)) - { - $thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); - if($thread['replies'] != 1) - { - $lang_reply_text = $lang->archive_replies; - } - else - { - $lang_reply_text = $lang->archive_reply; - } - - $plugins->run_hooks("archive_forum_thread"); - - $thread['replies'] = my_number_format($thread['replies']); - - echo "
  1. {$thread['subject']}"; - echo " ({$thread['replies']} {$lang_reply_text})
  2. "; - } - echo "
\n
\n"; - } - } - - echo "
\n"; - - archive_multipage($threadcount, $perpage, $page, "{$base_url}forum-$id"); - - $plugins->run_hooks("archive_forum_end"); - - archive_footer(); - break; - - // Display the board home. - case "index": - // Build our forum listing - $forums = build_archive_forumbits(0); - archive_header("", $mybb->settings['bbname_orig'], $mybb->settings['bburl']."/index.php"); - - $plugins->run_hooks("archive_index_start"); - - echo "
\n
{$mybb->settings['bbname']}
\n
\n
    \n"; - echo $forums; - echo "\n
\n
\n
"; - - $plugins->run_hooks("archive_index_end"); - - archive_footer(); - break; - default: - header("HTTP/1.0 404 Not Found"); - switch($action2) - { - case "announcement": - archive_error($lang->error_invalidannouncement); - case "thread": - archive_error($lang->error_invalidthread); - case "forum": - archive_error($lang->error_invalidforum); - default: - archive_error($lang->archive_not_found); - } -} - -$plugins->run_hooks("archive_end"); - -/** -* Gets a list of forums and possibly subforums. -* -* @param int $pid The parent forum to get the childforums for. -* @return array Array of information regarding the child forums of this parent forum -*/ -function build_archive_forumbits($pid=0) -{ - global $db, $forumpermissions, $mybb, $base_url; - - // Sort out the forum cache first. - static $fcache; - if(!is_array($fcache)) - { - // Fetch forums - $query = $db->simple_select("forums", "*", "active!=0 AND password=''", array('order_by' =>'pid, disporder')); - while($forum = $db->fetch_array($query)) - { - $fcache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; - } - $forumpermissions = forum_permissions(); - } - - $forums = ''; - - // Start the process. - if(is_array($fcache[$pid])) - { - foreach($fcache[$pid] as $key => $main) - { - foreach($main as $key => $forum) - { - $perms = $forumpermissions[$forum['fid']]; - if(($perms['canview'] == 1 || $mybb->settings['hideprivateforums'] == 0) && $forum['active'] != 0) - { - if($forum['linkto']) - { - $forums .= "
  • {$forum['name']}"; - } - elseif($forum['type'] == "c") - { - $forums .= "
  • {$forum['name']}"; - } - else - { - $forums .= "
  • {$forum['name']}"; - } - if(!empty($fcache[$forum['fid']])) - { - $forums .= "\n
      \n"; - $forums .= build_archive_forumbits($forum['fid']); - $forums .= "
    \n"; - } - $forums .= "
  • \n"; - } - } - } - } - return $forums; -} diff --git a/html/forums/archive/print.css b/html/forums/archive/print.css deleted file mode 100644 index fc76cea..0000000 --- a/html/forums/archive/print.css +++ /dev/null @@ -1,144 +0,0 @@ -body { - background: #fff; - color: #000; - font: small Verdana; -} - -#container { - border: 1px solid #ccc; - background: #fff; - padding: 20px; -} - -h1 { - font-family: 'Trebuchet MS', 'Lucida Grande', Verdana, Arial, Sans-Serif; - font-weight: bold; - color: #000; -} -h1 a { - color: #000; - text-decoration: none; -} - -.navigation { - border: 1px solid #ccc; - background: #F5F5F4; - padding: 4px; - margin-bottom: 10px; - font-size: 13px; -} - -#infobox { - padding: 4px; - color: #777; - font-size: 0.8em; - margin-bottom: 10px; -} - -#fullversion { - font-size: 1.1em; -} - -.post { - border: 1px solid #ccc; - padding: 1px; - background: #F5F5F4; - margin-bottom: 10px; -} - -.post .header { - background: #F5F5F4; -} - -.post .header .author a { - color: #000; - text-decoration: none; -} - -.post .header .dateline { - padding: 4px; - color: #777; - float: right; - margin-top: -20px; -} - -.post .message { - background: #fff; - padding: 4px; -} - -.listing { - border: 1px solid #ccc; - margin-bottom: 10px; -} - -.header { - background: #F5F5F4; - font-weight: bold; - padding: 4px; - border-bottom: 1px solid #ccc; -} - -.threadlist .threads { - padding: 4px; -} - -.threadlist .threads .replycount { - color: #777; - font-size: 0.8em; -} - -.header h2 { - font-size: 1.0em; - margin: 0; -} - -h3 { - font-size: 1.0em; - margin: 5px 0 0 10px; -} - -.forumlist .forums ul { - list-style: none; -} - -.error { - border: 1px solid #ccc; - margin-bottom: 10px; -} - -.error .header { - background: #F5F5F4; - font-weight: bold; - padding: 4px; - border-bottom: 1px solid #ccc; -} - -.error .message { - padding: 4px; -} - -.multipage { - background: #F5F5F4; - border: 1px solid #ccc; - margin-bottom: 10px; - padding: 4px; -} - -#printinfo { - display: none; -} - -#footer { - padding-top: 10px; - text-align: center; - font-size: 0.8em; -} - -#footer a { - color: #000; -} - -.quote_body, .code_body { - margin-left: 18px; -} \ No newline at end of file diff --git a/html/forums/archive/screen.css b/html/forums/archive/screen.css deleted file mode 100644 index fc76cea..0000000 --- a/html/forums/archive/screen.css +++ /dev/null @@ -1,144 +0,0 @@ -body { - background: #fff; - color: #000; - font: small Verdana; -} - -#container { - border: 1px solid #ccc; - background: #fff; - padding: 20px; -} - -h1 { - font-family: 'Trebuchet MS', 'Lucida Grande', Verdana, Arial, Sans-Serif; - font-weight: bold; - color: #000; -} -h1 a { - color: #000; - text-decoration: none; -} - -.navigation { - border: 1px solid #ccc; - background: #F5F5F4; - padding: 4px; - margin-bottom: 10px; - font-size: 13px; -} - -#infobox { - padding: 4px; - color: #777; - font-size: 0.8em; - margin-bottom: 10px; -} - -#fullversion { - font-size: 1.1em; -} - -.post { - border: 1px solid #ccc; - padding: 1px; - background: #F5F5F4; - margin-bottom: 10px; -} - -.post .header { - background: #F5F5F4; -} - -.post .header .author a { - color: #000; - text-decoration: none; -} - -.post .header .dateline { - padding: 4px; - color: #777; - float: right; - margin-top: -20px; -} - -.post .message { - background: #fff; - padding: 4px; -} - -.listing { - border: 1px solid #ccc; - margin-bottom: 10px; -} - -.header { - background: #F5F5F4; - font-weight: bold; - padding: 4px; - border-bottom: 1px solid #ccc; -} - -.threadlist .threads { - padding: 4px; -} - -.threadlist .threads .replycount { - color: #777; - font-size: 0.8em; -} - -.header h2 { - font-size: 1.0em; - margin: 0; -} - -h3 { - font-size: 1.0em; - margin: 5px 0 0 10px; -} - -.forumlist .forums ul { - list-style: none; -} - -.error { - border: 1px solid #ccc; - margin-bottom: 10px; -} - -.error .header { - background: #F5F5F4; - font-weight: bold; - padding: 4px; - border-bottom: 1px solid #ccc; -} - -.error .message { - padding: 4px; -} - -.multipage { - background: #F5F5F4; - border: 1px solid #ccc; - margin-bottom: 10px; - padding: 4px; -} - -#printinfo { - display: none; -} - -#footer { - padding-top: 10px; - text-align: center; - font-size: 0.8em; -} - -#footer a { - color: #000; -} - -.quote_body, .code_body { - margin-left: 18px; -} \ No newline at end of file diff --git a/html/forums/attachment.php b/html/forums/attachment.php deleted file mode 100644 index ae1b75f..0000000 --- a/html/forums/attachment.php +++ /dev/null @@ -1,217 +0,0 @@ -settings['enableattachments'] != 1) -{ - error($lang->attachments_disabled); -} - -// Find the AID we're looking for -if(isset($mybb->input['thumbnail'])) -{ - $aid = $mybb->get_input('thumbnail', MyBB::INPUT_INT); -} -else -{ - $aid = $mybb->get_input('aid', MyBB::INPUT_INT); -} - -$pid = $mybb->get_input('pid', MyBB::INPUT_INT); - -// Select attachment data from database -if($aid) -{ - $query = $db->simple_select("attachments", "*", "aid='{$aid}'"); -} -else -{ - $query = $db->simple_select("attachments", "*", "pid='{$pid}'"); -} -$attachment = $db->fetch_array($query); - -$plugins->run_hooks("attachment_start"); - -if(!$attachment) -{ - error($lang->error_invalidattachment); -} - -if($attachment['thumbnail'] == '' && isset($mybb->input['thumbnail'])) -{ - error($lang->error_invalidattachment); -} - -$attachtypes = (array)$cache->read('attachtypes'); -$ext = get_extension($attachment['filename']); - -if(empty($attachtypes[$ext])) -{ - error($lang->error_invalidattachment); -} - -$attachtype = $attachtypes[$ext]; - -$pid = $attachment['pid']; - -// Don't check the permissions on preview -if($pid || $attachment['uid'] != $mybb->user['uid']) -{ - $post = get_post($pid); - $thread = get_thread($post['tid']); - - if(!$thread && !isset($mybb->input['thumbnail'])) - { - error($lang->error_invalidthread); - } - $fid = $thread['fid']; - - // Get forum info - $forum = get_forum($fid); - - // Permissions - $forumpermissions = forum_permissions($fid); - - if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0 || (isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0 && $thread['uid'] != $mybb->user['uid']) || ($forumpermissions['candlattachments'] == 0 && !$mybb->input['thumbnail'])) - { - error_no_permission(); - } - - // Error if attachment is invalid or not visible - if(!$attachment['attachname'] || (!is_moderator($fid, "canviewunapprove") && ($attachment['visible'] != 1 || $thread['visible'] != 1 || $post['visible'] != 1))) - { - error($lang->error_invalidattachment); - } - - if($attachtype['forums'] != -1 && strpos(','.$attachtype['forums'].',', ','.$fid.',') === false) - { - error_no_permission(); - } -} - -if(!isset($mybb->input['thumbnail'])) // Only increment the download count if this is not a thumbnail -{ - if(!is_member($attachtype['groups'])) - { - error_no_permission(); - } - - $attachupdate = array( - "downloads" => $attachment['downloads']+1, - ); - $db->update_query("attachments", $attachupdate, "aid='{$attachment['aid']}'"); -} - -// basename isn't UTF-8 safe. This is a workaround. -$attachment['filename'] = ltrim(basename(' '.$attachment['filename'])); - -$plugins->run_hooks("attachment_end"); - -if(isset($mybb->input['thumbnail'])) -{ - if(!file_exists($mybb->settings['uploadspath']."/".$attachment['thumbnail'])) - { - error($lang->error_invalidattachment); - } - - $ext = get_extension($attachment['thumbnail']); - switch($ext) - { - case "gif": - $type = "image/gif"; - break; - case "bmp": - $type = "image/bmp"; - break; - case "png": - $type = "image/png"; - break; - case "jpg": - case "jpeg": - case "jpe": - $type = "image/jpeg"; - break; - default: - $type = "image/unknown"; - break; - } - - header("Content-disposition: filename=\"{$attachment['filename']}\""); - header("Content-type: ".$type); - $thumb = $mybb->settings['uploadspath']."/".$attachment['thumbnail']; - header("Content-length: ".@filesize($thumb)); - $handle = fopen($thumb, 'rb'); - while(!feof($handle)) - { - echo fread($handle, 8192); - } - fclose($handle); -} -else -{ - if(!file_exists($mybb->settings['uploadspath']."/".$attachment['attachname'])) - { - error($lang->error_invalidattachment); - } - - $ext = get_extension($attachment['filename']); - - switch($attachment['filetype']) - { - case "application/pdf": - case "image/bmp": - case "image/gif": - case "image/jpeg": - case "image/pjpeg": - case "image/png": - case "text/plain": - header("Content-type: {$attachment['filetype']}"); - $disposition = "inline"; - break; - - default: - $filetype = $attachment['filetype']; - - if(!$filetype) - { - $filetype = 'application/force-download'; - } - - header("Content-type: {$filetype}"); - $disposition = "attachment"; - } - - if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), "msie") !== false) - { - header("Content-disposition: attachment; filename=\"{$attachment['filename']}\""); - } - else - { - header("Content-disposition: {$disposition}; filename=\"{$attachment['filename']}\""); - } - - if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), "msie 6.0") !== false) - { - header("Expires: -1"); - } - - header("Content-length: {$attachment['filesize']}"); - header("Content-range: bytes=0-".($attachment['filesize']-1)."/".$attachment['filesize']); - $handle = fopen($mybb->settings['uploadspath']."/".$attachment['attachname'], 'rb'); - while(!feof($handle)) - { - echo fread($handle, 8192); - } - fclose($handle); -} diff --git a/html/forums/cache/index.html b/html/forums/cache/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/cache/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/cache/themes/index.html b/html/forums/cache/themes/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/cache/themes/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/calendar.php b/html/forums/calendar.php deleted file mode 100644 index 6533e1b..0000000 --- a/html/forums/calendar.php +++ /dev/null @@ -1,2531 +0,0 @@ -load("calendar"); - -if($mybb->settings['enablecalendar'] == 0) -{ - error($lang->calendar_disabled); -} - -if($mybb->usergroup['canviewcalendar'] == 0) -{ - error_no_permission(); -} - -$monthnames = array( - "offset", - $lang->alt_month_1, - $lang->alt_month_2, - $lang->alt_month_3, - $lang->alt_month_4, - $lang->alt_month_5, - $lang->alt_month_6, - $lang->alt_month_7, - $lang->alt_month_8, - $lang->alt_month_9, - $lang->alt_month_10, - $lang->alt_month_11, - $lang->alt_month_12 -); - -$plugins->run_hooks("calendar_start"); - -// Make navigation -add_breadcrumb($lang->nav_calendar, "calendar.php"); - -$mybb->input['calendar'] = $mybb->get_input('calendar', MyBB::INPUT_INT); -$calendars = cache_calendars(); - -$calendar_jump = ''; -if(count($calendars) > 1) -{ - $calendar_jump = build_calendar_jump($mybb->input['calendar']); -} - -$mybb->input['action'] = $mybb->get_input('action'); -// Add an event -if($mybb->input['action'] == "do_addevent" && $mybb->request_method == "post") -{ - $query = $db->simple_select("calendars", "*", "cid='{$mybb->input['calendar']}'"); - $calendar = $db->fetch_array($query); - - // Invalid calendar? - if(!$calendar) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar or post events? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - if($calendar_permissions['canviewcalendar'] != 1 || $calendar_permissions['canaddevents'] != 1) - { - error_no_permission(); - } - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("calendar_do_addevent_start"); - - // Set up event handler. - require_once MYBB_ROOT."inc/datahandler.php"; - require_once MYBB_ROOT."inc/datahandlers/event.php"; - $eventhandler = new EventDataHandler("insert"); - - $mybb->input['type'] = $mybb->get_input('type'); - - // Prepare an array for the eventhandler. - $event = array( - "cid" => $calendar['cid'], - "uid" => $mybb->user['uid'], - "name" => $mybb->get_input('name'), - "description" => $mybb->get_input('description'), - "private" => $mybb->get_input('private', MyBB::INPUT_INT), - "type" => $mybb->input['type'] - ); - - // Now we add in our date/time info depending on the type of event - if($mybb->input['type'] == "single") - { - $event['start_date'] = array( - "day" => $mybb->get_input('single_day', MyBB::INPUT_INT), - "month" => $mybb->get_input('single_month', MyBB::INPUT_INT), - "year" => $mybb->get_input('single_year', MyBB::INPUT_INT) - ); - $event['repeats'] = ''; - } - else if($mybb->input['type'] == "ranged") - { - $event['start_date'] = array( - "day" => $mybb->get_input('start_day', MyBB::INPUT_INT), - "month" => $mybb->get_input('start_month', MyBB::INPUT_INT), - "year" => $mybb->get_input('start_year', MyBB::INPUT_INT), - "time" => $mybb->get_input('start_time') - ); - $event['end_date'] = array( - "day" => $mybb->get_input('end_day', MyBB::INPUT_INT), - "month" => $mybb->get_input('end_month', MyBB::INPUT_INT), - "year" => $mybb->get_input('end_year', MyBB::INPUT_INT), - "time" => $mybb->get_input('end_time') - ); - $event['timezone'] = $mybb->get_input('timezone'); - $event['ignoretimezone'] = $mybb->get_input('ignoretimezone', MyBB::INPUT_INT); - $repeats = array(); - switch($mybb->input['repeats']) - { - case 1: - $repeats['repeats'] = 1; - $repeats['days'] = $mybb->get_input('repeats_1_days', MyBB::INPUT_INT); - break; - case 2: - $repeats['repeats'] = 2; - break; - case 3: - $repeats['repeats'] = 3; - $repeats['weeks'] = $mybb->get_input('repeats_3_weeks', MyBB::INPUT_INT); - $mybb->input['repeats_3_days'] = $mybb->get_input('repeats_3_days', MyBB::INPUT_ARRAY); - ksort($mybb->input['repeats_3_days']); - $days = array(); - foreach($mybb->input['repeats_3_days'] as $weekday => $value) - { - if($value != 1) - { - continue; - } - $days[] = $weekday; - } - $repeats['days'] = $days; - break; - case 4: - $repeats['repeats'] = 4; - if($mybb->get_input('repeats_4_type', MyBB::INPUT_INT) == 1) - { - $repeats['day'] = $mybb->get_input('repeats_4_day', MyBB::INPUT_INT); - $repeats['months'] = $mybb->get_input('repeats_4_months', MyBB::INPUT_INT); - } - else - { - $repeats['months'] = $mybb->get_input('repeats_4_months2', MyBB::INPUT_INT); - $repeats['occurance'] = $mybb->get_input('repeats_4_occurance'); - $repeats['weekday'] = $mybb->get_input('repeats_4_weekday', MyBB::INPUT_INT); - } - break; - case 5: - $repeats['repeats'] = 5; - if($mybb->get_input('repeats_5_type', MyBB::INPUT_INT) == 1) - { - $repeats['day'] = $mybb->get_input('repeats_5_day', MyBB::INPUT_INT); - $repeats['month'] = $mybb->get_input('repeats_5_month', MyBB::INPUT_INT); - $repeats['years'] = $mybb->get_input('repeats_5_years', MyBB::INPUT_INT); - } - else - { - $repeats['occurance'] = $mybb->get_input('repeats_5_occurance'); - $repeats['weekday'] = $mybb->get_input('repeats_5_weekday', MyBB::INPUT_INT); - $repeats['month'] = $mybb->get_input('repeats_5_month2', MyBB::INPUT_INT); - $repeats['years'] = $mybb->get_input('repeats_5_years', MyBB::INPUT_INT); - } - break; - default: - $repeats['repeats'] = 0; - } - $event['repeats'] = $repeats; - } - - $eventhandler->set_data($event); - - // Now let the eventhandler do all the hard work. - if(!$eventhandler->validate_event()) - { - $event_errors = $eventhandler->get_friendly_errors(); - $event_errors = inline_error($event_errors); - $mybb->input['action'] = "addevent"; - } - else - { - $details = $eventhandler->insert_event(); - $plugins->run_hooks("calendar_do_addevent_end"); - if($details['visible'] == 1) - { - redirect(get_event_link($details['eid']), $lang->redirect_eventadded); - } - else - { - redirect(get_calendar_link($event['cid']), $lang->redirect_eventadded_moderation); - } - } -} - -if($mybb->input['action'] == "addevent") -{ - $query = $db->simple_select("calendars", "*", "cid='".$mybb->input['calendar']."'"); - $calendar = $db->fetch_array($query); - - // Invalid calendar? - if(!$calendar['cid']) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar or post events? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - if($calendar_permissions['canviewcalendar'] != 1 || $calendar_permissions['canaddevents'] != 1) - { - error_no_permission(); - } - - add_breadcrumb(htmlspecialchars_uni($calendar['name']), get_calendar_link($calendar['cid'])); - add_breadcrumb($lang->nav_addevent); - - $plugins->run_hooks("calendar_addevent_start"); - - // If MyCode is on for this forum and the MyCode editor is enabled inthe Admin CP, draw the code buttons and smilie inserter. - if($mybb->settings['bbcodeinserter'] != 0 && (!$mybb->user['uid'] || $mybb->user['showcodebuttons'] != 0) && $calendar['allowmycode'] == 1) - { - $codebuttons = build_mycode_inserter("message", $calendar['allowsmilies']); - if($calendar['allowsmilies'] == 1) - { - $smilieinserter = build_clickable_smilies(); - } - } - - // Previous selections - $name = $description = ''; - if(isset($mybb->input['name'])) - { - $name = htmlspecialchars_uni($mybb->get_input('name')); - } - - if(isset($mybb->input['description'])) - { - $description = htmlspecialchars_uni($mybb->get_input('description')); - } - - $single_month = $start_month = $end_month = $repeats_sel = $repeats_3_days = $repeats_4_occurance = $repeats_4_weekday = $repeats_5_month = $repeats_5_occurance = $repeats_5_weekday = $repeats_5_month2 = array(); - foreach(range(1, 12) as $number) - { - $single_month[$number] = $start_month[$number] = $end_month[$number] = $repeats_5_month[$number] = $repeats_5_month2[$number] = ''; - } - foreach(range(1, 5) as $number) - { - $repeats_sel[$number] = ''; - } - foreach(range(0, 6) as $number) - { - $repeats_3_days[$number] = $repeats_4_weekday[$number] = $repeats_5_weekday[$number] = ''; - } - foreach(range(1, 4) as $number) - { - $repeats_4_occurance[$number] = $repeats_5_occurance[$number] = ''; - } - $repeats_4_occurance['last'] = $repeats_5_occurance['last'] = ''; - $repeats_4_type = array(1 => '', 2 => ''); - $repeats_5_type = array(1 => '', 2 => ''); - - if($mybb->request_method == "post") - { - $single_day = $mybb->get_input('single_day', MyBB::INPUT_INT); - $single_month[$mybb->get_input('single_month', MyBB::INPUT_INT)] = " selected=\"selected\""; - $single_year = $mybb->get_input('single_year', MyBB::INPUT_INT); - $start_day = $mybb->get_input('start_day', MyBB::INPUT_INT); - $start_month[$mybb->get_input('start_month', MyBB::INPUT_INT)] = " selected=\"selected\""; - $start_year = $mybb->get_input('start_year', MyBB::INPUT_INT); - $start_time = htmlspecialchars_uni($mybb->get_input('start_time')); - $end_day = $mybb->get_input('end_day', MyBB::INPUT_INT); - $end_month[$mybb->get_input('end_month', MyBB::INPUT_INT)] = " selected=\"selected\""; - $end_year = $mybb->get_input('end_year', MyBB::INPUT_INT); - $end_time = htmlspecialchars_uni($mybb->get_input('end_time')); - if($mybb->get_input('type') == "single") - { - $type_single = "checked=\"checked\""; - $type_ranged = ''; - $type = "single"; - } - else - { - $type_ranged = "checked=\"checked\""; - $type_single = ''; - $type = "ranged"; - } - if(!empty($mybb->input['repeats'])) - { - $repeats_sel[$mybb->get_input('repeats', MyBB::INPUT_INT)] = " selected=\"selected\""; - } - $repeats_1_days = $mybb->get_input('repeats_1_days', MyBB::INPUT_INT); - $repeats_3_weeks = $mybb->get_input('repeats_3_weeks', MyBB::INPUT_INT); - foreach($mybb->get_input('repeats_3_days', MyBB::INPUT_ARRAY) as $day => $val) - { - if($val != 1) - { - continue; - } - $day = (int)$day; - $repeats_3_days[$day] = " checked=\"checked\""; - } - $repeats_4_type = array(); - if($mybb->get_input('repeats_4_type', MyBB::INPUT_INT) == 1) - { - $repeats_4_type[1] = "checked=\"checked\""; - $repeats_4_type[2] = ''; - } - else - { - $repeats_4_type[2] = "checked=\"checked\""; - $repeats_4_type[1] = ''; - } - $repeats_4_day = $mybb->get_input('repeats_4_day', MyBB::INPUT_INT); - $repeats_4_months = $mybb->get_input('repeats_4_months', MyBB::INPUT_INT); - $repeats_4_occurance[$mybb->get_input('repeats_4_occurance')] = "selected=\"selected\""; - $repeats_4_weekday[$mybb->get_input('repeats_4_weekday', MyBB::INPUT_INT)] = "selected=\"selected\""; - $repeats_4_months2 = $mybb->get_input('repeats_4_months2', MyBB::INPUT_INT); - if($mybb->get_input('repeats_5_type', MyBB::INPUT_INT) == 1) - { - $repeats_5_type[1] = "checked=\"checked\""; - } - else - { - $repeats_5_type[2] = "checked=\"checked\""; - } - $repeats_5_day = $mybb->get_input('repeats_5_day', MyBB::INPUT_INT); - $repeats_5_month[$mybb->get_input('repeats_5_month', MyBB::INPUT_INT)] = "selected=\"selected\""; - $repeats_5_years = $mybb->get_input('repeats_5_years', MyBB::INPUT_INT); - $repeats_5_occurance[$mybb->get_input('repeats_5_occurance')] = "selected=\"selected\""; - $repeats_5_weekday[$mybb->get_input('repeats_5_weekday', MyBB::INPUT_INT)] = "selected=\"selected\""; - $repeats_5_month2[$mybb->get_input('repeats_5_month2', MyBB::INPUT_INT)] = "selected=\"selected\""; - $repeats_5_years2 = $mybb->get_input('repeats_5_years2', MyBB::INPUT_INT); - - $timezone = $mybb->get_input('timezone', MyBB::INPUT_INT); - } - else - { - if(!empty($mybb->input['day'])) - { - $single_day = $start_day = $end_day = $mybb->get_input('day', MyBB::INPUT_INT); - } - else - { - $single_day = $start_day = $end_day = my_date("j"); - } - if(!empty($mybb->input['month'])) - { - $month = $mybb->get_input('month', MyBB::INPUT_INT); - } - else - { - $month = my_date("n"); - } - $single_month[$month] = $start_month[$month] = $end_month[$month] = "selected=\"selected\""; - if(!empty($mybb->input['year'])) - { - $single_year = $start_year = $end_year = $mybb->get_input('year', MyBB::INPUT_INT); - } - else - { - $single_year = $start_year = $end_year = my_date("Y"); - } - $start_time = $end_time = ""; - $type_single = "checked=\"checked\""; - $type_ranged = ''; - $type = "single"; - $repeats_1_days = 1; - $repeats_3_weeks = 1; - $repeats_4_type[1] = "checked=\"checked\""; - $repeats_4_day = 1; - $repeats_4_months = 1; - $repeats_4_occurance[1] = "selected=\"selected\""; - $repeats_4_weekday[0] = "selected=\"selected\""; - $repeats_4_months2 = 1; - $repeats_5_type[1] = "checked=\"checked\""; - $repeats_5_day = 1; - $repeats_5_month[1] = "selected=\"selected\""; - $repeats_5_years = 1; - $repeats_5_occurance[1] = "selected=\"selected\""; - $repeats_5_weekday[0] = "selected=\"selected\""; - $repeats_5_month2[1] = "selected=\"selected\""; - $repeats_5_years2 = 1; - $timezone = $mybb->user['timezone']; - } - - $single_years = $start_years = $end_years = ''; - - // Construct option list for years - for($year = my_date('Y'); $year < (my_date('Y') + 5); ++$year) - { - if($year == $single_year) - { - $selected = "selected=\"selected\""; - eval("\$single_years .= \"".$templates->get("calendar_year")."\";"); - } - else - { - $selected = ""; - eval("\$single_years .= \"".$templates->get("calendar_year")."\";"); - } - - if($year == $start_year) - { - $selected = "selected=\"selected\""; - eval("\$start_years .= \"".$templates->get("calendar_year")."\";"); - } - else - { - $selected = ""; - eval("\$start_years .= \"".$templates->get("calendar_year")."\";"); - } - - if($year == $end_year) - { - $selected = "selected=\"selected\""; - eval("\$end_years .= \"".$templates->get("calendar_year")."\";"); - } - else - { - $selected = ""; - eval("\$end_years .= \"".$templates->get("calendar_year")."\";"); - } - } - - $single_days = $start_days = $end_days = ''; - - // Construct option list for days - for($day = 1; $day <= 31; ++$day) - { - if($day == $single_day) - { - $selected = "selected=\"selected\""; - eval("\$single_days .= \"".$templates->get("calendar_day")."\";"); - } - else - { - $selected = ""; - eval("\$single_days .= \"".$templates->get("calendar_day")."\";"); - } - - if($day == $start_day) - { - $selected = "selected=\"selected\""; - eval("\$start_days .= \"".$templates->get("calendar_day")."\";"); - } - else - { - $selected = ""; - eval("\$start_days .= \"".$templates->get("calendar_day")."\";"); - } - - if($day == $end_day) - { - $selected = "selected=\"selected\""; - eval("\$end_days .= \"".$templates->get("calendar_day")."\";"); - } - else - { - $selected = ""; - eval("\$end_days .= \"".$templates->get("calendar_day")."\";"); - } - } - - $timezones = build_timezone_select("timezone", $timezone); - - if($mybb->get_input('ignoretimezone', MyBB::INPUT_INT) == 1) - { - $ignore_timezone = "checked=\"checked\""; - } - else - { - $ignore_timezone = ''; - } - - if($mybb->get_input('private', MyBB::INPUT_INT) == 1) - { - $privatecheck = " checked=\"checked\""; - } - else - { - $privatecheck = ''; - } - - $select_calendar = $calendar_select = ''; - $calendarcount = 0; - - // Build calendar select - $calendar_permissions = get_calendar_permissions(); - $query = $db->simple_select("calendars", "*", "", array("order_by" => "name", "order_dir" => "asc")); - while($calendar_option = $db->fetch_array($query)) - { - if($calendar_permissions[$calendar['cid']]['canviewcalendar'] == 1) - { - $calendar_option['name'] = htmlspecialchars_uni($calendar_option['name']); - if($calendar_option['cid'] == $mybb->input['calendar']) - { - $selected = " selected=\"selected\""; - } - else - { - $selected = ""; - } - - ++$calendarcount; - eval("\$select_calendar .= \"".$templates->get("calendar_select")."\";"); - } - } - - if($calendarcount > 1) - { - eval("\$calendar_select .= \"".$templates->get("calendar_addevent_calendarselect")."\";"); - } - else - { - eval("\$calendar_select .= \"".$templates->get("calendar_addevent_calendarselect_hidden")."\";"); - } - - if(!isset($event_errors)) - { - $event_errors = ''; - } - - $plugins->run_hooks("calendar_addevent_end"); - - eval("\$addevent = \"".$templates->get("calendar_addevent")."\";"); - output_page($addevent); -} - -// Delete an event -if($mybb->input['action'] == "do_deleteevent" && $mybb->request_method == "post") -{ - $query = $db->simple_select("events", "*", "eid='{$mybb->input['eid']}'"); - $event = $db->fetch_array($query); - - if(!$event) - { - error($lang->error_invalidevent); - } - - $query = $db->simple_select("calendars", "*", "cid='{$event['cid']}'"); - $calendar = $db->fetch_array($query); - - // Invalid calendar? - if(!$calendar) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar or post events? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - if($calendar_permissions['canviewcalendar'] != 1 || $calendar_permissions['canaddevents'] != 1) - { - error_no_permission(); - } - - if(($event['uid'] != $mybb->user['uid'] || $mybb->user['uid'] == 0) && $calendar_permissions['canmoderateevents'] != 1) - { - error_no_permission(); - } - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("calendar_do_deleteevent_start"); - - // Is the checkbox set? - if($mybb->get_input('delete', MyBB::INPUT_INT) == 1) - { - $db->delete_query("events", "eid='{$event['eid']}'"); - $plugins->run_hooks("calendar_do_deleteevent_end"); - - // Redirect back to the main calendar view. - redirect("calendar.php", $lang->redirect_eventdeleted); - } - else - { - error($lang->delete_no_checkbox); - } -} - -// Edit an event -if($mybb->input['action'] == "do_editevent" && $mybb->request_method == "post") -{ - $query = $db->simple_select("events", "*", "eid='{$mybb->input['eid']}'"); - $event = $db->fetch_array($query); - - if(!$event) - { - error($lang->error_invalidevent); - } - - $query = $db->simple_select("calendars", "*", "cid='{$event['cid']}'"); - $calendar = $db->fetch_array($query); - - // Invalid calendar? - if(!$calendar) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar or post events? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - if($calendar_permissions['canviewcalendar'] != 1 || $calendar_permissions['canaddevents'] != 1) - { - error_no_permission(); - } - - if(($event['uid'] != $mybb->user['uid'] || $mybb->user['uid'] == 0) && $calendar_permissions['canmoderateevents'] != 1) - { - error_no_permission(); - } - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("calendar_do_editevent_start"); - - // Set up event handler. - require_once MYBB_ROOT."inc/datahandler.php"; - require_once MYBB_ROOT."inc/datahandlers/event.php"; - $eventhandler = new EventDataHandler("update"); - $mybb->input['type'] = $mybb->get_input('type'); - - // Prepare an array for the eventhandler. - $event = array( - "eid" => $event['eid'], - "name" => $mybb->get_input('name'), - "description" => $mybb->get_input('description'), - "private" => $mybb->get_input('private', MyBB::INPUT_INT), - "type" => $mybb->input['type'] - ); - - // Now we add in our date/time info depending on the type of event - if($mybb->input['type'] == "single") - { - $event['start_date'] = array( - "day" => $mybb->get_input('single_day', MyBB::INPUT_INT), - "month" => $mybb->get_input('single_month', MyBB::INPUT_INT), - "year" => $mybb->get_input('single_year', MyBB::INPUT_INT) - ); - $event['repeats'] = ''; - } - else if($mybb->input['type'] == "ranged") - { - $event['start_date'] = array( - "day" => $mybb->get_input('start_day', MyBB::INPUT_INT), - "month" => $mybb->get_input('start_month', MyBB::INPUT_INT), - "year" => $mybb->get_input('start_year', MyBB::INPUT_INT), - "time" => $mybb->get_input('start_time') - ); - $event['end_date'] = array( - "day" => $mybb->get_input('end_day', MyBB::INPUT_INT), - "month" => $mybb->get_input('end_month', MyBB::INPUT_INT), - "year" => $mybb->get_input('end_year', MyBB::INPUT_INT), - "time" => $mybb->get_input('end_time') - ); - $event['timezone'] = $mybb->get_input('timezone'); - $event['ignoretimezone'] = $mybb->get_input('ignoretimezone', MyBB::INPUT_INT); - $repeats = array(); - switch($mybb->input['repeats']) - { - case 1: - $repeats['repeats'] = 1; - $repeats['days'] = $mybb->get_input('repeats_1_days', MyBB::INPUT_INT); - break; - case 2: - $repeats['repeats'] = 2; - break; - case 3: - $repeats['repeats'] = 3; - $repeats['weeks'] = $mybb->get_input('repeats_3_weeks', MyBB::INPUT_INT); - $mybb->input['repeats_3_days'] = $mybb->get_input('repeats_3_days', MyBB::INPUT_ARRAY); - ksort($mybb->input['repeats_3_days']); - $days = array(); - foreach($mybb->input['repeats_3_days'] as $weekday => $value) - { - if($value != 1) - { - continue; - } - $days[] = $weekday; - } - $repeats['days'] = $days; - break; - case 4: - $repeats['repeats'] = 4; - if($mybb->get_input('repeats_4_type', MyBB::INPUT_INT) == 1) - { - $repeats['day'] = $mybb->get_input('repeats_4_day', MyBB::INPUT_INT); - $repeats['months'] = $mybb->get_input('repeats_4_months', MyBB::INPUT_INT); - } - else - { - $repeats['months'] = $mybb->get_input('repeats_4_months2', MyBB::INPUT_INT); - $repeats['occurance'] = $mybb->get_input('repeats_4_occurance'); - $repeats['weekday'] = $mybb->get_input('repeats_4_weekday', MyBB::INPUT_INT); - } - break; - case 5: - $repeats['repeats'] = 5; - if($mybb->get_input('repeats_5_type', MyBB::INPUT_INT) == 1) - { - $repeats['day'] = $mybb->get_input('repeats_5_day', MyBB::INPUT_INT); - $repeats['month'] = $mybb->get_input('repeats_5_month', MyBB::INPUT_INT); - $repeats['years'] = $mybb->get_input('repeats_5_years', MyBB::INPUT_INT); - } - else - { - $repeats['occurance'] = $mybb->get_input('repeats_5_occurance'); - $repeats['weekday'] = $mybb->get_input('repeats_5_weekday', MyBB::INPUT_INT); - $repeats['month'] = $mybb->get_input('repeats_5_month2', MyBB::INPUT_INT); - $repeats['years'] = $mybb->get_input('repeats_5_years', MyBB::INPUT_INT); - } - break; - default: - $repeats['repeats'] = 0; - } - $event['repeats'] = $repeats; - } - - $eventhandler->set_data($event); - - // Now let the eventhandler do all the hard work. - if(!$eventhandler->validate_event()) - { - $event_errors = $eventhandler->get_friendly_errors(); - $event_errors = inline_error($event_errors); - $mybb->input['action'] = "editevent"; - } - else - { - $details = $eventhandler->update_event(); - $plugins->run_hooks("calendar_do_editevent_end"); - redirect(get_event_link($event['eid']), $lang->redirect_eventupdated); - } -} - -if($mybb->input['action'] == "editevent") -{ - // Event already fetched in do_editevent? - if(!isset($event)) - { - $query = $db->simple_select("events", "*", "eid='{$mybb->input['eid']}'"); - $event = $db->fetch_array($query); - - if(!$event) - { - error($lang->error_invalidevent); - } - - $query = $db->simple_select("calendars", "*", "cid='{$event['cid']}'"); - $calendar = $db->fetch_array($query); - - // Invalid calendar? - if(!$calendar['cid']) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar or post events? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - if($calendar_permissions['canviewcalendar'] != 1 || $calendar_permissions['canaddevents'] != 1) - { - error_no_permission(); - } - - if(($event['uid'] != $mybb->user['uid'] || $mybb->user['uid'] == 0) && $calendar_permissions['canmoderateevents'] != 1) - { - error_no_permission(); - } - } - - $event['name'] = htmlspecialchars_uni($event['name']); - $event['timezone'] = (float)$event['timezone']; - - add_breadcrumb(htmlspecialchars_uni($calendar['name']), get_calendar_link($calendar['cid'])); - add_breadcrumb($event['name'], get_event_link($event['eid'])); - add_breadcrumb($lang->nav_editevent); - - $plugins->run_hooks("calendar_editevent_start"); - - // If MyCode is on for this forum and the MyCode editor is enabled inthe Admin CP, draw the code buttons and smilie inserter. - if($mybb->settings['bbcodeinserter'] != 0 && (!$mybb->user['uid'] || $mybb->user['showcodebuttons'] != 0) && $calendar['allowmycode'] == 1) - { - $codebuttons = build_mycode_inserter("message", $calendar['allowsmilies']); - if($calendar['allowsmilies'] == 1) - { - $smilieinserter = build_clickable_smilies(); - } - } - - $single_month = $start_month = $end_month = $repeats_sel = $repeats_3_days = $repeats_4_occurance = $repeats_4_weekday = $repeats_5_month = $repeats_5_occurance = $repeats_5_weekday = $repeats_5_month2 = array(); - foreach(range(1, 12) as $number) - { - $single_month[$number] = $start_month[$number] = $end_month[$number] = $repeats_5_month[$number] = $repeats_5_month2[$number] = ''; - } - foreach(range(1, 5) as $number) - { - $repeats_sel[$number] = ''; - } - foreach(range(0, 6) as $number) - { - $repeats_3_days[$number] = $repeats_4_weekday[$number] = $repeats_5_weekday[$number] = ''; - } - foreach(range(1, 4) as $number) - { - $repeats_4_occurance[$number] = $repeats_5_occurance[$number] = ''; - } - $repeats_4_occurance['last'] = $repeats_5_occurance['last'] = ''; - $repeats_4_type = array(1 => '', 2 => ''); - $repeats_5_type = array(1 => '', 2 => ''); - - // Previous selections - if(isset($event_errors)) - { - $name = htmlspecialchars_uni($mybb->get_input('name')); - $description = htmlspecialchars_uni($mybb->get_input('description')); - $single_day = $mybb->get_input('single_day', MyBB::INPUT_INT); - $single_month[$mybb->get_input('single_month', MyBB::INPUT_INT)] = " selected=\"selected\""; - $single_year = $mybb->get_input('single_year', MyBB::INPUT_INT); - $start_day = $mybb->get_input('start_day', MyBB::INPUT_INT); - $start_month[$mybb->get_input('start_month', MyBB::INPUT_INT)] = " selected=\"selected\""; - $start_year = $mybb->get_input('start_year', MyBB::INPUT_INT); - $start_time = htmlspecialchars_uni($mybb->get_input('start_time')); - $end_day = $mybb->get_input('end_day', MyBB::INPUT_INT); - $end_month[$mybb->get_input('end_month', MyBB::INPUT_INT)] = " selected=\"selected\""; - $end_year = $mybb->get_input('end_year', MyBB::INPUT_INT); - $end_time = htmlspecialchars_uni($mybb->get_input('end_time')); - if($mybb->get_input('type') == "single") - { - $type_single = "checked=\"checked\""; - $type_ranged = ''; - $type = "single"; - } - else - { - $type_ranged = "checked=\"checked\""; - $type_single = ''; - $type = "ranged"; - } - if(!empty($mybb->input['repeats'])) - { - $repeats_sel[$mybb->get_input('repeats', MyBB::INPUT_INT)] = " selected=\"selected\""; - } - $repeats_1_days = $mybb->get_input('repeats_1_days', MyBB::INPUT_INT); - $repeats_3_weeks = $mybb->get_input('repeats_3_weeks', MyBB::INPUT_INT); - foreach($mybb->get_input('repeats_3_days', MyBB::INPUT_ARRAY) as $day => $val) - { - if($val != 1) - { - continue; - } - $day = (int)$day; - $repeats_3_days[$day] = " checked=\"checked\""; - } - $repeats_4_type = array(); - if($mybb->get_input('repeats_4_type', MyBB::INPUT_INT) == 1) - { - $repeats_4_type[1] = "checked=\"checked\""; - $repeats_4_type[2] = ''; - } - else - { - $repeats_4_type[2] = "checked=\"checked\""; - $repeats_4_type[1] = ''; - } - $repeats_4_day = $mybb->get_input('repeats_4_day', MyBB::INPUT_INT); - $repeats_4_months = $mybb->get_input('repeats_4_months', MyBB::INPUT_INT); - $repeats_4_occurance[$mybb->get_input('repeats_4_occurance')] = "selected=\"selected\""; - $repeats_4_weekday[$mybb->get_input('repeats_4_weekday', MyBB::INPUT_INT)] = "selected=\"selected\""; - $repeats_4_months2 = $mybb->get_input('repeats_4_months2', MyBB::INPUT_INT); - if($mybb->get_input('repeats_5_type', MyBB::INPUT_INT) == 1) - { - $repeats_5_type[1] = "checked=\"checked\""; - } - else - { - $repeats_5_type[2] = "checked=\"checked\""; - } - $repeats_5_day = $mybb->get_input('repeats_5_day', MyBB::INPUT_INT); - $repeats_5_month[$mybb->get_input('repeats_5_month', MyBB::INPUT_INT)] = "selected=\"selected\""; - $repeats_5_years = $mybb->get_input('repeats_5_years', MyBB::INPUT_INT); - $repeats_5_occurance[$mybb->get_input('repeats_5_occurance')] = "selected=\"selected\""; - $repeats_5_weekday[$mybb->get_input('repeats_5_weekday', MyBB::INPUT_INT)] = "selected=\"selected\""; - $repeats_5_month2[$mybb->get_input('repeats_5_month2', MyBB::INPUT_INT)] = "selected=\"selected\""; - $repeats_5_years2 = $mybb->get_input('repeats_5_years2', MyBB::INPUT_INT); - - if($mybb->get_input('private', MyBB::INPUT_INT) == 1) - { - $privatecheck = " checked=\"checked\""; - } - else - { - $privatecheck = ''; - } - - if($mybb->get_input('ignoretimezone', MyBB::INPUT_INT) == 1) - { - $ignore_timezone = "checked=\"checked\""; - } - else - { - $ignore_timezone = ''; - } - - $timezone = $mybb->get_input('timezone'); - } - else - { - $event_errors = ''; - $mybb->input['calendar'] = $event['cid']; - $name = htmlspecialchars_uni($event['name']); - $description = htmlspecialchars_uni($event['description']); - if($event['private'] == 1) - { - $privatecheck = " checked=\"checked\""; - } - else - { - $privatecheck = ''; - } - $start_date = explode("-", gmdate("j-n-Y", $event['starttime']+$event['timezone']*3600)); - $single_day = $start_date[0]; - $single_month[$start_date[1]] = " selected=\"selected\""; - $single_year = $start_date[2]; - $start_day = $start_date[0]; - $start_month[$start_date[1]] = " selected=\"selected\""; - $start_year = $start_date[2]; - if($event['usingtime']) - { - $start_time = gmdate($mybb->settings['timeformat'], $event['starttime']+$event['timezone']*3600); - } - else - { - $start_time = ''; - } - if($event['endtime']) - { - $end_date = explode("-", gmdate("j-n-Y", $event['endtime']+$event['timezone']*3600)); - $end_day = $end_date[0]; - $end_month[$end_date[1]] = " selected=\"selected\""; - $end_year = $end_date[2]; - if($event['usingtime']) - { - $end_time = gmdate($mybb->settings['timeformat'], $event['endtime']+$event['timezone']*3600); - } - else - { - $end_time = ''; - } - $type_ranged = "checked=\"checked\""; - $type_single = ''; - $type = "ranged"; - $repeats = my_unserialize($event['repeats']); - if($repeats['repeats'] >= 0) - { - $repeats_sel[$repeats['repeats']] = " selected=\"selected\""; - switch($repeats['repeats']) - { - case 1: - $repeats_1_days = $repeats['days']; - $repeats_3_weeks = 1; - $repeats_4_type[1] = "checked=\"checked\""; - $repeats_4_day = 1; - $repeats_4_months = 1; - $repeats_4_months2 = 1; - $repeats_5_type[1] = "checked=\"checked\""; - $repeats_5_day = 1; - $repeats_5_years = $repeats_5_years2 = 1; - break; - case 3: - $repeats_1_days = 1; - $repeats_3_weeks = $repeats['weeks']; - if(is_array($repeats['days'])) - { - foreach($repeats['days'] as $weekday) - { - $repeats_3_days[$weekday] = " checked=\"checked\""; - } - } - $repeats_4_type[1] = "checked=\"checked\""; - $repeats_4_day = 1; - $repeats_4_months = 1; - $repeats_4_months2 = 1; - $repeats_5_type[1] = "checked=\"checked\""; - $repeats_5_day = 1; - $repeats_5_years = $repeats_5_years2 = 1; - break; - case 4: - $repeats_1_days = 1; - $repeats_3_weeks = 1; - if($repeats['day']) - { - $repeats_4_type[1] = "checked=\"checked\""; - $repeats_4_day = $repeats['day']; - $repeats_4_months = $repeats_4_months2 = $repeats['months']; - } - else - { - $repeats_4_type[2] = "checked=\"checked\""; - $repeats_4_day = 1; - $repeats_4_months2 = $repeats_4_months = $repeats['months']; - $repeats_4_occurance[$repeats['occurance']] = "selected=\"selected\""; - $repeats_4_weekday[$repeats['weekday']] = "selected=\"selected\""; - } - $repeats_5_type[1] = "checked=\"checked\""; - $repeats_5_day = 1; - $repeats_5_years = $repeats_5_years2 = 1; - break; - case 5: - $repeats_1_days = 1; - $repeats_3_weeks = 1; - $repeats_4_type[1] = "checked=\"checked\""; - $repeats_4_day = 1; - $repeats_4_months = 1; - $repeats_4_months2 = 1; - if($repeats['day']) - { - $repeats_5_type[1] = "checked=\"checked\""; - $repeats_5_day = $repeats['day']; - $repeats_5_month[$repeats['month']] = $repeats_5_month2[$repeats['month']] = "selected=\"selected\""; - $repeats_5_years = $repeats_5_years2 = $repeats['years']; - } - else - { - $repeats_5_type[2] = "checked=\"checked\""; - $repeats_5_occurance[$repeats['occurance']] = "selected=\"selected\""; - $repeats_5_weekday[$repeats['weekday']] = "selected=\"selected\""; - $repeats_5_month[$repeats['month']] = $repeats_5_month2[$repeats['month']] = "selected=\"selected\""; - $repeats_5_years = $repeats_5_years2 = $repeats['years']; - } - break; - } - } - if($event['ignoretimezone']) - { - $timezone = 0; - $ignore_timezone = "checked=\"checked\""; - } - else - { - $timezone = $event['timezone']; - $ignore_timezone = ''; - } - } - else - { - $type_single = "checked=\"checked\""; - $type_ranged = $ignore_timezone = $repeats_1_days = $repeats_3_weeks = $repeats_4_day = $repeats_4_months = $repeats_4_months2 = $repeats_5_day = $repeats_5_years = $timezone = $end_time = ''; - $type = "single"; - // set some defaults if the user wants to make a ranged event - $end_day = $start_day; - $end_month = $start_month; - $end_year = $start_year; - } - } - - $single_years = $start_years = $end_years = ''; - - // Construct option list for years - for($year = my_date('Y'); $year < (my_date('Y') + 5); ++$year) - { - if($year == $single_year) - { - $selected = "selected=\"selected\""; - eval("\$single_years .= \"".$templates->get("calendar_year")."\";"); - } - else - { - $selected = ""; - eval("\$single_years .= \"".$templates->get("calendar_year")."\";"); - } - - if($year == $start_year) - { - $selected = "selected=\"selected\""; - eval("\$start_years .= \"".$templates->get("calendar_year")."\";"); - } - else - { - $selected = ""; - eval("\$start_years .= \"".$templates->get("calendar_year")."\";"); - } - - if($year == $end_year) - { - $selected = "selected=\"selected\""; - eval("\$end_years .= \"".$templates->get("calendar_year")."\";"); - } - else - { - $selected = ""; - eval("\$end_years .= \"".$templates->get("calendar_year")."\";"); - } - } - - $single_days = $start_days = $end_days = ''; - - // Construct option list for days - for($day = 1; $day <= 31; ++$day) - { - if($day == $single_day) - { - $selected = "selected=\"selected\""; - eval("\$single_days .= \"".$templates->get("calendar_day")."\";"); - } - else - { - $selected = ""; - eval("\$single_days .= \"".$templates->get("calendar_day")."\";"); - } - - if($day == $start_day) - { - $selected = "selected=\"selected\""; - eval("\$start_days .= \"".$templates->get("calendar_day")."\";"); - } - else - { - $selected = ""; - eval("\$start_days .= \"".$templates->get("calendar_day")."\";"); - } - - if($day == $end_day) - { - $selected = "selected=\"selected\""; - eval("\$end_days .= \"".$templates->get("calendar_day")."\";"); - } - else - { - $selected = ""; - eval("\$end_days .= \"".$templates->get("calendar_day")."\";"); - } - } - - $timezones = build_timezone_select("timezone", $timezone); - - $plugins->run_hooks("calendar_editevent_end"); - - eval("\$editevent = \"".$templates->get("calendar_editevent")."\";"); - output_page($editevent); -} - -// Move an event to another calendar -if($mybb->input['action'] == "move") -{ - $query = $db->simple_select("events", "*", "eid='{$mybb->input['eid']}'"); - $event = $db->fetch_array($query); - - if(!$event) - { - error($lang->error_invalidevent); - } - - $query = $db->simple_select("calendars", "*", "cid='{$event['cid']}'"); - $calendar = $db->fetch_array($query); - - // Invalid calendar? - if(!$calendar) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar or post events? - $calendar_permissions = get_calendar_permissions(); - if($calendar_permissions[$calendar['cid']]['canviewcalendar'] != 1) - { - error_no_permission(); - } - - if($calendar_permissions[$calendar['cid']]['canmoderateevents'] != 1) - { - error_no_permission(); - } - - $event['name'] = htmlspecialchars_uni($event['name']); - - add_breadcrumb(htmlspecialchars_uni($calendar['name']), get_calendar_link($calendar['cid'])); - add_breadcrumb($event['name'], get_event_link($event['eid'])); - add_breadcrumb($lang->nav_move_event); - - $plugins->run_hooks("calendar_move_start"); - - $calendar_select = $selected = ''; - - // Build calendar select - $query = $db->simple_select("calendars", "*", "", array("order_by" => "name", "order_dir" => "asc")); - while($calendar_option = $db->fetch_array($query)) - { - if($calendar_permissions[$calendar['cid']]['canviewcalendar'] == 1) - { - $calendar_option['name'] = htmlspecialchars_uni($calendar_option['name']); - eval("\$calendar_select .= \"".$templates->get("calendar_select")."\";"); - } - } - - $plugins->run_hooks("calendar_move_end"); - - eval("\$moveevent = \"".$templates->get("calendar_move")."\";"); - output_page($moveevent); -} - -// Actually move the event -if($mybb->input['action'] == "do_move" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $query = $db->simple_select("events", "*", "eid='{$mybb->input['eid']}'"); - $event = $db->fetch_array($query); - - if(!$event) - { - error($lang->error_invalidevent); - } - - $query = $db->simple_select("calendars", "*", "cid='{$event['cid']}'"); - $calendar = $db->fetch_array($query); - - // Invalid calendar? - if(!$calendar) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar? - $calendar_permissions = get_calendar_permissions(); - if($calendar_permissions[$calendar['cid']]['canviewcalendar'] != 1) - { - error_no_permission(); - } - - if($calendar_permissions[$calendar['cid']]['canmoderateevents'] != 1) - { - error_no_permission(); - } - - $query = $db->simple_select("calendars", "*", "cid='".$mybb->get_input('new_calendar', MyBB::INPUT_INT)."'"); - $new_calendar = $db->fetch_array($query); - - if(!$new_calendar) - { - error($lang->invalid_calendar); - } - - if($calendar_permissions[$mybb->input['new_calendar']]['canviewcalendar'] != 1) - { - error_no_permission(); - } - - $updated_event = array( - "cid" => $new_calendar['cid'] - ); - - $plugins->run_hooks("calendar_do_move_start"); - - $db->update_query("events", $updated_event, "eid='{$event['eid']}'"); - - $plugins->run_hooks("calendar_do_move_end"); - - redirect(get_event_link($event['eid']), $lang->redirect_eventmoved); -} - -// Approve an event -if($mybb->input['action'] == "approve") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $query = $db->simple_select("events", "*", "eid='{$mybb->input['eid']}'"); - $event = $db->fetch_array($query); - - if(!$event) - { - error($lang->error_invalidevent); - } - - $query = $db->simple_select("calendars", "*", "cid='{$event['cid']}'"); - $calendar = $db->fetch_array($query); - - // Invalid calendar? - if(!$calendar) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - if($calendar_permissions['canviewcalendar'] != 1) - { - error_no_permission(); - } - - if($calendar_permissions['canmoderateevents'] != 1) - { - error_no_permission(); - } - - $updated_event = array( - "visible" => 1 - ); - - $plugins->run_hooks("calendar_approve_start"); - - $db->update_query("events", $updated_event, "eid='{$event['eid']}'"); - - $plugins->run_hooks("calendar_approve_end"); - - redirect(get_event_link($event['eid']), $lang->redirect_eventapproved); -} - -// Unapprove an event -if($mybb->input['action'] == "unapprove") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $query = $db->simple_select("events", "*", "eid='{$mybb->input['eid']}'"); - $event = $db->fetch_array($query); - - if(!$event) - { - error($lang->error_invalidevent); - } - - $query = $db->simple_select("calendars", "*", "cid='{$event['cid']}'"); - $calendar = $db->fetch_array($query); - - // Invalid calendar? - if(!$calendar) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - if($calendar_permissions['canviewcalendar'] != 1) - { - error_no_permission(); - } - - if($calendar_permissions['canmoderateevents'] != 1) - { - error_no_permission(); - } - - $updated_event = array( - "visible" => 0 - ); - - $plugins->run_hooks("calendar_unapprove_start"); - - $db->update_query("events", $updated_event, "eid='{$event['eid']}'"); - - $plugins->run_hooks("calendar_unapprove_end"); - - redirect(get_event_link($event['eid']), $lang->redirect_eventunapproved); -} - -// Showing specific event -if($mybb->input['action'] == "event") -{ - $query = $db->query(" - SELECT u.*, e.* - FROM ".TABLE_PREFIX."events e - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=e.uid) - WHERE e.eid='{$mybb->input['eid']}' - "); - $event = $db->fetch_array($query); - - if(!$event || ($event['private'] == 1 && $event['uid'] != $mybb->user['uid'])) - { - error($lang->error_invalidevent); - } - - $query = $db->simple_select("calendars", "*", "cid='{$event['cid']}'"); - $calendar = $db->fetch_array($query); - - // Invalid calendar? - if(!$calendar) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - if($calendar_permissions['canviewcalendar'] != 1 || ($calendar_permissions['canmoderateevents'] != 1 && $event['visible'] == 0)) - { - error_no_permission(); - } - - $event['name'] = htmlspecialchars_uni($event['name']); - - add_breadcrumb(htmlspecialchars_uni($calendar['name']), get_calendar_link($calendar['cid'])); - add_breadcrumb($event['name'], get_event_link($event['eid'])); - - $plugins->run_hooks("calendar_event_start"); - - $event_parser_options = array( - "allow_html" => $calendar['allowhtml'], - "allow_mycode" => $calendar['allowmycode'], - "allow_smilies" => $calendar['allowsmilies'], - "allow_imgcode" => $calendar['allowimgcode'], - "allow_videocode" => $calendar['allowvideocode'] - ); - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $event_parser_options['allow_imgcode'] = 0; - } - - if($mybb->user['showvideos'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestvideos'] != 1 && $mybb->user['uid'] == 0) - { - $event_parser_options['allow_videocode'] = 0; - } - - $event['description'] = $parser->parse_message($event['description'], $event_parser_options); - - // Get the usergroup - if($event['username']) - { - if(!$event['displaygroup']) - { - $event['displaygroup'] = $event['usergroup']; - } - $user_usergroup = $groupscache[$event['displaygroup']]; - } - else - { - $user_usergroup = $groupscache[1]; - } - - $titles_cache = $cache->read("usertitles"); - - // Event made by registered user - if($event['uid'] > 0 && $event['username']) - { - $event['username'] = htmlspecialchars_uni($event['username']); - $event['profilelink'] = build_profile_link(format_name($event['username'], $event['usergroup'], $event['displaygroup']), $event['uid']); - - if(trim($event['usertitle']) != "") - { - // Do nothing, no need for an extra variable.. - } - elseif($user_usergroup['usertitle'] != "") - { - $event['usertitle'] = $user_usergroup['usertitle']; - } - elseif(is_array($titles_cache) && !$user_usergroup['usertitle']) - { - reset($titles_cache); - foreach($titles_cache as $title) - { - if($event['postnum'] >= $title['posts']) - { - $event['usertitle'] = $title['title']; - $event['stars'] = $title['stars']; - $event['starimage'] = $title['starimage']; - break; - } - } - } - - if($user_usergroup['stars']) - { - $event['stars'] = $user_usergroup['stars']; - } - - if(empty($event['starimage'])) - { - $event['starimage'] = $user_usergroup['starimage']; - } - $event['starimage'] = str_replace("{theme}", $theme['imgdir'], $event['starimage']); - - $event['userstars'] = ''; - for($i = 0; $i < $event['stars']; ++$i) - { - eval("\$event['userstars'] .= \"".$templates->get("calendar_event_userstar", 1, 0)."\";"); - } - - if($event['userstars'] && $event['starimage'] && $event['stars']) - { - $event['userstars'] .= "
    "; - } - } - // Created by a guest or an unknown user - else - { - if(!$event['username']) - { - $event['username'] = $lang->guest; - } - - $event['username'] = htmlspecialchars_uni($event['username']); - $event['profilelink'] = format_name($event['username'], 1); - - if($user_usergroup['usertitle']) - { - $event['usertitle'] = $user_usergroup['usertitle']; - } - else - { - $event['usertitle'] = $lang->guest; - } - $event['userstars'] = ''; - } - - $event['usertitle'] = htmlspecialchars_uni($event['usertitle']); - - if($event['ignoretimezone'] == 0) - { - $offset = (float)$event['timezone']; - } - else - { - $offset = (float)$mybb->user['timezone']; - } - - $event['starttime_user'] = $event['starttime']+$offset*3600; - - // Events over more than one day - $time_period = ''; - if($event['endtime'] > 0 && $event['endtime'] != $event['starttime']) - { - $event['endtime_user'] = $event['endtime']+$offset*3600; - $start_day = adodb_gmmktime(0, 0, 0, gmdate("n", $event['starttime_user']), gmdate("j", $event['starttime_user']), gmdate("Y", $event['starttime_user'])); - $end_day = adodb_gmmktime(0, 0, 0, gmdate("n", $event['endtime_user']), gmdate("j", $event['endtime_user']), gmdate("Y", $event['endtime_user'])); - $start_time = gmdate("Hi", $event['starttime_user']); - $end_time = gmdate("Hi", $event['endtime_user']); - - $event['repeats'] = my_unserialize($event['repeats']); - - // Event only runs over one day - if($start_day == $end_day && $event['repeats']['repeats'] == 0) - { - $time_period = gmdate($mybb->settings['dateformat'], $event['starttime_user']); - // Event runs all day - if($start_time != 0000 && $end_time != 2359) - { - $time_period .= $lang->comma.gmdate($mybb->settings['timeformat'], $event['starttime_user'])." - ".gmdate($mybb->settings['timeformat'], $event['endtime_user']); - } - else - { - $time_period .= $lang->comma.$lang->all_day; - } - } - else - { - $time_period = gmdate($mybb->settings['dateformat'], $event['starttime_user']).", ".gmdate($mybb->settings['timeformat'], $event['starttime_user']); - $time_period .= " - "; - $time_period .= gmdate($mybb->settings['dateformat'], $event['endtime_user']).", ".gmdate($mybb->settings['timeformat'], $event['endtime_user']); - } - } - else - { - $time_period = gmdate($mybb->settings['dateformat'], $event['starttime_user']); - } - - $repeats = fetch_friendly_repetition($event); - if($repeats) - { - eval("\$repeats = \"".$templates->get("calendar_repeats")."\";"); - } - - $event_class = ''; - if($calendar_permissions['canmoderateevents'] == 1 || ($mybb->user['uid'] > 0 && $mybb->user['uid'] == $event['uid'])) - { - eval("\$edit_event = \"".$templates->get("calendar_event_editbutton")."\";"); - if($calendar_permissions['canmoderateevents'] == 1) - { - if($event['visible'] == 1) - { - $approve = $lang->unapprove_event; - $approve_value = "unapprove"; - } - else - { - $approve = $lang->approve_event; - $approve_value = "approve"; - } - eval("\$moderator_options = \"".$templates->get("calendar_event_modoptions")."\";"); - } - - if($event['visible'] == 0) - { - $event_class = " trow_shaded"; - } - } - - $month = my_date("n"); - - $yearsel = ''; - for($year_sel = my_date("Y"); $year_sel < (my_date("Y") + 5); ++$year_sel) - { - eval("\$yearsel .= \"".$templates->get("calendar_year_sel")."\";"); - } - - $addevent = ''; - if($mybb->usergroup['canaddevents'] == 1) - { - eval("\$addevent = \"".$templates->get("calendar_addeventlink")."\";"); - } - - // Now output the page - $plugins->run_hooks("calendar_event_end"); - eval("\$event = \"".$templates->get("calendar_event")."\";"); - output_page($event); -} - -// View all events on a specific day. -if($mybb->input['action'] == "dayview") -{ - // Showing a particular calendar - if($mybb->input['calendar']) - { - $query = $db->simple_select("calendars", "*", "cid='{$mybb->input['calendar']}'"); - $calendar = $db->fetch_array($query); - } - // Showing the default calendar - else - { - $query = $db->simple_select("calendars", "*", "disporder='1'"); - $calendar = $db->fetch_array($query); - } - - // Invalid calendar? - if(!$calendar) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - if($calendar_permissions['canviewcalendar'] != 1) - { - error_no_permission(); - } - - // Incoming year? - if(isset($mybb->input['year']) && $mybb->get_input('year', MyBB::INPUT_INT) <= my_date("Y")+5) - { - $year = $mybb->get_input('year', MyBB::INPUT_INT); - } - else - { - $year = my_date("Y"); - } - - // Then the month - $mybb->input['month'] = $mybb->get_input('month', MyBB::INPUT_INT); - if($mybb->input['month'] >= 1 && $mybb->input['month'] <= 12) - { - $month = $mybb->input['month']; - } - else - { - $month = my_date("n"); - } - - // And day? - $mybb->input['day'] = $mybb->get_input('day', MyBB::INPUT_INT); - if($mybb->input['day'] && $mybb->input['day'] <= gmdate("t", adodb_gmmktime(0, 0, 0, $month, 1, $year))) - { - $day = $mybb->input['day']; - } - else - { - $day = my_date("j"); - } - - add_breadcrumb(htmlspecialchars_uni($calendar['name']), get_calendar_link($calendar['cid'])); - add_breadcrumb("$day $monthnames[$month] $year", get_calendar_link($calendar['cid'], $year, $month, $day)); - - $plugins->run_hooks("calendar_dayview_start"); - - // Load Birthdays for this day - $birthday_list = $birthdays = ''; - if($calendar['showbirthdays']) - { - $birthdays2 = get_birthdays($month, $day); - $bdayhidden = 0; - if(is_array($birthdays2)) - { - foreach($birthdays2 as $birthday) - { - if($birthday['birthdayprivacy'] == 'all') - { - $bday = explode("-", $birthday['birthday']); - if($bday[2] && $bday[2] < $year) - { - $age = $year - $bday[2]; - $age = " (".$lang->sprintf($lang->years_old, $age).")"; - } - else - { - $age = ''; - } - - $birthday['username'] = format_name(htmlspecialchars_uni($birthday['username']), $birthday['usergroup'], $birthday['displaygroup']); - $birthday['profilelink'] = build_profile_link($birthday['username'], $birthday['uid']); - eval("\$birthday_list .= \"".$templates->get("calendar_dayview_birthdays_bday", 1, 0)."\";"); - $comma = $lang->comma; - } - else - { - ++$bdayhidden; - } - } - } - if($bdayhidden > 0) - { - if($birthday_list) - { - $birthday_list .= " - "; - } - $birthday_list .= "{$bdayhidden} {$lang->birthdayhidden}"; - } - if($birthday_list) - { - $bdaydate = my_date($mybb->settings['dateformat'], adodb_gmmktime(0, 0, 0, $month, $day, $year), 0, 0); - $lang->birthdays_on_day = $lang->sprintf($lang->birthdays_on_day, $bdaydate); - eval("\$birthdays = \"".$templates->get("calendar_dayview_birthdays", 1, 0)."\";"); - } - } - - // So now we fetch events for this month - $start_timestamp = adodb_gmmktime(0, 0, 0, $month, $day, $year); - $end_timestamp = adodb_gmmktime(23, 59, 59, $month, $day, $year); - - $events_cache = get_events($calendar, $start_timestamp, $end_timestamp, $calendar_permissions['canmoderateevents']); - - $events = ''; - if(isset($events_cache["$day-$month-$year"]) && is_array($events_cache["$day-$month-$year"])) - { - foreach($events_cache["$day-$month-$year"] as $event) - { - $event['name'] = htmlspecialchars_uni($event['name']); - - $event_parser_options = array( - "allow_html" => $calendar['allowhtml'], - "allow_mycode" => $calendar['allowmycode'], - "allow_smilies" => $calendar['allowsmilies'], - "allow_imgcode" => $calendar['allowimgcode'], - "allow_videocode" => $calendar['allowvideocode'] - ); - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $event_parser_options['allow_imgcode'] = 0; - } - - if($mybb->user['showvideos'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestvideos'] != 1 && $mybb->user['uid'] == 0) - { - $event_parser_options['allow_videocode'] = 0; - } - - $event['description'] = $parser->parse_message($event['description'], $event_parser_options); - - // Get the usergroup - if($event['username']) - { - if(!$event['displaygroup']) - { - $event['displaygroup'] = $event['usergroup']; - } - $user_usergroup = $groupscache[$event['displaygroup']]; - } - else - { - $user_usergroup = $groupscache[1]; - } - - $titles_cache = $cache->read("usertitles"); - - // Event made by registered user - if($event['uid'] > 0 && $event['username']) - { - $event['username'] = htmlspecialchars_uni($event['username']); - $event['profilelink'] = build_profile_link(format_name($event['username'], $event['usergroup'], $event['displaygroup']), $event['uid']); - - if(trim($event['usertitle']) != "") - { - // Do nothing, no need for an extra variable.. - } - elseif($user_usergroup['usertitle'] != "") - { - $event['usertitle'] = $user_usergroup['usertitle']; - } - elseif(is_array($titles_cache) && !$user_usergroup['usertitle']) - { - reset($titles_cache); - foreach($titles_cache as $title) - { - if($event['postnum'] >= $title['posts']) - { - $event['usertitle'] = $title['title']; - $event['stars'] = $title['stars']; - $event['starimage'] = $title['starimage']; - break; - } - } - } - - if($user_usergroup['stars']) - { - $event['stars'] = $user_usergroup['stars']; - } - - if(empty($event['starimage'])) - { - $event['starimage'] = $user_usergroup['starimage']; - } - - $event['userstars'] = ''; - for($i = 0; $i < $event['stars']; ++$i) - { - eval("\$event['userstars'] .= \"".$templates->get("calendar_event_userstar", 1, 0)."\";"); - } - - if($event['userstars'] && $event['starimage'] && $event['stars']) - { - $event['userstars'] .= "
    "; - } - } - // Created by a guest or an unknown user - else - { - if(!$event['username']) - { - $event['username'] = $lang->guest; - } - - $event['username'] = htmlspecialchars_uni($event['username']); - $event['profilelink'] = format_name($event['username'], 1); - - if($user_usergroup['usertitle']) - { - $event['usertitle'] = $user_usergroup['usertitle']; - } - else - { - $event['usertitle'] = $lang->guest; - } - $event['userstars'] = ''; - } - - $event['usertitle'] = htmlspecialchars_uni($event['usertitle']); - - if($event['ignoretimezone'] == 0) - { - $offset = (float)$event['timezone']; - } - else - { - $offset = (float)$mybb->user['timezone']; - } - - $event['starttime_user'] = $event['starttime']+$offset*3600; - - // Events over more than one day - $time_period = ''; - if($event['endtime'] > 0 && $event['endtime'] != $event['starttime']) - { - $event['endtime_user'] = $event['endtime']+$offset*3600; - $start_day = adodb_gmmktime(0, 0, 0, gmdate("n", $event['starttime_user']), gmdate("j", $event['starttime_user']), gmdate("Y", $event['starttime_user'])); - $end_day = adodb_gmmktime(0, 0, 0, gmdate("n", $event['endtime_user']), gmdate("j", $event['endtime_user']), gmdate("Y", $event['endtime_user'])); - $start_time = gmdate("Hi", $event['starttime_user']); - $end_time = gmdate("Hi", $event['endtime_user']); - - // Event only runs over one day - if($start_day == $end_day && $event['repeats']['repeats'] == 0) - { - $time_period = gmdate($mybb->settings['dateformat'], $event['starttime_user']); - // Event runs all day - if($start_time != 0000 && $end_time != 2359) - { - $time_period .= $lang->comma.gmdate($mybb->settings['timeformat'], $event['starttime_user'])." - ".gmdate($mybb->settings['timeformat'], $event['endtime_user']); - } - else - { - $time_period .= $lang->comma.$lang->all_day; - } - } - else - { - $time_period = gmdate($mybb->settings['dateformat'], $event['starttime_user']).", ".gmdate($mybb->settings['timeformat'], $event['starttime_user']); - $time_period .= " - "; - $time_period .= gmdate($mybb->settings['dateformat'], $event['endtime_user']).", ".gmdate($mybb->settings['timeformat'], $event['endtime_user']); - } - } - else - { - $time_period = gmdate($mybb->settings['dateformat'], $event['starttime_user']); - } - - $repeats = fetch_friendly_repetition($event); - if($repeats) - { - eval("\$repeats = \"".$templates->get("calendar_repeats")."\";"); - } - - $edit_event = $moderator_options = $event_class = ""; - if($calendar_permissions['canmoderateevents'] == 1 || ($mybb->user['uid'] > 0 && $mybb->user['uid'] == $event['uid'])) - { - eval("\$edit_event = \"".$templates->get("calendar_event_editbutton")."\";"); - if($calendar_permissions['canmoderateevents'] == 1) - { - if($event['visible'] == 1) - { - $approve = $lang->unapprove_event; - $approve_value = "unapprove"; - } - else - { - $approve = $lang->approve_event; - $approve_value = "approve"; - } - eval("\$moderator_options = \"".$templates->get("calendar_event_modoptions")."\";"); - } - if($event['visible'] == 0) - { - $event_class = " trow_shaded"; - } - } - eval("\$events .= \"".$templates->get("calendar_dayview_event")."\";"); - } - } - - $yearsel = ''; - for($year_sel = my_date("Y"); $year_sel < (my_date("Y") + 5); ++$year_sel) - { - eval("\$yearsel .= \"".$templates->get("calendar_year_sel")."\";"); - } - - $addevent = ''; - if($mybb->usergroup['canaddevents'] == 1) - { - eval("\$addevent = \"".$templates->get("calendar_addeventlink")."\";"); - } - - if(!$events) - { - $lang->no_events = $lang->sprintf($lang->no_events, $calendar['cid'], $day, $month, $year); - eval("\$events = \"".$templates->get("calendar_dayview_noevents")."\";"); - } - - // Now output the page - $plugins->run_hooks("calendar_dayview_end"); - - eval("\$day_view = \"".$templates->get("calendar_dayview")."\";"); - output_page($day_view); -} - -// View all events for a specific week -if($mybb->input['action'] == "weekview") -{ - // Showing a particular calendar - if($mybb->input['calendar']) - { - $query = $db->simple_select("calendars", "*", "cid='{$mybb->input['calendar']}'"); - $calendar = $db->fetch_array($query); - } - // Showing the default calendar - else - { - $query = $db->simple_select("calendars", "*", "disporder='1'"); - $calendar = $db->fetch_array($query); - } - - // Invalid calendar? - if(!$calendar) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - if($calendar_permissions['canviewcalendar'] != 1) - { - error_no_permission(); - } - - $weekdays = fetch_weekday_structure($calendar['startofweek']); - - $yearsel = ''; - for($year_sel = my_date("Y"); $year_sel < (my_date("Y") + 5); ++$year_sel) - { - eval("\$yearsel .= \"".$templates->get("calendar_year_sel")."\";"); - } - - // No incoming week, show THIS week - if(empty($mybb->input['week'])) - { - list($day, $month, $year) = explode("-", my_date("j-n-Y")); - $php_weekday = gmdate("w", adodb_gmmktime(0, 0, 0, $month, $day, $year)); - $my_weekday = array_search($php_weekday, $weekdays); - // So now we have the start day of this week to show - $start_day = $day-$my_weekday; - $mybb->input['week'] = adodb_gmmktime(0, 0, 0, $month, $start_day, $year); - } - else - { - $mybb->input['week'] = (int)str_replace("n", "-", $mybb->get_input('week')); - // No negative years please ;) - if($mybb->input['week'] < -62167219200) - { - $mybb->input['week'] = -62167219200; - } - } - - // This is where we've come from and where we're headed - $week_from = explode("-", gmdate("j-n-Y", $mybb->input['week'])); - $week_from_one = $week_from[1]; - $friendly_week_from = gmdate($mybb->settings['dateformat'], $mybb->input['week']); - $week_to_stamp = adodb_gmmktime(0, 0, 0, $week_from[1], $week_from[0]+6, $week_from[2]); - $week_to = explode("-", gmdate("j-n-Y-t", $week_to_stamp)); - $friendly_week_to = gmdate($mybb->settings['dateformat'], $week_to_stamp); - - add_breadcrumb(htmlspecialchars_uni($calendar['name']), get_calendar_link($calendar['cid'])); - add_breadcrumb("{$monthnames[$week_from[1]]} {$week_from[2]}", get_calendar_link($calendar['cid'], $week_from[2], $week_from[1])); - add_breadcrumb($lang->weekly_overview); - - $plugins->run_hooks("calendar_weekview_start"); - - // Establish if we have a month ending in this week - if($week_from[1] != $week_to[1]) - { - $different_months = true; - $week_months = array(array($week_from[1], $week_from[2]), array($week_to[1], $week_to[2])); - $bday_months = array($week_from[1], $week_to[1]); - } - else - { - $week_months = array(array($week_from[1], $week_from[2])); - $bday_months = array($week_from[1]); - } - - // Load Birthdays for this month - if($calendar['showbirthdays'] == 1) - { - $birthdays = get_birthdays($bday_months); - } - - // We load events for the entire month date range - for our mini calendars too - $events_from = adodb_gmmktime(0, 0, 0, $week_from[1], 1, $week_from[2]); - $events_to = adodb_gmmktime(0, 0, 0, $week_to[1], $week_to[3], $week_to[2]); - - $events_cache = get_events($calendar, $events_from, $events_to, $calendar_permissions['canmoderateevents']); - - $today = my_date("dnY"); - - $next_week = $mybb->input['week'] + 604800; - $next_link = get_calendar_week_link($calendar['cid'], $next_week); - $prev_week = $mybb->input['week'] - 604800; - $prev_link = get_calendar_week_link($calendar['cid'], $prev_week); - - $weekday_date = $mybb->input['week']; - - while($weekday_date <= $week_to_stamp) - { - $weekday = gmdate("w", $weekday_date); - $weekday_name = fetch_weekday_name($weekday); - $weekday_month = gmdate("n", $weekday_date); - $weekday_year = gmdate("Y", $weekday_date); - $weekday_day = gmdate("j", $weekday_date); - - // Special shading for today - $day_shaded = ''; - if(gmdate("dnY", $weekday_date) == $today) - { - $day_shaded = ' trow_shaded'; - } - - $day_events = ''; - - // Any events on this specific day? - if(is_array($events_cache) && array_key_exists("{$weekday_day}-{$weekday_month}-{$weekday_year}", $events_cache)) - { - foreach($events_cache["$weekday_day-$weekday_month-$weekday_year"] as $event) - { - $event['eventlink'] = get_event_link($event['eid']); - $event['name'] = htmlspecialchars_uni($event['name']); - $event['fullname'] = $event['name']; - if(my_strlen($event['name']) > 50) - { - $event['name'] = my_substr($event['name'], 0, 50) . "..."; - } - // Events over more than one day - $time_period = ''; - if($event['endtime'] > 0 && $event['endtime'] != $event['starttime']) - { - $start_day = adodb_gmmktime(0, 0, 0, gmdate("n", $event['starttime_user']), gmdate("j", $event['starttime_user']), gmdate("Y", $event['starttime_user'])); - $end_day = adodb_gmmktime(0, 0, 0, gmdate("n", $event['endtime_user']), gmdate("j", $event['endtime_user']), gmdate("Y", $event['endtime_user'])); - $start_time = gmdate("Hi", $event['starttime_user']); - $end_time = gmdate("Hi", $event['endtime_user']); - // Event only runs over one day - if($start_day == $end_day || $event['repeats'] > 0) - { - // Event runs all day - if($start_time == 0000 && $end_time == 2359) - { - $time_period = $lang->all_day; - } - else - { - $time_period = gmdate($mybb->settings['timeformat'], $event['starttime_user'])." - ".gmdate($mybb->settings['timeformat'], $event['endtime_user']); - } - } - // Event starts on this day - else if($start_day == $weekday_date) - { - // Event runs all day - if($start_time == 0000) - { - $time_period = $lang->all_day; - } - else - { - $time_period = $lang->starts.gmdate($mybb->settings['timeformat'], $event['starttime_user']); - } - } - // Event finishes on this day - else if($end_day == $weekday_date) - { - // Event runs all day - if($end_time == 2359) - { - $time_period = $lang->all_day; - } - else - { - $time_period = $lang->finishes.gmdate($mybb->settings['timeformat'], $event['endtime_user']); - } - } - // Event is in the middle - else - { - $time_period = $lang->all_day; - } - } - $event_time = ''; - if($time_period) - { - eval("\$event_time = \"".$templates->get("calendar_weekview_day_event_time")."\";"); - } - if($event['private'] == 1) - { - $event_class = " private_event"; - } - else - { - $event_class = " public_event"; - } - if($event['visible'] == 0) - { - $event_class .= " trow_shaded"; - } - eval("\$day_events .= \"".$templates->get("calendar_weekview_day_event")."\";"); - } - } - - // Birthdays on this day? - $day_birthdays = $calendar_link = $birthday_lang = ''; - if($calendar['showbirthdays'] && is_array($birthdays) && array_key_exists("{$weekday_day}-{$weekday_month}", $birthdays)) - { - $bday_count = count($birthdays["$weekday_day-$weekday_month"]); - if($bday_count > 1) - { - $birthday_lang = $lang->birthdays; - } - else - { - $birthday_lang = $lang->birthday; - } - - $calendar_link = get_calendar_link($calendar['cid'], $weekday_year, $weekday_month, $weekday_day); - eval("\$day_birthdays = \"".$templates->get("calendar_weekview_day_birthdays")."\";"); - } - - $day_link = get_calendar_link($calendar['cid'], $weekday_year, $weekday_month, $weekday_day); - if(!isset($day_bits[$weekday_month])) - { - $day_bits[$weekday_month] = ''; - } - eval("\$day_bits[$weekday_month] .= \"".$templates->get("calendar_weekview_day")."\";"); - $day_events = $day_birthdays = ""; - $weekday_date = adodb_gmmktime(0, 0, 0, $weekday_month, $weekday_day+1, $weekday_year); - } - - // Now we build our month headers - $mini_calendars = $weekday_bits = ''; - foreach($week_months as $month) - { - $weekday_month = $monthnames[$month[0]]; - $weekday_year = $month[1]; - - // Fetch mini calendar for each month in this week - $mini_calendars .= build_mini_calendar($calendar, $month[0], $weekday_year, $events_cache)."
    "; - - // Fetch out the days for this month - $days = $day_bits[$month[0]]; - - eval("\$weekday_bits .= \"".$templates->get("calendar_weekview_month")."\";"); - } - - $addevent = ''; - if($mybb->usergroup['canaddevents'] == 1) - { - eval("\$addevent = \"".$templates->get("calendar_addeventlink")."\";"); - } - - // Now output the page - $plugins->run_hooks("calendar_weekview_end"); - - eval("\$weekview = \"".$templates->get("calendar_weekview")."\";"); - output_page($weekview); -} - -// Showing a calendar -if(!$mybb->input['action']) -{ - // Showing a particular calendar - if($mybb->input['calendar']) - { - $query = $db->simple_select("calendars", "*", "cid='{$mybb->input['calendar']}'"); - $calendar = $db->fetch_array($query); - } - // Showing the default calendar - else - { - $query = $db->simple_select("calendars", "*", "", array('order_by' => 'disporder', 'limit' => 1)); - $calendar = $db->fetch_array($query); - } - - // Invalid calendar? - if(!$calendar['cid']) - { - error($lang->invalid_calendar); - } - - // Do we have permission to view this calendar? - $calendar_permissions = get_calendar_permissions($calendar['cid']); - - if($calendar_permissions['canviewcalendar'] != 1) - { - error_no_permission(); - } - - $plugins->run_hooks("calendar_main_view"); - - // Incoming year? - if(isset($mybb->input['year']) && $mybb->get_input('year', MyBB::INPUT_INT) <= my_date("Y")+5) - { - $year = $mybb->get_input('year', MyBB::INPUT_INT); - } - else - { - $year = my_date("Y"); - } - - // Then the month - $mybb->input['month'] = $mybb->get_input('month', MyBB::INPUT_INT); - if($mybb->input['month'] >= 1 && $mybb->input['month'] <= 12) - { - $month = $mybb->input['month']; - } - else - { - $month = my_date("n"); - } - - add_breadcrumb(htmlspecialchars_uni($calendar['name']), get_calendar_link($calendar['cid'])); - add_breadcrumb("$monthnames[$month] $year", get_calendar_link($calendar['cid'], $year, $month)); - - $next_month = get_next_month($month, $year); - $prev_month = get_prev_month($month, $year); - - $prev_link = get_calendar_link($calendar['cid'], $prev_month['year'], $prev_month['month']); - $next_link = get_calendar_link($calendar['cid'], $next_month['year'], $next_month['month']); - - // Start constructing the calendar - - $weekdays = fetch_weekday_structure($calendar['startofweek']); - - $month_start_weekday = gmdate("w", adodb_gmmktime(0, 0, 0, $month, $calendar['startofweek']+1, $year)); - - $prev_month_days = gmdate("t", adodb_gmmktime(0, 0, 0, $prev_month['month'], 1, $prev_month['year'])); - - // This is if we have days in the previous month to show - if($month_start_weekday != $weekdays[0] || $calendar['startofweek'] != 0) - { - $prev_days = $day = gmdate("t", adodb_gmmktime(0, 0, 0, $prev_month['month'], 1, $prev_month['year'])); - $day -= array_search(($month_start_weekday), $weekdays); - $day += $calendar['startofweek']+1; - if($day > $prev_month_days+1) - { - // Go one week back - $day -= 7; - } - $calendar_month = $prev_month['month']; - $calendar_year = $prev_month['year']; - } - else - { - $day = $calendar['startofweek']+1; - $calendar_month = $month; - $calendar_year = $year; - } - - // So now we fetch events for this month (nb, cache events for past month, current month and next month for mini calendars too) - $start_timestamp = adodb_gmmktime(0, 0, 0, $calendar_month, $day, $calendar_year); - $num_days = gmdate("t", adodb_gmmktime(0, 0, 0, $month, 1, $year)); - - $month_end_weekday = gmdate("w", adodb_gmmktime(0, 0, 0, $month, $num_days, $year)); - $next_days = 6-$month_end_weekday+$calendar['startofweek']; - - // More than a week? Go one week back - if($next_days >= 7) - { - $next_days -= 7; - } - if($next_days > 0) - { - $end_timestamp = adodb_gmmktime(23, 59, 59, $next_month['month'], $next_days, $next_month['year']); - } - else - { - // We don't need days from the next month - $end_timestamp = adodb_gmmktime(23, 59, 59, $month, $num_days, $year); - } - - $events_cache = get_events($calendar, $start_timestamp, $end_timestamp, $calendar_permissions['canmoderateevents']); - - // Fetch birthdays - if($calendar['showbirthdays']) - { - $bday_months = array($month, $prev_month['month'], $next_month['month']); - $birthdays = get_birthdays($bday_months); - } - - $today = my_date("dnY"); - $weekday_headers = ''; - - // Build weekday headers - foreach($weekdays as $weekday) - { - $weekday_name = fetch_weekday_name($weekday); - eval("\$weekday_headers .= \"".$templates->get("calendar_weekdayheader")."\";"); - } - - $in_month = 0; - $day_bits = $calendar_rows = ''; - for($row = 0; $row < 6; ++$row) // Iterate weeks (each week gets a row) - { - foreach($weekdays as $weekday_id => $weekday) - { - // Current month always starts on 1st row - if($row == 0 && $day == $calendar['startofweek']+1) - { - $in_month = 1; - $calendar_month = $month; - $calendar_year = $year; - } - else if($calendar_month == $prev_month['month'] && $day > $prev_month_days) - { - $day = 1; - $in_month = 1; - $calendar_month = $month; - $calendar_year = $year; - } - else if($day > $num_days && $calendar_month != $prev_month['month']) - { - $in_month = 0; - $calendar_month = $next_month['month']; - $calendar_year = $next_month['year']; - $day = 1; - if($calendar_month == $month) - { - $in_month = 1; - } - } - - if($weekday_id == 0) - { - $week_stamp = adodb_gmmktime(0, 0, 0, $calendar_month, $day, $calendar_year); - $week_link = get_calendar_week_link($calendar['cid'], $week_stamp); - } - - if($weekday_id == 0 && $calendar_month == $next_month['month']) - { - break; - } - - // Any events on this specific day? - $day_events = $event_lang = ''; - if(is_array($events_cache) && array_key_exists("{$day}-{$calendar_month}-{$calendar_year}", $events_cache)) - { - $total_events = count($events_cache["$day-$calendar_month-$calendar_year"]); - if($total_events > $calendar['eventlimit'] && $calendar['eventlimit'] != 0) - { - if($total_events > 1) - { - $event_lang = $lang->events; - } - else - { - $event_lang = $lang->event; - } - - $calendar['link'] = get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day); - eval("\$day_events = \"".$templates->get("calendar_weekrow_day_events")."\";"); - } - else - { - foreach($events_cache["$day-$calendar_month-$calendar_year"] as $event) - { - $event['eventlink'] = get_event_link($event['eid']); - $event['fullname'] = htmlspecialchars_uni($event['name']); - if(my_strlen($event['name']) > 15) - { - $event['name'] = my_substr($event['name'], 0, 15) . "..."; - } - $event['name'] = htmlspecialchars_uni($event['name']); - if($event['private'] == 1) - { - $event_class = " private_event"; - } - else - { - $event_class = " public_event"; - } - if($event['visible'] == 0) - { - $event_class .= " trow_shaded"; - } - eval("\$day_events .= \"".$templates->get("calendar_eventbit")."\";"); - } - } - } - - // Birthdays on this day? - $day_birthdays = $birthday_lang = ''; - if($calendar['showbirthdays'] && is_array($birthdays) && array_key_exists("$day-$calendar_month", $birthdays)) - { - $bday_count = count($birthdays["$day-$calendar_month"]); - if($bday_count > 1) - { - $birthday_lang = $lang->birthdays; - } - else - { - $birthday_lang = $lang->birthday; - } - - $calendar['link'] = get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day); - eval("\$day_birthdays = \"".$templates->get("calendar_weekrow_day_birthdays")."\";"); - } - - $day_link = get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day); - - // Is the current day - if($day.$calendar_month.$year == $today && $month == $calendar_month) - { - $day_class = "trow_sep"; - } - // Not in this month - else if($in_month == 0) - { - $day_class = "trow1"; - } - // Just a normal day in this month - else - { - $day_class = "trow2"; - } - eval("\$day_bits .= \"".$templates->get("calendar_weekrow_day")."\";"); - $day_birthdays = $day_events = ""; - ++$day; - } - if($day_bits) - { - eval("\$calendar_rows .= \"".$templates->get("calendar_weekrow")."\";"); - } - $day_bits = ""; - } - - $yearsel = ''; - for($year_sel = my_date("Y"); $year_sel < (my_date("Y") + 5); ++$year_sel) - { - eval("\$yearsel .= \"".$templates->get("calendar_year_sel")."\";"); - } - - $addevent = ''; - if($mybb->usergroup['canaddevents'] == 1) - { - eval("\$addevent = \"".$templates->get("calendar_addeventlink")."\";"); - } - - $plugins->run_hooks("calendar_end"); - - eval("\$calendar = \"".$templates->get("calendar")."\";"); - output_page($calendar); -} diff --git a/html/forums/captcha.php b/html/forums/captcha.php deleted file mode 100644 index 5ae4ec4..0000000 --- a/html/forums/captcha.php +++ /dev/null @@ -1,311 +0,0 @@ -input['imagehash'] = $mybb->get_input('imagehash'); -if($mybb->input['imagehash']) -{ - $query = $db->simple_select("captcha", "*", "imagehash='".$db->escape_string($mybb->get_input('imagehash'))."' AND used=0", array("limit" => 1)); - $regimage = $db->fetch_array($query); - if(!$regimage) - { - exit; - } - // Mark captcha as used - $db->update_query('captcha', array('used' => 1), "imagehash='".$db->escape_string($regimage['imagehash'])."'"); - $imagestring = $regimage['imagestring']; -} -else -{ - exit; -} - -$ttf_fonts = array(); - -// We have support for true-type fonts (FreeType 2) -if(function_exists("imagefttext")) -{ - // Get a list of the files in the 'catpcha_fonts' directory - $ttfdir = @opendir(MYBB_ROOT."inc/captcha_fonts"); - if($ttfdir !== false) - { - while(($file = readdir($ttfdir)) !== false) - { - // If this file is a ttf file, add it to the list - if(is_file(MYBB_ROOT."inc/captcha_fonts/".$file) && get_extension($file) == "ttf") - { - $ttf_fonts[] = MYBB_ROOT."inc/captcha_fonts/".$file; - } - } - closedir($ttfdir); - } -} - -// Have one or more TTF fonts in our array, we can use TTF captha's -if(count($ttf_fonts) > 0) -{ - $use_ttf = 1; -} -else -{ - $use_ttf = 0; -} - -// Check for GD >= 2, create base image -if(gd_version() >= 2) -{ - $im = imagecreatetruecolor($img_width, $img_height); -} -else -{ - $im = imagecreate($img_width, $img_height); -} - -// No GD support, die. -if(!$im) -{ - die("No GD support."); -} - -// Fill the background with white -$bg_color = imagecolorallocate($im, 255, 255, 255); -imagefill($im, 0, 0, $bg_color); - -// Draw random circles, squares or lines? -$to_draw = rand(0, 2); -if($to_draw == 1) -{ - draw_circles($im); -} -else if($to_draw == 2) -{ - draw_squares($im); -} -else -{ - draw_lines($im); -} - -// Draw dots on the image -draw_dots($im); - -// Write the image string to the image -draw_string($im, $imagestring); - -// Draw a nice border around the image -$border_color = imagecolorallocate($im, 0, 0, 0); -imagerectangle($im, 0, 0, $img_width-1, $img_height-1, $border_color); - -// Output the image -header("Content-type: image/png"); -imagepng($im); -imagedestroy($im); - -/** - * Draws a random number of lines on the image. - * - * @param resource $im The image. - */ -function draw_lines(&$im) -{ - global $img_width, $img_height; - - for($i = 10; $i < $img_width; $i += 10) - { - $color = imagecolorallocate($im, rand(150, 255), rand(150, 255), rand(150, 255)); - imageline($im, $i, 0, $i, $img_height, $color); - } - for($i = 10; $i < $img_height; $i += 10) - { - $color = imagecolorallocate($im, rand(150, 255), rand(150, 255), rand(150, 255)); - imageline($im, 0, $i, $img_width, $i, $color); - } -} - -/** - * Draws a random number of circles on the image. - * - * @param resource $im The image. - */ -function draw_circles(&$im) -{ - global $img_width, $img_height; - - $circles = $img_width*$img_height / 100; - for($i = 0; $i <= $circles; ++$i) - { - $color = imagecolorallocate($im, rand(180, 255), rand(180, 255), rand(180, 255)); - $pos_x = rand(1, $img_width); - $pos_y = rand(1, $img_height); - $circ_width = ceil(rand(1, $img_width)/2); - $circ_height = rand(1, $img_height); - imagearc($im, $pos_x, $pos_y, $circ_width, $circ_height, 0, rand(200, 360), $color); - } -} - -/** - * Draws a random number of dots on the image. - * - * @param resource $im The image. - */ -function draw_dots(&$im) -{ - global $img_width, $img_height; - - $dot_count = $img_width*$img_height/5; - for($i = 0; $i <= $dot_count; ++$i) - { - $color = imagecolorallocate($im, rand(200, 255), rand(200, 255), rand(200, 255)); - imagesetpixel($im, rand(0, $img_width), rand(0, $img_height), $color); - } -} - -/** - * Draws a random number of squares on the image. - * - * @param resource $im The image. - */ -function draw_squares(&$im) -{ - global $img_width, $img_height; - - $square_count = 30; - for($i = 0; $i <= $square_count; ++$i) - { - $color = imagecolorallocate($im, rand(150, 255), rand(150, 255), rand(150, 255)); - $pos_x = rand(1, $img_width); - $pos_y = rand(1, $img_height); - $sq_width = $sq_height = rand(10, 20); - $pos_x2 = $pos_x + $sq_height; - $pos_y2 = $pos_y + $sq_width; - imagefilledrectangle($im, $pos_x, $pos_y, $pos_x2, $pos_y2, $color); - } -} - -/** - * Writes text to the image. - * - * @param resource $im The image. - * @param string $string The string to be written - * - * @return bool False if string is empty, true otherwise - */ -function draw_string(&$im, $string) -{ - global $use_ttf, $min_size, $max_size, $min_angle, $max_angle, $ttf_fonts, $img_height, $img_width; - - if(empty($string)) - { - return false; - } - - $spacing = $img_width / my_strlen($string); - $string_length = my_strlen($string); - for($i = 0; $i < $string_length; ++$i) - { - // Using TTF fonts - if($use_ttf) - { - // Select a random font size - $font_size = rand($min_size, $max_size); - - // Select a random font - $font = array_rand($ttf_fonts); - $font = $ttf_fonts[$font]; - - // Select a random rotation - $rotation = rand($min_angle, $max_angle); - - // Set the colour - $r = rand(0, 200); - $g = rand(0, 200); - $b = rand(0, 200); - $color = imagecolorallocate($im, $r, $g, $b); - - // Fetch the dimensions of the character being added - $dimensions = imageftbbox($font_size, $rotation, $font, $string[$i], array()); - $string_width = $dimensions[2] - $dimensions[0]; - $string_height = $dimensions[3] - $dimensions[5]; - - // Calculate character offsets - //$pos_x = $pos_x + $string_width + ($string_width/4); - $pos_x = $spacing / 4 + $i * $spacing; - $pos_y = ceil(($img_height-$string_height/2)); - - // Draw a shadow - $shadow_x = rand(-3, 3) + $pos_x; - $shadow_y = rand(-3, 3) + $pos_y; - $shadow_color = imagecolorallocate($im, $r+20, $g+20, $b+20); - imagefttext($im, $font_size, $rotation, $shadow_x, $shadow_y, $shadow_color, $font, $string[$i], array()); - - // Write the character to the image - imagefttext($im, $font_size, $rotation, $pos_x, $pos_y, $color, $font, $string[$i], array()); - } - else - { - // Get width/height of the character - $string_width = imagefontwidth(5); - $string_height = imagefontheight(5); - - // Calculate character offsets - $pos_x = $spacing / 4 + $i * $spacing; - $pos_y = $img_height / 2 - $string_height -10 + rand(-3, 3); - - // Create a temporary image for this character - if(gd_version() >= 2) - { - $temp_im = imagecreatetruecolor(15, 20); - } - else - { - $temp_im = imagecreate(15, 20); - } - $bg_color = imagecolorallocate($temp_im, 255, 255, 255); - imagefill($temp_im, 0, 0, $bg_color); - imagecolortransparent($temp_im, $bg_color); - - // Set the colour - $r = rand(0, 200); - $g = rand(0, 200); - $b = rand(0, 200); - $color = imagecolorallocate($temp_im, $r, $g, $b); - - // Draw a shadow - $shadow_x = rand(-1, 1); - $shadow_y = rand(-1, 1); - $shadow_color = imagecolorallocate($temp_im, $r+50, $g+50, $b+50); - imagestring($temp_im, 5, 1+$shadow_x, 1+$shadow_y, $string[$i], $shadow_color); - - imagestring($temp_im, 5, 1, 1, $string[$i], $color); - - // Copy to main image - imagecopyresized($im, $temp_im, $pos_x, $pos_y, 0, 0, 40, 55, 15, 20); - imagedestroy($temp_im); - } - } - return true; -} - diff --git a/html/forums/contact.php b/html/forums/contact.php deleted file mode 100644 index fb2f450..0000000 --- a/html/forums/contact.php +++ /dev/null @@ -1,296 +0,0 @@ -load("contact"); - -$plugins->run_hooks('contact_start'); - -// Make navigation -add_breadcrumb($lang->contact, "contact.php"); - -if($mybb->settings['contact'] != 1 || (!$mybb->user['uid'] && $mybb->settings['contact_guests'] == 1)) -{ - error_no_permission(); -} - -if($mybb->settings['contactemail']) -{ - $contactemail = $mybb->settings['contactemail']; -} -else -{ - $contactemail = $mybb->settings['adminemail']; -} - -// Check group limits -if($mybb->usergroup['maxemails'] > 0) -{ - if($mybb->user['uid'] > 0) - { - $user_check = "fromuid='{$mybb->user['uid']}'"; - } - else - { - $user_check = "ipaddress=".$db->escape_binary($session->packedip); - } - - $query = $db->simple_select("maillogs", "COUNT(mid) AS sent_count", "{$user_check} AND dateline >= ".(TIME_NOW - (60*60*24))); - $sent_count = $db->fetch_field($query, "sent_count"); - if($sent_count >= $mybb->usergroup['maxemails']) - { - $lang->error_max_emails_day = $lang->sprintf($lang->error_max_emails_day, $mybb->usergroup['maxemails']); - error($lang->error_max_emails_day); - } -} - -// Check email flood control -if($mybb->usergroup['emailfloodtime'] > 0) -{ - if($mybb->user['uid'] > 0) - { - $user_check = "fromuid='{$mybb->user['uid']}'"; - } - else - { - $user_check = "ipaddress=".$db->escape_binary($session->packedip); - } - - $timecut = TIME_NOW-$mybb->usergroup['emailfloodtime']*60; - - $query = $db->simple_select("maillogs", "mid, dateline", "{$user_check} AND dateline > '{$timecut}'", array('order_by' => "dateline", 'order_dir' => "DESC")); - $last_email = $db->fetch_array($query); - - // Users last email was within the flood time, show the error - if($last_email['mid']) - { - $remaining_time = ($mybb->usergroup['emailfloodtime']*60)-(TIME_NOW-$last_email['dateline']); - - if($remaining_time == 1) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_1_second, $mybb->usergroup['emailfloodtime']); - } - elseif($remaining_time < 60) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_seconds, $mybb->usergroup['emailfloodtime'], $remaining_time); - } - elseif($remaining_time > 60 && $remaining_time < 120) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_1_minute, $mybb->usergroup['emailfloodtime']); - } - else - { - $remaining_time_minutes = ceil($remaining_time/60); - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_minutes, $mybb->usergroup['emailfloodtime'], $remaining_time_minutes); - } - - error($lang->error_emailflooding); - } -} - -$errors = array(); - -$mybb->input['message'] = trim_blank_chrs($mybb->get_input('message')); -$mybb->input['subject'] = trim_blank_chrs($mybb->get_input('subject')); -$mybb->input['email'] = trim_blank_chrs($mybb->get_input('email')); - -if($mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks('contact_do_start'); - - // Validate input - if(empty($mybb->input['subject'])) - { - $errors[] = $lang->contact_no_subject; - } - - if(strlen($mybb->input['subject']) > $mybb->settings['contact_maxsubjectlength'] && $mybb->settings['contact_maxsubjectlength'] > 0) - { - $errors[] = $lang->sprintf($lang->subject_too_long, $mybb->settings['contact_maxsubjectlength'], strlen($mybb->input['subject'])); - } - - if(empty($mybb->input['message'])) - { - $errors[] = $lang->contact_no_message; - } - - if(strlen($mybb->input['message']) > $mybb->settings['contact_maxmessagelength'] && $mybb->settings['contact_maxmessagelength'] > 0) - { - $errors[] = $lang->sprintf($lang->message_too_long, $mybb->settings['contact_maxmessagelength'], strlen($mybb->input['message'])); - } - - if(strlen($mybb->input['message']) < $mybb->settings['contact_minmessagelength'] && $mybb->settings['contact_minmessagelength'] > 0) - { - $errors[] = $lang->sprintf($lang->message_too_short, $mybb->settings['contact_minmessagelength'], strlen($mybb->input['message'])); - } - - if(empty($mybb->input['email'])) - { - $errors[] = $lang->contact_no_email; - } - else - { - // Validate email - if(!validate_email_format($mybb->input['email'])) - { - $errors[] = $lang->contact_no_email; - } - } - - // Should we have a CAPTCHA? Perhaps yes, but only for guests like in other pages... - if($mybb->settings['captchaimage'] && !$mybb->user['uid']) - { - $captcha = new captcha; - - if($captcha->validate_captcha() == false) - { - // CAPTCHA validation failed - foreach($captcha->get_errors() as $error) - { - $errors[] = $error; - } - } - } - - if(!$mybb->user['uid'] && $mybb->settings['stopforumspam_on_contact']) - { - require_once MYBB_ROOT . '/inc/class_stopforumspamchecker.php'; - - $stop_forum_spam_checker = new StopForumSpamChecker( - $plugins, - $mybb->settings['stopforumspam_min_weighting_before_spam'], - $mybb->settings['stopforumspam_check_usernames'], - $mybb->settings['stopforumspam_check_emails'], - $mybb->settings['stopforumspam_check_ips'], - $mybb->settings['stopforumspam_log_blocks'] - ); - - try { - if($stop_forum_spam_checker->is_user_a_spammer('', $mybb->input['email'], get_ip())) - { - $errors[] = $lang->sprintf($lang->error_stop_forum_spam_spammer, - $stop_forum_spam_checker->getErrorText(array( - 'stopforumspam_check_emails', - 'stopforumspam_check_ips'))); - } - } - catch (Exception $e) - { - if($mybb->settings['stopforumspam_block_on_error']) - { - $errors[] = $lang->error_stop_forum_spam_fetching; - } - } - } - - if(empty($errors)) - { - if($mybb->settings['contact_badwords'] == 1) - { - // Load the post parser - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - - $mybb->input['subject'] = $parser->parse_badwords($mybb->input['subject']); - $mybb->input['message'] = $parser->parse_badwords($mybb->input['message']); - } - - $user = $lang->na; - if($mybb->user['uid']) - { - $user = htmlspecialchars_uni($mybb->user['username']).' - '.$mybb->settings['bburl'].'/'.get_profile_link($mybb->user['uid']); - } - - $subject = $lang->sprintf($lang->email_contact_subject, $mybb->input['subject']); - $message = $lang->sprintf($lang->email_contact, $mybb->input['email'], $user, $session->ipaddress, $mybb->input['message']); - - // Email the administrator - my_mail($contactemail, $subject, $message, $mybb->input['email']); - - $plugins->run_hooks('contact_do_end'); - - if($mybb->settings['mail_logging'] > 0) - { - // Log the message - $log_entry = array( - "subject" => $db->escape_string($subject), - "message" => $db->escape_string($message), - "dateline" => TIME_NOW, - "fromuid" => $mybb->user['uid'], - "fromemail" => $db->escape_string($mybb->input['email']), - "touid" => 0, - "toemail" => $db->escape_string($contactemail), - "tid" => 0, - "ipaddress" => $db->escape_binary($session->packedip), - "type" => 3 - ); - $db->insert_query("maillogs", $log_entry); - } - - if($mybb->usergroup['emailfloodtime'] > 0 || (isset($sent_count) && $sent_count + 1 >= $mybb->usergroup['maxemails'])) - { - redirect('index.php', $lang->contact_success_message, '', true); - } - else - { - redirect('contact.php', $lang->contact_success_message, '', true); - } - } - else - { - $errors = inline_error($errors); - } -} - -if(empty($errors)) -{ - $errors = ''; -} - -// Generate CAPTCHA? -$captcha = ''; - -if($mybb->settings['captchaimage'] && !$mybb->user['uid']) -{ - $post_captcha = new captcha(true, "post_captcha"); - - if($post_captcha->html) - { - $captcha = $post_captcha->html; - } -} - -$mybb->input['subject'] = htmlspecialchars_uni($mybb->input['subject']); -$mybb->input['message'] = htmlspecialchars_uni($mybb->input['message']); - -if($mybb->user['uid'] && !$mybb->get_input('email')) -{ - $mybb->input['email'] = htmlspecialchars_uni($mybb->user['email']); -} -else -{ - $mybb->input['email'] = htmlspecialchars_uni($mybb->get_input('email')); -} - -$plugins->run_hooks('contact_end'); - -eval("\$page = \"".$templates->get("contact")."\";"); -output_page($page); diff --git a/html/forums/css.php b/html/forums/css.php deleted file mode 100644 index 565f548..0000000 --- a/html/forums/css.php +++ /dev/null @@ -1,40 +0,0 @@ -get_input('stylesheet', MyBB::INPUT_INT); - -if($stylesheet) -{ - $options = array( - "limit" => 1 - ); - $query = $db->simple_select("themestylesheets", "stylesheet", "sid=".$stylesheet, $options); - $stylesheet = $db->fetch_field($query, "stylesheet"); - - $plugins->run_hooks("css_start"); - - if(!empty($mybb->settings['minifycss'])) - { - $stylesheet = minify_stylesheet($stylesheet); - } - - $plugins->run_hooks("css_end"); - - header("Content-type: text/css"); - echo $stylesheet; -} -exit; diff --git a/html/forums/editpost.php b/html/forums/editpost.php deleted file mode 100644 index e290eff..0000000 --- a/html/forums/editpost.php +++ /dev/null @@ -1,947 +0,0 @@ -load("editpost"); - -$plugins->run_hooks("editpost_start"); - -// No permission for guests -if(!$mybb->user['uid']) -{ - error_no_permission(); -} - -// Get post info -$pid = $mybb->get_input('pid', MyBB::INPUT_INT); - -// if we already have the post information... -if(isset($style) && $style['pid'] == $pid && $style['type'] != 'f') -{ - $post = &$style; -} -else -{ - $post = get_post($pid); -} - -if(!$post) -{ - error($lang->error_invalidpost); -} - -// Get thread info -$tid = $post['tid']; -$thread = get_thread($tid); - -if(!$thread) -{ - error($lang->error_invalidthread); -} - -$thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); - -// Get forum info -$fid = $post['fid']; -$forum = get_forum($fid); - -if($thread['visible'] == 0 && !is_moderator($fid, "canviewunapprove") || $thread['visible'] == -1 && !is_moderator($fid, "canviewdeleted") || ($thread['visible'] < -1 && $thread['uid'] != $mybb->user['uid'])) -{ - error($lang->error_invalidthread); -} -if(!$forum || $forum['type'] != "f") -{ - error($lang->error_closedinvalidforum); -} -if(($forum['open'] == 0 && !is_moderator($fid, "caneditposts")) || $mybb->user['suspendposting'] == 1) -{ - error_no_permission(); -} - -// Add prefix to breadcrumb -$breadcrumbprefix = ''; -if($thread['prefix']) -{ - $threadprefixes = build_prefixes(); - if(!empty($threadprefixes[$thread['prefix']])) - { - $breadcrumbprefix = $threadprefixes[$thread['prefix']]['displaystyle'].' '; - } -} - -// Make navigation -build_forum_breadcrumb($fid); -add_breadcrumb($breadcrumbprefix.$thread['subject'], get_thread_link($thread['tid'])); -add_breadcrumb($lang->nav_editpost); - -$forumpermissions = forum_permissions($fid); - -if($mybb->settings['bbcodeinserter'] != 0 && $forum['allowmycode'] != 0 && $mybb->user['showcodebuttons'] != 0) -{ - $codebuttons = build_mycode_inserter("message", $mybb->settings['smilieinserter']); -} -if($mybb->settings['smilieinserter'] != 0) -{ - $smilieinserter = build_clickable_smilies(); -} - -$mybb->input['action'] = $mybb->get_input('action'); -if(!$mybb->input['action'] || isset($mybb->input['previewpost'])) -{ - $mybb->input['action'] = "editpost"; -} - -if($mybb->input['action'] == "deletepost" && $mybb->request_method == "post") -{ - if(!is_moderator($fid, "candeleteposts") && !is_moderator($fid, "cansoftdeleteposts") && $pid != $thread['firstpost'] || !is_moderator($fid, "candeletethreads") && !is_moderator($fid, "cansoftdeletethreads") && $pid == $thread['firstpost']) - { - if($thread['closed'] == 1) - { - error($lang->redirect_threadclosed); - } - if($forumpermissions['candeleteposts'] == 0 && $pid != $thread['firstpost'] || $forumpermissions['candeletethreads'] == 0 && $pid == $thread['firstpost']) - { - error_no_permission(); - } - if($mybb->user['uid'] != $post['uid']) - { - error_no_permission(); - } - // User can't delete unapproved post - if($post['visible'] == 0) - { - error_no_permission(); - } - } - if($post['visible'] == -1 && $mybb->settings['soft_delete'] == 1) - { - error($lang->error_already_deleted); - } -} -elseif($mybb->input['action'] == "restorepost" && $mybb->request_method == "post") -{ - if(!is_moderator($fid, "canrestoreposts") && $pid != $thread['firstpost'] || !is_moderator($fid, "canrestorethreads") && $pid == $thread['firstpost'] || $post['visible'] != -1) - { - error_no_permission(); - } -} -else -{ - if(!is_moderator($fid, "caneditposts")) - { - if($thread['closed'] == 1) - { - error($lang->redirect_threadclosed); - } - if($forumpermissions['caneditposts'] == 0) - { - error_no_permission(); - } - if($mybb->user['uid'] != $post['uid']) - { - error_no_permission(); - } - // Edit time limit - $time = TIME_NOW; - if($mybb->usergroup['edittimelimit'] != 0 && $post['dateline'] < ($time-($mybb->usergroup['edittimelimit']*60))) - { - $lang->edit_time_limit = $lang->sprintf($lang->edit_time_limit, $mybb->usergroup['edittimelimit']); - error($lang->edit_time_limit); - } - // User can't edit unapproved post - if($post['visible'] == 0 || $post['visible'] == -1) - { - error_no_permission(); - } - } -} - -// Check if this forum is password protected and we have a valid password -check_forum_password($forum['fid']); - -if((empty($_POST) && empty($_FILES)) && $mybb->get_input('processed', MyBB::INPUT_INT) == '1') -{ - error($lang->error_cannot_upload_php_post); -} - -$attacherror = ''; -if($mybb->settings['enableattachments'] == 1 && !$mybb->get_input('attachmentaid', MyBB::INPUT_INT) && ($mybb->get_input('newattachment') || $mybb->get_input('updateattachment') || ($mybb->input['action'] == "do_editpost" && isset($mybb->input['submit']) && $_FILES['attachment']))) -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - // If there's an attachment, check it and upload it - if($_FILES['attachment']['size'] > 0 && $forumpermissions['canpostattachments'] != 0) - { - $query = $db->simple_select("attachments", "aid", "filename='".$db->escape_string($_FILES['attachment']['name'])."' AND pid='{$pid}'"); - $updateattach = $db->fetch_field($query, "aid"); - - $update_attachment = false; - if($updateattach > 0 && $mybb->get_input('updateattachment') && ($mybb->usergroup['caneditattachments'] || $forumpermissions['caneditattachments'])) - { - $update_attachment = true; - } - $attachedfile = upload_attachment($_FILES['attachment'], $update_attachment); - } - if(!empty($attachedfile['error'])) - { - eval("\$attacherror = \"".$templates->get("error_attacherror")."\";"); - $mybb->input['action'] = "editpost"; - } - if(!isset($mybb->input['submit'])) - { - $mybb->input['action'] = "editpost"; - } -} - -if($mybb->settings['enableattachments'] == 1 && $mybb->get_input('attachmentaid', MyBB::INPUT_INT) && isset($mybb->input['attachmentact']) && $mybb->input['action'] == "do_editpost" && $mybb->request_method == "post") // Lets remove/approve/unapprove the attachment -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $mybb->input['attachmentaid'] = $mybb->get_input('attachmentaid', MyBB::INPUT_INT); - if($mybb->input['attachmentact'] == "remove") - { - remove_attachment($pid, "", $mybb->input['attachmentaid']); - } - elseif($mybb->get_input('attachmentact') == "approve" && is_moderator($fid, 'canapproveunapproveattachs')) - { - $update_sql = array("visible" => 1); - $db->update_query("attachments", $update_sql, "aid='{$mybb->input['attachmentaid']}'"); - update_thread_counters($post['tid'], array('attachmentcount' => "+1")); - } - elseif($mybb->get_input('attachmentact') == "unapprove" && is_moderator($fid, 'canapproveunapproveattachs')) - { - $update_sql = array("visible" => 0); - $db->update_query("attachments", $update_sql, "aid='{$mybb->input['attachmentaid']}'"); - update_thread_counters($post['tid'], array('attachmentcount' => "-1")); - } - if(!isset($mybb->input['submit'])) - { - $mybb->input['action'] = "editpost"; - } -} - -if($mybb->input['action'] == "deletepost" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("editpost_deletepost"); - - if($mybb->get_input('delete', MyBB::INPUT_INT) == 1) - { - $query = $db->simple_select("posts", "pid", "tid='{$tid}'", array("limit" => 1, "order_by" => "dateline", "order_dir" => "asc")); - $firstcheck = $db->fetch_array($query); - if($firstcheck['pid'] == $pid) - { - $firstpost = 1; - } - else - { - $firstpost = 0; - } - - $modlogdata['fid'] = $fid; - $modlogdata['tid'] = $tid; - if($firstpost) - { - if($forumpermissions['candeletethreads'] == 1 || is_moderator($fid, "candeletethreads") || is_moderator($fid, "cansoftdeletethreads")) - { - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation; - - if($mybb->settings['soft_delete'] == 1 || is_moderator($fid, "cansoftdeletethreads")) - { - $modlogdata['pid'] = $pid; - - $moderation->soft_delete_threads(array($tid)); - log_moderator_action($modlogdata, $lang->thread_soft_deleted); - } - else - { - $moderation->delete_thread($tid); - mark_reports($tid, "thread"); - log_moderator_action($modlogdata, $lang->thread_deleted); - } - - if($mybb->input['ajax'] == 1) - { - header("Content-type: application/json; charset={$lang->settings['charset']}"); - if(is_moderator($fid, "canviewdeleted")) - { - echo json_encode(array("data" => '1')); - } - else - { - echo json_encode(array("data" => '3', "url" => get_forum_link($fid))); - } - } - else - { - redirect(get_forum_link($fid), $lang->redirect_threaddeleted); - } - } - else - { - error_no_permission(); - } - } - else - { - if($forumpermissions['candeleteposts'] == 1 || is_moderator($fid, "candeleteposts") || is_moderator($fid, "cansoftdeleteposts")) - { - // Select the first post before this - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation; - - if($mybb->settings['soft_delete'] == 1 || is_moderator($fid, "cansoftdeleteposts")) - { - $modlogdata['pid'] = $pid; - - $moderation->soft_delete_posts(array($pid)); - log_moderator_action($modlogdata, $lang->post_soft_deleted); - } - else - { - $moderation->delete_post($pid); - mark_reports($pid, "post"); - log_moderator_action($modlogdata, $lang->post_deleted); - } - - $query = $db->simple_select("posts", "pid", "tid='{$tid}' AND dateline <= '{$post['dateline']}'", array("limit" => 1, "order_by" => "dateline", "order_dir" => "desc")); - $next_post = $db->fetch_array($query); - if($next_post['pid']) - { - $redirect = get_post_link($next_post['pid'], $tid)."#pid{$next_post['pid']}"; - } - else - { - $redirect = get_thread_link($tid); - } - - if($mybb->input['ajax'] == 1) - { - header("Content-type: application/json; charset={$lang->settings['charset']}"); - if(is_moderator($fid, "canviewdeleted")) - { - echo json_encode(array("data" => '1')); - } - else - { - echo json_encode(array("data" => '2')); - } - } - else - { - redirect($redirect, $lang->redirect_postdeleted); - } - } - else - { - error_no_permission(); - } - } - } - else - { - error($lang->redirect_nodelete); - } -} - -if($mybb->input['action'] == "restorepost" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("editpost_restorepost"); - - if($mybb->get_input('restore', MyBB::INPUT_INT) == 1) - { - $query = $db->simple_select("posts", "pid", "tid='{$tid}'", array("limit" => 1, "order_by" => "dateline", "order_dir" => "asc")); - $firstcheck = $db->fetch_array($query); - if($firstcheck['pid'] == $pid) - { - $firstpost = 1; - } - else - { - $firstpost = 0; - } - - $modlogdata['fid'] = $fid; - $modlogdata['tid'] = $tid; - $modlogdata['pid'] = $pid; - if($firstpost) - { - if(is_moderator($fid, "canrestorethreads")) - { - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation; - $moderation->restore_threads(array($tid)); - log_moderator_action($modlogdata, $lang->thread_restored); - if($mybb->input['ajax'] == 1) - { - header("Content-type: application/json; charset={$lang->settings['charset']}"); - echo json_encode(array("data" => '1')); - } - else - { - redirect(get_forum_link($fid), $lang->redirect_threadrestored); - } - } - else - { - error_no_permission(); - } - } - else - { - if(is_moderator($fid, "canrestoreposts")) - { - // Select the first post before this - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation; - $moderation->restore_posts(array($pid)); - log_moderator_action($modlogdata, $lang->post_restored); - $redirect = get_post_link($pid, $tid)."#pid{$pid}"; - - if($mybb->input['ajax'] == 1) - { - header("Content-type: application/json; charset={$lang->settings['charset']}"); - echo json_encode(array("data" => '1')); - } - else - { - redirect($redirect, $lang->redirect_postrestored); - } - } - else - { - error_no_permission(); - } - } - } - else - { - error($lang->redirect_norestore); - } -} - -if($mybb->input['action'] == "do_editpost" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("editpost_do_editpost_start"); - - // Set up posthandler. - require_once MYBB_ROOT."inc/datahandlers/post.php"; - $posthandler = new PostDataHandler("update"); - $posthandler->action = "post"; - - // Set the post data that came from the input to the $post array. - $post = array( - "pid" => $mybb->input['pid'], - "prefix" => $mybb->get_input('threadprefix', MyBB::INPUT_INT), - "subject" => $mybb->get_input('subject'), - "icon" => $mybb->get_input('icon', MyBB::INPUT_INT), - "uid" => $post['uid'], - "username" => $post['username'], - "edit_uid" => $mybb->user['uid'], - "message" => $mybb->get_input('message'), - "editreason" => $mybb->get_input('editreason'), - ); - - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - if(!isset($postoptions['signature'])) - { - $postoptions['signature'] = 0; - } - if(!isset($postoptions['subscriptionmethod'])) - { - $postoptions['subscriptionmethod'] = 0; - } - if(!isset($postoptions['disablesmilies'])) - { - $postoptions['disablesmilies'] = 0; - } - - // Set up the post options from the input. - $post['options'] = array( - "signature" => $postoptions['signature'], - "subscriptionmethod" => $postoptions['subscriptionmethod'], - "disablesmilies" => $postoptions['disablesmilies'] - ); - - $posthandler->set_data($post); - - // Now let the post handler do all the hard work. - if(!$posthandler->validate_post()) - { - $post_errors = $posthandler->get_friendly_errors(); - $post_errors = inline_error($post_errors); - $mybb->input['action'] = "editpost"; - } - // No errors were found, we can call the update method. - else - { - $postinfo = $posthandler->update_post(); - $visible = $postinfo['visible']; - $first_post = $postinfo['first_post']; - - // Help keep our attachments table clean. - $db->delete_query("attachments", "filename='' OR filesize<1"); - - // Did the user choose to post a poll? Redirect them to the poll posting page. - if($mybb->get_input('postpoll', MyBB::INPUT_INT) && $forumpermissions['canpostpolls']) - { - $url = "polls.php?action=newpoll&tid=$tid&polloptions=".$mybb->get_input('numpolloptions', MyBB::INPUT_INT); - $lang->redirect_postedited = $lang->redirect_postedited_poll; - } - else if($visible == 0 && $first_post && !is_moderator($fid, "canviewunapprove", $mybb->user['uid'])) - { - // Moderated post - $lang->redirect_postedited .= $lang->redirect_thread_moderation; - $url = get_forum_link($fid); - } - else if($visible == 0 && !is_moderator($fid, "canviewunapprove", $mybb->user['uid'])) - { - $lang->redirect_postedited .= $lang->redirect_post_moderation; - $url = get_thread_link($tid); - } - // Otherwise, send them back to their post - else - { - $lang->redirect_postedited .= $lang->redirect_postedited_redirect; - $url = get_post_link($pid, $tid)."#pid{$pid}"; - } - $plugins->run_hooks("editpost_do_editpost_end"); - - redirect($url, $lang->redirect_postedited); - } -} - -if(!$mybb->input['action'] || $mybb->input['action'] == "editpost") -{ - $plugins->run_hooks("editpost_action_start"); - - if(!isset($mybb->input['previewpost'])) - { - $icon = $post['icon']; - } - - if($forum['allowpicons'] != 0) - { - $posticons = get_post_icons(); - } - - $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); - eval("\$loginbox = \"".$templates->get("changeuserbox")."\";"); - - $deletebox = ''; - // Can we delete posts? - if($post['visible'] != -1 && (is_moderator($fid, "candeleteposts") || $forumpermissions['candeleteposts'] == 1 && $mybb->user['uid'] == $post['uid'])) - { - eval("\$deletebox = \"".$templates->get("editpost_delete")."\";"); - } - - $bgcolor = "trow1"; - if($mybb->settings['enableattachments'] != 0 && $forumpermissions['canpostattachments'] != 0) - { // Get a listing of the current attachments, if there are any - $attachcount = 0; - $query = $db->simple_select("attachments", "*", "pid='{$pid}'"); - $attachments = ''; - while($attachment = $db->fetch_array($query)) - { - $attachment['size'] = get_friendly_size($attachment['filesize']); - $attachment['icon'] = get_attachment_icon(get_extension($attachment['filename'])); - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - - if($mybb->settings['bbcodeinserter'] != 0 && $forum['allowmycode'] != 0 && $mybb->user['showcodebuttons'] != 0) - { - eval("\$postinsert = \"".$templates->get("post_attachments_attachment_postinsert")."\";"); - } - // Moderating options - $attach_mod_options = ''; - if(is_moderator($fid)) - { - if($attachment['visible'] == 1) - { - eval("\$attach_mod_options = \"".$templates->get("post_attachments_attachment_mod_unapprove")."\";"); - } - else - { - eval("\$attach_mod_options = \"".$templates->get("post_attachments_attachment_mod_approve")."\";"); - } - } - - // Remove Attachment - eval("\$attach_rem_options = \"".$templates->get("post_attachments_attachment_remove")."\";"); - - if($attachment['visible'] != 1) - { - eval("\$attachments .= \"".$templates->get("post_attachments_attachment_unapproved")."\";"); - } - else - { - eval("\$attachments .= \"".$templates->get("post_attachments_attachment")."\";"); - } - $attachcount++; - } - $query = $db->simple_select("attachments", "SUM(filesize) AS ausage", "uid='".$mybb->user['uid']."'"); - $usage = $db->fetch_array($query); - if($usage['ausage'] > ($mybb->usergroup['attachquota']*1024) && $mybb->usergroup['attachquota'] != 0) - { - $noshowattach = 1; - } - else - { - $noshowattach = 0; - } - if($mybb->usergroup['attachquota'] == 0) - { - $friendlyquota = $lang->unlimited; - } - else - { - $friendlyquota = get_friendly_size($mybb->usergroup['attachquota']*1024); - } - $friendlyusage = get_friendly_size($usage['ausage']); - $lang->attach_quota = $lang->sprintf($lang->attach_quota, $friendlyusage, $friendlyquota); - if($mybb->settings['maxattachments'] == 0 || ($mybb->settings['maxattachments'] != 0 && $attachcount < $mybb->settings['maxattachments']) && !$noshowattach) - { - eval("\$attach_add_options = \"".$templates->get("post_attachments_add")."\";"); - } - - if(($mybb->usergroup['caneditattachments'] || $forumpermissions['caneditattachments']) && $attachcount > 0) - { - eval("\$attach_update_options = \"".$templates->get("post_attachments_update")."\";"); - } - - if($attach_add_options || $attach_update_options) - { - eval("\$newattach = \"".$templates->get("post_attachments_new")."\";"); - } - eval("\$attachbox = \"".$templates->get("post_attachments")."\";"); - } - if(!$mybb->get_input('attachmentaid', MyBB::INPUT_INT) && !$mybb->get_input('newattachment') && !$mybb->get_input('updateattachment') && !isset($mybb->input['previewpost'])) - { - $message = $post['message']; - $subject = $post['subject']; - $reason = htmlspecialchars_uni($post['editreason']); - } - else - { - $message = $mybb->get_input('message'); - $subject = $mybb->get_input('subject'); - $reason = htmlspecialchars_uni($mybb->get_input('editreason')); - } - - if(!isset($post_errors)) - { - $post_errors = ''; - } - - $postoptions_subscriptionmethod_dont = $postoptions_subscriptionmethod_none = $postoptions_subscriptionmethod_email = $postoptions_subscriptionmethod_pm = ''; - $postoptionschecked = array('signature' => '', 'disablesmilies' => ''); - - if(!empty($mybb->input['previewpost']) || $post_errors) - { - // Set up posthandler. - require_once MYBB_ROOT."inc/datahandlers/post.php"; - $posthandler = new PostDataHandler("update"); - $posthandler->action = "post"; - - // Set the post data that came from the input to the $post array. - $post = array( - "pid" => $mybb->input['pid'], - "prefix" => $mybb->get_input('threadprefix', MyBB::INPUT_INT), - "subject" => $mybb->get_input('subject'), - "icon" => $mybb->get_input('icon', MyBB::INPUT_INT), - "uid" => $post['uid'], - "username" => $post['username'], - "edit_uid" => $mybb->user['uid'], - "message" => $mybb->get_input('message'), - ); - - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - if(!isset($postoptions['signature'])) - { - $postoptions['signature'] = 0; - } - if(!isset($postoptions['emailnotify'])) - { - $postoptions['emailnotify'] = 0; - } - if(!isset($postoptions['disablesmilies'])) - { - $postoptions['disablesmilies'] = 0; - } - - // Set up the post options from the input. - $post['options'] = array( - "signature" => $postoptions['signature'], - "emailnotify" => $postoptions['emailnotify'], - "disablesmilies" => $postoptions['disablesmilies'] - ); - - $posthandler->set_data($post); - - // Now let the post handler do all the hard work. - if(!$posthandler->validate_post()) - { - $post_errors = $posthandler->get_friendly_errors(); - $post_errors = inline_error($post_errors); - $mybb->input['action'] = "editpost"; - $mybb->input['previewpost'] = 0; - } - else - { - $previewmessage = $message; - $previewsubject = $subject; - $message = htmlspecialchars_uni($message); - $subject = htmlspecialchars_uni($subject); - - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - - if(isset($postoptions['signature']) && $postoptions['signature'] == 1) - { - $postoptionschecked['signature'] = " checked=\"checked\""; - } - - if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "none") - { - $postoptions_subscriptionmethod_none = "checked=\"checked\""; - } - else if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "email") - { - $postoptions_subscriptionmethod_email = "checked=\"checked\""; - } - else if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "pm") - { - $postoptions_subscriptionmethod_pm = "checked=\"checked\""; - } - else - { - $postoptions_subscriptionmethod_dont = "checked=\"checked\""; - } - - if(isset($postoptions['disablesmilies']) && $postoptions['disablesmilies'] == 1) - { - $postoptionschecked['disablesmilies'] = " checked=\"checked\""; - } - } - } - - if(!empty($mybb->input['previewpost'])) - { - if(!$post['uid']) - { - $query = $db->simple_select('posts', 'username, dateline', "pid='{$pid}'"); - $postinfo = $db->fetch_array($query); - } - else - { - // Figure out the poster's other information. - $query = $db->query(" - SELECT u.*, f.*, p.dateline - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.uid=u.uid) - WHERE u.uid='{$post['uid']}' AND p.pid='{$pid}' - LIMIT 1 - "); - $postinfo = $db->fetch_array($query); - $postinfo['userusername'] = $postinfo['username']; - } - - $query = $db->simple_select("attachments", "*", "pid='{$pid}'"); - while($attachment = $db->fetch_array($query)) - { - $attachcache[0][$attachment['aid']] = $attachment; - } - - if(!isset($postoptions['disablesmilies'])) - { - $postoptions['disablesmilies'] = 0; - } - - // Set the values of the post info array. - $postinfo['message'] = $previewmessage; - $postinfo['subject'] = $previewsubject; - $postinfo['icon'] = $icon; - $postinfo['smilieoff'] = $postoptions['disablesmilies']; - - $postbit = build_postbit($postinfo, 1); - eval("\$preview = \"".$templates->get("previewpost")."\";"); - } - else if(!$post_errors) - { - $message = htmlspecialchars_uni($message); - $subject = htmlspecialchars_uni($subject); - - $preview = ''; - - if($post['includesig'] != 0) - { - $postoptionschecked['signature'] = " checked=\"checked\""; - } - - if($post['smilieoff'] == 1) - { - $postoptionschecked['disablesmilies'] = " checked=\"checked\""; - } - - $query = $db->simple_select("threadsubscriptions", "notification", "tid='{$tid}' AND uid='{$mybb->user['uid']}'"); - if($db->num_rows($query) > 0) - { - $notification = $db->fetch_field($query, 'notification'); - - if($notification == 0) - { - $postoptions_subscriptionmethod_none = "checked=\"checked\""; - } - else if($notification == 1) - { - $postoptions_subscriptionmethod_email = "checked=\"checked\""; - } - else if($notification == 2) - { - $postoptions_subscriptionmethod_pm = "checked=\"checked\""; - } - else - { - $postoptions_subscriptionmethod_dont = "checked=\"checked\""; - } - } - } - - // Generate thread prefix selector if this is the first post of the thread - if($thread['firstpost'] == $pid) - { - if(!$mybb->get_input('threadprefix', MyBB::INPUT_INT)) - { - $mybb->input['threadprefix'] = $thread['prefix']; - } - - $prefixselect = build_prefix_select($forum['fid'], $mybb->get_input('threadprefix', MyBB::INPUT_INT), 0, $thread['prefix']); - } - else - { - $prefixselect = ""; - } - - $editreason = ''; - if($mybb->settings['alloweditreason'] == 1) - { - eval("\$editreason = \"".$templates->get("editpost_reason")."\";"); - $bgcolor = "trow2"; - $bgcolor2 = "trow1"; - } - else - { - $bgcolor = "trow1"; - $bgcolor2 = "trow2"; - } - - // Fetch subscription select box - eval("\$subscriptionmethod = \"".$templates->get("post_subscription_method")."\";"); - - $query = $db->simple_select("posts", "*", "tid='{$tid}'", array("limit" => 1, "order_by" => "dateline", "order_dir" => "asc")); - $firstcheck = $db->fetch_array($query); - - $time = TIME_NOW; - if($firstcheck['pid'] == $pid && $forumpermissions['canpostpolls'] != 0 && $thread['poll'] < 1 && (is_moderator($fid, "canmanagepolls") || $thread['dateline'] > ($time-($mybb->settings['polltimelimit']*60*60)) || $mybb->settings['polltimelimit'] == 0)) - { - $lang->max_options = $lang->sprintf($lang->max_options, $mybb->settings['maxpolloptions']); - $numpolloptions = $mybb->get_input('numpolloptions', MyBB::INPUT_INT); - $postpollchecked = ''; - - if($numpolloptions < 1) - { - $numpolloptions = 2; - } - - if($mybb->get_input('postpoll', MyBB::INPUT_INT) == 1) - { - $postpollchecked = 'checked="checked"'; - } - - eval("\$pollbox = \"".$templates->get("newthread_postpoll")."\";"); - } - else - { - $pollbox = ''; - } - - // Hide signature option if no permission - $signature = ''; - if($mybb->usergroup['canusesig'] == 1 && !$mybb->user['suspendsignature']) - { - eval("\$signature = \"".$templates->get('editpost_signature')."\";"); - } - - // Can we disable smilies or are they disabled already? - $disablesmilies = ''; - if($forum['allowsmilies'] != 0) - { - eval("\$disablesmilies = \"".$templates->get("editpost_disablesmilies")."\";"); - } - - $postoptions = ''; - if(!empty($signature) || !empty($disablesmilies)) - { - eval("\$postoptions = \"".$templates->get("editpost_postoptions")."\";"); - } - - $moderation_notice = ''; - if(!is_moderator($forum['fid'], "canapproveunapproveattachs")) - { - if($forumpermissions['modattachments'] == 1 && $forumpermissions['canpostattachments'] != 0) - { - $moderation_text = $lang->moderation_forum_attachments; - eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); - } - } - - if(!is_moderator($forum['fid'], "canapproveunapproveposts")) - { - if($forumpermissions['mod_edit_posts'] == 1) - { - $moderation_text = $lang->moderation_forum_edits; - eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); - } - } - - $plugins->run_hooks("editpost_end"); - - $forum['name'] = strip_tags($forum['name']); - - eval("\$editpost = \"".$templates->get("editpost")."\";"); - output_page($editpost); -} diff --git a/html/forums/forumdisplay.php b/html/forums/forumdisplay.php deleted file mode 100644 index fc49efc..0000000 --- a/html/forums/forumdisplay.php +++ /dev/null @@ -1,1498 +0,0 @@ - '', 'subject' => '', 'starter' => '', 'started' => '', 'replies' => '', 'views' => '', 'lastpost' => ''); -$ordersel = array('asc' => '', 'desc' => ''); -$datecutsel = array(1 => '', 5 => '', 10 => '', 20 => '', 50 => '', 75 => '', 100 => '', 365 => '', 9999 => ''); -$rules = ''; - -// Load global language phrases -$lang->load("forumdisplay"); - -$plugins->run_hooks("forumdisplay_start"); - -$fid = $mybb->get_input('fid', MyBB::INPUT_INT); -if($fid < 0) -{ - switch($fid) - { - case "-1": - $location = "index.php"; - break; - case "-2": - $location = "search.php"; - break; - case "-3": - $location = "usercp.php"; - break; - case "-4": - $location = "private.php"; - break; - case "-5": - $location = "online.php"; - break; - } - if($location) - { - header("Location: ".$location); - exit; - } -} - -// Get forum info -$foruminfo = get_forum($fid); -if(!$foruminfo) -{ - error($lang->error_invalidforum); -} - -$archive_url = build_archive_link("forum", $fid); - -$currentitem = $fid; -build_forum_breadcrumb($fid); -$parentlist = $foruminfo['parentlist']; - -// To validate, turn & to & but support unicode -$foruminfo['name'] = preg_replace("#&(?!\#[0-9]+;)#si", "&", $foruminfo['name']); - -$forumpermissions = forum_permissions(); -$fpermissions = $forumpermissions[$fid]; - -if($fpermissions['canview'] != 1) -{ - error_no_permission(); -} - -if($mybb->user['uid'] == 0) -{ - // Cookie'd forum read time - $forumsread = array(); - if(isset($mybb->cookies['mybb']['forumread'])) - { - $forumsread = my_unserialize($mybb->cookies['mybb']['forumread']); - } - - if(is_array($forumsread) && empty($forumsread)) - { - if(isset($mybb->cookies['mybb']['readallforums'])) - { - $forumsread[$fid] = $mybb->cookies['mybb']['lastvisit']; - } - else - { - $forumsread = array(); - } - } - - $query = $db->simple_select("forums", "*", "active != 0", array("order_by" => "pid, disporder")); -} -else -{ - // Build a forum cache from the database - $query = $db->query(" - SELECT f.*, fr.dateline AS lastread - FROM ".TABLE_PREFIX."forums f - LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}') - WHERE f.active != 0 - ORDER BY pid, disporder - "); -} - -while($forum = $db->fetch_array($query)) -{ - if($mybb->user['uid'] == 0 && isset($forumsread[$forum['fid']])) - { - $forum['lastread'] = $forumsread[$forum['fid']]; - } - - $fcache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; -} - -// Get the forum moderators if the setting is enabled. -if($mybb->settings['modlist'] != 0) -{ - $moderatorcache = $cache->read("moderators"); -} - -$bgcolor = "trow1"; -if($mybb->settings['subforumsindex'] != 0) -{ - $showdepth = 3; -} -else -{ - $showdepth = 2; -} - -$subforums = ''; -$child_forums = build_forumbits($fid, 2); -$forums = $child_forums['forum_list']; - -if($forums) -{ - $lang->sub_forums_in = $lang->sprintf($lang->sub_forums_in, $foruminfo['name']); - eval("\$subforums = \"".$templates->get("forumdisplay_subforums")."\";"); -} - -$excols = "forumdisplay"; - -// Password protected forums -check_forum_password($foruminfo['fid']); - -if($foruminfo['linkto']) -{ - header("Location: {$foruminfo['linkto']}"); - exit; -} - -// Make forum jump... -if($mybb->settings['enableforumjump'] != 0) -{ - $forumjump = build_forum_jump("", $fid, 1); -} - -if($foruminfo['type'] == "f" && $foruminfo['open'] != 0 && $fpermissions['canpostthreads'] != 0 && $mybb->user['suspendposting'] == 0) -{ - eval("\$newthread = \"".$templates->get("forumdisplay_newthread")."\";"); -} - -if($fpermissions['cansearch'] != 0 && $foruminfo['type'] == "f") -{ - eval("\$searchforum = \"".$templates->get("forumdisplay_searchforum")."\";"); -} - -// Gather forum stats -$has_announcements = $has_modtools = false; -$forum_stats = $cache->read("forumsdisplay"); - -if(is_array($forum_stats)) -{ - if(!empty($forum_stats[-1]['modtools']) || !empty($forum_stats[$fid]['modtools'])) - { - // Mod tools are specific to forums, not parents - $has_modtools = true; - } - - if(!empty($forum_stats[-1]['announcements']) || !empty($forum_stats[$fid]['announcements'])) - { - // Global or forum-specific announcements - $has_announcements = true; - } -} - -$done_moderators = array( - "users" => array(), - "groups" => array() -); - -$moderators = ''; -$parentlistexploded = explode(",", $parentlist); - -foreach($parentlistexploded as $mfid) -{ - // This forum has moderators - if(is_array($moderatorcache[$mfid])) - { - // Fetch each moderator from the cache and format it, appending it to the list - foreach($moderatorcache[$mfid] as $modtype) - { - foreach($modtype as $moderator) - { - if($moderator['isgroup']) - { - if(in_array($moderator['id'], $done_moderators['groups'])) - { - continue; - } - - $moderator['title'] = htmlspecialchars_uni($moderator['title']); - - eval("\$moderators .= \"".$templates->get("forumbit_moderators_group", 1, 0)."\";"); - $done_moderators['groups'][] = $moderator['id']; - } - else - { - if(in_array($moderator['id'], $done_moderators['users'])) - { - continue; - } - - $moderator['profilelink'] = get_profile_link($moderator['id']); - $moderator['username'] = format_name(htmlspecialchars_uni($moderator['username']), $moderator['usergroup'], $moderator['displaygroup']); - - eval("\$moderators .= \"".$templates->get("forumbit_moderators_user", 1, 0)."\";"); - $done_moderators['users'][] = $moderator['id']; - } - $comma = $lang->comma; - } - } - } - - if(!empty($forum_stats[$mfid]['announcements'])) - { - $has_announcements = true; - } -} -$comma = ''; - -// If we have a moderators list, load the template -if($moderators) -{ - eval("\$moderatedby = \"".$templates->get("forumdisplay_moderatedby")."\";"); -} -else -{ - $moderatedby = ''; -} - -// Get the users browsing this forum. -if($mybb->settings['browsingthisforum'] != 0) -{ - $timecut = TIME_NOW - $mybb->settings['wolcutoff']; - - $comma = ''; - $guestcount = 0; - $membercount = 0; - $inviscount = 0; - $onlinemembers = ''; - $doneusers = array(); - - $query = $db->query(" - SELECT s.ip, s.uid, u.username, s.time, u.invisible, u.usergroup, u.usergroup, u.displaygroup - FROM ".TABLE_PREFIX."sessions s - LEFT JOIN ".TABLE_PREFIX."users u ON (s.uid=u.uid) - WHERE s.time > '$timecut' AND location1='$fid' AND nopermission != 1 - ORDER BY u.username ASC, s.time DESC - "); - - while($user = $db->fetch_array($query)) - { - if($user['uid'] == 0) - { - ++$guestcount; - } - else - { - if(empty($doneusers[$user['uid']]) || $doneusers[$user['uid']] < $user['time']) - { - $doneusers[$user['uid']] = $user['time']; - ++$membercount; - if($user['invisible'] == 1) - { - $invisiblemark = "*"; - ++$inviscount; - } - else - { - $invisiblemark = ''; - } - - if($user['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid']) - { - $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); - $user['profilelink'] = build_profile_link($user['username'], $user['uid']); - eval("\$onlinemembers .= \"".$templates->get("forumdisplay_usersbrowsing_user", 1, 0)."\";"); - $comma = $lang->comma; - } - } - } - } - - $guestsonline = ''; - if($guestcount) - { - $guestsonline = $lang->sprintf($lang->users_browsing_forum_guests, $guestcount); - } - - $invisonline = ''; - if($mybb->user['invisible'] == 1) - { - // the user was counted as invisible user --> correct the inviscount - $inviscount -= 1; - } - if($inviscount && $mybb->usergroup['canviewwolinvis'] != 1) - { - $invisonline = $lang->sprintf($lang->users_browsing_forum_invis, $inviscount); - } - - - $onlinesep = ''; - if($invisonline != '' && $onlinemembers) - { - $onlinesep = $lang->comma; - } - - $onlinesep2 = ''; - if($invisonline != '' && $guestcount || $onlinemembers && $guestcount) - { - $onlinesep2 = $lang->comma; - } - - eval("\$usersbrowsing = \"".$templates->get("forumdisplay_usersbrowsing")."\";"); -} - -// Do we have any forum rules to show for this forum? -$forumrules = ''; -if($foruminfo['rulestype'] != 0 && $foruminfo['rules']) -{ - if(!$foruminfo['rulestitle']) - { - $foruminfo['rulestitle'] = $lang->sprintf($lang->forum_rules, $foruminfo['name']); - } - - $rules_parser = array( - "allow_html" => 1, - "allow_mycode" => 1, - "allow_smilies" => 1, - "allow_imgcode" => 1 - ); - - $foruminfo['rules'] = $parser->parse_message($foruminfo['rules'], $rules_parser); - if($foruminfo['rulestype'] == 1 || $foruminfo['rulestype'] == 3) - { - eval("\$rules = \"".$templates->get("forumdisplay_rules")."\";"); - } - else if($foruminfo['rulestype'] == 2) - { - eval("\$rules = \"".$templates->get("forumdisplay_rules_link")."\";"); - } -} - -$bgcolor = "trow1"; - -// Set here to fetch only approved/deleted topics (and then below for a moderator we change this). -if($fpermissions['canviewdeletionnotice'] != 0) -{ - $visibleonly = "AND visible IN (-1,1)"; - $tvisibleonly = "AND t.visible IN (-1,1)"; -} -else -{ - $visibleonly = "AND visible='1'"; - $tvisibleonly = "AND t.visible='1'"; -} - -// Check if the active user is a moderator and get the inline moderation tools. -if(is_moderator($fid)) -{ - eval("\$inlinemodcol = \"".$templates->get("forumdisplay_inlinemoderation_col")."\";"); - $ismod = true; - $inlinecount = "0"; - $inlinemod = ''; - $inlinecookie = "inlinemod_forum".$fid; - - if(is_moderator($fid, "canviewdeleted") == true || is_moderator($fid, "canviewunapprove") == true) - { - if(is_moderator($fid, "canviewunapprove") == true && is_moderator($fid, "canviewdeleted") == false) - { - $visibleonly = "AND visible IN (0,1)"; - $tvisibleonly = "AND t.visible IN (0,1)"; - } - elseif(is_moderator($fid, "canviewdeleted") == true && is_moderator($fid, "canviewunapprove") == false) - { - $visibleonly = "AND visible IN (-1,1)"; - $tvisibleonly = "AND t.visible IN (-1,1)"; - } - else - { - $visibleonly = " AND visible IN (-1,0,1)"; - $tvisibleonly = " AND t.visible IN (-1,0,1)"; - } - } -} -else -{ - $inlinemod = $inlinemodcol = ''; - $ismod = false; -} - -if(is_moderator($fid, "caneditposts") || $fpermissions['caneditposts'] == 1) -{ - $can_edit_titles = 1; -} -else -{ - $can_edit_titles = 0; -} - -unset($rating); - -// Pick out some sorting options. -// First, the date cut for the threads. -$datecut = 9999; -if(empty($mybb->input['datecut'])) -{ - // If the user manually set a date cut, use it. - if(!empty($mybb->user['daysprune'])) - { - $datecut = $mybb->user['daysprune']; - } - else - { - // If the forum has a non-default date cut, use it. - if(!empty($foruminfo['defaultdatecut'])) - { - $datecut = $foruminfo['defaultdatecut']; - } - } -} -// If there was a manual date cut override, use it. -else -{ - $datecut = $mybb->get_input('datecut', MyBB::INPUT_INT); -} - -$datecutsel[(int)$datecut] = ' selected="selected"'; -if($datecut > 0 && $datecut != 9999) -{ - $checkdate = TIME_NOW - ($datecut * 86400); - $datecutsql = "AND (lastpost >= '$checkdate' OR sticky = '1')"; - $datecutsql2 = "AND (t.lastpost >= '$checkdate' OR t.sticky = '1')"; -} -else -{ - $datecutsql = ''; - $datecutsql2 = ''; -} - -// Sort by thread prefix -$tprefix = $mybb->get_input('prefix', MyBB::INPUT_INT); -if($tprefix > 0) -{ - $prefixsql = "AND prefix = {$tprefix}"; - $prefixsql2 = "AND t.prefix = {$tprefix}"; -} -else if($tprefix == -1) -{ - $prefixsql = "AND prefix = 0"; - $prefixsql2 = "AND t.prefix = 0"; -} -else if($tprefix == -2) -{ - $prefixsql = "AND prefix != 0"; - $prefixsql2 = "AND t.prefix != 0"; -} -else -{ - $prefixsql = $prefixsql2 = ''; -} - -// Pick the sort order. -if(!isset($mybb->input['order']) && !empty($foruminfo['defaultsortorder'])) -{ - $mybb->input['order'] = $foruminfo['defaultsortorder']; -} -else -{ - $mybb->input['order'] = $mybb->get_input('order'); -} - -$mybb->input['order'] = htmlspecialchars_uni($mybb->get_input('order')); - -switch(my_strtolower($mybb->input['order'])) -{ - case "asc": - $sortordernow = "asc"; - $ordersel['asc'] = ' selected="selected"'; - $oppsort = $lang->desc; - $oppsortnext = "desc"; - break; - default: - $sortordernow = "desc"; - $ordersel['desc'] = ' selected="selected"'; - $oppsort = $lang->asc; - $oppsortnext = "asc"; - break; -} - -// Sort by which field? -if(!isset($mybb->input['sortby']) && !empty($foruminfo['defaultsortby'])) -{ - $mybb->input['sortby'] = $foruminfo['defaultsortby']; -} -else -{ - $mybb->input['sortby'] = $mybb->get_input('sortby'); -} - -$t = 't.'; -$sortfield2 = ''; - -$sortby = htmlspecialchars_uni($mybb->input['sortby']); - -switch($mybb->input['sortby']) -{ - case "subject": - $sortfield = "subject"; - break; - case "replies": - $sortfield = "replies"; - break; - case "views": - $sortfield = "views"; - break; - case "starter": - $sortfield = "username"; - break; - case "rating": - $t = ""; - $sortfield = "averagerating"; - $sortfield2 = ", t.totalratings DESC"; - break; - case "started": - $sortfield = "dateline"; - break; - default: - $sortby = "lastpost"; - $sortfield = "lastpost"; - $mybb->input['sortby'] = "lastpost"; - break; -} - -$sortsel['rating'] = ''; // Needs to be initialized in order to speed-up things. Fixes #2031 -$sortsel[$mybb->input['sortby']] = ' selected="selected"'; - -// Pick the right string to join the sort URL -if($mybb->seo_support == true) -{ - $string = "?"; -} -else -{ - $string = "&"; -} - -// Are we viewing a specific page? -$mybb->input['page'] = $mybb->get_input('page', MyBB::INPUT_INT); -if($mybb->input['page'] > 1) -{ - $sorturl = get_forum_link($fid, $mybb->input['page']).$string."datecut=$datecut&prefix=$tprefix"; -} -else -{ - $sorturl = get_forum_link($fid).$string."datecut=$datecut&prefix=$tprefix"; -} - -eval("\$orderarrow['$sortby'] = \"".$templates->get("forumdisplay_orderarrow")."\";"); - -$threadcount = 0; -$useronly = $tuseronly = ""; -if(isset($fpermissions['canonlyviewownthreads']) && $fpermissions['canonlyviewownthreads'] == 1) -{ - $useronly = "AND uid={$mybb->user['uid']}"; - $tuseronly = "AND t.uid={$mybb->user['uid']}"; -} - -if($fpermissions['canviewthreads'] != 0) -{ - // How many posts are there? - if(($datecut > 0 && $datecut != 9999) || isset($fpermissions['canonlyviewownthreads']) && $fpermissions['canonlyviewownthreads'] == 1) - { - $query = $db->simple_select("threads", "COUNT(tid) AS threads", "fid = '$fid' $useronly $visibleonly $datecutsql $prefixsql"); - $threadcount = $db->fetch_field($query, "threads"); - } - else - { - $query = $db->simple_select("forums", "threads, unapprovedthreads, deletedthreads", "fid = '{$fid}'", array('limit' => 1)); - $forum_threads = $db->fetch_array($query); - $threadcount = $forum_threads['threads']; - if($ismod == true) - { - $threadcount += $forum_threads['unapprovedthreads'] + $forum_threads['deletedthreads']; - } - - // If we have 0 threads double check there aren't any "moved" threads - if($threadcount == 0) - { - $query = $db->simple_select("threads", "COUNT(tid) AS threads", "fid = '$fid' $useronly $visibleonly", array('limit' => 1)); - $threadcount = $db->fetch_field($query, "threads"); - } - } -} - -// How many pages are there? -if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) -{ - $mybb->settings['threadsperpage'] = 20; -} - -$perpage = $mybb->settings['threadsperpage']; - -if($mybb->input['page'] > 0) -{ - $page = $mybb->input['page']; - $start = ($page-1) * $perpage; - $pages = $threadcount / $perpage; - $pages = ceil($pages); - if($page > $pages || $page <= 0) - { - $start = 0; - $page = 1; - } -} -else -{ - $start = 0; - $page = 1; -} - -$end = $start + $perpage; -$lower = $start + 1; -$upper = $end; - -if($upper > $threadcount) -{ - $upper = $threadcount; -} - -// Assemble page URL -if($mybb->input['sortby'] || $mybb->input['order'] || $mybb->input['datecut'] || $mybb->input['prefix']) // Ugly URL -{ - $page_url = str_replace("{fid}", $fid, FORUM_URL_PAGED); - - if($mybb->seo_support == true) - { - $q = "?"; - $and = ''; - } - else - { - $q = ''; - $and = "&"; - } - - if((!empty($foruminfo['defaultsortby']) && $sortby != $foruminfo['defaultsortby']) || (empty($foruminfo['defaultsortby']) && $sortby != "lastpost")) - { - $page_url .= "{$q}{$and}sortby={$sortby}"; - $q = ''; - $and = "&"; - } - - if($sortordernow != "desc") - { - $page_url .= "{$q}{$and}order={$sortordernow}"; - $q = ''; - $and = "&"; - } - - if($datecut > 0 && $datecut != 9999) - { - $page_url .= "{$q}{$and}datecut={$datecut}"; - $q = ''; - $and = "&"; - } - - if($tprefix != 0) - { - $page_url .= "{$q}{$and}prefix={$tprefix}"; - } -} -else -{ - $page_url = str_replace("{fid}", $fid, FORUM_URL_PAGED); -} -$multipage = multipage($threadcount, $perpage, $page, $page_url); - -if($mybb->settings['allowthreadratings'] != 0 && $foruminfo['allowtratings'] != 0 && $fpermissions['canviewthreads'] != 0) -{ - $lang->load("ratethread"); - - switch($db->type) - { - case "pgsql": - $ratingadd = "CASE WHEN t.numratings=0 THEN 0 ELSE t.totalratings/t.numratings::numeric END AS averagerating, "; - break; - default: - $ratingadd = "(t.totalratings/t.numratings) AS averagerating, "; - } - - $lpbackground = "trow2"; - eval("\$ratingcol = \"".$templates->get("forumdisplay_threadlist_rating")."\";"); - eval("\$ratingsort = \"".$templates->get("forumdisplay_threadlist_sortrating")."\";"); - $colspan = "7"; -} -else -{ - if($sortfield == "averagerating") - { - $t = "t."; - $sortfield = "lastpost"; - } - $ratingadd = ''; - $lpbackground = "trow1"; - $colspan = "6"; -} - -if($ismod) -{ - ++$colspan; -} - -// Get Announcements -$announcementlist = ''; -if($has_announcements == true) -{ - $limit = ''; - $announcements = ''; - if($mybb->settings['announcementlimit']) - { - $limit = "LIMIT 0, ".$mybb->settings['announcementlimit']; - } - - $sql = build_parent_list($fid, "fid", "OR", $parentlist); - $time = TIME_NOW; - $query = $db->query(" - SELECT a.*, u.username - FROM ".TABLE_PREFIX."announcements a - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=a.uid) - WHERE a.startdate<='$time' AND (a.enddate>='$time' OR a.enddate='0') AND ($sql OR fid='-1') - ORDER BY a.startdate DESC $limit - "); - - // See if this announcement has been read in our announcement array - $cookie = array(); - if(isset($mybb->cookies['mybb']['announcements'])) - { - $cookie = my_unserialize(stripslashes($mybb->cookies['mybb']['announcements'])); - } - - $announcementlist = ''; - $bgcolor = alt_trow(true); // Reset the trow colors - while($announcement = $db->fetch_array($query)) - { - if($announcement['startdate'] > $mybb->user['lastvisit'] && !$cookie[$announcement['aid']]) - { - $new_class = ' class="subject_new"'; - $folder = "newfolder"; - } - else - { - $new_class = ' class="subject_old"'; - $folder = "folder"; - } - - // Mmm, eat those announcement cookies if they're older than our last visit - if(isset($cookie[$announcement['aid']]) && $cookie[$announcement['aid']] < $mybb->user['lastvisit']) - { - unset($cookie[$announcement['aid']]); - } - - $announcement['announcementlink'] = get_announcement_link($announcement['aid']); - $announcement['subject'] = $parser->parse_badwords($announcement['subject']); - $announcement['subject'] = htmlspecialchars_uni($announcement['subject']); - $postdate = my_date('relative', $announcement['startdate']); - - $announcement['username'] = htmlspecialchars_uni($announcement['username']); - - $announcement['profilelink'] = build_profile_link($announcement['username'], $announcement['uid']); - - if($mybb->settings['allowthreadratings'] != 0 && $foruminfo['allowtratings'] != 0 && $fpermissions['canviewthreads'] != 0) - { - eval("\$rating = \"".$templates->get("forumdisplay_announcement_rating")."\";"); - $lpbackground = "trow2"; - } - else - { - $rating = ''; - $lpbackground = "trow1"; - } - - if($ismod) - { - eval("\$modann = \"".$templates->get("forumdisplay_announcements_announcement_modbit")."\";"); - } - else - { - $modann = ''; - } - - $plugins->run_hooks("forumdisplay_announcement"); - eval("\$announcements .= \"".$templates->get("forumdisplay_announcements_announcement")."\";"); - $bgcolor = alt_trow(); - } - - if($announcements) - { - eval("\$announcementlist = \"".$templates->get("forumdisplay_announcements")."\";"); - $shownormalsep = true; - } - - if(empty($cookie)) - { - // Clean up cookie crumbs - my_setcookie('mybb[announcements]', 0, (TIME_NOW - (60*60*24*365))); - } - else if(!empty($cookie)) - { - my_setcookie("mybb[announcements]", addslashes(my_serialize($cookie)), -1); - } -} -else -{ - $announcementlist = ''; -} - -$tids = $threadcache = array(); -$icon_cache = $cache->read("posticons"); - -if($fpermissions['canviewthreads'] != 0) -{ - $plugins->run_hooks("forumdisplay_get_threads"); - - // Start Getting Threads - $query = $db->query(" - SELECT t.*, {$ratingadd}t.username AS threadusername, u.username - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid = t.uid) - WHERE t.fid='$fid' $tuseronly $tvisibleonly $datecutsql2 $prefixsql2 - ORDER BY t.sticky DESC, {$t}{$sortfield} $sortordernow $sortfield2 - LIMIT $start, $perpage - "); - - $ratings = false; - $moved_threads = array(); - while($thread = $db->fetch_array($query)) - { - $threadcache[$thread['tid']] = $thread; - - if($thread['numratings'] > 0 && $ratings == false) - { - $ratings = true; // Looks for ratings in the forum - } - - // If this is a moved thread - set the tid for participation marking and thread read marking to that of the moved thread - if(substr($thread['closed'], 0, 5) == "moved") - { - $tid = substr($thread['closed'], 6); - if(!isset($tids[$tid])) - { - $moved_threads[$tid] = $thread['tid']; - $tids[$thread['tid']] = $tid; - } - } - // Otherwise - set it to the plain thread ID - else - { - $tids[$thread['tid']] = $thread['tid']; - if(isset($moved_threads[$thread['tid']])) - { - unset($moved_threads[$thread['tid']]); - } - } - } - - if($mybb->settings['allowthreadratings'] != 0 && $foruminfo['allowtratings'] != 0 && $mybb->user['uid'] && !empty($threadcache) && $ratings == true) - { - // Check if we've rated threads on this page - // Guests get the pleasure of not being ID'd, but will be checked when they try and rate - $imp = implode(",", array_keys($threadcache)); - $query = $db->simple_select("threadratings", "tid, uid", "tid IN ({$imp}) AND uid = '{$mybb->user['uid']}'"); - - while($rating = $db->fetch_array($query)) - { - $threadcache[$rating['tid']]['rated'] = 1; - } - } -} - -// If user has moderation tools available, prepare the Select All feature -$selectall = ''; -if(is_moderator($fid) && $threadcount > $perpage) -{ - $lang->page_selected = $lang->sprintf($lang->page_selected, count($threadcache)); - $lang->select_all = $lang->sprintf($lang->select_all, (int)$threadcount); - $lang->all_selected = $lang->sprintf($lang->all_selected, (int)$threadcount); - eval("\$selectall = \"".$templates->get("forumdisplay_inlinemoderation_selectall")."\";"); -} - -if(!empty($tids)) -{ - $tids = implode(",", $tids); -} - -// Check participation by the current user in any of these threads - for 'dot' folder icons -if($mybb->settings['dotfolders'] != 0 && $mybb->user['uid'] && !empty($threadcache)) -{ - $query = $db->simple_select("posts", "DISTINCT tid,uid", "uid='{$mybb->user['uid']}' AND tid IN ({$tids}) {$visibleonly}"); - while($post = $db->fetch_array($query)) - { - if(!empty($moved_threads[$post['tid']])) - { - $post['tid'] = $moved_threads[$post['tid']]; - } - if($threadcache[$post['tid']]) - { - $threadcache[$post['tid']]['doticon'] = 1; - } - } -} - -// Read threads -if($mybb->user['uid'] && $mybb->settings['threadreadcut'] > 0 && !empty($threadcache)) -{ - $query = $db->simple_select("threadsread", "*", "uid='{$mybb->user['uid']}' AND tid IN ({$tids})"); - while($readthread = $db->fetch_array($query)) - { - if(!empty($moved_threads[$readthread['tid']])) - { - $readthread['tid'] = $moved_threads[$readthread['tid']]; - } - if($threadcache[$readthread['tid']]) - { - $threadcache[$readthread['tid']]['lastread'] = $readthread['dateline']; - } - } -} - -if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid']) -{ - $query = $db->simple_select("forumsread", "dateline", "fid='{$fid}' AND uid='{$mybb->user['uid']}'"); - $forum_read = $db->fetch_field($query, "dateline"); - - $read_cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - if($forum_read == 0 || $forum_read < $read_cutoff) - { - $forum_read = $read_cutoff; - } -} -else -{ - $forum_read = my_get_array_cookie("forumread", $fid); - - if(isset($mybb->cookies['mybb']['readallforums']) && !$forum_read) - { - $forum_read = $mybb->cookies['mybb']['lastvisit']; - } -} - -$unreadpost = 0; -$threads = ''; -if(!empty($threadcache) && is_array($threadcache)) -{ - if(!$mybb->settings['maxmultipagelinks']) - { - $mybb->settings['maxmultipagelinks'] = 5; - } - - if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) - { - $mybb->settings['postsperpage'] = 20; - } - - foreach($threadcache as $thread) - { - $plugins->run_hooks("forumdisplay_thread"); - - $moved = explode("|", $thread['closed']); - - if($thread['visible'] == 0) - { - $bgcolor = "trow_shaded"; - } - elseif($thread['visible'] == -1 && is_moderator($fid, "canviewdeleted")) - { - $bgcolor = "trow_shaded trow_deleted"; - } - else - { - $bgcolor = alt_trow(); - } - - if($thread['sticky'] == 1) - { - $thread_type_class = " forumdisplay_sticky"; - } - else - { - $thread_type_class = " forumdisplay_regular"; - } - - $folder = ''; - $prefix = ''; - - $thread['author'] = $thread['uid']; - if(!$thread['username']) - { - $thread['username'] = $thread['profilelink'] = htmlspecialchars_uni($thread['threadusername']); - } - else - { - $thread['username'] = htmlspecialchars_uni($thread['username']); - $thread['profilelink'] = build_profile_link($thread['username'], $thread['uid']); - } - - // If this thread has a prefix, insert a space between prefix and subject - $thread['threadprefix'] = $threadprefix = ''; - if($thread['prefix'] != 0) - { - $threadprefix = build_prefixes($thread['prefix']); - if(!empty($threadprefix)) - { - $thread['threadprefix'] = $threadprefix['displaystyle'].' '; - } - } - - $thread['subject'] = $parser->parse_badwords($thread['subject']); - $thread['subject'] = htmlspecialchars_uni($thread['subject']); - - if($thread['icon'] > 0 && $icon_cache[$thread['icon']]) - { - $icon = $icon_cache[$thread['icon']]; - $icon['path'] = str_replace("{theme}", $theme['imgdir'], $icon['path']); - $icon['path'] = htmlspecialchars_uni($icon['path']); - $icon['name'] = htmlspecialchars_uni($icon['name']); - eval("\$icon = \"".$templates->get("forumdisplay_thread_icon")."\";"); - } - else - { - $icon = " "; - } - - $prefix = ''; - if($thread['poll']) - { - $prefix = $lang->poll_prefix; - } - - if($thread['sticky'] == "1" && !isset($donestickysep)) - { - eval("\$threads .= \"".$templates->get("forumdisplay_sticky_sep")."\";"); - $shownormalsep = true; - $donestickysep = true; - } - else if($thread['sticky'] == 0 && !empty($shownormalsep)) - { - eval("\$threads .= \"".$templates->get("forumdisplay_threads_sep")."\";"); - $shownormalsep = false; - } - - $rating = ''; - if($mybb->settings['allowthreadratings'] != 0 && $foruminfo['allowtratings'] != 0) - { - if($moved[0] == "moved" || ($fpermissions['canviewdeletionnotice'] != 0 && $thread['visible'] == -1)) - { - eval("\$rating = \"".$templates->get("forumdisplay_thread_rating_moved")."\";"); - } - else - { - $thread['averagerating'] = (float)round($thread['averagerating'], 2); - $thread['width'] = (int)round($thread['averagerating'])*20; - $thread['numratings'] = (int)$thread['numratings']; - - $not_rated = ''; - if(!isset($thread['rated']) || empty($thread['rated'])) - { - $not_rated = ' star_rating_notrated'; - } - - $ratingvotesav = $lang->sprintf($lang->rating_votes_average, $thread['numratings'], $thread['averagerating']); - eval("\$rating = \"".$templates->get("forumdisplay_thread_rating")."\";"); - } - } - - $thread['pages'] = 0; - $thread['multipage'] = ''; - $threadpages = ''; - $morelink = ''; - $thread['posts'] = $thread['replies'] + 1; - - if($thread['unapprovedposts'] > 0 && $ismod) - { - $thread['posts'] += $thread['unapprovedposts'] + $thread['deletedposts']; - } - - if($thread['posts'] > $mybb->settings['postsperpage']) - { - $thread['pages'] = $thread['posts'] / $mybb->settings['postsperpage']; - $thread['pages'] = ceil($thread['pages']); - - if($thread['pages'] > $mybb->settings['maxmultipagelinks']) - { - $pagesstop = $mybb->settings['maxmultipagelinks'] - 1; - $page_link = get_thread_link($thread['tid'], $thread['pages']); - eval("\$morelink = \"".$templates->get("forumdisplay_thread_multipage_more")."\";"); - } - else - { - $pagesstop = $thread['pages']; - } - - for($i = 1; $i <= $pagesstop; ++$i) - { - $page_link = get_thread_link($thread['tid'], $i); - eval("\$threadpages .= \"".$templates->get("forumdisplay_thread_multipage_page")."\";"); - } - - eval("\$thread['multipage'] = \"".$templates->get("forumdisplay_thread_multipage")."\";"); - } - else - { - $threadpages = ''; - $morelink = ''; - $thread['multipage'] = ''; - } - - if($ismod) - { - if(isset($mybb->cookies[$inlinecookie]) && my_strpos($mybb->cookies[$inlinecookie], "|{$thread['tid']}|")) - { - $inlinecheck = "checked=\"checked\""; - ++$inlinecount; - } - else - { - $inlinecheck = ''; - } - - $multitid = $thread['tid']; - eval("\$modbit = \"".$templates->get("forumdisplay_thread_modbit")."\";"); - } - else - { - $modbit = ''; - } - - if($moved[0] == "moved") - { - $prefix = $lang->moved_prefix; - $thread['tid'] = $moved[1]; - $thread['replies'] = "-"; - $thread['views'] = "-"; - } - - $thread['threadlink'] = get_thread_link($thread['tid']); - $thread['lastpostlink'] = get_thread_link($thread['tid'], 0, "lastpost"); - - // Determine the folder - $folder = ''; - $folder_label = ''; - - if(isset($thread['doticon'])) - { - $folder = "dot_"; - $folder_label .= $lang->icon_dot; - } - - $gotounread = ''; - $isnew = 0; - $donenew = 0; - - if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid'] && $thread['lastpost'] > $forum_read) - { - if(!empty($thread['lastread'])) - { - $last_read = $thread['lastread']; - } - else - { - $last_read = $read_cutoff; - } - } - else - { - $last_read = my_get_array_cookie("threadread", $thread['tid']); - } - - if($forum_read > $last_read) - { - $last_read = $forum_read; - } - - if($thread['lastpost'] > $last_read && $moved[0] != "moved") - { - $folder .= "new"; - $folder_label .= $lang->icon_new; - $new_class = "subject_new"; - $thread['newpostlink'] = get_thread_link($thread['tid'], 0, "newpost"); - eval("\$gotounread = \"".$templates->get("forumdisplay_thread_gotounread")."\";"); - $unreadpost = 1; - } - else - { - $folder_label .= $lang->icon_no_new; - $new_class = "subject_old"; - } - - if($thread['replies'] >= $mybb->settings['hottopic'] || $thread['views'] >= $mybb->settings['hottopicviews']) - { - $folder .= "hot"; - $folder_label .= $lang->icon_hot; - } - - if($thread['closed'] == 1) - { - $folder .= "lock"; - $folder_label .= $lang->icon_lock; - } - - if($moved[0] == "moved") - { - $folder = "move"; - $gotounread = ''; - } - - $folder .= "folder"; - - $inline_edit_tid = $thread['tid']; - - // If this user is the author of the thread and it is not closed or they are a moderator, they can edit - $inline_edit_class = ''; - if(($thread['uid'] == $mybb->user['uid'] && $thread['closed'] != 1 && $mybb->user['uid'] != 0 && $can_edit_titles == 1) || $ismod == true) - { - $inline_edit_class = "subject_editable"; - } - - $lastposter = htmlspecialchars_uni($thread['lastposter']); - $lastposteruid = $thread['lastposteruid']; - $lastpostdate = my_date('relative', $thread['lastpost']); - - // Don't link to guest's profiles (they have no profile). - if($lastposteruid == 0) - { - $lastposterlink = $lastposter; - } - else - { - $lastposterlink = build_profile_link($lastposter, $lastposteruid); - } - - $thread['replies'] = my_number_format($thread['replies']); - $thread['views'] = my_number_format($thread['views']); - - // Threads and posts requiring moderation - if($thread['unapprovedposts'] > 0 && is_moderator($fid, "canviewunapprove")) - { - if($thread['unapprovedposts'] > 1) - { - $unapproved_posts_count = $lang->sprintf($lang->thread_unapproved_posts_count, $thread['unapprovedposts']); - } - else - { - $unapproved_posts_count = $lang->sprintf($lang->thread_unapproved_post_count, 1); - } - - $thread['unapprovedposts'] = my_number_format($thread['unapprovedposts']); - eval("\$unapproved_posts = \"".$templates->get("forumdisplay_thread_unapproved_posts")."\";"); - } - else - { - $unapproved_posts = ''; - } - - // If this thread has 1 or more attachments show the papperclip - if($mybb->settings['enableattachments'] == 1 && $thread['attachmentcount'] > 0) - { - if($thread['attachmentcount'] > 1) - { - $attachment_count = $lang->sprintf($lang->attachment_count_multiple, $thread['attachmentcount']); - } - else - { - $attachment_count = $lang->attachment_count; - } - - eval("\$attachment_count = \"".$templates->get("forumdisplay_thread_attachment_count")."\";"); - } - else - { - $attachment_count = ''; - } - - $plugins->run_hooks("forumdisplay_thread_end"); - - if($fpermissions['canviewdeletionnotice'] != 0 && $thread['visible'] == -1 && !is_moderator($fid, "canviewdeleted")) - { - eval("\$threads .= \"".$templates->get("forumdisplay_thread_deleted")."\";"); - } - else - { - eval("\$threads .= \"".$templates->get("forumdisplay_thread")."\";"); - } - } - - $customthreadtools = $standardthreadtools = ''; - if($ismod) - { - if(is_moderator($fid, "canusecustomtools") && $has_modtools == true) - { - $gids = explode(',', $mybb->user['additionalgroups']); - $gids[] = $mybb->user['usergroup']; - $gids = array_filter(array_unique($gids)); - - $gidswhere = ''; - switch($db->type) - { - case "pgsql": - case "sqlite": - foreach($gids as $gid) - { - $gid = (int)$gid; - $gidswhere .= " OR ','||groups||',' LIKE '%,{$gid},%'"; - } - $query = $db->simple_select("modtools", 'tid, name', "(','||forums||',' LIKE '%,$fid,%' OR ','||forums||',' LIKE '%,-1,%' OR forums='') AND (groups='' OR ','||groups||',' LIKE '%,-1,%'{$gidswhere}) AND type = 't'"); - break; - default: - foreach($gids as $gid) - { - $gid = (int)$gid; - $gidswhere .= " OR CONCAT(',',groups,',') LIKE '%,{$gid},%'"; - } - $query = $db->simple_select("modtools", 'tid, name', "(CONCAT(',',forums,',') LIKE '%,$fid,%' OR CONCAT(',',forums,',') LIKE '%,-1,%' OR forums='') AND (groups='' OR CONCAT(',',groups,',') LIKE '%,-1,%'{$gidswhere}) AND type = 't'"); - break; - } - - while($tool = $db->fetch_array($query)) - { - eval("\$customthreadtools .= \"".$templates->get("forumdisplay_inlinemoderation_custom_tool")."\";"); - } - - if($customthreadtools) - { - eval("\$customthreadtools = \"".$templates->get("forumdisplay_inlinemoderation_custom")."\";"); - } - } - - $inlinemodopenclose = $inlinemodstickunstick = $inlinemodsoftdelete = $inlinemodrestore = $inlinemoddelete = $inlinemodmanage = $inlinemodapproveunapprove = ''; - - if(is_moderator($fid, "canopenclosethreads")) - { - eval("\$inlinemodopenclose = \"".$templates->get("forumdisplay_inlinemoderation_openclose")."\";"); - } - - if(is_moderator($fid, "canstickunstickthreads")) - { - eval("\$inlinemodstickunstick = \"".$templates->get("forumdisplay_inlinemoderation_stickunstick")."\";"); - } - - if(is_moderator($fid, "cansoftdeletethreads")) - { - eval("\$inlinemodsoftdelete = \"".$templates->get("forumdisplay_inlinemoderation_softdelete")."\";"); - } - - if(is_moderator($fid, "canrestorethreads")) - { - eval("\$inlinemodrestore = \"".$templates->get("forumdisplay_inlinemoderation_restore")."\";"); - } - - if(is_moderator($fid, "candeletethreads")) - { - eval("\$inlinemoddelete = \"".$templates->get("forumdisplay_inlinemoderation_delete")."\";"); - } - - if(is_moderator($fid, "canmanagethreads")) - { - eval("\$inlinemodmanage = \"".$templates->get("forumdisplay_inlinemoderation_manage")."\";"); - } - - if(is_moderator($fid, "canapproveunapprovethreads")) - { - eval("\$inlinemodapproveunapprove = \"".$templates->get("forumdisplay_inlinemoderation_approveunapprove")."\";"); - } - - if(!empty($inlinemodopenclose) || !empty($inlinemodstickunstick) || !empty($inlinemodsoftdelete) || !empty($inlinemodrestore) || !empty($inlinemoddelete) || !empty($inlinemodmanage) || !empty($inlinemodapproveunapprove)) - { - eval("\$standardthreadtools = \"".$templates->get("forumdisplay_inlinemoderation_standard")."\";"); - } - - // Only show inline mod menu if there's options to show - if(!empty($standardthreadtools) || !empty($customthreadtools)) - { - eval("\$inlinemod = \"".$templates->get("forumdisplay_inlinemoderation")."\";"); - } - } -} - -// If there are no unread threads in this forum and no unread child forums - mark it as read -require_once MYBB_ROOT."inc/functions_indicators.php"; - -$unread_threads = fetch_unread_count($fid); -if($unread_threads !== false && $unread_threads == 0 && empty($unread_forums)) -{ - mark_forum_read($fid); -} - -// Subscription status -$add_remove_subscription = 'add'; -$add_remove_subscription_text = $lang->subscribe_forum; - -if($mybb->user['uid']) -{ - $query = $db->simple_select("forumsubscriptions", "fid", "fid='".$fid."' AND uid='{$mybb->user['uid']}'", array('limit' => 1)); - - if($db->fetch_field($query, 'fid')) - { - $add_remove_subscription = 'remove'; - $add_remove_subscription_text = $lang->unsubscribe_forum; - } -} - -$inline_edit_js = $clearstoredpass = ''; - -// Is this a real forum with threads? -if($foruminfo['type'] != "c") -{ - if($fpermissions['canviewthreads'] != 1) - { - eval("\$threads = \"".$templates->get("forumdisplay_nopermission")."\";"); - } - - if(!$threadcount && $fpermissions['canviewthreads'] == 1) - { - eval("\$threads = \"".$templates->get("forumdisplay_nothreads")."\";"); - } - - $clearstoredpass = ''; - if($foruminfo['password'] != '') - { - eval("\$clearstoredpass = \"".$templates->get("forumdisplay_threadlist_clearpass")."\";"); - } - - $prefixselect = build_forum_prefix_select($fid, $tprefix); - - $lang->rss_discovery_forum = $lang->sprintf($lang->rss_discovery_forum, htmlspecialchars_uni(strip_tags($foruminfo['name']))); - eval("\$rssdiscovery = \"".$templates->get("forumdisplay_rssdiscovery")."\";"); - eval("\$threadslist = \"".$templates->get("forumdisplay_threadlist")."\";"); -} -else -{ - $rssdiscovery = ''; - $threadslist = ''; - - if(empty($forums)) - { - error($lang->error_containsnoforums); - } -} - -$plugins->run_hooks("forumdisplay_end"); - -$foruminfo['name'] = strip_tags($foruminfo['name']); - -eval("\$forums = \"".$templates->get("forumdisplay")."\";"); -output_page($forums); \ No newline at end of file diff --git a/html/forums/global.php b/html/forums/global.php deleted file mode 100644 index c6c2170..0000000 --- a/html/forums/global.php +++ /dev/null @@ -1,1138 +0,0 @@ -read('usergroups'); - -// If the groups cache doesn't exist, update it and re-read it -if(!is_array($groupscache)) -{ - $cache->update_usergroups(); - $groupscache = $cache->read('usergroups'); -} - -if(!defined('THIS_SCRIPT')) -{ - define('THIS_SCRIPT', ''); -} - -$current_page = my_strtolower(basename(THIS_SCRIPT)); - -// Send page headers - don't send no-cache headers for attachment.php -if($current_page != 'attachment.php') -{ - send_page_headers(); -} - -// Do not use session system for defined pages -if((isset($mybb->input['action']) && isset($nosession[$mybb->input['action']])) || (isset($mybb->input['thumbnail']) && $current_page == 'attachment.php')) -{ - define('NO_ONLINE', 1); -} - -// Create session for this user -require_once MYBB_ROOT.'inc/class_session.php'; -$session = new session; -$session->init(); -$mybb->session = &$session; - -$mybb->user['ismoderator'] = is_moderator(0, '', $mybb->user['uid']); - -// Set our POST validation code here -$mybb->post_code = generate_post_check(); - -// Set and load the language -if(isset($mybb->input['language']) && $lang->language_exists($mybb->get_input('language')) && verify_post_check($mybb->get_input('my_post_key'), true)) -{ - $mybb->settings['bblanguage'] = $mybb->get_input('language'); - // If user is logged in, update their language selection with the new one - if($mybb->user['uid']) - { - if(isset($mybb->cookies['mybblang'])) - { - my_unsetcookie('mybblang'); - } - - $db->update_query('users', array('language' => $db->escape_string($mybb->settings['bblanguage'])), "uid = '{$mybb->user['uid']}'"); - } - // Guest = cookie - else - { - my_setcookie('mybblang', $mybb->settings['bblanguage']); - } - $mybb->user['language'] = $mybb->settings['bblanguage']; -} -// Cookied language! -else if(!$mybb->user['uid'] && !empty($mybb->cookies['mybblang']) && $lang->language_exists($mybb->cookies['mybblang'])) -{ - $mybb->settings['bblanguage'] = $mybb->cookies['mybblang']; -} -else if(!isset($mybb->settings['bblanguage'])) -{ - $mybb->settings['bblanguage'] = 'english'; -} - -// Load language -$lang->set_language($mybb->settings['bblanguage']); -$lang->load('global'); -$lang->load('messages'); - -// Run global_start plugin hook now that the basics are set up -$plugins->run_hooks('global_start'); - -if(function_exists('mb_internal_encoding') && !empty($lang->settings['charset'])) -{ - @mb_internal_encoding($lang->settings['charset']); -} - -// Select the board theme to use. -$loadstyle = ''; -$load_from_forum = $load_from_user = 0; -$style = array(); - -// The user used our new quick theme changer -if(isset($mybb->input['theme']) && verify_post_check($mybb->get_input('my_post_key'), true)) -{ - // Set up user handler. - require_once MYBB_ROOT.'inc/datahandlers/user.php'; - $userhandler = new UserDataHandler('update'); - - $user = array( - 'uid' => $mybb->user['uid'], - 'style' => $mybb->get_input('theme', MyBB::INPUT_INT), - 'usergroup' => $mybb->user['usergroup'], - 'additionalgroups' => $mybb->user['additionalgroups'] - ); - - $userhandler->set_data($user); - - // validate_user verifies the style if it is set in the data array. - if($userhandler->validate_user()) - { - $mybb->user['style'] = $user['style']; - - // If user is logged in, update their theme selection with the new one - if($mybb->user['uid']) - { - if(isset($mybb->cookies['mybbtheme'])) - { - my_unsetcookie('mybbtheme'); - } - - $userhandler->update_user(); - } - // Guest = cookie - else - { - my_setcookie('mybbtheme', $user['style']); - } - } -} -// Cookied theme! -else if(!$mybb->user['uid'] && !empty($mybb->cookies['mybbtheme'])) -{ - $mybb->user['style'] = (int)$mybb->cookies['mybbtheme']; -} - -// This user has a custom theme set in their profile -if(isset($mybb->user['style']) && (int)$mybb->user['style'] != 0) -{ - $mybb->user['style'] = (int)$mybb->user['style']; - - $loadstyle = "tid = '{$mybb->user['style']}'"; - $load_from_user = 1; -} - -$valid = array( - 'showthread.php', - 'forumdisplay.php', - 'newthread.php', - 'newreply.php', - 'ratethread.php', - 'editpost.php', - 'polls.php', - 'sendthread.php', - 'printthread.php', - 'moderation.php' -); - -if(in_array($current_page, $valid)) -{ - cache_forums(); - - // If we're accessing a post, fetch the forum theme for it and if we're overriding it - if(isset($mybb->input['pid']) && THIS_SCRIPT != "polls.php") - { - $query = $db->simple_select("posts", "fid", "pid = '{$mybb->input['pid']}'", array("limit" => 1)); - $fid = $db->fetch_field($query, 'fid'); - - if($fid) - { - $style = $forum_cache[$fid]; - $load_from_forum = 1; - } - } - // We have a thread id and a forum id, we can easily fetch the theme for this forum - else if(isset($mybb->input['tid'])) - { - $query = $db->simple_select('threads', 'fid', "tid = '{$mybb->input['tid']}'", array('limit' => 1)); - $fid = $db->fetch_field($query, 'fid'); - - if($fid) - { - $style = $forum_cache[$fid]; - $load_from_forum = 1; - } - } - // If we're accessing poll results, fetch the forum theme for it and if we're overriding it - else if(isset($mybb->input['pid']) && THIS_SCRIPT == "polls.php") - { - $query = $db->simple_select('threads', 'fid', "poll = '{$mybb->input['pid']}'", array('limit' => 1)); - $fid = $db->fetch_field($query, 'fid'); - - if($fid) - { - $style = $forum_cache[$fid]; - $load_from_forum = 1; - } - } - // We have a forum id - simply load the theme from it - else if(isset($mybb->input['fid']) && isset($forum_cache[$mybb->input['fid']])) - { - $style = $forum_cache[$mybb->input['fid']]; - $load_from_forum = 1; - } -} -unset($valid); - -// From all of the above, a theme was found -if(isset($style['style']) && $style['style'] > 0) -{ - $style['style'] = (int)$style['style']; - - // This theme is forced upon the user, overriding their selection - if($style['overridestyle'] == 1 || !isset($mybb->user['style'])) - { - $loadstyle = "tid = '{$style['style']}'"; - } -} - -// After all of that no theme? Load the board default -if(empty($loadstyle)) -{ - $loadstyle = "def='1'"; -} - -// Fetch the theme to load from the cache -if($loadstyle != "def='1'") -{ - $query = $db->simple_select('themes', 'name, tid, properties, stylesheets, allowedgroups', $loadstyle, array('limit' => 1)); - $theme = $db->fetch_array($query); - - if(isset($theme['tid']) && !$load_from_forum && !is_member($theme['allowedgroups']) && $theme['allowedgroups'] != 'all') - { - if($load_from_user == 1) - { - $db->update_query('users', array('style' => 0), "style='{$mybb->user['style']}' AND uid='{$mybb->user['uid']}'"); - } - - if(isset($mybb->cookies['mybbtheme'])) - { - my_unsetcookie('mybbtheme'); - } - - $loadstyle = "def='1'"; - } -} - -if($loadstyle == "def='1'") -{ - if(!$cache->read('default_theme')) - { - $cache->update_default_theme(); - } - - $theme = $cache->read('default_theme'); - - $load_from_forum = $load_from_user = 0; -} - -// No theme was found - we attempt to load the master or any other theme -if(!isset($theme['tid']) || isset($theme['tid']) && !$theme['tid']) -{ - // Missing theme was from a forum, run a query to set any forums using the theme to the default - if($load_from_forum == 1) - { - $db->update_query('forums', array('style' => 0), "style = '{$style['style']}'"); - } - // Missing theme was from a user, run a query to set any users using the theme to the default - else if($load_from_user == 1) - { - $db->update_query('users', array('style' => 0), "style = '{$mybb->user['style']}'"); - } - - // Attempt to load the master or any other theme if the master is not available - $query = $db->simple_select('themes', 'name, tid, properties, stylesheets', '', array('order_by' => 'tid', 'limit' => 1)); - $theme = $db->fetch_array($query); -} -$theme = @array_merge($theme, my_unserialize($theme['properties'])); - -// Fetch all necessary stylesheets -$stylesheets = ''; -$theme['stylesheets'] = my_unserialize($theme['stylesheets']); -$stylesheet_scripts = array("global", basename($_SERVER['PHP_SELF'])); -if(!empty($theme['color'])) -{ - $stylesheet_scripts[] = $theme['color']; -} -$stylesheet_actions = array("global"); -if(!empty($mybb->input['action'])) -{ - $stylesheet_actions[] = $mybb->get_input('action'); -} -foreach($stylesheet_scripts as $stylesheet_script) -{ - // Load stylesheets for global actions and the current action - foreach($stylesheet_actions as $stylesheet_action) - { - if(!$stylesheet_action) - { - continue; - } - - if(!empty($theme['stylesheets'][$stylesheet_script][$stylesheet_action])) - { - // Actually add the stylesheets to the list - foreach($theme['stylesheets'][$stylesheet_script][$stylesheet_action] as $page_stylesheet) - { - if(!empty($already_loaded[$page_stylesheet])) - { - continue; - } - - if(strpos($page_stylesheet, 'css.php') !== false) - { - $stylesheet_url = $mybb->settings['bburl'] . '/' . $page_stylesheet; - } - else - { - $stylesheet_url = $mybb->get_asset_url($page_stylesheet); - } - - if($mybb->settings['minifycss']) - { - $stylesheet_url = str_replace('.css', '.min.css', $stylesheet_url); - } - - if(strpos($page_stylesheet, 'css.php') !== false) - { - // We need some modification to get it working with the displayorder - $query_string = parse_url($stylesheet_url, PHP_URL_QUERY); - $id = (int) my_substr($query_string, 11); - $query = $db->simple_select("themestylesheets", "name", "sid={$id}"); - $real_name = $db->fetch_field($query, "name"); - $theme_stylesheets[$real_name] = "\n"; - } - else - { - $theme_stylesheets[basename($page_stylesheet)] = "\n"; - } - - $already_loaded[$page_stylesheet] = 1; - } - } - } -} -unset($actions); - -if(!empty($theme_stylesheets) && is_array($theme['disporder'])) -{ - foreach($theme['disporder'] as $style_name => $order) - { - if(!empty($theme_stylesheets[$style_name])) - { - $stylesheets .= $theme_stylesheets[$style_name]; - } - } -} - -// Are we linking to a remote theme server? -if(my_validate_url($theme['imgdir'])) -{ - // If a language directory for the current language exists within the theme - we use it - if(!empty($mybb->user['language'])) - { - $theme['imglangdir'] = $theme['imgdir'].'/'.$mybb->user['language']; - } - else - { - // Check if a custom language directory exists for this theme - if(!empty($mybb->settings['bblanguage'])) - { - $theme['imglangdir'] = $theme['imgdir'].'/'.$mybb->settings['bblanguage']; - } - // Otherwise, the image language directory is the same as the language directory for the theme - else - { - $theme['imglangdir'] = $theme['imgdir']; - } - } -} -else -{ - $img_directory = $theme['imgdir']; - - if($mybb->settings['usecdn'] && !empty($mybb->settings['cdnpath'])) - { - $img_directory = rtrim($mybb->settings['cdnpath'], '/') . '/' . ltrim($theme['imgdir'], '/'); - } - - if(!@is_dir($img_directory)) - { - $theme['imgdir'] = 'images'; - } - - // If a language directory for the current language exists within the theme - we use it - if(!empty($mybb->user['language']) && is_dir($img_directory.'/'.$mybb->user['language'])) - { - $theme['imglangdir'] = $theme['imgdir'].'/'.$mybb->user['language']; - } - else - { - // Check if a custom language directory exists for this theme - if(is_dir($img_directory.'/'.$mybb->settings['bblanguage'])) - { - $theme['imglangdir'] = $theme['imgdir'].'/'.$mybb->settings['bblanguage']; - } - // Otherwise, the image language directory is the same as the language directory for the theme - else - { - $theme['imglangdir'] = $theme['imgdir']; - } - } - - $theme['imgdir'] = $mybb->get_asset_url($theme['imgdir']); - $theme['imglangdir'] = $mybb->get_asset_url($theme['imglangdir']); -} - -// Theme logo - is it a relative URL to the forum root? Append bburl -if(!preg_match("#^(\.\.?(/|$)|([a-z0-9]+)://)#i", $theme['logo']) && substr($theme['logo'], 0, 1) != '/') -{ - $theme['logo'] = $mybb->get_asset_url($theme['logo']); -} - -// Load Main Templates and Cached Templates -if(isset($templatelist)) -{ - $templatelist .= ','; -} -else -{ - $templatelist = ''; -} - -$templatelist .= "headerinclude,header,footer,gobutton,htmldoctype,header_welcomeblock_member,header_welcomeblock_member_user,header_welcomeblock_member_moderator,header_welcomeblock_member_admin,error"; -$templatelist .= ",global_pending_joinrequests,global_awaiting_activation,nav,nav_sep,nav_bit,nav_sep_active,nav_bit_active,footer_languageselect,footer_themeselect,global_unreadreports,footer_contactus"; -$templatelist .= ",global_boardclosed_warning,global_bannedwarning,error_inline,error_nopermission_loggedin,error_nopermission,global_pm_alert,header_menu_search,header_menu_portal,redirect,footer_languageselect_option"; -$templatelist .= ",video_dailymotion_embed,video_facebook_embed,video_liveleak_embed,video_metacafe_embed,video_myspacetv_embed,video_veoh_embed,video_vimeo_embed,video_yahoo_embed,video_youtube_embed,debug_summary"; -$templatelist .= ",smilieinsert_row,smilieinsert_row_empty,smilieinsert,smilieinsert_getmore,smilieinsert_smilie,global_board_offline_modal,footer_themeselector,task_image,usercp_themeselector_option"; -$templatelist .= ",mycode_code,mycode_email,mycode_img,mycode_php,mycode_quote_post,mycode_size_int,mycode_url,global_no_permission_modal,global_boardclosed_reason,nav_dropdown,global_remote_avatar_notice"; -$templatelist .= ",header_welcomeblock_member_pms,header_welcomeblock_member_search,header_welcomeblock_guest,header_menu_calendar,header_menu_memberlist,global_dst_detection,header_quicksearch,smilie"; -$templates->cache($db->escape_string($templatelist)); - -// Set the current date and time now -$datenow = my_date($mybb->settings['dateformat'], TIME_NOW, '', false); -$timenow = my_date($mybb->settings['timeformat'], TIME_NOW); -$lang->welcome_current_time = $lang->sprintf($lang->welcome_current_time, $datenow . $lang->comma . $timenow); - -// Format the last visit date of this user appropriately -if(isset($mybb->user['lastvisit'])) -{ - $lastvisit = my_date('relative', $mybb->user['lastvisit'], '', 2); -} -// Otherwise, they've never visited before -else -{ - $lastvisit = $lang->lastvisit_never; -} - -$plugins->run_hooks('global_intermediate'); - -// If the board is closed and we have a usergroup allowed to view the board when closed, then show board closed warning -$bbclosedwarning = ''; -if($mybb->settings['boardclosed'] == 1 && $mybb->usergroup['canviewboardclosed'] == 1) -{ - eval('$bbclosedwarning = "'.$templates->get('global_boardclosed_warning').'";'); -} - -// Prepare the main templates for use -$admincplink = $modcplink = $usercplink = ''; - -// Load appropriate welcome block for the current logged in user -if($mybb->user['uid'] != 0) -{ - // User can access the admin cp and we're not hiding admin cp links, fetch it - if($mybb->usergroup['cancp'] == 1 && $mybb->config['hide_admin_links'] != 1) - { - $admin_dir = $config['admin_dir']; - eval('$admincplink = "'.$templates->get('header_welcomeblock_member_admin').'";'); - } - - if($mybb->usergroup['canmodcp'] == 1) - { - eval('$modcplink = "'.$templates->get('header_welcomeblock_member_moderator').'";'); - } - - if($mybb->usergroup['canusercp'] == 1) - { - eval('$usercplink = "'.$templates->get('header_welcomeblock_member_user').'";'); - } - - // Format the welcome back message - $lang->welcome_back = $lang->sprintf($lang->welcome_back, build_profile_link(htmlspecialchars_uni($mybb->user['username']), $mybb->user['uid']), $lastvisit); - - $searchlink = ''; - if($mybb->usergroup['cansearch'] == 1) - { - eval('$searchlink = "'.$templates->get('header_welcomeblock_member_search').'";'); - } - - // Tell the user their PM usage - $pmslink = ''; - if($mybb->settings['enablepms'] != 0 && $mybb->usergroup['canusepms'] == 1) - { - $lang->welcome_pms_usage = $lang->sprintf($lang->welcome_pms_usage, my_number_format($mybb->user['pms_unread']), my_number_format($mybb->user['pms_total'])); - - eval('$pmslink = "'.$templates->get('header_welcomeblock_member_pms').'";'); - } - - eval('$welcomeblock = "'.$templates->get('header_welcomeblock_member').'";'); -} -// Otherwise, we have a guest -else -{ - switch($mybb->settings['username_method']) - { - case 0: - $login_username = $lang->login_username; - break; - case 1: - $login_username = $lang->login_username1; - break; - case 2: - $login_username = $lang->login_username2; - break; - default: - $login_username = $lang->login_username; - break; - } - eval('$welcomeblock = "'.$templates->get('header_welcomeblock_guest').'";'); -} - -// Display menu links and quick search if user has permission -$menu_search = $menu_memberlist = $menu_portal = $menu_calendar = $quicksearch = ''; -if($mybb->usergroup['cansearch'] == 1) -{ - eval('$menu_search = "'.$templates->get('header_menu_search').'";'); - eval('$quicksearch = "'.$templates->get('header_quicksearch').'";'); -} - -if($mybb->settings['enablememberlist'] == 1 && $mybb->usergroup['canviewmemberlist'] == 1) -{ - eval('$menu_memberlist = "'.$templates->get('header_menu_memberlist').'";'); -} - -if($mybb->settings['enablecalendar'] == 1 && $mybb->usergroup['canviewcalendar'] == 1) -{ - eval('$menu_calendar = "'.$templates->get('header_menu_calendar').'";'); -} - -if($mybb->settings['portal'] == 1) -{ - eval('$menu_portal = "'.$templates->get('header_menu_portal').'";'); -} - -// See if there are any pending join requests for group leaders -$pending_joinrequests = ''; -$groupleaders = $cache->read('groupleaders'); -if($mybb->user['uid'] != 0 && is_array($groupleaders) && array_key_exists($mybb->user['uid'], $groupleaders)) -{ - $groupleader = $groupleaders[$mybb->user['uid']]; - - $gids = "'0'"; - foreach($groupleader as $user) - { - if($user['canmanagerequests'] != 1) - { - continue; - } - - $user['gid'] = (int)$user['gid']; - $gids .= ",'{$user['gid']}'"; - } - - $query = $db->simple_select('joinrequests', 'COUNT(uid) as total', "gid IN ({$gids}) AND invite='0'"); - $total_joinrequests = $db->fetch_field($query, 'total'); - - if($total_joinrequests > 0) - { - if($total_joinrequests == 1) - { - $lang->pending_joinrequests = $lang->pending_joinrequest; - } - else - { - $total_joinrequests = my_number_format($total_joinrequests); - $lang->pending_joinrequests = $lang->sprintf($lang->pending_joinrequests, $total_joinrequests); - } - - eval('$pending_joinrequests = "'.$templates->get('global_pending_joinrequests').'";'); - } -} - -$unreadreports = ''; -// This user is a moderator, super moderator or administrator -if($mybb->settings['reportmethod'] == "db" && ($mybb->usergroup['cancp'] == 1 || ($mybb->user['ismoderator'] && $mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canmanagereportedcontent'] == 1))) -{ - // Only worth checking if we are here because we have ACP permissions and the other condition fails - if($mybb->usergroup['cancp'] == 1 && !($mybb->user['ismoderator'] && $mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canmanagereportedcontent'] == 1)) - { - // First we check if the user's a super admin: if yes, we don't care about permissions - $can_access_moderationqueue = true; - $is_super_admin = is_super_admin($mybb->user['uid']); - if(!$is_super_admin) - { - // Include admin functions - if(!file_exists(MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions.php")) - { - $can_access_moderationqueue = false; - } - - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions.php"; - - // Verify if we have permissions to access forum-moderation_queue - require_once MYBB_ROOT.$mybb->config['admin_dir']."/modules/forum/module_meta.php"; - if(function_exists("forum_admin_permissions")) - { - // Get admin permissions - $adminperms = get_admin_permissions($mybb->user['uid']); - - $permissions = forum_admin_permissions(); - if(array_key_exists('moderation_queue', $permissions['permissions']) && $adminperms['forum']['moderation_queue'] != 1) - { - $can_access_moderationqueue = false; - } - } - } - } - else - { - $can_access_moderationqueue = false; - } - - if($can_access_moderationqueue || ($mybb->user['ismoderator'] && $mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canmanagereportedcontent'] == 1)) - { - // Read the reported content cache - $reported = $cache->read('reportedcontent'); - - // 0 or more reported items currently exist - if($reported['unread'] > 0) - { - // We want to avoid one extra query for users that can moderate any forum - if($mybb->usergroup['cancp'] || $mybb->usergroup['issupermod']) - { - $unread = (int)$reported['unread']; - } - else - { - $unread = 0; - $query = $db->simple_select('reportedcontent', 'id3', "reportstatus='0' AND (type = 'post' OR type = '')"); - - while($fid = $db->fetch_field($query, 'id3')) - { - if(is_moderator($fid, "canmanagereportedposts")) - { - ++$unread; - } - } - } - - if($unread > 0) - { - if($unread == 1) - { - $lang->unread_reports = $lang->unread_report; - } - else - { - $lang->unread_reports = $lang->sprintf($lang->unread_reports, my_number_format($unread)); - } - - eval('$unreadreports = "'.$templates->get('global_unreadreports').'";'); - } - } - } -} - -// Got a character set? -$charset = 'UTF-8'; -if(isset($lang->settings['charset']) && $lang->settings['charset']) -{ - $charset = $lang->settings['charset']; -} - -// Is this user apart of a banned group? -$bannedwarning = ''; -if($mybb->usergroup['isbannedgroup'] == 1) -{ - // Fetch details on their ban - $query = $db->simple_select('banned', '*', "uid = '{$mybb->user['uid']}'", array('limit' => 1)); - $ban = $db->fetch_array($query); - - if($ban['uid']) - { - // Format their ban lift date and reason appropriately - $banlift = $lang->banned_lifted_never; - $reason = htmlspecialchars_uni($ban['reason']); - - if($ban['lifted'] > 0) - { - $banlift = my_date($mybb->settings['dateformat'], $ban['lifted']) . $lang->comma . my_date($mybb->settings['timeformat'], $ban['lifted']); - } - } - - if(empty($reason)) - { - $reason = $lang->unknown; - } - - if(empty($banlift)) - { - $banlift = $lang->unknown; - } - - // Display a nice warning to the user - eval('$bannedwarning = "'.$templates->get('global_bannedwarning').'";'); -} - -$lang->ajax_loading = str_replace("'", "\\'", $lang->ajax_loading); - -// Check if this user has a new private message. -$pm_notice = ''; -if(isset($mybb->user['pmnotice']) && $mybb->user['pmnotice'] == 2 && $mybb->user['pms_unread'] > 0 && $mybb->settings['enablepms'] != 0 && $mybb->usergroup['canusepms'] != 0 && $mybb->usergroup['canview'] != 0 && ($current_page != "private.php" || $mybb->get_input('action') != "read")) -{ - if(!isset($parser)) - { - require_once MYBB_ROOT.'inc/class_parser.php'; - $parser = new postParser; - } - - $query = $db->query(" - SELECT pm.subject, pm.pmid, fu.username AS fromusername, fu.uid AS fromuid - FROM ".TABLE_PREFIX."privatemessages pm - LEFT JOIN ".TABLE_PREFIX."users fu on (fu.uid=pm.fromid) - WHERE pm.folder = '1' AND pm.uid = '{$mybb->user['uid']}' AND pm.status = '0' - ORDER BY pm.dateline DESC - LIMIT 1 - "); - - $pm = $db->fetch_array($query); - $pm['subject'] = $parser->parse_badwords($pm['subject']); - - if($pm['fromuid'] == 0) - { - $pm['fromusername'] = $lang->mybb_engine; - $user_text = $pm['fromusername']; - } - else - { - $pm['fromusername'] = htmlspecialchars_uni($pm['fromusername']); - $user_text = build_profile_link($pm['fromusername'], $pm['fromuid']); - } - - if($mybb->user['pms_unread'] == 1) - { - $privatemessage_text = $lang->sprintf($lang->newpm_notice_one, $user_text, $mybb->settings['bburl'], $pm['pmid'], htmlspecialchars_uni($pm['subject'])); - } - else - { - $privatemessage_text = $lang->sprintf($lang->newpm_notice_multiple, $mybb->user['pms_unread'], $user_text, $mybb->settings['bburl'], $pm['pmid'], htmlspecialchars_uni($pm['subject'])); - } - eval('$pm_notice = "'.$templates->get('global_pm_alert').'";'); -} - -$remote_avatar_notice = ''; -if(($mybb->user['avatartype'] === 'remote' || $mybb->user['avatartype'] === 'gravatar') && !$mybb->settings['allowremoteavatars']) -{ - eval('$remote_avatar_notice = "'.$templates->get('global_remote_avatar_notice').'";'); -} - -if($mybb->settings['awactialert'] == 1 && $mybb->usergroup['cancp'] == 1) -{ - $awaitingusers = $cache->read('awaitingactivation'); - - if(isset($awaitingusers['time']) && $awaitingusers['time'] + 86400 < TIME_NOW) - { - $cache->update_awaitingactivation(); - $awaitingusers = $cache->read('awaitingactivation'); - } - - if(!empty($awaitingusers['users'])) - { - $awaitingusers = (int)$awaitingusers['users']; - } - else - { - $awaitingusers = 0; - } - - if($awaitingusers < 1) - { - $awaitingusers = 0; - } - else - { - $awaitingusers = my_number_format($awaitingusers); - } - - if($awaitingusers > 0) - { - if($awaitingusers == 1) - { - $awaiting_message = $lang->awaiting_message_single; - } - else - { - $awaiting_message = $lang->sprintf($lang->awaiting_message_plural, $awaitingusers); - } - - if($admincplink) - { - $awaiting_message .= $lang->sprintf($lang->awaiting_message_link, $mybb->settings['bburl'], $admin_dir); - } - - eval('$awaitingusers = "'.$templates->get('global_awaiting_activation').'";'); - } - else - { - $awaitingusers = ''; - } -} - -// Set up some of the default templates -eval('$headerinclude = "'.$templates->get('headerinclude').'";'); -eval('$gobutton = "'.$templates->get('gobutton').'";'); -eval('$htmldoctype = "'.$templates->get('htmldoctype', 1, 0).'";'); -eval('$header = "'.$templates->get('header').'";'); - -$copy_year = my_date('Y', TIME_NOW); - -// Are we showing version numbers in the footer? -$mybbversion = ''; -if($mybb->settings['showvernum'] == 1) -{ - $mybbversion = ' '.$mybb->version; -} - -// Check to see if we have any tasks to run -$task_image = ''; -$task_cache = $cache->read('tasks'); -if(!$task_cache['nextrun']) -{ - $task_cache['nextrun'] = TIME_NOW; -} - -if($task_cache['nextrun'] <= TIME_NOW) -{ - eval("\$task_image = \"".$templates->get("task_image")."\";"); -} - -// Post code -$post_code_string = ''; -if($mybb->user['uid']) -{ - $post_code_string = '&my_post_key='.$mybb->post_code; -} - -// Are we showing the quick language selection box? -$lang_select = $lang_options = ''; -if($mybb->settings['showlanguageselect'] != 0) -{ - $languages = $lang->get_languages(); - - if(count($languages) > 1) - { - foreach($languages as $key => $language) - { - $language = htmlspecialchars_uni($language); - - // Current language matches - if($lang->language == $key) - { - $selected = " selected=\"selected\""; - } - else - { - $selected = ''; - } - - eval('$lang_options .= "'.$templates->get('footer_languageselect_option').'";'); - } - - $lang_redirect_url = get_current_location(true, 'language'); - eval('$lang_select = "'.$templates->get('footer_languageselect').'";'); - } -} - -// Are we showing the quick theme selection box? -$theme_select = $theme_options = ''; -if($mybb->settings['showthemeselect'] != 0) -{ - $theme_options = build_theme_select("theme", $mybb->user['style'], 0, '', false, true); - - if(!empty($theme_options)) - { - $theme_redirect_url = get_current_location(true, 'theme'); - eval('$theme_select = "'.$templates->get('footer_themeselect').'";'); - } -} - -// If we use the contact form, show 'Contact Us' link when appropriate -$contact_us = ''; -if(($mybb->settings['contactlink'] == "contact.php" && $mybb->settings['contact'] == 1 && ($mybb->settings['contact_guests'] != 1 && $mybb->user['uid'] == 0 || $mybb->user['uid'] > 0)) || $mybb->settings['contactlink'] != "contact.php") -{ - if(!my_validate_url($mybb->settings['contactlink'], true) && my_substr($mybb->settings['contactlink'], 0, 7) != 'mailto:') - { - $mybb->settings['contactlink'] = $mybb->settings['bburl'].'/'.$mybb->settings['contactlink']; - } - - eval('$contact_us = "'.$templates->get('footer_contactus').'";'); -} - -// DST Auto detection enabled? -$auto_dst_detection = ''; -if($mybb->user['uid'] > 0 && $mybb->user['dstcorrection'] == 2) -{ - $timezone = (float)$mybb->user['timezone'] + $mybb->user['dst']; - eval('$auto_dst_detection = "'.$templates->get('global_dst_detection').'";'); -} - -eval('$footer = "'.$templates->get('footer').'";'); - -// Add our main parts to the navigation -$navbits = array(); -$navbits[0]['name'] = $mybb->settings['bbname_orig']; -$navbits[0]['url'] = $mybb->settings['bburl'].'/index.php'; - -// Set the link to the archive. -$archive_url = build_archive_link(); - -// Check banned ip addresses -if(is_banned_ip($session->ipaddress, true)) -{ - if($mybb->user['uid']) - { - $db->delete_query('sessions', "ip = ".$db->escape_binary($session->packedip)." OR uid='{$mybb->user['uid']}'"); - } - else - { - $db->delete_query('sessions', "ip = ".$db->escape_binary($session->packedip)); - } - error($lang->error_banned); -} - -$closed_bypass = array( - 'member.php' => array( - 'login', - 'do_login', - 'logout', - ), - 'captcha.php', -); - -// If the board is closed, the user is not an administrator and they're not trying to login, show the board closed message -if($mybb->settings['boardclosed'] == 1 && $mybb->usergroup['canviewboardclosed'] != 1 && !in_array($current_page, $closed_bypass) && (!is_array($closed_bypass[$current_page]) || !in_array($mybb->get_input('action'), $closed_bypass[$current_page]))) -{ - // Show error - if(!$mybb->settings['boardclosed_reason']) - { - $mybb->settings['boardclosed_reason'] = $lang->boardclosed_reason; - } - - eval('$reason = "'.$templates->get('global_boardclosed_reason').'";'); - $lang->error_boardclosed .= $reason; - - if(!$mybb->get_input('modal')) - { - error($lang->error_boardclosed); - } - else - { - $output = ''; - eval('$output = "'.$templates->get('global_board_offline_modal', 1, 0).'";'); - echo($output); - } - exit; -} - -$force_bypass = array( - 'member.php' => array( - 'login', - 'do_login', - 'logout', - 'register', - 'do_register', - 'lostpw', - 'do_lostpw', - 'activate', - 'resendactivation', - 'do_resendactivation', - 'resetpassword', - ), - 'captcha.php', -); - -// If the board forces user to login/register, and the user is a guest, show the force login message -if($mybb->settings['forcelogin'] == 1 && $mybb->user['uid'] == 0 && !in_array($current_page, $force_bypass) && (!is_array($force_bypass[$current_page]) || !in_array($mybb->get_input('action'), $force_bypass[$current_page]))) -{ - // Show error - error_no_permission(); - exit; -} - -// Load Limiting -if($mybb->usergroup['cancp'] != 1 && $mybb->settings['load'] > 0 && ($load = get_server_load()) && $load != $lang->unknown && $load > $mybb->settings['load']) -{ - // User is not an administrator and the load limit is higher than the limit, show an error - error($lang->error_loadlimit); -} - -// If there is a valid referrer in the URL, cookie it -if(!$mybb->user['uid'] && $mybb->settings['usereferrals'] == 1 && (isset($mybb->input['referrer']) || isset($mybb->input['referrername']))) -{ - if(isset($mybb->input['referrername'])) - { - $condition = "username = '".$db->escape_string($mybb->get_input('referrername'))."'"; - } - else - { - $condition = "uid = '".$mybb->get_input('referrer', MyBB::INPUT_INT)."'"; - } - - $query = $db->simple_select('users', 'uid', $condition, array('limit' => 1)); - $referrer = $db->fetch_array($query); - - if($referrer['uid']) - { - my_setcookie('mybb[referrer]', $referrer['uid']); - } -} - -$output = ''; -$notallowed = false; -if($mybb->usergroup['canview'] != 1) -{ - // Check pages allowable even when not allowed to view board - if(defined('ALLOWABLE_PAGE')) - { - if(is_string(ALLOWABLE_PAGE)) - { - $allowable_actions = explode(',', ALLOWABLE_PAGE); - if(!in_array($mybb->get_input('action'), $allowable_actions)) - { - $notallowed = true; - } - - unset($allowable_actions); - } - else if(ALLOWABLE_PAGE !== 1) - { - $notallowed = true; - } - } - else - { - $notallowed = true; - } - - if($notallowed == true) - { - if(!$mybb->get_input('modal')) - { - error_no_permission(); - } - else - { - eval('$output = "'.$templates->get('global_no_permission_modal', 1, 0).'";'); - echo($output); - exit; - } - } -} - -// Find out if this user of ours is using a banned email address. -// If they are, redirect them to change it -if($mybb->user['uid'] && is_banned_email($mybb->user['email']) && $mybb->settings['emailkeep'] != 1) -{ - if(THIS_SCRIPT != 'usercp.php' || THIS_SCRIPT == 'usercp.php' && $mybb->get_input('action') != 'email' && $mybb->get_input('action') != 'do_email') - { - redirect('usercp.php?action=email'); - } - else if($mybb->request_method != 'post') - { - $banned_email_error = inline_error(array($lang->banned_email_warning)); - } -} - -// work out which items the user has collapsed -$colcookie = ''; -if(!empty($mybb->cookies['collapsed'])) -{ - $colcookie = $mybb->cookies['collapsed']; -} - -// set up collapsable items (to automatically show them us expanded) -$collapsed = array('boardstats' => '', 'boardstats_e' => '', 'quickreply' => '', 'quickreply_e' => ''); -$collapsedimg = $collapsed; - -if($colcookie) -{ - $col = explode("|", $colcookie); - if(!is_array($col)) - { - $col[0] = $colcookie; // only one item - } - unset($collapsed); - foreach($col as $key => $val) - { - $ex = $val."_e"; - $co = $val."_c"; - $collapsed[$co] = "display: show;"; - $collapsed[$ex] = "display: none;"; - $collapsedimg[$val] = "_collapsed"; - $collapsedthead[$val] = " thead_collapsed"; - } -} - -// Run hooks for end of global.php -$plugins->run_hooks('global_end'); - -$globaltime = $maintimer->getTime(); diff --git a/html/forums/htaccess-nginx.txt b/html/forums/htaccess-nginx.txt deleted file mode 100644 index 753003b..0000000 --- a/html/forums/htaccess-nginx.txt +++ /dev/null @@ -1,28 +0,0 @@ -# Note: You are able to choose a different name in the Admin CP. If you've done that you need to change it here too -location ~ /error.log -{ - deny all; -} - -# Note: You are able to rename the admin directory. If you've done that, you need to change it here too -location /admin/backups { - deny all; -} - -rewrite ^/forum-([0-9]+).html$ /forumdisplay.php?fid=$1 last; -rewrite ^/forum-([0-9]+)-page-([0-9]+).html$ /forumdisplay.php?fid=$1&page=$2 last; -rewrite ^/thread-([0-9]+).html$ /showthread.php?tid=$1 last; -rewrite ^/thread-([0-9]+)-page-([0-9]+).html$ /showthread.php?tid=$1&page=$2 last; -rewrite ^/thread-([0-9]+)-lastpost.html$ /showthread.php?tid=$1&action=lastpost last; -rewrite ^/thread-([0-9]+)-nextnewest.html$ /showthread.php?tid=$1&action=nextnewest last; -rewrite ^/thread-([0-9]+)-nextoldest.html$ /showthread.php?tid=$1&action=nextoldest last; -rewrite ^/thread-([0-9]+)-newpost.html$ /showthread.php?tid=$1&action=newpost last; -rewrite ^/thread-([0-9]+)-post-([0-9]+).html$ /showthread.php?tid=$1&pid=$2 last; -rewrite ^/post-([0-9]+).html$ /showthread.php?pid=$1 last; -rewrite ^/announcement-([0-9]+).html$ /announcements.php?aid=$1 last; -rewrite ^/user-([0-9]+).html$ /member.php?action=profile&uid=$1 last; -rewrite ^/calendar-([0-9]+).html$ /calendar.php?calendar=$1 last; -rewrite ^/calendar-([0-9]+)-year-([0-9]+)-month-([0-9]+).html$ /calendar.php?calendar=$1&year=$2&month=$3 last; -rewrite ^/calendar-([0-9]+)-year-([0-9]+)-month-([0-9]+)-day-([0-9]+).html$ /calendar.php?action=dayview&calendar=$1&year=$2&month=$3&day=$4 last; -rewrite ^/calendar-([0-9]+)-week-(n?[0-9]+).html$ /calendar.php?action=weekview&calendar=$1&week=$2 last; -rewrite ^/event-([0-9]+).html$ /calendar.php?action=event&eid=$1 last; diff --git a/html/forums/htaccess.txt b/html/forums/htaccess.txt deleted file mode 100644 index 341e884..0000000 --- a/html/forums/htaccess.txt +++ /dev/null @@ -1,67 +0,0 @@ -Options -MultiViews +FollowSymlinks -Indexes - -# -# If mod_security is enabled, attempt to disable it. -# - Note, this will work on the majority of hosts but on -# MediaTemple, it is known to cause random Internal Server -# errors. For MediaTemple, please remove the block below -# - - # Turn off mod_security filtering. - SecFilterEngine Off - - # The below probably isn't needed, but better safe than sorry. - SecFilterScanPOST Off - - -# -# MyBB "search engine friendly" URL rewrites -# - Note, for these to work with MyBB please make sure you have -# the setting enabled in the Admin CP and you have this file -# named .htaccess -# - - RewriteEngine on - RewriteRule ^forum-([0-9]+)\.html$ forumdisplay.php?fid=$1 [L,QSA] - RewriteRule ^forum-([0-9]+)-page-([0-9]+)\.html$ forumdisplay.php?fid=$1&page=$2 [L,QSA] - - RewriteRule ^thread-([0-9]+)\.html$ showthread.php?tid=$1 [L,QSA] - RewriteRule ^thread-([0-9]+)-page-([0-9]+)\.html$ showthread.php?tid=$1&page=$2 [L,QSA] - RewriteRule ^thread-([0-9]+)-lastpost\.html$ showthread.php?tid=$1&action=lastpost [L,QSA] - RewriteRule ^thread-([0-9]+)-nextnewest\.html$ showthread.php?tid=$1&action=nextnewest [L,QSA] - RewriteRule ^thread-([0-9]+)-nextoldest\.html$ showthread.php?tid=$1&action=nextoldest [L,QSA] - RewriteRule ^thread-([0-9]+)-newpost\.html$ showthread.php?tid=$1&action=newpost [L,QSA] - RewriteRule ^thread-([0-9]+)-post-([0-9]+)\.html$ showthread.php?tid=$1&pid=$2 [L,QSA] - - RewriteRule ^post-([0-9]+)\.html$ showthread.php?pid=$1 [L,QSA] - - RewriteRule ^announcement-([0-9]+)\.html$ announcements.php?aid=$1 [L,QSA] - - RewriteRule ^user-([0-9]+)\.html$ member.php?action=profile&uid=$1 [L,QSA] - - RewriteRule ^calendar-([0-9]+)\.html$ calendar.php?calendar=$1 [L,QSA] - RewriteRule ^calendar-([0-9]+)-year-([0-9]+)-month-([0-9]+)\.html$ calendar.php?calendar=$1&year=$2&month=$3 [L,QSA] - RewriteRule ^calendar-([0-9]+)-year-([0-9]+)-month-([0-9]+)-day-([0-9]+)\.html$ calendar.php?action=dayview&calendar=$1&year=$2&month=$3&day=$4 [L,QSA] - RewriteRule ^calendar-([0-9]+)-week-(n?[0-9]+)\.html$ calendar.php?action=weekview&calendar=$1&week=$2 [L,QSA] - - RewriteRule ^event-([0-9]+)\.html$ calendar.php?action=event&eid=$1 [L,QSA] - - - SetEnv SEO_SUPPORT 1 - - - -# -# If Apache is compiled with built in mod_deflade/GZIP support -# then GZIP Javascript, CSS, HTML and XML so they're sent to -# the client faster. -# - - AddOutputFilterByType DEFLATE text/css text/html application/xhtml+xml text/xml application/xml text/plain text/x-component application/javascript application/x-javascript application/rss+xml application/atom+xml application/json application/manifest+json application/x-web-app-manifest+json application/vnd.ms-fontobject application/font-sfnt application/font-woff application/font-woff2 image/svg+xml image/x-icon - - -# Note: You are able to choose a different name in the Admin CP. If you've done that you need to change it here too - - Order Deny,Allow - Deny from all - diff --git a/html/forums/images/arrow_down.png b/html/forums/images/arrow_down.png deleted file mode 100644 index ab28811..0000000 Binary files a/html/forums/images/arrow_down.png and /dev/null differ diff --git a/html/forums/images/attachtypes/blank.png b/html/forums/images/attachtypes/blank.png deleted file mode 100644 index be471b1..0000000 Binary files a/html/forums/images/attachtypes/blank.png and /dev/null differ diff --git a/html/forums/images/attachtypes/css.png b/html/forums/images/attachtypes/css.png deleted file mode 100644 index 0c478b3..0000000 Binary files a/html/forums/images/attachtypes/css.png and /dev/null differ diff --git a/html/forums/images/attachtypes/doc.png b/html/forums/images/attachtypes/doc.png deleted file mode 100644 index 80a9f93..0000000 Binary files a/html/forums/images/attachtypes/doc.png and /dev/null differ diff --git a/html/forums/images/attachtypes/html.png b/html/forums/images/attachtypes/html.png deleted file mode 100644 index 3c216d8..0000000 Binary files a/html/forums/images/attachtypes/html.png and /dev/null differ diff --git a/html/forums/images/attachtypes/image.png b/html/forums/images/attachtypes/image.png deleted file mode 100644 index 3696cf9..0000000 Binary files a/html/forums/images/attachtypes/image.png and /dev/null differ diff --git a/html/forums/images/attachtypes/pdf.png b/html/forums/images/attachtypes/pdf.png deleted file mode 100644 index a12adf8..0000000 Binary files a/html/forums/images/attachtypes/pdf.png and /dev/null differ diff --git a/html/forums/images/attachtypes/php.png b/html/forums/images/attachtypes/php.png deleted file mode 100644 index a3625ed..0000000 Binary files a/html/forums/images/attachtypes/php.png and /dev/null differ diff --git a/html/forums/images/attachtypes/ppt.png b/html/forums/images/attachtypes/ppt.png deleted file mode 100644 index 8cc75cb..0000000 Binary files a/html/forums/images/attachtypes/ppt.png and /dev/null differ diff --git a/html/forums/images/attachtypes/psd.png b/html/forums/images/attachtypes/psd.png deleted file mode 100644 index dbfc427..0000000 Binary files a/html/forums/images/attachtypes/psd.png and /dev/null differ diff --git a/html/forums/images/attachtypes/tar.png b/html/forums/images/attachtypes/tar.png deleted file mode 100644 index 3fc5485..0000000 Binary files a/html/forums/images/attachtypes/tar.png and /dev/null differ diff --git a/html/forums/images/attachtypes/txt.png b/html/forums/images/attachtypes/txt.png deleted file mode 100644 index 0976879..0000000 Binary files a/html/forums/images/attachtypes/txt.png and /dev/null differ diff --git a/html/forums/images/attachtypes/unknown.png b/html/forums/images/attachtypes/unknown.png deleted file mode 100644 index 48aef59..0000000 Binary files a/html/forums/images/attachtypes/unknown.png and /dev/null differ diff --git a/html/forums/images/attachtypes/xls.png b/html/forums/images/attachtypes/xls.png deleted file mode 100644 index af04b06..0000000 Binary files a/html/forums/images/attachtypes/xls.png and /dev/null differ diff --git a/html/forums/images/attachtypes/zip.png b/html/forums/images/attachtypes/zip.png deleted file mode 100644 index 56cbc71..0000000 Binary files a/html/forums/images/attachtypes/zip.png and /dev/null differ diff --git a/html/forums/images/buddies.png b/html/forums/images/buddies.png deleted file mode 100644 index 1bc4970..0000000 Binary files a/html/forums/images/buddies.png and /dev/null differ diff --git a/html/forums/images/buddy_away.png b/html/forums/images/buddy_away.png deleted file mode 100644 index bff1763..0000000 Binary files a/html/forums/images/buddy_away.png and /dev/null differ diff --git a/html/forums/images/buddy_delete.png b/html/forums/images/buddy_delete.png deleted file mode 100644 index a06c560..0000000 Binary files a/html/forums/images/buddy_delete.png and /dev/null differ diff --git a/html/forums/images/buddy_offline.png b/html/forums/images/buddy_offline.png deleted file mode 100644 index d7d4c7d..0000000 Binary files a/html/forums/images/buddy_offline.png and /dev/null differ diff --git a/html/forums/images/buddy_online.png b/html/forums/images/buddy_online.png deleted file mode 100644 index 68760ae..0000000 Binary files a/html/forums/images/buddy_online.png and /dev/null differ diff --git a/html/forums/images/buttons_bg.png b/html/forums/images/buttons_bg.png deleted file mode 100644 index f39ea8f..0000000 Binary files a/html/forums/images/buttons_bg.png and /dev/null differ diff --git a/html/forums/images/buttons_sprite.png b/html/forums/images/buttons_sprite.png deleted file mode 100644 index 51ff894..0000000 Binary files a/html/forums/images/buttons_sprite.png and /dev/null differ diff --git a/html/forums/images/close.png b/html/forums/images/close.png deleted file mode 100644 index b0ad987..0000000 Binary files a/html/forums/images/close.png and /dev/null differ diff --git a/html/forums/images/collapse.png b/html/forums/images/collapse.png deleted file mode 100644 index b005ef3..0000000 Binary files a/html/forums/images/collapse.png and /dev/null differ diff --git a/html/forums/images/collapse_collapsed.png b/html/forums/images/collapse_collapsed.png deleted file mode 100644 index 8b5e692..0000000 Binary files a/html/forums/images/collapse_collapsed.png and /dev/null differ diff --git a/html/forums/images/colors/black_header.png b/html/forums/images/colors/black_header.png deleted file mode 100644 index 6b97efa..0000000 Binary files a/html/forums/images/colors/black_header.png and /dev/null differ diff --git a/html/forums/images/colors/black_tcat.png b/html/forums/images/colors/black_tcat.png deleted file mode 100644 index 22d5997..0000000 Binary files a/html/forums/images/colors/black_tcat.png and /dev/null differ diff --git a/html/forums/images/colors/black_thead.png b/html/forums/images/colors/black_thead.png deleted file mode 100644 index 125d1e5..0000000 Binary files a/html/forums/images/colors/black_thead.png and /dev/null differ diff --git a/html/forums/images/colors/calm_header.png b/html/forums/images/colors/calm_header.png deleted file mode 100644 index 81d13c9..0000000 Binary files a/html/forums/images/colors/calm_header.png and /dev/null differ diff --git a/html/forums/images/colors/calm_tcat.png b/html/forums/images/colors/calm_tcat.png deleted file mode 100644 index 7f67873..0000000 Binary files a/html/forums/images/colors/calm_tcat.png and /dev/null differ diff --git a/html/forums/images/colors/calm_thead.png b/html/forums/images/colors/calm_thead.png deleted file mode 100644 index 85f712c..0000000 Binary files a/html/forums/images/colors/calm_thead.png and /dev/null differ diff --git a/html/forums/images/colors/dawn_header.png b/html/forums/images/colors/dawn_header.png deleted file mode 100644 index df5ddd1..0000000 Binary files a/html/forums/images/colors/dawn_header.png and /dev/null differ diff --git a/html/forums/images/colors/dawn_tcat.png b/html/forums/images/colors/dawn_tcat.png deleted file mode 100644 index 7f67873..0000000 Binary files a/html/forums/images/colors/dawn_tcat.png and /dev/null differ diff --git a/html/forums/images/colors/dawn_thead.png b/html/forums/images/colors/dawn_thead.png deleted file mode 100644 index c877b44..0000000 Binary files a/html/forums/images/colors/dawn_thead.png and /dev/null differ diff --git a/html/forums/images/colors/earth_header.png b/html/forums/images/colors/earth_header.png deleted file mode 100644 index 5fa5399..0000000 Binary files a/html/forums/images/colors/earth_header.png and /dev/null differ diff --git a/html/forums/images/colors/earth_tcat.png b/html/forums/images/colors/earth_tcat.png deleted file mode 100644 index 7f67873..0000000 Binary files a/html/forums/images/colors/earth_tcat.png and /dev/null differ diff --git a/html/forums/images/colors/earth_thead.png b/html/forums/images/colors/earth_thead.png deleted file mode 100644 index 8388eb5..0000000 Binary files a/html/forums/images/colors/earth_thead.png and /dev/null differ diff --git a/html/forums/images/colors/flame_header.png b/html/forums/images/colors/flame_header.png deleted file mode 100644 index 1e7229e..0000000 Binary files a/html/forums/images/colors/flame_header.png and /dev/null differ diff --git a/html/forums/images/colors/flame_tcat.png b/html/forums/images/colors/flame_tcat.png deleted file mode 100644 index 7f67873..0000000 Binary files a/html/forums/images/colors/flame_tcat.png and /dev/null differ diff --git a/html/forums/images/colors/flame_thead.png b/html/forums/images/colors/flame_thead.png deleted file mode 100644 index a280975..0000000 Binary files a/html/forums/images/colors/flame_thead.png and /dev/null differ diff --git a/html/forums/images/colors/leaf_header.png b/html/forums/images/colors/leaf_header.png deleted file mode 100644 index 32fb41d..0000000 Binary files a/html/forums/images/colors/leaf_header.png and /dev/null differ diff --git a/html/forums/images/colors/leaf_tcat.png b/html/forums/images/colors/leaf_tcat.png deleted file mode 100644 index 7f67873..0000000 Binary files a/html/forums/images/colors/leaf_tcat.png and /dev/null differ diff --git a/html/forums/images/colors/leaf_thead.png b/html/forums/images/colors/leaf_thead.png deleted file mode 100644 index 0cc5b19..0000000 Binary files a/html/forums/images/colors/leaf_thead.png and /dev/null differ diff --git a/html/forums/images/colors/night_header.png b/html/forums/images/colors/night_header.png deleted file mode 100644 index 4e853c3..0000000 Binary files a/html/forums/images/colors/night_header.png and /dev/null differ diff --git a/html/forums/images/colors/night_tcat.png b/html/forums/images/colors/night_tcat.png deleted file mode 100644 index 7f67873..0000000 Binary files a/html/forums/images/colors/night_tcat.png and /dev/null differ diff --git a/html/forums/images/colors/night_thead.png b/html/forums/images/colors/night_thead.png deleted file mode 100644 index 4b1048d..0000000 Binary files a/html/forums/images/colors/night_thead.png and /dev/null differ diff --git a/html/forums/images/colors/sun_header.png b/html/forums/images/colors/sun_header.png deleted file mode 100644 index 52d6dff..0000000 Binary files a/html/forums/images/colors/sun_header.png and /dev/null differ diff --git a/html/forums/images/colors/sun_tcat.png b/html/forums/images/colors/sun_tcat.png deleted file mode 100644 index 7f67873..0000000 Binary files a/html/forums/images/colors/sun_tcat.png and /dev/null differ diff --git a/html/forums/images/colors/sun_thead.png b/html/forums/images/colors/sun_thead.png deleted file mode 100644 index 72f787f..0000000 Binary files a/html/forums/images/colors/sun_thead.png and /dev/null differ diff --git a/html/forums/images/colors/twilight_header.png b/html/forums/images/colors/twilight_header.png deleted file mode 100644 index 59a9cea..0000000 Binary files a/html/forums/images/colors/twilight_header.png and /dev/null differ diff --git a/html/forums/images/colors/twilight_tcat.png b/html/forums/images/colors/twilight_tcat.png deleted file mode 100644 index 7f67873..0000000 Binary files a/html/forums/images/colors/twilight_tcat.png and /dev/null differ diff --git a/html/forums/images/colors/twilight_thead.png b/html/forums/images/colors/twilight_thead.png deleted file mode 100644 index c480703..0000000 Binary files a/html/forums/images/colors/twilight_thead.png and /dev/null differ diff --git a/html/forums/images/colors/water_header.png b/html/forums/images/colors/water_header.png deleted file mode 100644 index 3a132e1..0000000 Binary files a/html/forums/images/colors/water_header.png and /dev/null differ diff --git a/html/forums/images/colors/water_tcat.png b/html/forums/images/colors/water_tcat.png deleted file mode 100644 index 7f67873..0000000 Binary files a/html/forums/images/colors/water_tcat.png and /dev/null differ diff --git a/html/forums/images/colors/water_thead.png b/html/forums/images/colors/water_thead.png deleted file mode 100644 index 869e729..0000000 Binary files a/html/forums/images/colors/water_thead.png and /dev/null differ diff --git a/html/forums/images/default_avatar.png b/html/forums/images/default_avatar.png deleted file mode 100644 index 6af480c..0000000 Binary files a/html/forums/images/default_avatar.png and /dev/null differ diff --git a/html/forums/images/dismiss_notice.png b/html/forums/images/dismiss_notice.png deleted file mode 100644 index 8b1bad7..0000000 Binary files a/html/forums/images/dismiss_notice.png and /dev/null differ diff --git a/html/forums/images/error.png b/html/forums/images/error.png deleted file mode 100644 index 599be74..0000000 Binary files a/html/forums/images/error.png and /dev/null differ diff --git a/html/forums/images/folders_sprite.png b/html/forums/images/folders_sprite.png deleted file mode 100644 index c123869..0000000 Binary files a/html/forums/images/folders_sprite.png and /dev/null differ diff --git a/html/forums/images/forum_icon_sprite.png b/html/forums/images/forum_icon_sprite.png deleted file mode 100644 index 0944c69..0000000 Binary files a/html/forums/images/forum_icon_sprite.png and /dev/null differ diff --git a/html/forums/images/fw_pm.png b/html/forums/images/fw_pm.png deleted file mode 100644 index 13200cd..0000000 Binary files a/html/forums/images/fw_pm.png and /dev/null differ diff --git a/html/forums/images/groupimages/english/team-administrator.png b/html/forums/images/groupimages/english/team-administrator.png deleted file mode 100644 index d133540..0000000 Binary files a/html/forums/images/groupimages/english/team-administrator.png and /dev/null differ diff --git a/html/forums/images/groupimages/english/team-designer.png b/html/forums/images/groupimages/english/team-designer.png deleted file mode 100644 index 0f1f69d..0000000 Binary files a/html/forums/images/groupimages/english/team-designer.png and /dev/null differ diff --git a/html/forums/images/groupimages/english/team-developer.png b/html/forums/images/groupimages/english/team-developer.png deleted file mode 100644 index 32710a2..0000000 Binary files a/html/forums/images/groupimages/english/team-developer.png and /dev/null differ diff --git a/html/forums/images/groupimages/english/team-management.png b/html/forums/images/groupimages/english/team-management.png deleted file mode 100644 index 672c573..0000000 Binary files a/html/forums/images/groupimages/english/team-management.png and /dev/null differ diff --git a/html/forums/images/groupimages/english/team-mod.png b/html/forums/images/groupimages/english/team-mod.png deleted file mode 100644 index a97ae6b..0000000 Binary files a/html/forums/images/groupimages/english/team-mod.png and /dev/null differ diff --git a/html/forums/images/groupimages/english/team-supermod.png b/html/forums/images/groupimages/english/team-supermod.png deleted file mode 100644 index da7847b..0000000 Binary files a/html/forums/images/groupimages/english/team-supermod.png and /dev/null differ diff --git a/html/forums/images/groupimages/english/team-support.png b/html/forums/images/groupimages/english/team-support.png deleted file mode 100644 index 7ea7bde..0000000 Binary files a/html/forums/images/groupimages/english/team-support.png and /dev/null differ diff --git a/html/forums/images/groupimages/english/team-tester.png b/html/forums/images/groupimages/english/team-tester.png deleted file mode 100644 index 5c8d270..0000000 Binary files a/html/forums/images/groupimages/english/team-tester.png and /dev/null differ diff --git a/html/forums/images/headerlinks_sprite.png b/html/forums/images/headerlinks_sprite.png deleted file mode 100644 index c4620a2..0000000 Binary files a/html/forums/images/headerlinks_sprite.png and /dev/null differ diff --git a/html/forums/images/icons/bell.png b/html/forums/images/icons/bell.png deleted file mode 100644 index 309aec7..0000000 Binary files a/html/forums/images/icons/bell.png and /dev/null differ diff --git a/html/forums/images/icons/biggrin.png b/html/forums/images/icons/biggrin.png deleted file mode 100644 index bfd2974..0000000 Binary files a/html/forums/images/icons/biggrin.png and /dev/null differ diff --git a/html/forums/images/icons/brick.png b/html/forums/images/icons/brick.png deleted file mode 100644 index 02effd1..0000000 Binary files a/html/forums/images/icons/brick.png and /dev/null differ diff --git a/html/forums/images/icons/bug.png b/html/forums/images/icons/bug.png deleted file mode 100644 index 210a989..0000000 Binary files a/html/forums/images/icons/bug.png and /dev/null differ diff --git a/html/forums/images/icons/car.png b/html/forums/images/icons/car.png deleted file mode 100644 index 4186c21..0000000 Binary files a/html/forums/images/icons/car.png and /dev/null differ diff --git a/html/forums/images/icons/exclamation.png b/html/forums/images/icons/exclamation.png deleted file mode 100644 index c18dbc3..0000000 Binary files a/html/forums/images/icons/exclamation.png and /dev/null differ diff --git a/html/forums/images/icons/game.png b/html/forums/images/icons/game.png deleted file mode 100644 index 3584fa3..0000000 Binary files a/html/forums/images/icons/game.png and /dev/null differ diff --git a/html/forums/images/icons/heart.png b/html/forums/images/icons/heart.png deleted file mode 100644 index 1f5ae8e..0000000 Binary files a/html/forums/images/icons/heart.png and /dev/null differ diff --git a/html/forums/images/icons/information.png b/html/forums/images/icons/information.png deleted file mode 100644 index 3ad15ea..0000000 Binary files a/html/forums/images/icons/information.png and /dev/null differ diff --git a/html/forums/images/icons/lightbulb.png b/html/forums/images/icons/lightbulb.png deleted file mode 100644 index eeca7aa..0000000 Binary files a/html/forums/images/icons/lightbulb.png and /dev/null differ diff --git a/html/forums/images/icons/lightning.png b/html/forums/images/icons/lightning.png deleted file mode 100644 index 8e838e8..0000000 Binary files a/html/forums/images/icons/lightning.png and /dev/null differ diff --git a/html/forums/images/icons/music.png b/html/forums/images/icons/music.png deleted file mode 100644 index 25b387c..0000000 Binary files a/html/forums/images/icons/music.png and /dev/null differ diff --git a/html/forums/images/icons/pencil.png b/html/forums/images/icons/pencil.png deleted file mode 100644 index 517874a..0000000 Binary files a/html/forums/images/icons/pencil.png and /dev/null differ diff --git a/html/forums/images/icons/photo.png b/html/forums/images/icons/photo.png deleted file mode 100644 index 3696cf9..0000000 Binary files a/html/forums/images/icons/photo.png and /dev/null differ diff --git a/html/forums/images/icons/question.png b/html/forums/images/icons/question.png deleted file mode 100644 index a4d2005..0000000 Binary files a/html/forums/images/icons/question.png and /dev/null differ diff --git a/html/forums/images/icons/rainbow.png b/html/forums/images/icons/rainbow.png deleted file mode 100644 index 0620a85..0000000 Binary files a/html/forums/images/icons/rainbow.png and /dev/null differ diff --git a/html/forums/images/icons/sad.png b/html/forums/images/icons/sad.png deleted file mode 100644 index 82e8699..0000000 Binary files a/html/forums/images/icons/sad.png and /dev/null differ diff --git a/html/forums/images/icons/shield.png b/html/forums/images/icons/shield.png deleted file mode 100644 index 47323e9..0000000 Binary files a/html/forums/images/icons/shield.png and /dev/null differ diff --git a/html/forums/images/icons/shocked.png b/html/forums/images/icons/shocked.png deleted file mode 100644 index 761f083..0000000 Binary files a/html/forums/images/icons/shocked.png and /dev/null differ diff --git a/html/forums/images/icons/smile.png b/html/forums/images/icons/smile.png deleted file mode 100644 index e5597ef..0000000 Binary files a/html/forums/images/icons/smile.png and /dev/null differ diff --git a/html/forums/images/icons/sport.png b/html/forums/images/icons/sport.png deleted file mode 100644 index 1e4ded2..0000000 Binary files a/html/forums/images/icons/sport.png and /dev/null differ diff --git a/html/forums/images/icons/star.png b/html/forums/images/icons/star.png deleted file mode 100644 index 6ca853b..0000000 Binary files a/html/forums/images/icons/star.png and /dev/null differ diff --git a/html/forums/images/icons/thumbsdown.png b/html/forums/images/icons/thumbsdown.png deleted file mode 100644 index de08ba1..0000000 Binary files a/html/forums/images/icons/thumbsdown.png and /dev/null differ diff --git a/html/forums/images/icons/thumbsup.png b/html/forums/images/icons/thumbsup.png deleted file mode 100644 index 208e487..0000000 Binary files a/html/forums/images/icons/thumbsup.png and /dev/null differ diff --git a/html/forums/images/icons/tongue.png b/html/forums/images/icons/tongue.png deleted file mode 100644 index 6006573..0000000 Binary files a/html/forums/images/icons/tongue.png and /dev/null differ diff --git a/html/forums/images/icons/user.png b/html/forums/images/icons/user.png deleted file mode 100644 index dd82fa6..0000000 Binary files a/html/forums/images/icons/user.png and /dev/null differ diff --git a/html/forums/images/icons/video.png b/html/forums/images/icons/video.png deleted file mode 100644 index d230cd4..0000000 Binary files a/html/forums/images/icons/video.png and /dev/null differ diff --git a/html/forums/images/icons/wink.png b/html/forums/images/icons/wink.png deleted file mode 100644 index d0deb12..0000000 Binary files a/html/forums/images/icons/wink.png and /dev/null differ diff --git a/html/forums/images/index.html b/html/forums/images/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/images/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/images/invalid.png b/html/forums/images/invalid.png deleted file mode 100644 index 13d9a99..0000000 Binary files a/html/forums/images/invalid.png and /dev/null differ diff --git a/html/forums/images/jump.png b/html/forums/images/jump.png deleted file mode 100644 index 930134a..0000000 Binary files a/html/forums/images/jump.png and /dev/null differ diff --git a/html/forums/images/logo.png b/html/forums/images/logo.png deleted file mode 100644 index 531dc80..0000000 Binary files a/html/forums/images/logo.png and /dev/null differ diff --git a/html/forums/images/logo_white.png b/html/forums/images/logo_white.png deleted file mode 100644 index f13701f..0000000 Binary files a/html/forums/images/logo_white.png and /dev/null differ diff --git a/html/forums/images/mini_status_sprite.png b/html/forums/images/mini_status_sprite.png deleted file mode 100644 index 3949597..0000000 Binary files a/html/forums/images/mini_status_sprite.png and /dev/null differ diff --git a/html/forums/images/modcp_sprite.png b/html/forums/images/modcp_sprite.png deleted file mode 100644 index 9e3c212..0000000 Binary files a/html/forums/images/modcp_sprite.png and /dev/null differ diff --git a/html/forums/images/nav_bit.png b/html/forums/images/nav_bit.png deleted file mode 100644 index 130ebbd..0000000 Binary files a/html/forums/images/nav_bit.png and /dev/null differ diff --git a/html/forums/images/new_pm.png b/html/forums/images/new_pm.png deleted file mode 100644 index 4aa7ca8..0000000 Binary files a/html/forums/images/new_pm.png and /dev/null differ diff --git a/html/forums/images/old_pm.png b/html/forums/images/old_pm.png deleted file mode 100644 index dce3aa7..0000000 Binary files a/html/forums/images/old_pm.png and /dev/null differ diff --git a/html/forums/images/paperclip.png b/html/forums/images/paperclip.png deleted file mode 100644 index 1cfcb07..0000000 Binary files a/html/forums/images/paperclip.png and /dev/null differ diff --git a/html/forums/images/pollbar.png b/html/forums/images/pollbar.png deleted file mode 100644 index 7dadc5a..0000000 Binary files a/html/forums/images/pollbar.png and /dev/null differ diff --git a/html/forums/images/printable.png b/html/forums/images/printable.png deleted file mode 100644 index db6477f..0000000 Binary files a/html/forums/images/printable.png and /dev/null differ diff --git a/html/forums/images/re_pm.png b/html/forums/images/re_pm.png deleted file mode 100644 index 20ce3df..0000000 Binary files a/html/forums/images/re_pm.png and /dev/null differ diff --git a/html/forums/images/send.png b/html/forums/images/send.png deleted file mode 100644 index 4aa7ca8..0000000 Binary files a/html/forums/images/send.png and /dev/null differ diff --git a/html/forums/images/showthread_sprite.png b/html/forums/images/showthread_sprite.png deleted file mode 100644 index edd34cd..0000000 Binary files a/html/forums/images/showthread_sprite.png and /dev/null differ diff --git a/html/forums/images/smilies/angel.png b/html/forums/images/smilies/angel.png deleted file mode 100644 index b78abb1..0000000 Binary files a/html/forums/images/smilies/angel.png and /dev/null differ diff --git a/html/forums/images/smilies/angry.png b/html/forums/images/smilies/angry.png deleted file mode 100644 index 6ba5bb5..0000000 Binary files a/html/forums/images/smilies/angry.png and /dev/null differ diff --git a/html/forums/images/smilies/arrow.png b/html/forums/images/smilies/arrow.png deleted file mode 100644 index 1accfc0..0000000 Binary files a/html/forums/images/smilies/arrow.png and /dev/null differ diff --git a/html/forums/images/smilies/at.png b/html/forums/images/smilies/at.png deleted file mode 100644 index 194020f..0000000 Binary files a/html/forums/images/smilies/at.png and /dev/null differ diff --git a/html/forums/images/smilies/biggrin.png b/html/forums/images/smilies/biggrin.png deleted file mode 100644 index 42d49d8..0000000 Binary files a/html/forums/images/smilies/biggrin.png and /dev/null differ diff --git a/html/forums/images/smilies/blush.png b/html/forums/images/smilies/blush.png deleted file mode 100644 index 2601982..0000000 Binary files a/html/forums/images/smilies/blush.png and /dev/null differ diff --git a/html/forums/images/smilies/confused.png b/html/forums/images/smilies/confused.png deleted file mode 100644 index 9e8fe70..0000000 Binary files a/html/forums/images/smilies/confused.png and /dev/null differ diff --git a/html/forums/images/smilies/cool.png b/html/forums/images/smilies/cool.png deleted file mode 100644 index cdfa4df..0000000 Binary files a/html/forums/images/smilies/cool.png and /dev/null differ diff --git a/html/forums/images/smilies/cry.png b/html/forums/images/smilies/cry.png deleted file mode 100644 index a33974e..0000000 Binary files a/html/forums/images/smilies/cry.png and /dev/null differ diff --git a/html/forums/images/smilies/dodgy.png b/html/forums/images/smilies/dodgy.png deleted file mode 100644 index a74c2ce..0000000 Binary files a/html/forums/images/smilies/dodgy.png and /dev/null differ diff --git a/html/forums/images/smilies/exclamation.png b/html/forums/images/smilies/exclamation.png deleted file mode 100644 index 4b885b0..0000000 Binary files a/html/forums/images/smilies/exclamation.png and /dev/null differ diff --git a/html/forums/images/smilies/heart.png b/html/forums/images/smilies/heart.png deleted file mode 100644 index f51ffb4..0000000 Binary files a/html/forums/images/smilies/heart.png and /dev/null differ diff --git a/html/forums/images/smilies/huh.png b/html/forums/images/smilies/huh.png deleted file mode 100644 index 9163a8b..0000000 Binary files a/html/forums/images/smilies/huh.png and /dev/null differ diff --git a/html/forums/images/smilies/lightbulb.png b/html/forums/images/smilies/lightbulb.png deleted file mode 100644 index c6897ae..0000000 Binary files a/html/forums/images/smilies/lightbulb.png and /dev/null differ diff --git a/html/forums/images/smilies/my.png b/html/forums/images/smilies/my.png deleted file mode 100644 index 1e0fd5f..0000000 Binary files a/html/forums/images/smilies/my.png and /dev/null differ diff --git a/html/forums/images/smilies/rolleyes.png b/html/forums/images/smilies/rolleyes.png deleted file mode 100644 index 79cefe5..0000000 Binary files a/html/forums/images/smilies/rolleyes.png and /dev/null differ diff --git a/html/forums/images/smilies/sad.png b/html/forums/images/smilies/sad.png deleted file mode 100644 index 948d564..0000000 Binary files a/html/forums/images/smilies/sad.png and /dev/null differ diff --git a/html/forums/images/smilies/shy.png b/html/forums/images/smilies/shy.png deleted file mode 100644 index f8e8351..0000000 Binary files a/html/forums/images/smilies/shy.png and /dev/null differ diff --git a/html/forums/images/smilies/sick.png b/html/forums/images/smilies/sick.png deleted file mode 100644 index 70186fe..0000000 Binary files a/html/forums/images/smilies/sick.png and /dev/null differ diff --git a/html/forums/images/smilies/sleepy.png b/html/forums/images/smilies/sleepy.png deleted file mode 100644 index a462de1..0000000 Binary files a/html/forums/images/smilies/sleepy.png and /dev/null differ diff --git a/html/forums/images/smilies/smile.png b/html/forums/images/smilies/smile.png deleted file mode 100644 index 91fe67f..0000000 Binary files a/html/forums/images/smilies/smile.png and /dev/null differ diff --git a/html/forums/images/smilies/tongue.png b/html/forums/images/smilies/tongue.png deleted file mode 100644 index f37c165..0000000 Binary files a/html/forums/images/smilies/tongue.png and /dev/null differ diff --git a/html/forums/images/smilies/undecided.png b/html/forums/images/smilies/undecided.png deleted file mode 100644 index 64d5be5..0000000 Binary files a/html/forums/images/smilies/undecided.png and /dev/null differ diff --git a/html/forums/images/smilies/wink.png b/html/forums/images/smilies/wink.png deleted file mode 100644 index 2260afe..0000000 Binary files a/html/forums/images/smilies/wink.png and /dev/null differ diff --git a/html/forums/images/spinner.gif b/html/forums/images/spinner.gif deleted file mode 100644 index 529e72f..0000000 Binary files a/html/forums/images/spinner.gif and /dev/null differ diff --git a/html/forums/images/spinner_big.gif b/html/forums/images/spinner_big.gif deleted file mode 100644 index 0ca7ada..0000000 Binary files a/html/forums/images/spinner_big.gif and /dev/null differ diff --git a/html/forums/images/star.png b/html/forums/images/star.png deleted file mode 100644 index 86950ee..0000000 Binary files a/html/forums/images/star.png and /dev/null differ diff --git a/html/forums/images/star_rating.png b/html/forums/images/star_rating.png deleted file mode 100644 index 20abef1..0000000 Binary files a/html/forums/images/star_rating.png and /dev/null differ diff --git a/html/forums/images/tcat.png b/html/forums/images/tcat.png deleted file mode 100644 index c159e75..0000000 Binary files a/html/forums/images/tcat.png and /dev/null differ diff --git a/html/forums/images/thead.png b/html/forums/images/thead.png deleted file mode 100644 index 7a56d81..0000000 Binary files a/html/forums/images/thead.png and /dev/null differ diff --git a/html/forums/images/usercp_sprite.png b/html/forums/images/usercp_sprite.png deleted file mode 100644 index d8cacc8..0000000 Binary files a/html/forums/images/usercp_sprite.png and /dev/null differ diff --git a/html/forums/images/valid.png b/html/forums/images/valid.png deleted file mode 100644 index 711c2f0..0000000 Binary files a/html/forums/images/valid.png and /dev/null differ diff --git a/html/forums/inc/3rdparty/2fa/GoogleAuthenticator.php b/html/forums/inc/3rdparty/2fa/GoogleAuthenticator.php deleted file mode 100644 index 02c645f..0000000 --- a/html/forums/inc/3rdparty/2fa/GoogleAuthenticator.php +++ /dev/null @@ -1,252 +0,0 @@ -_getBase32LookupTable(); - - // Valid secret lengths are 80 to 640 bits - if ($secretLength < 16 || $secretLength > 128) { - throw new Exception('Bad secret length'); - } - $secret = ''; - $rnd = false; - if (function_exists('random_bytes')) { - $rnd = random_bytes($secretLength); - } elseif (function_exists('mcrypt_create_iv')) { - $rnd = mcrypt_create_iv($secretLength, MCRYPT_DEV_URANDOM); - } elseif (function_exists('openssl_random_pseudo_bytes')) { - $rnd = openssl_random_pseudo_bytes($secretLength, $cryptoStrong); - if (!$cryptoStrong) { - $rnd = false; - } - } - if ($rnd !== false) { - for ($i = 0; $i < $secretLength; ++$i) { - $secret .= $validChars[ord($rnd[$i]) & 31]; - } - } else { - throw new Exception('No source of secure random'); - } - - return $secret; - } - - /** - * Calculate the code, with given secret and point in time. - * - * @param string $secret - * @param int|null $timeSlice - * - * @return string - */ - public function getCode($secret, $timeSlice = null) - { - if ($timeSlice === null) { - $timeSlice = floor(time() / 30); - } - - $secretkey = $this->_base32Decode($secret); - - // Pack time into binary string - $time = chr(0).chr(0).chr(0).chr(0).pack('N*', $timeSlice); - // Hash it with users secret key - $hm = hash_hmac('SHA1', $time, $secretkey, true); - // Use last nipple of result as index/offset - $offset = ord(substr($hm, -1)) & 0x0F; - // grab 4 bytes of the result - $hashpart = substr($hm, $offset, 4); - - // Unpak binary value - $value = unpack('N', $hashpart); - $value = $value[1]; - // Only 32 bits - $value = $value & 0x7FFFFFFF; - - $modulo = pow(10, $this->_codeLength); - - return str_pad($value % $modulo, $this->_codeLength, '0', STR_PAD_LEFT); - } - - /** - * Get QR-Code URL for image, from google charts. - * - * @param string $name - * @param string $secret - * @param string $title - * @param array $params - * - * @return string - */ - public function getQRCodeGoogleUrl($name, $secret, $title = null, $params = array()) - { - $width = !empty($params['width']) && (int) $params['width'] > 0 ? (int) $params['width'] : 200; - $height = !empty($params['height']) && (int) $params['height'] > 0 ? (int) $params['height'] : 200; - $level = !empty($params['level']) && array_search($params['level'], array('L', 'M', 'Q', 'H')) !== false ? $params['level'] : 'M'; - - $urlencoded = urlencode('otpauth://totp/'.$name.'?secret='.$secret.''); - if (isset($title)) { - $urlencoded .= urlencode('&issuer='.urlencode($title)); - } - - return 'https://chart.googleapis.com/chart?chs='.$width.'x'.$height.'&chld='.$level.'|0&cht=qr&chl='.$urlencoded.''; - } - - /** - * Check if the code is correct. This will accept codes starting from $discrepancy*30sec ago to $discrepancy*30sec from now. - * - * @param string $secret - * @param string $code - * @param int $discrepancy This is the allowed time drift in 30 second units (8 means 4 minutes before or after) - * @param int|null $currentTimeSlice time slice if we want use other that time() - * - * @return bool - */ - public function verifyCode($secret, $code, $discrepancy = 1, $currentTimeSlice = null) - { - if ($currentTimeSlice === null) { - $currentTimeSlice = floor(time() / 30); - } - - if (strlen($code) != 6) { - return false; - } - - for ($i = -$discrepancy; $i <= $discrepancy; ++$i) { - $calculatedCode = $this->getCode($secret, $currentTimeSlice + $i); - if ($this->timingSafeEquals($calculatedCode, $code)) { - return true; - } - } - - return false; - } - - /** - * Set the code length, should be >=6. - * - * @param int $length - * - * @return PHPGangsta_GoogleAuthenticator - */ - public function setCodeLength($length) - { - $this->_codeLength = $length; - - return $this; - } - - /** - * Helper class to decode base32. - * - * @param $secret - * - * @return bool|string - */ - protected function _base32Decode($secret) - { - if (empty($secret)) { - return ''; - } - - $base32chars = $this->_getBase32LookupTable(); - $base32charsFlipped = array_flip($base32chars); - - $paddingCharCount = substr_count($secret, $base32chars[32]); - $allowedValues = array(6, 4, 3, 1, 0); - if (!in_array($paddingCharCount, $allowedValues)) { - return false; - } - for ($i = 0; $i < 4; ++$i) { - if ($paddingCharCount == $allowedValues[$i] && - substr($secret, -($allowedValues[$i])) != str_repeat($base32chars[32], $allowedValues[$i])) { - return false; - } - } - $secret = str_replace('=', '', $secret); - $secret = str_split($secret); - $binaryString = ''; - for ($i = 0; $i < count($secret); $i = $i + 8) { - $x = ''; - if (!in_array($secret[$i], $base32chars)) { - return false; - } - for ($j = 0; $j < 8; ++$j) { - $x .= str_pad(base_convert(@$base32charsFlipped[@$secret[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT); - } - $eightBits = str_split($x, 8); - for ($z = 0; $z < count($eightBits); ++$z) { - $binaryString .= (($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48) ? $y : ''; - } - } - - return $binaryString; - } - - /** - * Get array with all 32 characters for decoding from/encoding to base32. - * - * @return array - */ - protected function _getBase32LookupTable() - { - return array( - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7 - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15 - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23 - 'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31 - '=', // padding char - ); - } - - /** - * A timing safe equals comparison - * more info here: http://blog.ircmaxell.com/2014/11/its-all-about-time.html. - * - * @param string $safeString The internal (safe) value to be checked - * @param string $userString The user submitted (unsafe) value - * - * @return bool True if the two strings are identical - */ - private function timingSafeEquals($safeString, $userString) - { - if (function_exists('hash_equals')) { - return hash_equals($safeString, $userString); - } - $safeLen = strlen($safeString); - $userLen = strlen($userString); - - if ($userLen != $safeLen) { - return false; - } - - $result = 0; - - for ($i = 0; $i < $userLen; ++$i) { - $result |= (ord($safeString[$i]) ^ ord($userString[$i])); - } - - // They are only identical strings if $result is exactly 0... - return $result === 0; - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff.php b/html/forums/inc/3rdparty/diff/Diff.php deleted file mode 100644 index 2ce1329..0000000 --- a/html/forums/inc/3rdparty/diff/Diff.php +++ /dev/null @@ -1,261 +0,0 @@ -, and is used/adapted with his permission. - * - * Copyright 2004 Geoffrey T. Dairiki - * Copyright 2004-2011 Horde LLC (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you did - * not receive this file, see http://www.horde.org/licenses/lgpl21. - * - * @package Text_Diff - * @author Geoffrey T. Dairiki - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff -{ - /** - * Array of changes. - * - * @var array - */ - protected $_edits; - - /** - * Computes diffs between sequences of strings. - * - * @param string $engine Name of the diffing engine to use. 'auto' - * will automatically select the best. - * @param array $params Parameters to pass to the diffing engine. - * Normally an array of two arrays, each - * containing the lines from a file. - */ - public function __construct($engine, $params) - { - if ($engine == 'auto') { - $engine = extension_loaded('xdiff') ? 'Xdiff' : 'Native'; - } else { - $engine = Horde_String::ucfirst(basename($engine)); - } - - // Fugly; Include operational classes required for Text_Diff - $classes = array( - 'String.php', - "Engine/{$engine}.php", - 'Renderer/Inline.php', - 'Op/Base.php', - 'Op/Copy.php', - 'Op/Change.php', - 'Op/Add.php', - 'Op/Delete.php' - ); - - foreach($classes as $class) - { - require_once MYBB_ROOT."inc/3rdparty/diff/Diff/{$class}"; - } - - $class = 'Horde_Text_Diff_Engine_' . $engine; - $diff_engine = new $class(); - - $this->_edits = call_user_func_array(array($diff_engine, 'diff'), $params); - } - - /** - * Returns the array of differences. - */ - public function getDiff() - { - return $this->_edits; - } - - /** - * returns the number of new (added) lines in a given diff. - * - * @since Text_Diff 1.1.0 - * - * @return integer The number of new lines - */ - public function countAddedLines() - { - $count = 0; - foreach ($this->_edits as $edit) { - if ($edit instanceof Horde_Text_Diff_Op_Add || - $edit instanceof Horde_Text_Diff_Op_Change) { - $count += $edit->nfinal(); - } - } - return $count; - } - - /** - * Returns the number of deleted (removed) lines in a given diff. - * - * @since Text_Diff 1.1.0 - * - * @return integer The number of deleted lines - */ - public function countDeletedLines() - { - $count = 0; - foreach ($this->_edits as $edit) { - if ($edit instanceof Horde_Text_Diff_Op_Delete || - $edit instanceof Horde_Text_Diff_Op_Change) { - $count += $edit->norig(); - } - } - return $count; - } - - /** - * Computes a reversed diff. - * - * Example: - * - * $diff = new Horde_Text_Diff($lines1, $lines2); - * $rev = $diff->reverse(); - * - * - * @return Horde_Text_Diff A Diff object representing the inverse of the - * original diff. Note that we purposely don't return a - * reference here, since this essentially is a clone() - * method. - */ - public function reverse() - { - if (version_compare(zend_version(), '2', '>')) { - $rev = clone($this); - } else { - $rev = $this; - } - $rev->_edits = array(); - foreach ($this->_edits as $edit) { - $rev->_edits[] = $edit->reverse(); - } - return $rev; - } - - /** - * Checks for an empty diff. - * - * @return boolean True if two sequences were identical. - */ - public function isEmpty() - { - foreach ($this->_edits as $edit) { - if (!($edit instanceof Horde_Text_Diff_Op_Copy)) { - return false; - } - } - return true; - } - - /** - * Computes the length of the Longest Common Subsequence (LCS). - * - * This is mostly for diagnostic purposes. - * - * @return integer The length of the LCS. - */ - public function lcs() - { - $lcs = 0; - foreach ($this->_edits as $edit) { - if ($edit instanceof Horde_Text_Diff_Op_Copy) { - $lcs += count($edit->orig); - } - } - return $lcs; - } - - /** - * Gets the original set of lines. - * - * This reconstructs the $from_lines parameter passed to the constructor. - * - * @return array The original sequence of strings. - */ - public function getOriginal() - { - $lines = array(); - foreach ($this->_edits as $edit) { - if ($edit->orig) { - array_splice($lines, count($lines), 0, $edit->orig); - } - } - return $lines; - } - - /** - * Gets the final set of lines. - * - * This reconstructs the $to_lines parameter passed to the constructor. - * - * @return array The sequence of strings. - */ - public function getFinal() - { - $lines = array(); - foreach ($this->_edits as $edit) { - if ($edit->final) { - array_splice($lines, count($lines), 0, $edit->final); - } - } - return $lines; - } - - /** - * Removes trailing newlines from a line of text. This is meant to be used - * with array_walk(). - * - * @param string $line The line to trim. - * @param integer $key The index of the line in the array. Not used. - */ - static public function trimNewlines(&$line, $key) - { - $line = str_replace(array("\n", "\r"), '', $line); - } - - /** - * Checks a diff for validity. - * - * This is here only for debugging purposes. - */ - protected function _check($from_lines, $to_lines) - { - if (serialize($from_lines) != serialize($this->getOriginal())) { - trigger_error("Reconstructed original doesn't match", E_USER_ERROR); - } - if (serialize($to_lines) != serialize($this->getFinal())) { - trigger_error("Reconstructed final doesn't match", E_USER_ERROR); - } - - $rev = $this->reverse(); - if (serialize($to_lines) != serialize($rev->getOriginal())) { - trigger_error("Reversed original doesn't match", E_USER_ERROR); - } - if (serialize($from_lines) != serialize($rev->getFinal())) { - trigger_error("Reversed final doesn't match", E_USER_ERROR); - } - - $prevtype = null; - foreach ($this->_edits as $edit) { - if ($prevtype == get_class($edit)) { - trigger_error("Edit sequence is non-optimal", E_USER_ERROR); - } - $prevtype = get_class($edit); - } - - return true; - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Engine/Native.php b/html/forums/inc/3rdparty/diff/Diff/Engine/Native.php deleted file mode 100644 index e1db345..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Engine/Native.php +++ /dev/null @@ -1,442 +0,0 @@ - 2, and some optimizations) are from - * Geoffrey T. Dairiki . The original PHP version of this - * code was written by him, and is used/adapted with his permission. - * - * Copyright 2004-2011 Horde LLC (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you did - * not receive this file, see http://www.horde.org/licenses/lgpl21. - * - * @author Geoffrey T. Dairiki - * @package Text_Diff - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Engine_Native -{ - public function diff($from_lines, $to_lines) - { - array_walk($from_lines, array('Horde_Text_Diff', 'trimNewlines')); - array_walk($to_lines, array('Horde_Text_Diff', 'trimNewlines')); - - $n_from = count($from_lines); - $n_to = count($to_lines); - - $this->xchanged = $this->ychanged = array(); - $this->xv = $this->yv = array(); - $this->xind = $this->yind = array(); - unset($this->seq); - unset($this->in_seq); - unset($this->lcs); - - // Skip leading common lines. - for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) { - if ($from_lines[$skip] !== $to_lines[$skip]) { - break; - } - $this->xchanged[$skip] = $this->ychanged[$skip] = false; - } - - // Skip trailing common lines. - $xi = $n_from; $yi = $n_to; - for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) { - if ($from_lines[$xi] !== $to_lines[$yi]) { - break; - } - $this->xchanged[$xi] = $this->ychanged[$yi] = false; - } - - // Ignore lines which do not exist in both files. - for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { - $xhash[$from_lines[$xi]] = 1; - } - for ($yi = $skip; $yi < $n_to - $endskip; $yi++) { - $line = $to_lines[$yi]; - if (($this->ychanged[$yi] = empty($xhash[$line]))) { - continue; - } - $yhash[$line] = 1; - $this->yv[] = $line; - $this->yind[] = $yi; - } - for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { - $line = $from_lines[$xi]; - if (($this->xchanged[$xi] = empty($yhash[$line]))) { - continue; - } - $this->xv[] = $line; - $this->xind[] = $xi; - } - - // Find the LCS. - $this->_compareseq(0, count($this->xv), 0, count($this->yv)); - - // Merge edits when possible. - $this->_shiftBoundaries($from_lines, $this->xchanged, $this->ychanged); - $this->_shiftBoundaries($to_lines, $this->ychanged, $this->xchanged); - - // Compute the edit operations. - $edits = array(); - $xi = $yi = 0; - while ($xi < $n_from || $yi < $n_to) { - assert($yi < $n_to || $this->xchanged[$xi]); - assert($xi < $n_from || $this->ychanged[$yi]); - - // Skip matching "snake". - $copy = array(); - while ($xi < $n_from && $yi < $n_to - && !$this->xchanged[$xi] && !$this->ychanged[$yi]) { - $copy[] = $from_lines[$xi++]; - ++$yi; - } - if ($copy) { - $edits[] = new Horde_Text_Diff_Op_Copy($copy); - } - - // Find deletes & adds. - $delete = array(); - while ($xi < $n_from && $this->xchanged[$xi]) { - $delete[] = $from_lines[$xi++]; - } - - $add = array(); - while ($yi < $n_to && $this->ychanged[$yi]) { - $add[] = $to_lines[$yi++]; - } - - if ($delete && $add) { - $edits[] = new Horde_Text_Diff_Op_Change($delete, $add); - } elseif ($delete) { - $edits[] = new Horde_Text_Diff_Op_Delete($delete); - } elseif ($add) { - $edits[] = new Horde_Text_Diff_Op_Add($add); - } - } - - return $edits; - } - - /** - * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF, - * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized - * segments. - * - * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of - * NCHUNKS+1 (X, Y) indexes giving the diving points between sub - * sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1), - * the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) == - * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM). - * - * This public function assumes that the first lines of the specified portions of - * the two files do not match, and likewise that the last lines do not - * match. The caller must trim matching lines from the beginning and end - * of the portions it is going to specify. - */ - protected function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) - { - $flip = false; - - if ($xlim - $xoff > $ylim - $yoff) { - /* Things seems faster (I'm not sure I understand why) when the - * shortest sequence is in X. */ - $flip = true; - list ($xoff, $xlim, $yoff, $ylim) - = array($yoff, $ylim, $xoff, $xlim); - } - - if ($flip) { - for ($i = $ylim - 1; $i >= $yoff; $i--) { - $ymatches[$this->xv[$i]][] = $i; - } - } else { - for ($i = $ylim - 1; $i >= $yoff; $i--) { - $ymatches[$this->yv[$i]][] = $i; - } - } - - $this->lcs = 0; - $this->seq[0]= $yoff - 1; - $this->in_seq = array(); - $ymids[0] = array(); - - $numer = $xlim - $xoff + $nchunks - 1; - $x = $xoff; - for ($chunk = 0; $chunk < $nchunks; $chunk++) { - if ($chunk > 0) { - for ($i = 0; $i <= $this->lcs; $i++) { - $ymids[$i][$chunk - 1] = $this->seq[$i]; - } - } - - $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks); - for (; $x < $x1; $x++) { - $line = $flip ? $this->yv[$x] : $this->xv[$x]; - if (empty($ymatches[$line])) { - continue; - } - $matches = $ymatches[$line]; - reset($matches); - while (list(, $y) = each($matches)) { - if (empty($this->in_seq[$y])) { - $k = $this->_lcsPos($y); - assert($k > 0); - $ymids[$k] = $ymids[$k - 1]; - break; - } - } - while (list(, $y) = each($matches)) { - if ($y > $this->seq[$k - 1]) { - assert($y <= $this->seq[$k]); - /* Optimization: this is a common case: next match is - * just replacing previous match. */ - $this->in_seq[$this->seq[$k]] = false; - $this->seq[$k] = $y; - $this->in_seq[$y] = 1; - } elseif (empty($this->in_seq[$y])) { - $k = $this->_lcsPos($y); - assert($k > 0); - $ymids[$k] = $ymids[$k - 1]; - } - } - } - } - - $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff); - $ymid = $ymids[$this->lcs]; - for ($n = 0; $n < $nchunks - 1; $n++) { - $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks); - $y1 = $ymid[$n] + 1; - $seps[] = $flip ? array($y1, $x1) : array($x1, $y1); - } - $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim); - - return array($this->lcs, $seps); - } - - protected function _lcsPos($ypos) - { - $end = $this->lcs; - if ($end == 0 || $ypos > $this->seq[$end]) { - $this->seq[++$this->lcs] = $ypos; - $this->in_seq[$ypos] = 1; - return $this->lcs; - } - - $beg = 1; - while ($beg < $end) { - $mid = (int)(($beg + $end) / 2); - if ($ypos > $this->seq[$mid]) { - $beg = $mid + 1; - } else { - $end = $mid; - } - } - - assert($ypos != $this->seq[$end]); - - $this->in_seq[$this->seq[$end]] = false; - $this->seq[$end] = $ypos; - $this->in_seq[$ypos] = 1; - return $end; - } - - /** - * Finds LCS of two sequences. - * - * The results are recorded in the vectors $this->{x,y}changed[], by - * storing a 1 in the element for each line that is an insertion or - * deletion (ie. is not in the LCS). - * - * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1. - * - * Note that XLIM, YLIM are exclusive bounds. All line numbers are - * origin-0 and discarded lines are not counted. - */ - protected function _compareseq ($xoff, $xlim, $yoff, $ylim) - { - /* Slide down the bottom initial diagonal. */ - while ($xoff < $xlim && $yoff < $ylim - && $this->xv[$xoff] == $this->yv[$yoff]) { - ++$xoff; - ++$yoff; - } - - /* Slide up the top initial diagonal. */ - while ($xlim > $xoff && $ylim > $yoff - && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) { - --$xlim; - --$ylim; - } - - if ($xoff == $xlim || $yoff == $ylim) { - $lcs = 0; - } else { - /* This is ad hoc but seems to work well. $nchunks = - * sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); $nchunks = - * max(2,min(8,(int)$nchunks)); */ - $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1; - list($lcs, $seps) - = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks); - } - - if ($lcs == 0) { - /* X and Y sequences have no common subsequence: mark all - * changed. */ - while ($yoff < $ylim) { - $this->ychanged[$this->yind[$yoff++]] = 1; - } - while ($xoff < $xlim) { - $this->xchanged[$this->xind[$xoff++]] = 1; - } - } else { - /* Use the partitions to split this problem into subproblems. */ - reset($seps); - $pt1 = $seps[0]; - while ($pt2 = next($seps)) { - $this->_compareseq ($pt1[0], $pt2[0], $pt1[1], $pt2[1]); - $pt1 = $pt2; - } - } - } - - /** - * Adjusts inserts/deletes of identical lines to join changes as much as - * possible. - * - * We do something when a run of changed lines include a line at one end - * and has an excluded, identical line at the other. We are free to - * choose which identical line is included. `compareseq' usually chooses - * the one at the beginning, but usually it is cleaner to consider the - * following identical line to be the "change". - * - * This is extracted verbatim from analyze.c (GNU diffutils-2.7). - */ - protected function _shiftBoundaries($lines, &$changed, $other_changed) - { - $i = 0; - $j = 0; - - assert('count($lines) == count($changed)'); - $len = count($lines); - $other_len = count($other_changed); - - while (1) { - /* Scan forward to find the beginning of another run of - * changes. Also keep track of the corresponding point in the - * other file. - * - * Throughout this code, $i and $j are adjusted together so that - * the first $i elements of $changed and the first $j elements of - * $other_changed both contain the same number of zeros (unchanged - * lines). - * - * Furthermore, $j is always kept so that $j == $other_len or - * $other_changed[$j] == false. */ - while ($j < $other_len && $other_changed[$j]) { - $j++; - } - - while ($i < $len && ! $changed[$i]) { - assert('$j < $other_len && ! $other_changed[$j]'); - $i++; $j++; - while ($j < $other_len && $other_changed[$j]) { - $j++; - } - } - - if ($i == $len) { - break; - } - - $start = $i; - - /* Find the end of this run of changes. */ - while (++$i < $len && $changed[$i]) { - continue; - } - - do { - /* Record the length of this run of changes, so that we can - * later determine whether the run has grown. */ - $runlength = $i - $start; - - /* Move the changed region back, so long as the previous - * unchanged line matches the last changed one. This merges - * with previous changed regions. */ - while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) { - $changed[--$start] = 1; - $changed[--$i] = false; - while ($start > 0 && $changed[$start - 1]) { - $start--; - } - assert('$j > 0'); - while ($other_changed[--$j]) { - continue; - } - assert('$j >= 0 && !$other_changed[$j]'); - } - - /* Set CORRESPONDING to the end of the changed run, at the - * last point where it corresponds to a changed run in the - * other file. CORRESPONDING == LEN means no such point has - * been found. */ - $corresponding = $j < $other_len ? $i : $len; - - /* Move the changed region forward, so long as the first - * changed line matches the following unchanged one. This - * merges with following changed regions. Do this second, so - * that if there are no merges, the changed region is moved - * forward as far as possible. */ - while ($i < $len && $lines[$start] == $lines[$i]) { - $changed[$start++] = false; - $changed[$i++] = 1; - while ($i < $len && $changed[$i]) { - $i++; - } - - assert('$j < $other_len && ! $other_changed[$j]'); - $j++; - if ($j < $other_len && $other_changed[$j]) { - $corresponding = $i; - while ($j < $other_len && $other_changed[$j]) { - $j++; - } - } - } - } while ($runlength != $i - $start); - - /* If possible, move the fully-merged run of changes back to a - * corresponding run in the other file. */ - while ($corresponding < $i) { - $changed[--$start] = 1; - $changed[--$i] = 0; - assert('$j > 0'); - while ($other_changed[--$j]) { - continue; - } - assert('$j >= 0 && !$other_changed[$j]'); - } - } - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Engine/Shell.php b/html/forums/inc/3rdparty/diff/Diff/Engine/Shell.php deleted file mode 100644 index 601b965..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Engine/Shell.php +++ /dev/null @@ -1,165 +0,0 @@ - - * @package Text_Diff - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Engine_Shell -{ - /** - * Path to the diff executable - * - * @var string - */ - protected $_diffCommand = 'diff'; - - /** - * Returns the array of differences. - * - * @param array $from_lines lines of text from old file - * @param array $to_lines lines of text from new file - * - * @return array all changes made (array with Horde_Text_Diff_Op_* objects) - */ - public function diff($from_lines, $to_lines) - { - array_walk($from_lines, array('Horde_Text_Diff', 'trimNewlines')); - array_walk($to_lines, array('Horde_Text_Diff', 'trimNewlines')); - - // Execute gnu diff or similar to get a standard diff file. - $from_file = Horde_Util::getTempFile('Horde_Text_Diff'); - $to_file = Horde_Util::getTempFile('Horde_Text_Diff'); - $fp = fopen($from_file, 'w'); - fwrite($fp, implode("\n", $from_lines)); - fclose($fp); - $fp = fopen($to_file, 'w'); - fwrite($fp, implode("\n", $to_lines)); - fclose($fp); - $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file); - unlink($from_file); - unlink($to_file); - - if (is_null($diff)) { - // No changes were made - return array(new Horde_Text_Diff_Op_Copy($from_lines)); - } - - $from_line_no = 1; - $to_line_no = 1; - $edits = array(); - - // Get changed lines by parsing something like: - // 0a1,2 - // 1,2c4,6 - // 1,5d6 - preg_match_all('#^(\d+)(?:,(\d+))?([adc])(\d+)(?:,(\d+))?$#m', $diff, - $matches, PREG_SET_ORDER); - - foreach ($matches as $match) { - if (!isset($match[5])) { - // This paren is not set every time (see regex). - $match[5] = false; - } - - if ($match[3] == 'a') { - $from_line_no--; - } - - if ($match[3] == 'd') { - $to_line_no--; - } - - if ($from_line_no < $match[1] || $to_line_no < $match[4]) { - // copied lines - assert('$match[1] - $from_line_no == $match[4] - $to_line_no'); - array_push($edits, - new Horde_Text_Diff_Op_Copy( - $this->_getLines($from_lines, $from_line_no, $match[1] - 1), - $this->_getLines($to_lines, $to_line_no, $match[4] - 1))); - } - - switch ($match[3]) { - case 'd': - // deleted lines - array_push($edits, - new Horde_Text_Diff_Op_Delete( - $this->_getLines($from_lines, $from_line_no, $match[2]))); - $to_line_no++; - break; - - case 'c': - // changed lines - array_push($edits, - new Horde_Text_Diff_Op_Change( - $this->_getLines($from_lines, $from_line_no, $match[2]), - $this->_getLines($to_lines, $to_line_no, $match[5]))); - break; - - case 'a': - // added lines - array_push($edits, - new Horde_Text_Diff_Op_Add( - $this->_getLines($to_lines, $to_line_no, $match[5]))); - $from_line_no++; - break; - } - } - - if (!empty($from_lines)) { - // Some lines might still be pending. Add them as copied - array_push($edits, - new Horde_Text_Diff_Op_Copy( - $this->_getLines($from_lines, $from_line_no, - $from_line_no + count($from_lines) - 1), - $this->_getLines($to_lines, $to_line_no, - $to_line_no + count($to_lines) - 1))); - } - - return $edits; - } - - /** - * Get lines from either the old or new text - * - * @access private - * - * @param array &$text_lines Either $from_lines or $to_lines - * @param int &$line_no Current line number - * @param int $end Optional end line, when we want to chop more - * than one line. - * - * @return array The chopped lines - */ - protected function _getLines(&$text_lines, &$line_no, $end = false) - { - if (!empty($end)) { - $lines = array(); - // We can shift even more - while ($line_no <= $end) { - array_push($lines, array_shift($text_lines)); - $line_no++; - } - } else { - $lines = array(array_shift($text_lines)); - $line_no++; - } - - return $lines; - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Engine/String.php b/html/forums/inc/3rdparty/diff/Diff/Engine/String.php deleted file mode 100644 index 38d942c..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Engine/String.php +++ /dev/null @@ -1,254 +0,0 @@ - - * $patch = file_get_contents('example.patch'); - * $diff = new Horde_Text_Diff('string', array($patch)); - * $renderer = new Horde_Text_Diff_Renderer_inline(); - * echo $renderer->render($diff); - * - * - * Copyright 2005 Örjan Persson - * Copyright 2005-2011 Horde LLC (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you did - * not receive this file, see http://www.horde.org/licenses/lgpl21. - * - * @author Örjan Persson - * @package Text_Diff - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Engine_String -{ - /** - * Parses a unified or context diff. - * - * First param contains the whole diff and the second can be used to force - * a specific diff type. If the second parameter is 'autodetect', the - * diff will be examined to find out which type of diff this is. - * - * @param string $diff The diff content. - * @param string $mode The diff mode of the content in $diff. One of - * 'context', 'unified', or 'autodetect'. - * - * @return array List of all diff operations. - * @throws Horde_Text_Diff_Exception - */ - public function diff($diff, $mode = 'autodetect') - { - // Detect line breaks. - $lnbr = "\n"; - if (strpos($diff, "\r\n") !== false) { - $lnbr = "\r\n"; - } elseif (strpos($diff, "\r") !== false) { - $lnbr = "\r"; - } - - // Make sure we have a line break at the EOF. - if (substr($diff, -strlen($lnbr)) != $lnbr) { - $diff .= $lnbr; - } - - if ($mode != 'autodetect' && $mode != 'context' && $mode != 'unified') { - throw new Horde_Text_Diff_Exception('Type of diff is unsupported'); - } - - if ($mode == 'autodetect') { - $context = strpos($diff, '***'); - $unified = strpos($diff, '---'); - if ($context === $unified) { - throw new Horde_Text_Diff_Exception('Type of diff could not be detected'); - } elseif ($context === false || $unified === false) { - $mode = $context !== false ? 'context' : 'unified'; - } else { - $mode = $context < $unified ? 'context' : 'unified'; - } - } - - // Split by new line and remove the diff header, if there is one. - $diff = explode($lnbr, $diff); - if (($mode == 'context' && strpos($diff[0], '***') === 0) || - ($mode == 'unified' && strpos($diff[0], '---') === 0)) { - array_shift($diff); - array_shift($diff); - } - - if ($mode == 'context') { - return $this->parseContextDiff($diff); - } else { - return $this->parseUnifiedDiff($diff); - } - } - - /** - * Parses an array containing the unified diff. - * - * @param array $diff Array of lines. - * - * @return array List of all diff operations. - */ - public function parseUnifiedDiff($diff) - { - $edits = array(); - $end = count($diff) - 1; - for ($i = 0; $i < $end;) { - $diff1 = array(); - switch (substr($diff[$i], 0, 1)) { - case ' ': - do { - $diff1[] = substr($diff[$i], 1); - } while (++$i < $end && substr($diff[$i], 0, 1) == ' '); - $edits[] = new Horde_Text_Diff_Op_Copy($diff1); - break; - - case '+': - // get all new lines - do { - $diff1[] = substr($diff[$i], 1); - } while (++$i < $end && substr($diff[$i], 0, 1) == '+'); - $edits[] = new Horde_Text_Diff_Op_Add($diff1); - break; - - case '-': - // get changed or removed lines - $diff2 = array(); - do { - $diff1[] = substr($diff[$i], 1); - } while (++$i < $end && substr($diff[$i], 0, 1) == '-'); - - while ($i < $end && substr($diff[$i], 0, 1) == '+') { - $diff2[] = substr($diff[$i++], 1); - } - if (count($diff2) == 0) { - $edits[] = new Horde_Text_Diff_Op_Delete($diff1); - } else { - $edits[] = new Horde_Text_Diff_Op_Change($diff1, $diff2); - } - break; - - default: - $i++; - break; - } - } - - return $edits; - } - - /** - * Parses an array containing the context diff. - * - * @param array $diff Array of lines. - * - * @return array List of all diff operations. - */ - public function parseContextDiff(&$diff) - { - $edits = array(); - $i = $max_i = $j = $max_j = 0; - $end = count($diff) - 1; - while ($i < $end && $j < $end) { - while ($i >= $max_i && $j >= $max_j) { - // Find the boundaries of the diff output of the two files - for ($i = $j; - $i < $end && substr($diff[$i], 0, 3) == '***'; - $i++); - for ($max_i = $i; - $max_i < $end && substr($diff[$max_i], 0, 3) != '---'; - $max_i++); - for ($j = $max_i; - $j < $end && substr($diff[$j], 0, 3) == '---'; - $j++); - for ($max_j = $j; - $max_j < $end && substr($diff[$max_j], 0, 3) != '***'; - $max_j++); - } - - // find what hasn't been changed - $array = array(); - while ($i < $max_i && - $j < $max_j && - strcmp($diff[$i], $diff[$j]) == 0) { - $array[] = substr($diff[$i], 2); - $i++; - $j++; - } - - while ($i < $max_i && ($max_j-$j) <= 1) { - if ($diff[$i] != '' && substr($diff[$i], 0, 1) != ' ') { - break; - } - $array[] = substr($diff[$i++], 2); - } - - while ($j < $max_j && ($max_i-$i) <= 1) { - if ($diff[$j] != '' && substr($diff[$j], 0, 1) != ' ') { - break; - } - $array[] = substr($diff[$j++], 2); - } - if (count($array) > 0) { - $edits[] = new Horde_Text_Diff_Op_Copy($array); - } - - if ($i < $max_i) { - $diff1 = array(); - switch (substr($diff[$i], 0, 1)) { - case '!': - $diff2 = array(); - do { - $diff1[] = substr($diff[$i], 2); - if ($j < $max_j && substr($diff[$j], 0, 1) == '!') { - $diff2[] = substr($diff[$j++], 2); - } - } while (++$i < $max_i && substr($diff[$i], 0, 1) == '!'); - $edits[] = new Horde_Text_Diff_Op_Change($diff1, $diff2); - break; - - case '+': - do { - $diff1[] = substr($diff[$i], 2); - } while (++$i < $max_i && substr($diff[$i], 0, 1) == '+'); - $edits[] = new Horde_Text_Diff_Op_Add($diff1); - break; - - case '-': - do { - $diff1[] = substr($diff[$i], 2); - } while (++$i < $max_i && substr($diff[$i], 0, 1) == '-'); - $edits[] = new Horde_Text_Diff_Op_Delete($diff1); - break; - } - } - - if ($j < $max_j) { - $diff2 = array(); - switch (substr($diff[$j], 0, 1)) { - case '+': - do { - $diff2[] = substr($diff[$j++], 2); - } while ($j < $max_j && substr($diff[$j], 0, 1) == '+'); - $edits[] = new Horde_Text_Diff_Op_Add($diff2); - break; - - case '-': - do { - $diff2[] = substr($diff[$j++], 2); - } while ($j < $max_j && substr($diff[$j], 0, 1) == '-'); - $edits[] = new Horde_Text_Diff_Op_Delete($diff2); - break; - } - } - } - - return $edits; - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Engine/Xdiff.php b/html/forums/inc/3rdparty/diff/Diff/Engine/Xdiff.php deleted file mode 100644 index 949e71d..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Engine/Xdiff.php +++ /dev/null @@ -1,74 +0,0 @@ - - * @package Text_Diff - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Engine_Xdiff -{ - /** - */ - public function diff($from_lines, $to_lines) - { - if (!extension_loaded('xdiff')) { - throw new Horde_Text_Diff_Exception('The xdiff extension is required for this diff engine'); - } - - array_walk($from_lines, array('Horde_Text_Diff', 'trimNewlines')); - array_walk($to_lines, array('Horde_Text_Diff', 'trimNewlines')); - - /* Convert the two input arrays into strings for xdiff processing. */ - $from_string = implode("\n", $from_lines); - $to_string = implode("\n", $to_lines); - - /* Diff the two strings and convert the result to an array. */ - $diff = xdiff_string_diff($from_string, $to_string, count($to_lines)); - $diff = explode("\n", $diff); - - /* Walk through the diff one line at a time. We build the $edits - * array of diff operations by reading the first character of the - * xdiff output (which is in the "unified diff" format). - * - * Note that we don't have enough information to detect "changed" - * lines using this approach, so we can't add Horde_Text_Diff_Op_Changed - * instances to the $edits array. The result is still perfectly - * valid, albeit a little less descriptive and efficient. */ - $edits = array(); - foreach ($diff as $line) { - if (!strlen($line)) { - continue; - } - switch ($line[0]) { - case ' ': - $edits[] = new Horde_Text_Diff_Op_Copy(array(substr($line, 1))); - break; - - case '+': - $edits[] = new Horde_Text_Diff_Op_Add(array(substr($line, 1))); - break; - - case '-': - $edits[] = new Horde_Text_Diff_Op_Delete(array(substr($line, 1))); - break; - } - } - - return $edits; - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Engine/index.html b/html/forums/inc/3rdparty/diff/Diff/Engine/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Engine/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/3rdparty/diff/Diff/Exception.php b/html/forums/inc/3rdparty/diff/Diff/Exception.php deleted file mode 100644 index 48ea410..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Exception.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @category Horde - * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 - * @package Text_Diff - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Exception extends Horde_Exception_Wrapped -{ -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Mapped.php b/html/forums/inc/3rdparty/diff/Diff/Mapped.php deleted file mode 100644 index 36a6cdc..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Mapped.php +++ /dev/null @@ -1,59 +0,0 @@ - - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Mapped extends Horde_Text_Diff -{ - /** - * Computes a diff between sequences of strings. - * - * This can be used to compute things like case-insensitve diffs, or diffs - * which ignore changes in white-space. - * - * @param array $from_lines An array of strings. - * @param array $to_lines An array of strings. - * @param array $mapped_from_lines This array should have the same size - * number of elements as $from_lines. The - * elements in $mapped_from_lines and - * $mapped_to_lines are what is actually - * compared when computing the diff. - * @param array $mapped_to_lines This array should have the same number - * of elements as $to_lines. - */ - public function __construct($from_lines, $to_lines, - $mapped_from_lines, $mapped_to_lines) - { - assert(count($from_lines) == count($mapped_from_lines)); - assert(count($to_lines) == count($mapped_to_lines)); - - parent::__construct($mapped_from_lines, $mapped_to_lines); - - $xi = $yi = 0; - for ($i = 0; $i < count($this->_edits); $i++) { - $orig = &$this->_edits[$i]->orig; - if (is_array($orig)) { - $orig = array_slice($from_lines, $xi, count($orig)); - $xi += count($orig); - } - - $final = &$this->_edits[$i]->final; - if (is_array($final)) { - $final = array_slice($to_lines, $yi, count($final)); - $yi += count($final); - } - } - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Op/Add.php b/html/forums/inc/3rdparty/diff/Diff/Op/Add.php deleted file mode 100644 index c8c26b5..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Op/Add.php +++ /dev/null @@ -1,34 +0,0 @@ -, and is used/adapted with his permission. - * - * Copyright 2004 Geoffrey T. Dairiki - * Copyright 2004-2011 Horde LLC (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you did - * not receive this file, see http://www.horde.org/licenses/lgpl21. - * - * @package Text_Diff - * @author Geoffrey T. Dairiki - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Op_Add extends Horde_Text_Diff_Op_Base -{ - public function __construct($lines) - { - $this->final = $lines; - $this->orig = false; - } - - public function reverse() - { - return new Horde_Text_Diff_Op_Delete($this->final); - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Op/Base.php b/html/forums/inc/3rdparty/diff/Diff/Op/Base.php deleted file mode 100644 index 3a63c4b..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Op/Base.php +++ /dev/null @@ -1,38 +0,0 @@ -, and is used/adapted with his permission. - * - * Copyright 2004 Geoffrey T. Dairiki - * Copyright 2004-2011 Horde LLC (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you did - * not receive this file, see http://www.horde.org/licenses/lgpl21. - * - * @package Text_Diff - * @author Geoffrey T. Dairiki - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -abstract class Horde_Text_Diff_Op_Base -{ - public $orig; - public $final; - - abstract public function reverse(); - - public function norig() - { - return $this->orig ? count($this->orig) : 0; - } - - public function nfinal() - { - return $this->final ? count($this->final) : 0; - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Op/Change.php b/html/forums/inc/3rdparty/diff/Diff/Op/Change.php deleted file mode 100644 index 6512989..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Op/Change.php +++ /dev/null @@ -1,34 +0,0 @@ -, and is used/adapted with his permission. - * - * Copyright 2004 Geoffrey T. Dairiki - * Copyright 2004-2011 Horde LLC (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you did - * not receive this file, see http://www.horde.org/licenses/lgpl21. - * - * @package Text_Diff - * @author Geoffrey T. Dairiki - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Op_Change extends Horde_Text_Diff_Op_Base -{ - public function __construct($orig, $final) - { - $this->orig = $orig; - $this->final = $final; - } - - public function reverse() - { - return new Horde_Text_Diff_Op_Change($this->final, $this->orig); - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Op/Copy.php b/html/forums/inc/3rdparty/diff/Diff/Op/Copy.php deleted file mode 100644 index a3e8f4a..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Op/Copy.php +++ /dev/null @@ -1,37 +0,0 @@ -, and is used/adapted with his permission. - * - * Copyright 2004 Geoffrey T. Dairiki - * Copyright 2004-2011 Horde LLC (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you did - * not receive this file, see http://www.horde.org/licenses/lgpl21. - * - * @package Text_Diff - * @author Geoffrey T. Dairiki - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Op_Copy extends Horde_Text_Diff_Op_Base -{ - public function __construct($orig, $final = false) - { - if (!is_array($final)) { - $final = $orig; - } - $this->orig = $orig; - $this->final = $final; - } - - public function reverse() - { - return new Horde_Text_Diff_Op_Copy($this->final, $this->orig); - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Op/Delete.php b/html/forums/inc/3rdparty/diff/Diff/Op/Delete.php deleted file mode 100644 index 3fbf3b9..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Op/Delete.php +++ /dev/null @@ -1,34 +0,0 @@ -, and is used/adapted with his permission. - * - * Copyright 2004 Geoffrey T. Dairiki - * Copyright 2004-2011 Horde LLC (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you did - * not receive this file, see http://www.horde.org/licenses/lgpl21. - * - * @package Text_Diff - * @author Geoffrey T. Dairiki - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Op_Delete extends Horde_Text_Diff_Op_Base -{ - public function __construct($lines) - { - $this->orig = $lines; - $this->final = false; - } - - public function reverse() - { - return new Horde_Text_Diff_Op_Add($this->orig); - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Op/index.html b/html/forums/inc/3rdparty/diff/Diff/Op/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Op/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/3rdparty/diff/Diff/Renderer.php b/html/forums/inc/3rdparty/diff/Diff/Renderer.php deleted file mode 100644 index 3afcf6c..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Renderer.php +++ /dev/null @@ -1,241 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Renderer -{ - /** - * Number of leading context "lines" to preserve. - * - * This should be left at zero for this class, but subclasses may want to - * set this to other values. - */ - protected $_leading_context_lines = 0; - - /** - * Number of trailing context "lines" to preserve. - * - * This should be left at zero for this class, but subclasses may want to - * set this to other values. - */ - protected $_trailing_context_lines = 0; - - /** - * Constructor. - */ - public function __construct($params = array()) - { - foreach ($params as $param => $value) { - $v = '_' . $param; - if (isset($this->$v)) { - $this->$v = $value; - } - } - } - - /** - * Get any renderer parameters. - * - * @return array All parameters of this renderer object. - */ - public function getParams() - { - $params = array(); - foreach (get_object_vars($this) as $k => $v) { - if ($k[0] == '_') { - $params[substr($k, 1)] = $v; - } - } - - return $params; - } - - /** - * Renders a diff. - * - * @param Horde_Text_Diff $diff A Horde_Text_Diff object. - * - * @return string The formatted output. - */ - public function render($diff) - { - $xi = $yi = 1; - $block = false; - $context = array(); - - $nlead = $this->_leading_context_lines; - $ntrail = $this->_trailing_context_lines; - - $output = $this->_startDiff(); - - $diffs = $diff->getDiff(); - foreach ($diffs as $i => $edit) { - /* If these are unchanged (copied) lines, and we want to keep - * leading or trailing context lines, extract them from the copy - * block. */ - if ($edit instanceof Horde_Text_Diff_Op_Copy) { - /* Do we have any diff blocks yet? */ - if (is_array($block)) { - /* How many lines to keep as context from the copy - * block. */ - $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail; - if (count($edit->orig) <= $keep) { - /* We have less lines in the block than we want for - * context => keep the whole block. */ - $block[] = $edit; - } else { - if ($ntrail) { - /* Create a new block with as many lines as we need - * for the trailing context. */ - $context = array_slice($edit->orig, 0, $ntrail); - $block[] = new Horde_Text_Diff_Op_Copy($context); - } - /* @todo */ - $output .= $this->_block($x0, $ntrail + $xi - $x0, - $y0, $ntrail + $yi - $y0, - $block); - $block = false; - } - } - /* Keep the copy block as the context for the next block. */ - $context = $edit->orig; - } else { - /* Don't we have any diff blocks yet? */ - if (!is_array($block)) { - /* Extract context lines from the preceding copy block. */ - $context = array_slice($context, count($context) - $nlead); - $x0 = $xi - count($context); - $y0 = $yi - count($context); - $block = array(); - if ($context) { - $block[] = new Horde_Text_Diff_Op_Copy($context); - } - } - $block[] = $edit; - } - - if ($edit->orig) { - $xi += count($edit->orig); - } - if ($edit->final) { - $yi += count($edit->final); - } - } - - if (is_array($block)) { - $output .= $this->_block($x0, $xi - $x0, - $y0, $yi - $y0, - $block); - } - - return $output . $this->_endDiff(); - } - - protected function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) - { - $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen)); - - foreach ($edits as $edit) { - switch (get_class($edit)) { - case 'Horde_Text_Diff_Op_Copy': - $output .= $this->_context($edit->orig); - break; - - case 'Horde_Text_Diff_Op_Add': - $output .= $this->_added($edit->final); - break; - - case 'Horde_Text_Diff_Op_Delete': - $output .= $this->_deleted($edit->orig); - break; - - case 'Horde_Text_Diff_Op_Change': - $output .= $this->_changed($edit->orig, $edit->final); - break; - } - } - - return $output . $this->_endBlock(); - } - - protected function _startDiff() - { - return ''; - } - - protected function _endDiff() - { - return ''; - } - - protected function _blockHeader($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen > 1) { - $xbeg .= ',' . ($xbeg + $xlen - 1); - } - if ($ylen > 1) { - $ybeg .= ',' . ($ybeg + $ylen - 1); - } - - // this matches the GNU Diff behaviour - if ($xlen && !$ylen) { - $ybeg--; - } elseif (!$xlen) { - $xbeg--; - } - - return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg; - } - - protected function _startBlock($header) - { - return $header . "\n"; - } - - protected function _endBlock() - { - return ''; - } - - protected function _lines($lines, $prefix = ' ') - { - return $prefix . implode("\n$prefix", $lines) . "\n"; - } - - protected function _context($lines) - { - return $this->_lines($lines, ' '); - } - - protected function _added($lines) - { - return $this->_lines($lines, '> '); - } - - protected function _deleted($lines) - { - return $this->_lines($lines, '< '); - } - - protected function _changed($orig, $final) - { - return $this->_deleted($orig) . "---\n" . $this->_added($final); - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Renderer/Context.php b/html/forums/inc/3rdparty/diff/Diff/Renderer/Context.php deleted file mode 100644 index 6fc37ad..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Renderer/Context.php +++ /dev/null @@ -1,75 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Renderer_Context extends Horde_Text_Diff_Renderer -{ - /** - * Number of leading context "lines" to preserve. - */ - protected $_leading_context_lines = 4; - - /** - * Number of trailing context "lines" to preserve. - */ - protected $_trailing_context_lines = 4; - - protected $_second_block = ''; - - protected function _blockHeader($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen != 1) { - $xbeg .= ',' . $xlen; - } - if ($ylen != 1) { - $ybeg .= ',' . $ylen; - } - $this->_second_block = "--- $ybeg ----\n"; - return "***************\n*** $xbeg ****"; - } - - protected function _endBlock() - { - return $this->_second_block; - } - - protected function _context($lines) - { - $this->_second_block .= $this->_lines($lines, ' '); - return $this->_lines($lines, ' '); - } - - protected function _added($lines) - { - $this->_second_block .= $this->_lines($lines, '+ '); - return ''; - } - - protected function _deleted($lines) - { - return $this->_lines($lines, '- '); - } - - protected function _changed($orig, $final) - { - $this->_second_block .= $this->_lines($final, '! '); - return $this->_lines($orig, '! '); - } - -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Renderer/Inline.php b/html/forums/inc/3rdparty/diff/Diff/Renderer/Inline.php deleted file mode 100644 index cf829c8..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Renderer/Inline.php +++ /dev/null @@ -1,200 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Renderer_Inline extends Horde_Text_Diff_Renderer -{ - /** - * Number of leading context "lines" to preserve. - * - * @var integer - */ - protected $_leading_context_lines = 10000; - - /** - * Number of trailing context "lines" to preserve. - * - * @var integer - */ - protected $_trailing_context_lines = 10000; - - /** - * Prefix for inserted text. - * - * @var string - */ - protected $_ins_prefix = ''; - - /** - * Suffix for inserted text. - * - * @var string - */ - protected $_ins_suffix = ''; - - /** - * Prefix for deleted text. - * - * @var string - */ - protected $_del_prefix = ''; - - /** - * Suffix for deleted text. - * - * @var string - */ - protected $_del_suffix = ''; - - /** - * Header for each change block. - * - * @var string - */ - protected $_block_header = ''; - - /** - * Whether to split down to character-level. - * - * @var boolean - */ - protected $_split_characters = false; - - /** - * What are we currently splitting on? Used to recurse to show word-level - * or character-level changes. - * - * @var string - */ - protected $_split_level = 'lines'; - - protected function _blockHeader($xbeg, $xlen, $ybeg, $ylen) - { - return $this->_block_header; - } - - protected function _startBlock($header) - { - return $header; - } - - protected function _lines($lines, $prefix = ' ', $encode = true) - { - if ($encode) { - array_walk($lines, array(&$this, '_encode')); - } - - if ($this->_split_level == 'lines') { - return implode("\n", $lines) . "\n"; - } else { - return implode('', $lines); - } - } - - protected function _added($lines) - { - array_walk($lines, array(&$this, '_encode')); - $lines[0] = $this->_ins_prefix . $lines[0]; - $lines[count($lines) - 1] .= $this->_ins_suffix; - return $this->_lines($lines, ' ', false); - } - - protected function _deleted($lines, $words = false) - { - array_walk($lines, array(&$this, '_encode')); - $lines[0] = $this->_del_prefix . $lines[0]; - $lines[count($lines) - 1] .= $this->_del_suffix; - return $this->_lines($lines, ' ', false); - } - - protected function _changed($orig, $final) - { - /* If we've already split on characters, just display. */ - if ($this->_split_level == 'characters') { - return $this->_deleted($orig) - . $this->_added($final); - } - - /* If we've already split on words, just display. */ - if ($this->_split_level == 'words') { - $prefix = ''; - while ($orig[0] !== false && $final[0] !== false && - substr($orig[0], 0, 1) == ' ' && - substr($final[0], 0, 1) == ' ') { - $prefix .= substr($orig[0], 0, 1); - $orig[0] = substr($orig[0], 1); - $final[0] = substr($final[0], 1); - } - return $prefix . $this->_deleted($orig) . $this->_added($final); - } - - $text1 = implode("\n", $orig); - $text2 = implode("\n", $final); - - /* Non-printing newline marker. */ - $nl = "\0"; - - if ($this->_split_characters) { - $diff = new Horde_Text_Diff('native', - array(preg_split('//', $text1), - preg_split('//', $text2))); - } else { - /* We want to split on word boundaries, but we need to preserve - * whitespace as well. Therefore we split on words, but include - * all blocks of whitespace in the wordlist. */ - $diff = new Horde_Text_Diff('native', - array($this->_splitOnWords($text1, $nl), - $this->_splitOnWords($text2, $nl))); - } - - /* Get the diff in inline format. */ - $renderer = new Horde_Text_Diff_Renderer_inline - (array_merge($this->getParams(), - array('split_level' => $this->_split_characters ? 'characters' : 'words'))); - - /* Run the diff and get the output. */ - return str_replace($nl, "\n", $renderer->render($diff)) . "\n"; - } - - protected function _splitOnWords($string, $newlineEscape = "\n") - { - // Ignore \0; otherwise the while loop will never finish. - $string = str_replace("\0", '', $string); - - $words = array(); - $length = strlen($string); - $pos = 0; - - while ($pos < $length) { - // Eat a word with any preceding whitespace. - $spaces = strspn(substr($string, $pos), " \n"); - $nextpos = strcspn(substr($string, $pos + $spaces), " \n"); - $words[] = str_replace("\n", $newlineEscape, substr($string, $pos, $spaces + $nextpos)); - $pos += $spaces + $nextpos; - } - - return $words; - } - - protected function _encode(&$string) - { - $string = htmlspecialchars($string); - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Renderer/Unified.php b/html/forums/inc/3rdparty/diff/Diff/Renderer/Unified.php deleted file mode 100644 index d19f2ce..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Renderer/Unified.php +++ /dev/null @@ -1,64 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_Renderer_Unified extends Horde_Text_Diff_Renderer -{ - /** - * Number of leading context "lines" to preserve. - */ - protected $_leading_context_lines = 4; - - /** - * Number of trailing context "lines" to preserve. - */ - protected $_trailing_context_lines = 4; - - protected function _blockHeader($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen != 1) { - $xbeg .= ',' . $xlen; - } - if ($ylen != 1) { - $ybeg .= ',' . $ylen; - } - return "@@ -$xbeg +$ybeg @@"; - } - - protected function _context($lines) - { - return $this->_lines($lines, ' '); - } - - protected function _added($lines) - { - return $this->_lines($lines, '+'); - } - - protected function _deleted($lines) - { - return $this->_lines($lines, '-'); - } - - protected function _changed($orig, $final) - { - return $this->_deleted($orig) . $this->_added($final); - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/Renderer/index.html b/html/forums/inc/3rdparty/diff/Diff/Renderer/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/Renderer/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/3rdparty/diff/Diff/String.php b/html/forums/inc/3rdparty/diff/Diff/String.php deleted file mode 100644 index a6101ca..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/String.php +++ /dev/null @@ -1,778 +0,0 @@ - - * @category Horde - * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 - * @package Util - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_String -{ - /** - * lower() cache. - * - * @var array - */ - static protected $_lowers = array(); - - /** - * upper() cache. - * - * @var array - */ - static protected $_uppers = array(); - - /** - * Converts a string from one charset to another. - * - * Uses the iconv or the mbstring extensions. - * The original string is returned if conversion failed or none - * of the extensions were available. - * - * @param mixed $input The data to be converted. If $input is an an - * array, the array's values get converted - * recursively. - * @param string $from The string's current charset. - * @param string $to The charset to convert the string to. - * @param boolean $force Force conversion? - * - * @return mixed The converted input data. - */ - static public function convertCharset($input, $from, $to, $force = false) - { - /* Don't bother converting numbers. */ - if (is_numeric($input)) { - return $input; - } - - /* If the from and to character sets are identical, return now. */ - if (!$force && $from == $to) { - return $input; - } - $from = self::lower($from); - $to = self::lower($to); - if (!$force && $from == $to) { - return $input; - } - - if (is_array($input)) { - $tmp = array(); - reset($input); - while (list($key, $val) = each($input)) { - $tmp[self::_convertCharset($key, $from, $to)] = self::convertCharset($val, $from, $to, $force); - } - return $tmp; - } - - if (is_object($input)) { - // PEAR_Error/Exception objects are almost guaranteed to contain - // recursion, which will cause a segfault in PHP. We should never - // reach this line, but add a check. - if (($input instanceof Exception) || - ($input instanceof PEAR_Error)) { - return ''; - } - - $input = Horde_Util::cloneObject($input); - $vars = get_object_vars($input); - while (list($key, $val) = each($vars)) { - $input->$key = self::convertCharset($val, $from, $to, $force); - } - return $input; - } - - if (!is_string($input)) { - return $input; - } - - return self::_convertCharset($input, $from, $to); - } - - /** - * Internal function used to do charset conversion. - * - * @param string $input See self::convertCharset(). - * @param string $from See self::convertCharset(). - * @param string $to See self::convertCharset(). - * - * @return string The converted string. - */ - static protected function _convertCharset($input, $from, $to) - { - /* Use utf8_[en|de]code() if possible and if the string isn't too - * large (less than 16 MB = 16 * 1024 * 1024 = 16777216 bytes) - these - * functions use more memory. */ - if (Horde_Util::extensionExists('xml') && - ((strlen($input) < 16777216) || - !Horde_Util::extensionExists('iconv') || - !Horde_Util::extensionExists('mbstring'))) { - if (($to == 'utf-8') && - in_array($from, array('iso-8859-1', 'us-ascii', 'utf-8'))) { - return utf8_encode($input); - } - - if (($from == 'utf-8') && - in_array($to, array('iso-8859-1', 'us-ascii', 'utf-8'))) { - return utf8_decode($input); - } - } - - /* Try UTF7-IMAP conversions. */ - if (($from == 'utf7-imap') || ($to == 'utf7-imap')) { - try { - if ($from == 'utf7-imap') { - return self::convertCharset(Horde_Imap_Client_Utf7imap::Utf7ImapToUtf8($input), 'UTF-8', $to); - } else { - if ($from == 'utf-8') { - $conv = $input; - } else { - $conv = self::convertCharset($input, $from, 'UTF-8'); - } - return Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($conv); - } - } catch (Horde_Imap_Client_Exception $e) { - return $input; - } - } - - /* Try iconv with transliteration. */ - if (Horde_Util::extensionExists('iconv')) { - unset($php_errormsg); - ini_set('track_errors', 1); - $out = @iconv($from, $to . '//TRANSLIT', $input); - $errmsg = isset($php_errormsg); - ini_restore('track_errors'); - if (!$errmsg) { - return $out; - } - } - - /* Try mbstring. */ - if (Horde_Util::extensionExists('mbstring')) { - $out = @mb_convert_encoding($input, $to, self::_mbstringCharset($from)); - if (!empty($out)) { - return $out; - } - } - - return $input; - } - - /** - * Makes a string lowercase. - * - * @param string $string The string to be converted. - * @param boolean $locale If true the string will be converted based on - * a given charset, locale independent else. - * @param string $charset If $locale is true, the charset to use when - * converting. - * - * @return string The string with lowercase characters. - */ - static public function lower($string, $locale = false, $charset = null) - { - if ($locale) { - if (Horde_Util::extensionExists('mbstring')) { - if (is_null($charset)) { - throw new InvalidArgumentException('$charset argument must not be null'); - } - $ret = @mb_strtolower($string, self::_mbstringCharset($charset)); - if (!empty($ret)) { - return $ret; - } - } - return strtolower($string); - } - - if (!isset(self::$_lowers[$string])) { - $language = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'C'); - self::$_lowers[$string] = strtolower($string); - setlocale(LC_CTYPE, $language); - } - - return self::$_lowers[$string]; - } - - /** - * Makes a string uppercase. - * - * @param string $string The string to be converted. - * @param boolean $locale If true the string will be converted based on a - * given charset, locale independent else. - * @param string $charset If $locale is true, the charset to use when - * converting. If not provided the current charset. - * - * @return string The string with uppercase characters. - */ - static public function upper($string, $locale = false, $charset = null) - { - if ($locale) { - if (Horde_Util::extensionExists('mbstring')) { - if (is_null($charset)) { - throw new InvalidArgumentException('$charset argument must not be null'); - } - $ret = @mb_strtoupper($string, self::_mbstringCharset($charset)); - if (!empty($ret)) { - return $ret; - } - } - return strtoupper($string); - } - - if (!isset(self::$_uppers[$string])) { - $language = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'C'); - self::$_uppers[$string] = strtoupper($string); - setlocale(LC_CTYPE, $language); - } - - return self::$_uppers[$string]; - } - - /** - * Returns a string with the first letter capitalized if it is - * alphabetic. - * - * @param string $string The string to be capitalized. - * @param boolean $locale If true the string will be converted based on a - * given charset, locale independent else. - * @param string $charset The charset to use, defaults to current charset. - * - * @return string The capitalized string. - */ - static public function ucfirst($string, $locale = false, $charset = null) - { - if ($locale) { - if (is_null($charset)) { - throw new InvalidArgumentException('$charset argument must not be null'); - } - $first = self::substr($string, 0, 1, $charset); - if (self::isAlpha($first, $charset)) { - $string = self::upper($first, true, $charset) . self::substr($string, 1, null, $charset); - } - } else { - $string = self::upper(substr($string, 0, 1), false) . substr($string, 1); - } - - return $string; - } - - /** - * Returns a string with the first letter of each word capitalized if it is - * alphabetic. - * - * Sentences are splitted into words at whitestrings. - * - * @param string $string The string to be capitalized. - * @param boolean $locale If true the string will be converted based on a - * given charset, locale independent else. - * @param string $charset The charset to use, defaults to current charset. - * - * @return string The capitalized string. - */ - static public function ucwords($string, $locale = false, $charset = null) - { - $words = preg_split('/(\s+)/', $string, -1, PREG_SPLIT_DELIM_CAPTURE); - for ($i = 0, $c = count($words); $i < $c; $i += 2) { - $words[$i] = self::ucfirst($words[$i], $locale, $charset); - } - return implode('', $words); - } - - /** - * Returns part of a string. - * - * @param string $string The string to be converted. - * @param integer $start The part's start position, zero based. - * @param integer $length The part's length. - * @param string $charset The charset to use when calculating the part's - * position and length, defaults to current - * charset. - * - * @return string The string's part. - */ - static public function substr($string, $start, $length = null, - $charset = 'UTF-8') - { - if (is_null($length)) { - $length = self::length($string, $charset) - $start; - } - - if ($length == 0) { - return ''; - } - - /* Try mbstring. */ - if (Horde_Util::extensionExists('mbstring')) { - $ret = @mb_substr($string, $start, $length, self::_mbstringCharset($charset)); - - /* mb_substr() returns empty string on failure. */ - if (strlen($ret)) { - return $ret; - } - } - - /* Try iconv. */ - if (Horde_Util::extensionExists('iconv')) { - $ret = @iconv_substr($string, $start, $length, $charset); - - /* iconv_substr() returns false on failure. */ - if ($ret !== false) { - return $ret; - } - } - - return substr($string, $start, $length); - } - - /** - * Returns the character (not byte) length of a string. - * - * @param string $string The string to return the length of. - * @param string $charset The charset to use when calculating the string's - * length. - * - * @return integer The string's length. - */ - static public function length($string, $charset = 'UTF-8') - { - $charset = self::lower($charset); - - if ($charset == 'utf-8' || $charset == 'utf8') { - return strlen(utf8_decode($string)); - } - - if (Horde_Util::extensionExists('mbstring')) { - $ret = @mb_strlen($string, self::_mbstringCharset($charset)); - if (!empty($ret)) { - return $ret; - } - } - - return strlen($string); - } - - /** - * Returns the numeric position of the first occurrence of $needle - * in the $haystack string. - * - * @param string $haystack The string to search through. - * @param string $needle The string to search for. - * @param integer $offset Allows to specify which character in haystack - * to start searching. - * @param string $charset The charset to use when searching for the - * $needle string. - * - * @return integer The position of first occurrence. - */ - static public function pos($haystack, $needle, $offset = 0, - $charset = 'UTF-8') - { - if (Horde_Util::extensionExists('mbstring')) { - $track_errors = ini_set('track_errors', 1); - $ret = @mb_strpos($haystack, $needle, $offset, self::_mbstringCharset($charset)); - ini_set('track_errors', $track_errors); - if (!isset($php_errormsg)) { - return $ret; - } - } - - return strpos($haystack, $needle, $offset); - } - - /** - * Returns the numeric position of the last occurrence of $needle - * in the $haystack string. - * - * @param string $haystack The string to search through. - * @param string $needle The string to search for. - * @param integer $offset Allows to specify which character in haystack - * to start searching. - * @param string $charset The charset to use when searching for the - * $needle string. - * - * @return integer The position of first occurrence. - */ - static public function rpos($haystack, $needle, $offset = 0, - $charset = 'UTF-8') - { - if (Horde_Util::extensionExists('mbstring')) { - $track_errors = ini_set('track_errors', 1); - $ret = @mb_strrpos($haystack, $needle, $offset, self::_mbstringCharset($charset)); - ini_set('track_errors', $track_errors); - if (!isset($php_errormsg)) { - return $ret; - } - } - - return strrpos($haystack, $needle, $offset); - } - - /** - * Returns a string padded to a certain length with another string. - * This method behaves exactly like str_pad() but is multibyte safe. - * - * @param string $input The string to be padded. - * @param integer $length The length of the resulting string. - * @param string $pad The string to pad the input string with. Must - * be in the same charset like the input string. - * @param const $type The padding type. One of STR_PAD_LEFT, - * STR_PAD_RIGHT, or STR_PAD_BOTH. - * @param string $charset The charset of the input and the padding - * strings. - * - * @return string The padded string. - */ - static public function pad($input, $length, $pad = ' ', - $type = STR_PAD_RIGHT, $charset = 'UTF-8') - { - $mb_length = self::length($input, $charset); - $sb_length = strlen($input); - $pad_length = self::length($pad, $charset); - - /* Return if we already have the length. */ - if ($mb_length >= $length) { - return $input; - } - - /* Shortcut for single byte strings. */ - if ($mb_length == $sb_length && $pad_length == strlen($pad)) { - return str_pad($input, $length, $pad, $type); - } - - switch ($type) { - case STR_PAD_LEFT: - $left = $length - $mb_length; - $output = self::substr(str_repeat($pad, ceil($left / $pad_length)), 0, $left, $charset) . $input; - break; - - case STR_PAD_BOTH: - $left = floor(($length - $mb_length) / 2); - $right = ceil(($length - $mb_length) / 2); - $output = self::substr(str_repeat($pad, ceil($left / $pad_length)), 0, $left, $charset) . - $input . - self::substr(str_repeat($pad, ceil($right / $pad_length)), 0, $right, $charset); - break; - - case STR_PAD_RIGHT: - $right = $length - $mb_length; - $output = $input . self::substr(str_repeat($pad, ceil($right / $pad_length)), 0, $right, $charset); - break; - } - - return $output; - } - - /** - * Wraps the text of a message. - * - * @param string $string String containing the text to wrap. - * @param integer $width Wrap the string at this number of - * characters. - * @param string $break Character(s) to use when breaking lines. - * @param boolean $cut Whether to cut inside words if a line - * can't be wrapped. - * @param boolean $line_folding Whether to apply line folding rules per - * RFC 822 or similar. The correct break - * characters including leading whitespace - * have to be specified too. - * - * @return string String containing the wrapped text. - */ - static public function wordwrap($string, $width = 75, $break = "\n", - $cut = false, $line_folding = false) - { - $wrapped = ''; - - while (self::length($string, 'UTF-8') > $width) { - $line = self::substr($string, 0, $width, 'UTF-8'); - $string = self::substr($string, self::length($line, 'UTF-8'), null, 'UTF-8'); - - // Make sure we didn't cut a word, unless we want hard breaks - // anyway. - if (!$cut && preg_match('/^(.+?)((\s|\r?\n).*)/us', $string, $match)) { - $line .= $match[1]; - $string = $match[2]; - } - - // Wrap at existing line breaks. - if (preg_match('/^(.*?)(\r?\n)(.*)$/su', $line, $match)) { - $wrapped .= $match[1] . $match[2]; - $string = $match[3] . $string; - continue; - } - - // Wrap at the last colon or semicolon followed by a whitespace if - // doing line folding. - if ($line_folding && - preg_match('/^(.*?)(;|:)(\s+.*)$/u', $line, $match)) { - $wrapped .= $match[1] . $match[2] . $break; - $string = $match[3] . $string; - continue; - } - - // Wrap at the last whitespace of $line. - $sub = $line_folding - ? '(.+[^\s])' - : '(.*)'; - - if (preg_match('/^' . $sub . '(\s+)(.*)$/u', $line, $match)) { - $wrapped .= $match[1] . $break; - $string = ($line_folding ? $match[2] : '') . $match[3] . $string; - continue; - } - - // Hard wrap if necessary. - if ($cut) { - $wrapped .= $line . $break; - continue; - } - - $wrapped .= $line; - } - - return $wrapped . $string; - } - - /** - * Wraps the text of a message. - * - * @param string $text String containing the text to wrap. - * @param integer $length Wrap $text at this number of characters. - * @param string $break_char Character(s) to use when breaking lines. - * @param boolean $quote Ignore lines that are wrapped with the '>' - * character (RFC 2646)? If true, we don't - * remove any padding whitespace at the end of - * the string. - * - * @return string String containing the wrapped text. - */ - static public function wrap($text, $length = 80, $break_char = "\n", - $quote = false) - { - $paragraphs = array(); - - foreach (preg_split('/\r?\n/', $text) as $input) { - if ($quote && (strpos($input, '>') === 0)) { - $line = $input; - } else { - /* We need to handle the Usenet-style signature line - * separately; since the space after the two dashes is - * REQUIRED, we don't want to trim the line. */ - if ($input != '-- ') { - $input = rtrim($input); - } - $line = self::wordwrap($input, $length, $break_char); - } - - $paragraphs[] = $line; - } - - return implode($break_char, $paragraphs); - } - - /** - * Return a truncated string, suitable for notifications. - * - * @param string $text The original string. - * @param integer $length The maximum length. - * - * @return string The truncated string, if longer than $length. - */ - static public function truncate($text, $length = 100) - { - return (self::length($text) > $length) - ? rtrim(self::substr($text, 0, $length - 3)) . '...' - : $text; - } - - /** - * Return an abbreviated string, with characters in the middle of the - * excessively long string replaced by '...'. - * - * @param string $text The original string. - * @param integer $length The length at which to abbreviate. - * - * @return string The abbreviated string, if longer than $length. - */ - static public function abbreviate($text, $length = 20) - { - return (self::length($text) > $length) - ? rtrim(self::substr($text, 0, round(($length - 3) / 2))) . '...' . ltrim(self::substr($text, (($length - 3) / 2) * -1)) - : $text; - } - - /** - * Returns the common leading part of two strings. - * - * @param string $str1 A string. - * @param string $str2 Another string. - * - * @return string The start of $str1 and $str2 that is identical in both. - */ - static public function common($str1, $str2) - { - for ($result = '', $i = 0; - isset($str1[$i]) && isset($str2[$i]) && $str1[$i] == $str2[$i]; - $i++) { - $result .= $str1[$i]; - } - return $result; - } - - /** - * Returns true if the every character in the parameter is an alphabetic - * character. - * - * @param string $string The string to test. - * @param string $charset The charset to use when testing the string. - * - * @return boolean True if the parameter was alphabetic only. - */ - static public function isAlpha($string, $charset) - { - if (!Horde_Util::extensionExists('mbstring')) { - return ctype_alpha($string); - } - - $charset = self::_mbstringCharset($charset); - $old_charset = mb_regex_encoding(); - - if ($charset != $old_charset) { - @mb_regex_encoding($charset); - } - $alpha = !@mb_ereg_match('[^[:alpha:]]', $string); - if ($charset != $old_charset) { - @mb_regex_encoding($old_charset); - } - - return $alpha; - } - - /** - * Returns true if ever character in the parameter is a lowercase letter in - * the current locale. - * - * @param string $string The string to test. - * @param string $charset The charset to use when testing the string. - * - * @return boolean True if the parameter was lowercase. - */ - static public function isLower($string, $charset) - { - return ((self::lower($string, true, $charset) === $string) && - self::isAlpha($string, $charset)); - } - - /** - * Returns true if every character in the parameter is an uppercase letter - * in the current locale. - * - * @param string $string The string to test. - * @param string $charset The charset to use when testing the string. - * - * @return boolean True if the parameter was uppercase. - */ - static public function isUpper($string, $charset) - { - return ((self::upper($string, true, $charset) === $string) && - self::isAlpha($string, $charset)); - } - - /** - * Performs a multibyte safe regex match search on the text provided. - * - * @param string $text The text to search. - * @param array $regex The regular expressions to use, without perl - * regex delimiters (e.g. '/' or '|'). - * @param string $charset The character set of the text. - * - * @return array The matches array from the first regex that matches. - */ - static public function regexMatch($text, $regex, $charset = null) - { - if (!empty($charset)) { - $regex = self::convertCharset($regex, $charset, 'utf-8'); - $text = self::convertCharset($text, $charset, 'utf-8'); - } - - $matches = array(); - foreach ($regex as $val) { - if (preg_match('/' . $val . '/u', $text, $matches)) { - break; - } - } - - if (!empty($charset)) { - $matches = self::convertCharset($matches, 'utf-8', $charset); - } - - return $matches; - } - - /** - * Check to see if a string is valid UTF-8. - * - * @since 1.1.0 - * - * @param string $text The text to check. - * - * @return boolean True if valid UTF-8. - */ - static public function validUtf8($text) - { - /* Regex from: - * http://stackoverflow.com/questions/1523460/ensuring-valid-utf-8-in-php - */ - return preg_match('/^(?: - [\x09\x0A\x0D\x20-\x7E] # ASCII - | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte - | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs - | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte - | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates - | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 - )*$/xs', $text); - } - - /** - * Workaround charsets that don't work with mbstring functions. - * - * @param string $charset The original charset. - * - * @return string The charset to use with mbstring functions. - */ - static protected function _mbstringCharset($charset) - { - /* mbstring functions do not handle the 'ks_c_5601-1987' & - * 'ks_c_5601-1989' charsets. However, these charsets are used, for - * example, by various versions of Outlook to send Korean characters. - * Use UHC (CP949) encoding instead. See, e.g., - * http://lists.w3.org/Archives/Public/ietf-charsets/2001AprJun/0030.html */ - if ($charset == 'UTF-8' || $charset == 'utf-8') { - return $charset; - } - if (in_array(self::lower($charset), array('ks_c_5601-1987', 'ks_c_5601-1989'))) { - $charset = 'UHC'; - } - - return $charset; - } - -} diff --git a/html/forums/inc/3rdparty/diff/Diff/ThreeWay.php b/html/forums/inc/3rdparty/diff/Diff/ThreeWay.php deleted file mode 100644 index 83560ff..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/ThreeWay.php +++ /dev/null @@ -1,150 +0,0 @@ - - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_ThreeWay -{ - /** - * Array of changes. - * - * @var array - */ - protected $_edits; - - /** - * Conflict counter. - * - * @var integer - */ - protected $_conflictingBlocks = 0; - - /** - * Computes diff between 3 sequences of strings. - * - * @param array $orig The original lines to use. - * @param array $final1 The first version to compare to. - * @param array $final2 The second version to compare to. - */ - public function __construct($orig, $final1, $final2) - { - if (extension_loaded('xdiff')) { - $engine = new Horde_Text_Diff_Engine_Xdiff(); - } else { - $engine = new Horde_Text_Diff_Engine_Native(); - } - - $this->_edits = $this->_diff3($engine->diff($orig, $final1), - $engine->diff($orig, $final2)); - } - - /** - */ - public function mergedOutput($label1 = false, $label2 = false) - { - $lines = array(); - foreach ($this->_edits as $edit) { - if ($edit->isConflict()) { - /* FIXME: this should probably be moved somewhere else. */ - $lines = array_merge($lines, - array('<<<<<<<' . ($label1 ? ' ' . $label1 : '')), - $edit->final1, - array("======="), - $edit->final2, - array('>>>>>>>' . ($label2 ? ' ' . $label2 : ''))); - $this->_conflictingBlocks++; - } else { - $lines = array_merge($lines, $edit->merged()); - } - } - - return $lines; - } - - /** - */ - protected function _diff3($edits1, $edits2) - { - $edits = array(); - $bb = new Horde_Text_Diff_ThreeWay_BlockBuilder(); - - $e1 = current($edits1); - $e2 = current($edits2); - while ($e1 || $e2) { - if ($e1 && $e2 && - $e1 instanceof Horde_Text_Diff_Op_Copy && - $e2 instanceof Horde_Text_Diff_Op_Copy) { - /* We have copy blocks from both diffs. This is the (only) - * time we want to emit a diff3 copy block. Flush current - * diff3 diff block, if any. */ - if ($edit = $bb->finish()) { - $edits[] = $edit; - } - - $ncopy = min($e1->norig(), $e2->norig()); - assert($ncopy > 0); - $edits[] = new Horde_Text_Diff_ThreeWay_Op_Copy(array_slice($e1->orig, 0, $ncopy)); - - if ($e1->norig() > $ncopy) { - array_splice($e1->orig, 0, $ncopy); - array_splice($e1->final, 0, $ncopy); - } else { - $e1 = next($edits1); - } - - if ($e2->norig() > $ncopy) { - array_splice($e2->orig, 0, $ncopy); - array_splice($e2->final, 0, $ncopy); - } else { - $e2 = next($edits2); - } - } else { - if ($e1 && $e2) { - if ($e1->orig && $e2->orig) { - $norig = min($e1->norig(), $e2->norig()); - $orig = array_splice($e1->orig, 0, $norig); - array_splice($e2->orig, 0, $norig); - $bb->input($orig); - } - - if ($e1 instanceof Horde_Text_Diff_Op_Copy) { - $bb->out1(array_splice($e1->final, 0, $norig)); - } - - if ($e2 instanceof Horde_Text_Diff_Op_Copy) { - $bb->out2(array_splice($e2->final, 0, $norig)); - } - } - - if ($e1 && ! $e1->orig) { - $bb->out1($e1->final); - $e1 = next($edits1); - } - if ($e2 && ! $e2->orig) { - $bb->out2($e2->final); - $e2 = next($edits2); - } - } - } - - if ($edit = $bb->finish()) { - $edits[] = $edit; - } - - return $edits; - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/ThreeWay/BlockBuilder.php b/html/forums/inc/3rdparty/diff/Diff/ThreeWay/BlockBuilder.php deleted file mode 100644 index 639c59e..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/ThreeWay/BlockBuilder.php +++ /dev/null @@ -1,71 +0,0 @@ - - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_ThreeWay_BlockBuilder -{ - public function __construct() - { - $this->_init(); - } - - public function input($lines) - { - if ($lines) { - $this->_append($this->orig, $lines); - } - } - - public function out1($lines) - { - if ($lines) { - $this->_append($this->final1, $lines); - } - } - - public function out2($lines) - { - if ($lines) { - $this->_append($this->final2, $lines); - } - } - - public function isEmpty() - { - return !$this->orig && !$this->final1 && !$this->final2; - } - - public function finish() - { - if ($this->isEmpty()) { - return false; - } else { - $edit = new Horde_Text_Diff_ThreeWay_Op_Base($this->orig, $this->final1, $this->final2); - $this->_init(); - return $edit; - } - } - - protected function _init() - { - $this->orig = $this->final1 = $this->final2 = array(); - } - - protected function _append(&$array, $lines) - { - array_splice($array, sizeof($array), 0, $lines); - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/ThreeWay/Op/Base.php b/html/forums/inc/3rdparty/diff/Diff/ThreeWay/Op/Base.php deleted file mode 100644 index c10466c..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/ThreeWay/Op/Base.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_ThreeWay_Op_Base -{ - public function __construct($orig = false, $final1 = false, $final2 = false) - { - $this->orig = $orig ? $orig : array(); - $this->final1 = $final1 ? $final1 : array(); - $this->final2 = $final2 ? $final2 : array(); - } - - public function merged() - { - if (!isset($this->_merged)) { - if ($this->final1 === $this->final2) { - $this->_merged = &$this->final1; - } elseif ($this->final1 === $this->orig) { - $this->_merged = &$this->final2; - } elseif ($this->final2 === $this->orig) { - $this->_merged = &$this->final1; - } else { - $this->_merged = false; - } - } - - return $this->_merged; - } - - public function isConflict() - { - return $this->merged() === false; - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/ThreeWay/Op/Copy.php b/html/forums/inc/3rdparty/diff/Diff/ThreeWay/Op/Copy.php deleted file mode 100644 index 15f7a83..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/ThreeWay/Op/Copy.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ - -// Disallow direct access to this file for security reasons -if(!defined("IN_MYBB")) -{ - die("Direct initialization of this file is not allowed.

    Please make sure IN_MYBB is defined."); -} - -class Horde_Text_Diff_ThreeWay_Op_Copy extends Horde_Text_Diff_ThreeWay_Op_Base -{ - public function __construct($lines = false) - { - $this->orig = $lines ? $lines : array(); - $this->final1 = &$this->orig; - $this->final2 = &$this->orig; - } - - public function merged() - { - return $this->orig; - } - - public function isConflict() - { - return false; - } -} diff --git a/html/forums/inc/3rdparty/diff/Diff/ThreeWay/Op/index.html b/html/forums/inc/3rdparty/diff/Diff/ThreeWay/Op/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/ThreeWay/Op/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/3rdparty/diff/Diff/ThreeWay/index.html b/html/forums/inc/3rdparty/diff/Diff/ThreeWay/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/ThreeWay/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/3rdparty/diff/Diff/index.html b/html/forums/inc/3rdparty/diff/Diff/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/3rdparty/diff/Diff/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/3rdparty/diff/index.html b/html/forums/inc/3rdparty/diff/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/3rdparty/diff/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/3rdparty/index.html b/html/forums/inc/3rdparty/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/3rdparty/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/3rdparty/json/index.html b/html/forums/inc/3rdparty/json/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/3rdparty/json/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/3rdparty/json/json.php b/html/forums/inc/3rdparty/json/json.php deleted file mode 100644 index 4540e95..0000000 --- a/html/forums/inc/3rdparty/json/json.php +++ /dev/null @@ -1,822 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/** - * Converts to and from JSON format. - * - * JSON (JavaScript Object Notation) is a lightweight data-interchange - * format. It is easy for humans to read and write. It is easy for machines - * to parse and generate. It is based on a subset of the JavaScript - * Programming Language, Standard ECMA-262 3rd Edition - December 1999. - * This feature can also be found in Python. JSON is a text format that is - * completely language independent but uses conventions that are familiar - * to programmers of the C-family of languages, including C, C++, C#, Java, - * JavaScript, Perl, TCL, and many others. These properties make JSON an - * ideal data-interchange language. - * - * This package provides a simple encoder and decoder for JSON notation. It - * is intended for use with client-side Javascript applications that make - * use of HTTPRequest to perform server communication functions - data can - * be encoded into JSON notation for use in a client-side javascript, or - * decoded from incoming Javascript requests. JSON format is native to - * Javascript, and can be directly eval()'ed with no further parsing - * overhead - * - * All strings should be in ASCII or UTF-8 format! - * - * LICENSE: Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: Redistributions of source code must retain the - * above copyright notice, this list of conditions and the following - * disclaimer. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * @category - * @package Services_JSON - * @author Michal Migurski - * @author Matt Knapp - * @author Brett Stimmerman - * @copyright 2005 Michal Migurski - * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ - * @license http://www.opensource.org/licenses/bsd-license.php - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 - */ - -/** - * Marker constant for Services_JSON::decode(), used to flag stack state - */ -define('SERVICES_JSON_SLICE', 1); - -/** - * Marker constant for Services_JSON::decode(), used to flag stack state - */ -define('SERVICES_JSON_IN_STR', 2); - -/** - * Marker constant for Services_JSON::decode(), used to flag stack state - */ -define('SERVICES_JSON_IN_ARR', 3); - -/** - * Marker constant for Services_JSON::decode(), used to flag stack state - */ -define('SERVICES_JSON_IN_OBJ', 4); - -/** - * Marker constant for Services_JSON::decode(), used to flag stack state - */ -define('SERVICES_JSON_IN_CMT', 5); - -/** - * Behavior switch for Services_JSON::decode() - */ -define('SERVICES_JSON_LOOSE_TYPE', 16); - -/** - * Behavior switch for Services_JSON::decode() - */ -define('SERVICES_JSON_SUPPRESS_ERRORS', 32); - -/** - * Converts to and from JSON format. - * - * Brief example of use: - * - * - * // create a new instance of Services_JSON - * $json = new Services_JSON(); - * - * // convert a complexe value to JSON notation, and send it to the browser - * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); - * $output = $json->encode($value); - * - * print($output); - * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]] - * - * // accept incoming POST data, assumed to be in JSON notation - * $input = file_get_contents('php://input', 1000000); - * $value = $json->decode($input); - * - */ -class Services_JSON -{ - /** - * constructs a new JSON instance - * - * @param int $use object behavior flags; combine with boolean-OR - * - * possible values: - * - SERVICES_JSON_LOOSE_TYPE: loose typing. - * "{...}" syntax creates associative arrays - * instead of objects in decode(). - * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. - * Values which can't be encoded (e.g. resources) - * appear as NULL instead of throwing errors. - * By default, a deeply-nested resource will - * bubble up with an error, so all return values - * from encode() should be checked with isError() - */ - function Services_JSON($use = 0) - { - $this->use = $use; - } - - /** - * convert a string from one UTF-16 char to one UTF-8 char - * - * Normally should be handled by mb_convert_encoding, but - * provides a slower PHP-only method for installations - * that lack the multibye string extension. - * - * @param string $utf16 UTF-16 character - * @return string UTF-8 character - * @access private - */ - function utf162utf8($utf16) - { - // oh please oh please oh please oh please oh please - if(function_exists('mb_convert_encoding')) { - return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); - } - - $bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); - - switch(true) { - case ((0x7F & $bytes) == $bytes): - // this case should never be reached, because we are in ASCII range - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return chr(0x7F & $bytes); - - case (0x07FF & $bytes) == $bytes: - // return a 2-byte UTF-8 character - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return chr(0xC0 | (($bytes >> 6) & 0x1F)) - . chr(0x80 | ($bytes & 0x3F)); - - case (0xFFFF & $bytes) == $bytes: - // return a 3-byte UTF-8 character - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return chr(0xE0 | (($bytes >> 12) & 0x0F)) - . chr(0x80 | (($bytes >> 6) & 0x3F)) - . chr(0x80 | ($bytes & 0x3F)); - } - - // ignoring UTF-32 for now, sorry - return ''; - } - - /** - * convert a string from one UTF-8 char to one UTF-16 char - * - * Normally should be handled by mb_convert_encoding, but - * provides a slower PHP-only method for installations - * that lack the multibye string extension. - * - * @param string $utf8 UTF-8 character - * @return string UTF-16 character - * @access private - */ - function utf82utf16($utf8) - { - // oh please oh please oh please oh please oh please - if(function_exists('mb_convert_encoding')) { - return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); - } - - switch(strlen($utf8)) { - case 1: - // this case should never be reached, because we are in ASCII range - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return $utf8; - - case 2: - // return a UTF-16 character from a 2-byte UTF-8 char - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return chr(0x07 & (ord($utf8{0}) >> 2)) - . chr((0xC0 & (ord($utf8{0}) << 6)) - | (0x3F & ord($utf8{1}))); - - case 3: - // return a UTF-16 character from a 3-byte UTF-8 char - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return chr((0xF0 & (ord($utf8{0}) << 4)) - | (0x0F & (ord($utf8{1}) >> 2))) - . chr((0xC0 & (ord($utf8{1}) << 6)) - | (0x7F & ord($utf8{2}))); - } - - // ignoring UTF-32 for now, sorry - return ''; - } - - /** - * encodes an arbitrary variable into JSON format - * - * @param mixed $var any number, boolean, string, array, or object to be encoded. - * see argument 1 to Services_JSON() above for array-parsing behavior. - * if var is a strng, note that encode() always expects it - * to be in ASCII or UTF-8 format! - * - * @return mixed JSON string representation of input var or an error if a problem occurs - * @access public - */ - function encode($var) - { - switch (gettype($var)) { - case 'boolean': - return $var ? 'true' : 'false'; - - case 'NULL': - return 'null'; - - case 'integer': - return (int) $var; - - case 'double': - case 'float': - return (float) $var; - - case 'string': - // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT - $ascii = ''; - $strlen_var = strlen($var); - - /* - * Iterate over every character in the string, - * escaping with a slash or encoding to UTF-8 where necessary - */ - for ($c = 0; $c < $strlen_var; ++$c) { - - $ord_var_c = ord($var{$c}); - - switch (true) { - case $ord_var_c == 0x08: - $ascii .= '\b'; - break; - case $ord_var_c == 0x09: - $ascii .= '\t'; - break; - case $ord_var_c == 0x0A: - $ascii .= '\n'; - break; - case $ord_var_c == 0x0C: - $ascii .= '\f'; - break; - case $ord_var_c == 0x0D: - $ascii .= '\r'; - break; - - case $ord_var_c == 0x22: - case $ord_var_c == 0x2F: - case $ord_var_c == 0x5C: - // double quote, slash, slosh - $ascii .= '\\'.$var{$c}; - break; - - case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): - // characters U-00000000 - U-0000007F (same as ASCII) - $ascii .= $var{$c}; - break; - - case (($ord_var_c & 0xE0) == 0xC0): - // characters U-00000080 - U-000007FF, mask 110XXXXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, ord($var{$c + 1})); - $c += 1; - $utf16 = $this->utf82utf16($char); - $ascii .= sprintf('\u%04s', bin2hex($utf16)); - break; - - case (($ord_var_c & 0xF0) == 0xE0): - // characters U-00000800 - U-0000FFFF, mask 1110XXXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, - ord($var{$c + 1}), - ord($var{$c + 2})); - $c += 2; - $utf16 = $this->utf82utf16($char); - $ascii .= sprintf('\u%04s', bin2hex($utf16)); - break; - - case (($ord_var_c & 0xF8) == 0xF0): - // characters U-00010000 - U-001FFFFF, mask 11110XXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, - ord($var{$c + 1}), - ord($var{$c + 2}), - ord($var{$c + 3})); - $c += 3; - $utf16 = $this->utf82utf16($char); - $ascii .= sprintf('\u%04s', bin2hex($utf16)); - break; - - case (($ord_var_c & 0xFC) == 0xF8): - // characters U-00200000 - U-03FFFFFF, mask 111110XX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, - ord($var{$c + 1}), - ord($var{$c + 2}), - ord($var{$c + 3}), - ord($var{$c + 4})); - $c += 4; - $utf16 = $this->utf82utf16($char); - $ascii .= sprintf('\u%04s', bin2hex($utf16)); - break; - - case (($ord_var_c & 0xFE) == 0xFC): - // characters U-04000000 - U-7FFFFFFF, mask 1111110X - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, - ord($var{$c + 1}), - ord($var{$c + 2}), - ord($var{$c + 3}), - ord($var{$c + 4}), - ord($var{$c + 5})); - $c += 5; - $utf16 = $this->utf82utf16($char); - $ascii .= sprintf('\u%04s', bin2hex($utf16)); - break; - } - } - - return '"'.$ascii.'"'; - - case 'array': - /* - * As per JSON spec if any array key is not an integer - * we must treat the the whole array as an object. We - * also try to catch a sparsely populated associative - * array with numeric keys here because some JS engines - * will create an array with empty indexes up to - * max_index which can cause memory issues and because - * the keys, which may be relevant, will be remapped - * otherwise. - * - * As per the ECMA and JSON specification an object may - * have any string as a property. Unfortunately due to - * a hole in the ECMA specification if the key is a - * ECMA reserved word or starts with a digit the - * parameter is only accessible using ECMAScript's - * bracket notation. - */ - - // treat as a JSON object - if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { - $properties = array_map(array($this, 'name_value'), - array_keys($var), - array_values($var)); - - foreach($properties as $property) { - if(Services_JSON::isError($property)) { - return $property; - } - } - - return '{' . join(',', $properties) . '}'; - } - - // treat it like a regular array - $elements = array_map(array($this, 'encode'), $var); - - foreach($elements as $element) { - if(Services_JSON::isError($element)) { - return $element; - } - } - - return '[' . join(',', $elements) . ']'; - - case 'object': - $vars = get_object_vars($var); - - $properties = array_map(array($this, 'name_value'), - array_keys($vars), - array_values($vars)); - - foreach($properties as $property) { - if(Services_JSON::isError($property)) { - return $property; - } - } - - return '{' . join(',', $properties) . '}'; - - default: - return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) - ? 'null' - : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); - } - } - - /** - * array-walking function for use in generating JSON-formatted name-value pairs - * - * @param string $name name of key to use - * @param mixed $value reference to an array element to be encoded - * - * @return string JSON-formatted name-value pair, like '"name":value' - * @access private - */ - function name_value($name, $value) - { - $encoded_value = $this->encode($value); - - if(Services_JSON::isError($encoded_value)) { - return $encoded_value; - } - - return $this->encode((string)$name) . ':' . $encoded_value; - } - - /** - * reduce a string by removing leading and trailing comments and whitespace - * - * @param $str string string value to strip of comments and whitespace - * - * @return string string value stripped of comments and whitespace - * @access private - */ - function reduce_string($str) - { - $str = preg_replace(array( - - // eliminate single line comments in '// ...' form - '#^\s*//(.+)$#m', - - // eliminate multi-line comments in '/* ... */' form, at start of string - '#^\s*/\*(.+)\*/#Us', - - // eliminate multi-line comments in '/* ... */' form, at end of string - '#/\*(.+)\*/\s*$#Us' - - ), '', $str); - - // eliminate extraneous space - return trim($str); - } - - /** - * decodes a JSON string into appropriate variable - * - * @param string $str JSON-formatted string - * - * @return mixed number, boolean, string, array, or object - * corresponding to given JSON input string. - * See argument 1 to Services_JSON() above for object-output behavior. - * Note that decode() always returns strings - * in ASCII or UTF-8 format! - * @access public - */ - function decode($str) - { - $str = $this->reduce_string($str); - - switch (strtolower($str)) { - case 'true': - return true; - - case 'false': - return false; - - case 'null': - return null; - - default: - $m = array(); - - if (is_numeric($str)) { - // Lookie-loo, it's a number - - // This would work on its own, but I'm trying to be - // good about returning integers where appropriate: - // return (float)$str; - - // Return float or int, as appropriate - return ((float)$str == (integer)$str) - ? (integer)$str - : (float)$str; - - } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { - // STRINGS RETURNED IN UTF-8 FORMAT - $delim = substr($str, 0, 1); - $chrs = substr($str, 1, -1); - $utf8 = ''; - $strlen_chrs = strlen($chrs); - - for ($c = 0; $c < $strlen_chrs; ++$c) { - - $substr_chrs_c_2 = substr($chrs, $c, 2); - $ord_chrs_c = ord($chrs{$c}); - - switch (true) { - case $substr_chrs_c_2 == '\b': - $utf8 .= chr(0x08); - ++$c; - break; - case $substr_chrs_c_2 == '\t': - $utf8 .= chr(0x09); - ++$c; - break; - case $substr_chrs_c_2 == '\n': - $utf8 .= chr(0x0A); - ++$c; - break; - case $substr_chrs_c_2 == '\f': - $utf8 .= chr(0x0C); - ++$c; - break; - case $substr_chrs_c_2 == '\r': - $utf8 .= chr(0x0D); - ++$c; - break; - - case $substr_chrs_c_2 == '\\"': - case $substr_chrs_c_2 == '\\\'': - case $substr_chrs_c_2 == '\\\\': - case $substr_chrs_c_2 == '\\/': - if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || - ($delim == "'" && $substr_chrs_c_2 != '\\"')) { - $utf8 .= $chrs{++$c}; - } - break; - - case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): - // single, escaped unicode character - $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) - . chr(hexdec(substr($chrs, ($c + 4), 2))); - $utf8 .= $this->utf162utf8($utf16); - $c += 5; - break; - - case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): - $utf8 .= $chrs{$c}; - break; - - case ($ord_chrs_c & 0xE0) == 0xC0: - // characters U-00000080 - U-000007FF, mask 110XXXXX - //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $utf8 .= substr($chrs, $c, 2); - ++$c; - break; - - case ($ord_chrs_c & 0xF0) == 0xE0: - // characters U-00000800 - U-0000FFFF, mask 1110XXXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $utf8 .= substr($chrs, $c, 3); - $c += 2; - break; - - case ($ord_chrs_c & 0xF8) == 0xF0: - // characters U-00010000 - U-001FFFFF, mask 11110XXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $utf8 .= substr($chrs, $c, 4); - $c += 3; - break; - - case ($ord_chrs_c & 0xFC) == 0xF8: - // characters U-00200000 - U-03FFFFFF, mask 111110XX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $utf8 .= substr($chrs, $c, 5); - $c += 4; - break; - - case ($ord_chrs_c & 0xFE) == 0xFC: - // characters U-04000000 - U-7FFFFFFF, mask 1111110X - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $utf8 .= substr($chrs, $c, 6); - $c += 5; - break; - - } - - } - - return $utf8; - - } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { - // array, or object notation - - if ($str{0} == '[') { - $stk = array(SERVICES_JSON_IN_ARR); - $arr = array(); - } else { - if ($this->use & SERVICES_JSON_LOOSE_TYPE) { - $stk = array(SERVICES_JSON_IN_OBJ); - $obj = array(); - } else { - $stk = array(SERVICES_JSON_IN_OBJ); - $obj = new stdClass(); - } - } - - array_push($stk, array('what' => SERVICES_JSON_SLICE, - 'where' => 0, - 'delim' => false)); - - $chrs = substr($str, 1, -1); - $chrs = $this->reduce_string($chrs); - - if ($chrs == '') { - if (reset($stk) == SERVICES_JSON_IN_ARR) { - return $arr; - - } else { - return $obj; - - } - } - - //print("\nparsing {$chrs}\n"); - - $strlen_chrs = strlen($chrs); - - for ($c = 0; $c <= $strlen_chrs; ++$c) { - - $top = end($stk); - $substr_chrs_c_2 = substr($chrs, $c, 2); - - if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { - // found a comma that is not inside a string, array, etc., - // OR we've reached the end of the character list - $slice = substr($chrs, $top['where'], ($c - $top['where'])); - array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); - //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); - - if (reset($stk) == SERVICES_JSON_IN_ARR) { - // we are in an array, so just push an element onto the stack - array_push($arr, $this->decode($slice)); - - } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { - // we are in an object, so figure - // out the property name and set an - // element in an associative array, - // for now - $parts = array(); - - if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { - // "name":value pair - $key = $this->decode($parts[1]); - $val = $this->decode($parts[2]); - - if ($this->use & SERVICES_JSON_LOOSE_TYPE) { - $obj[$key] = $val; - } else { - $obj->$key = $val; - } - } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { - // name:value pair, where name is unquoted - $key = $parts[1]; - $val = $this->decode($parts[2]); - - if ($this->use & SERVICES_JSON_LOOSE_TYPE) { - $obj[$key] = $val; - } else { - $obj->$key = $val; - } - } - - } - - } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { - // found a quote, and we are not inside a string - array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); - //print("Found start of string at {$c}\n"); - - } elseif (($chrs{$c} == $top['delim']) && - ($top['what'] == SERVICES_JSON_IN_STR) && - ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) { - // found a quote, we're in a string, and it's not escaped - // we know that it's not escaped becase there is _not_ an - // odd number of backslashes at the end of the string so far - array_pop($stk); - //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); - - } elseif (($chrs{$c} == '[') && - in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { - // found a left-bracket, and we are in an array, object, or slice - array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); - //print("Found start of array at {$c}\n"); - - } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { - // found a right-bracket, and we're in an array - array_pop($stk); - //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); - - } elseif (($chrs{$c} == '{') && - in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { - // found a left-brace, and we are in an array, object, or slice - array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); - //print("Found start of object at {$c}\n"); - - } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { - // found a right-brace, and we're in an object - array_pop($stk); - //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); - - } elseif (($substr_chrs_c_2 == '/*') && - in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { - // found a comment start, and we are in an array, object, or slice - array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); - $c++; - //print("Found start of comment at {$c}\n"); - - } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { - // found a comment end, and we're in one now - array_pop($stk); - $c++; - - for ($i = $top['where']; $i <= $c; ++$i) - $chrs = substr_replace($chrs, ' ', $i, 1); - - //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); - - } - - } - - if (reset($stk) == SERVICES_JSON_IN_ARR) { - return $arr; - - } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { - return $obj; - - } - - } - } - } - - /** - * @todo Ultimately, this should just call PEAR::isError() - */ - function isError($data, $code = null) - { - if (class_exists('pear')) { - return PEAR::isError($data, $code); - } elseif (is_object($data) && (get_class($data) == 'services_json_error' || - is_subclass_of($data, 'services_json_error'))) { - return true; - } - - return false; - } -} - -if (class_exists('PEAR_Error')) { - - class Services_JSON_Error extends PEAR_Error - { - function Services_JSON_Error($message = 'unknown error', $code = null, - $mode = null, $options = null, $userinfo = null) - { - parent::PEAR_Error($message, $code, $mode, $options, $userinfo); - } - } - -} else { - - /** - * @todo Ultimately, this class shall be descended from PEAR_Error - */ - class Services_JSON_Error - { - function Services_JSON_Error($message = 'unknown error', $code = null, - $mode = null, $options = null, $userinfo = null) - { - - } - } - -} - -function json_encode($var) -{ - $JSON = new Services_JSON; - return $JSON->encode($var); -} - -function json_decode($var) -{ - $JSON = new Services_JSON; - return $JSON->decode($var); -} \ No newline at end of file diff --git a/html/forums/inc/adminfunctions_templates.php b/html/forums/inc/adminfunctions_templates.php deleted file mode 100644 index 1d7e4c6..0000000 --- a/html/forums/inc/adminfunctions_templates.php +++ /dev/null @@ -1,94 +0,0 @@ - 0 (based off master) - defaults to 1 - * @param mixed $sid Template SID to modify, false for every SID > 0 and SID = -1 - * @param int $limit The maximum possible replacements for the regular expression - * @return boolean true if updated one or more templates, false if not. - */ - -function find_replace_templatesets($title, $find, $replace, $autocreate=1, $sid=false, $limit=-1) -{ - global $db, $mybb; - - $return = false; - $template_sets = array(-2, -1); - - // Select all templates with that title (including global) if not working on a specific template set - $sqlwhere = '>0 OR sid=-1'; - $sqlwhere2 = '>0'; - - // Otherwise select just templates from that specific set - if($sid !== false) - { - $sid = (int)$sid; - $sqlwhere2 = $sqlwhere = "=$sid"; - } - - // Select all other modified templates with that title - $query = $db->simple_select("templates", "tid, sid, template", "title = '".$db->escape_string($title)."' AND (sid{$sqlwhere})"); - while($template = $db->fetch_array($query)) - { - // Keep track of which templates sets have a modified version of this template already - $template_sets[] = $template['sid']; - - // Update the template if there is a replacement term or a change - $new_template = preg_replace($find, $replace, $template['template'], $limit); - if($new_template == $template['template']) - { - continue; - } - - // The template is a custom template. Replace as normal. - $updated_template = array( - "template" => $db->escape_string($new_template) - ); - $db->update_query("templates", $updated_template, "tid='{$template['tid']}'"); - - $return = true; - } - - // Add any new templates if we need to and are allowed to - if($autocreate != 0) - { - // Select our master template with that title - $query = $db->simple_select("templates", "title, template", "title='".$db->escape_string($title)."' AND sid='-2'", array('limit' => 1)); - $master_template = $db->fetch_array($query); - $master_template['new_template'] = preg_replace($find, $replace, $master_template['template'], $limit); - - if($master_template['new_template'] != $master_template['template']) - { - // Update the rest of our template sets that are currently inheriting this template from our master set - $query = $db->simple_select("templatesets", "sid", "sid NOT IN (".implode(',', $template_sets).") AND (sid{$sqlwhere2})"); - while($template = $db->fetch_array($query)) - { - $insert_template = array( - "title" => $db->escape_string($master_template['title']), - "template" => $db->escape_string($master_template['new_template']), - "sid" => $template['sid'], - "version" => $mybb->version_code, - "status" => '', - "dateline" => TIME_NOW - ); - $db->insert_query("templates", $insert_template); - - $return = true; - } - } - } - - return $return; -} diff --git a/html/forums/inc/cachehandlers/apc.php b/html/forums/inc/cachehandlers/apc.php deleted file mode 100644 index 3fda52d..0000000 --- a/html/forums/inc/cachehandlers/apc.php +++ /dev/null @@ -1,114 +0,0 @@ -trigger_generic_error("apc_load_error"); - die; - } - } - } - - /** - * Connect and initialize this handler. - * - * @return boolean True if successful, false on failure - */ - function connect() - { - // Set a unique identifier for all queries in case other forums on this server also use this cache handler - $this->unique_id = md5(MYBB_ROOT); - - return true; - } - - /** - * Connect and initialize this handler. - * - * @param string $name - * @return boolean True if successful, false on failure - */ - function fetch($name) - { - if(apc_exists($this->unique_id."_".$name)) - { - $data = apc_fetch($this->unique_id."_".$name); - return unserialize($data); - } - - return false; - } - - /** - * Write an item to the cache. - * - * @param string $name The name of the cache - * @param mixed $contents The data to write to the cache item - * @return boolean True on success, false on failure - */ - function put($name, $contents) - { - $status = apc_store($this->unique_id."_".$name, serialize($contents)); - return $status; - } - - /** - * Delete a cache - * - * @param string $name The name of the cache - * @return boolean True on success, false on failure - */ - function delete($name) - { - return apc_delete($this->unique_id."_".$name); - } - - /** - * Disconnect from the cache - * - * @return bool - */ - function disconnect() - { - return true; - } - - /** - * @param string $name - * - * @return string - */ - function size_of($name='') - { - global $lang; - - return $lang->na; - } -} diff --git a/html/forums/inc/cachehandlers/disk.php b/html/forums/inc/cachehandlers/disk.php deleted file mode 100644 index 030ac47..0000000 --- a/html/forums/inc/cachehandlers/disk.php +++ /dev/null @@ -1,126 +0,0 @@ -trigger_generic_error("cache_no_write"); - return false; - } - - $cache_file = fopen(MYBB_ROOT."cache/{$name}.php", "w") or $mybb->trigger_generic_error("cache_no_write"); - flock($cache_file, LOCK_EX); - $cache_contents = ""; - fwrite($cache_file, $cache_contents); - flock($cache_file, LOCK_UN); - fclose($cache_file); - - return true; - } - - /** - * Delete a cache - * - * @param string $name The name of the cache - * @return boolean True on success, false on failure - */ - function delete($name) - { - return @unlink(MYBB_ROOT."/cache/{$name}.php"); - } - - /** - * Disconnect from the cache - * - * @return bool - */ - function disconnect() - { - return true; - } - - /** - * Select the size of the disk cache - * - * @param string $name The name of the cache - * @return integer the size of the disk cache - */ - function size_of($name='') - { - if($name != '') - { - return @filesize(MYBB_ROOT."/cache/{$name}.php"); - } - else - { - $total = 0; - $dir = opendir(MYBB_ROOT."/cache"); - while(($file = readdir($dir)) !== false) - { - if($file == "." || $file == ".." || $file == ".svn" || !is_file(MYBB_ROOT."/cache/{$file}")) - { - continue; - } - - $total += filesize(MYBB_ROOT."/cache/{$file}"); - } - return $total; - } - } -} diff --git a/html/forums/inc/cachehandlers/eaccelerator.php b/html/forums/inc/cachehandlers/eaccelerator.php deleted file mode 100644 index 808a007..0000000 --- a/html/forums/inc/cachehandlers/eaccelerator.php +++ /dev/null @@ -1,116 +0,0 @@ -trigger_generic_error("eaccelerator_load_error"); - die; - } - } - } - - /** - * Connect and initialize this handler. - * - * @return boolean True if successful, false on failure - */ - function connect() - { - // Set a unique identifier for all queries in case other forums on this server also use this cache handler - $this->unique_id = md5(MYBB_ROOT); - - return true; - } - - /** - * Retrieve an item from the cache. - * - * @param string $name The name of the cache - * @return mixed Cache data if successful, false if failure - */ - function fetch($name) - { - $data = eaccelerator_get($this->unique_id."_".$name); - if($data === false) - { - return false; - } - - return unserialize($data); - } - - /** - * Write an item to the cache. - * - * @param string $name The name of the cache - * @param mixed $contents The data to write to the cache item - * @return boolean True on success, false on failure - */ - function put($name, $contents) - { - eaccelerator_lock($this->unique_id."_".$name); - $status = eaccelerator_put($this->unique_id."_".$name, serialize($contents)); - eaccelerator_unlock($this->unique_id."_".$name); - return $status; - } - - /** - * Delete a cache - * - * @param string $name The name of the cache - * @return boolean True on success, false on failure - */ - function delete($name) - { - return eaccelerator_rm($this->unique_id."_".$name); - } - - /** - * Disconnect from the cache - * - * @return bool - */ - function disconnect() - { - return true; - } - - /** - * @param string $name - * - * @return string - */ - function size_of($name='') - { - global $lang; - - return $lang->na; - } -} diff --git a/html/forums/inc/cachehandlers/index.html b/html/forums/inc/cachehandlers/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/cachehandlers/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/cachehandlers/interface.php b/html/forums/inc/cachehandlers/interface.php deleted file mode 100644 index ddceac8..0000000 --- a/html/forums/inc/cachehandlers/interface.php +++ /dev/null @@ -1,61 +0,0 @@ -trigger_generic_error("memcache_load_error"); - die; - } - } - } - - /** - * Connect and initialize this handler. - * - * @return boolean True if successful, false on failure - */ - function connect() - { - global $mybb, $error_handler; - - $this->memcache = new Memcache; - - if($mybb->config['memcache']['host']) - { - $mybb->config['memcache'][0] = $mybb->config['memcache']; - unset($mybb->config['memcache']['host']); - unset($mybb->config['memcache']['port']); - } - - foreach($mybb->config['memcache'] as $memcache) - { - if(!$memcache['host']) - { - $message = "Please configure the memcache settings in inc/config.php before attempting to use this cache handler"; - $error_handler->trigger($message, MYBB_CACHEHANDLER_LOAD_ERROR); - die; - } - - if(!isset($memcache['port'])) - { - $memcache['port'] = "11211"; - } - - $this->memcache->addServer($memcache['host'], $memcache['port']); - - if(!$this->memcache) - { - $message = "Unable to connect to the memcache server on {$memcache['memcache_host']}:{$memcache['memcache_port']}. Are you sure it is running?"; - $error_handler->trigger($message, MYBB_CACHEHANDLER_LOAD_ERROR); - die; - } - } - - // Set a unique identifier for all queries in case other forums are using the same memcache server - $this->unique_id = md5(MYBB_ROOT); - - return true; - } - - /** - * Retrieve an item from the cache. - * - * @param string $name The name of the cache - * @return mixed Cache data if successful, false if failure - */ - function fetch($name) - { - $data = $this->memcache->get($this->unique_id."_".$name); - - if($data === false) - { - return false; - } - else - { - return $data; - } - } - - /** - * Write an item to the cache. - * - * @param string $name The name of the cache - * @param mixed $contents The data to write to the cache item - * @return boolean True on success, false on failure - */ - function put($name, $contents) - { - return $this->memcache->set($this->unique_id."_".$name, $contents); - } - - /** - * Delete a cache - * - * @param string $name The name of the cache - * @return boolean True on success, false on failure - */ - function delete($name) - { - return $this->memcache->delete($this->unique_id."_".$name); - } - - /** - * Disconnect from the cache - */ - function disconnect() - { - @$this->memcache->close(); - } - - /** - * @param string $name - * - * @return string - */ - function size_of($name='') - { - global $lang; - - return $lang->na; - } -} - diff --git a/html/forums/inc/cachehandlers/memcached.php b/html/forums/inc/cachehandlers/memcached.php deleted file mode 100644 index d4c8870..0000000 --- a/html/forums/inc/cachehandlers/memcached.php +++ /dev/null @@ -1,157 +0,0 @@ -trigger_generic_error("memcached_load_error"); - die; - } - } - } - - /** - * Connect and initialize this handler. - * - * @return boolean True if successful, false on failure - */ - function connect() - { - global $mybb, $error_handler; - - $this->memcached = new Memcached; - - if($mybb->config['memcache']['host']) - { - $mybb->config['memcache'][0] = $mybb->config['memcache']; - unset($mybb->config['memcache']['host']); - unset($mybb->config['memcache']['port']); - } - - foreach($mybb->config['memcache'] as $memcached) - { - if(!$memcached['host']) - { - $message = "Please configure the memcache settings in inc/config.php before attempting to use this cache handler"; - $error_handler->trigger($message, MYBB_CACHEHANDLER_LOAD_ERROR); - die; - } - - if(!isset($memcached['port'])) - { - $memcached['port'] = "11211"; - } - - $this->memcached->addServer($memcached['host'], $memcached['port']); - - if(!$this->memcached) - { - $message = "Unable to connect to the memcached server on {$memcached['memcache_host']}:{$memcached['memcache_port']}. Are you sure it is running?"; - $error_handler->trigger($message, MYBB_CACHEHANDLER_LOAD_ERROR); - die; - } - } - - // Set a unique identifier for all queries in case other forums are using the same memcache server - $this->unique_id = md5(MYBB_ROOT); - - return true; - } - - /** - * Retrieve an item from the cache. - * - * @param string $name The name of the cache - * @return mixed Cache data if successful, false if failure - */ - function fetch($name) - { - $data = $this->memcached->get($this->unique_id."_".$name); - - if($data === false) - { - return false; - } - else - { - return $data; - } - } - - /** - * Write an item to the cache. - * - * @param string $name The name of the cache - * @param mixed $contents The data to write to the cache item - * @return boolean True on success, false on failure - */ - function put($name, $contents) - { - return $this->memcached->set($this->unique_id."_".$name, $contents); - } - - /** - * Delete a cache - * - * @param string $name The name of the cache - * @return boolean True on success, false on failure - */ - function delete($name) - { - return $this->memcached->delete($this->unique_id."_".$name); - } - - /** - * Disconnect from the cache - */ - function disconnect() - { - @$this->memcached->quit(); - } - - /** - * @param string $name - * - * @return string - */ - function size_of($name='') - { - global $lang; - - return $lang->na; - } -} - diff --git a/html/forums/inc/cachehandlers/xcache.php b/html/forums/inc/cachehandlers/xcache.php deleted file mode 100644 index def8e14..0000000 --- a/html/forums/inc/cachehandlers/xcache.php +++ /dev/null @@ -1,111 +0,0 @@ -trigger_generic_error("xcache_load_error"); - die; - } - } - } - - /** - * Connect and initialize this handler. - * - * @return boolean True if successful, false on failure - */ - function connect() - { - // Set a unique identifier for all queries in case other forums on this server also use this cache handler - $this->unique_id = md5(MYBB_ROOT); - - return true; - } - - /** - * Retrieve an item from the cache. - * - * @param string $name The name of the cache - * @return mixed Cache data if successful, false if failure - */ - function fetch($name) - { - if(!xcache_isset($this->unique_id."_".$name)) - { - return false; - } - return xcache_get($this->unique_id."_".$name); - } - - /** - * Write an item to the cache. - * - * @param string $name The name of the cache - * @param mixed $contents The data to write to the cache item - * @return boolean True on success, false on failure - */ - function put($name, $contents) - { - return xcache_set($this->unique_id."_".$name, $contents); - } - - /** - * Delete a cache - * - * @param string $name The name of the cache - * @return boolean True on success, false on failure - */ - function delete($name) - { - return xcache_set($this->unique_id."_".$name, "", 1); - } - - /** - * Disconnect from the cache - * - * @return bool - */ - function disconnect() - { - return true; - } - - /** - * @param string $name - * - * @return string - */ - function size_of($name='') - { - global $lang; - - return $lang->na; - } -} diff --git a/html/forums/inc/captcha_fonts/MINYN___.ttf b/html/forums/inc/captcha_fonts/MINYN___.ttf deleted file mode 100644 index 0ab1fea..0000000 Binary files a/html/forums/inc/captcha_fonts/MINYN___.ttf and /dev/null differ diff --git a/html/forums/inc/captcha_fonts/edmunds.ttf b/html/forums/inc/captcha_fonts/edmunds.ttf deleted file mode 100644 index 5258ef5..0000000 Binary files a/html/forums/inc/captcha_fonts/edmunds.ttf and /dev/null differ diff --git a/html/forums/inc/captcha_fonts/index.html b/html/forums/inc/captcha_fonts/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/captcha_fonts/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/captcha_fonts/read_me.html b/html/forums/inc/captcha_fonts/read_me.html deleted file mode 100644 index 25f2dae..0000000 --- a/html/forums/inc/captcha_fonts/read_me.html +++ /dev/null @@ -1,253 +0,0 @@ - - - - - - Larabie Fonts "read me" file, license and FAQ - - - - - -

    - LARABIE FONTS README.TXT -

    -

    - All Larabie Fonts in this file are free to use for personal and/or commercial purposes. No - payment is necessary to use these fonts for personal or commercial use. For Software Products - who want to include Larabie Fonts see the License Agreement below. You can add this font to a - website but do not combine fonts into a single archive or alter them in any way. -

    -

    - All Larabie Fonts are free for commercial use but a sample of your product would be - gratefully appreciated so I can see how the font looks in use. Contact www.larabiefonts.com/donation.html for - mailing information. -

    -

    - Some Larabie Fonts have enhanced and expanded families available for sale at www.typodermic.com. -

    -

    - If you'd like to make a voluntary donation to Larabie Fonts for the use of the free fonts in - any amount please go to www.larabiefonts.com/donation.html -

    -

    - I accept CDs, magazines, t-shirts, a sample of your merchandise or anything featuring Larabie - Fonts. Please remember to list your item as a gift on the customs form or I will have to - pay import duties and taxes on the item. Mailing information is provided at the link above. -

    -

    - Font installation help is available at www.larabiefonts.com/help.html -

    -

    - LARABIE FONTS FREQUENTLY ASKED QUESTIONS -

    -
      -
    • Q: How do use these fonts in my favourite software? -
    • -
    • A: In Windows, you take the fonts out of the ZIP archive and place them in your fonts - folder which can be found in your Control Panel. The next time you run your software, the - font will be available. For example: If you install a new font, the next time you run - Microsoft Word, that font will be available in the menu under Format / Font. For anything - more complicated, or Mac installation, visit - www.larabiefonts.com/help.html -
    • -
    -
      -
    • Q: How can I use this font in AOL Instant - Messenger, MSN Messenger, Outlook, Outlook Express, Euodora or any other email software? -
    • -
    • A: At the time of this writing (Feb 2004) you cant. After installing one of my fonts, - you may be able to select it in the above applications but the person at the other end wont - see that same thing unless they have the font installed. If you really want to use my fonts - in these applications, make sure the people at the other end have the same fonts installed. -
    • -
    -
      -
    • Q: How can I use these fonts on a web page? -
    • -
    • A: If youre creating a web page using Flash, its easy. Consult your Flash manual. If - youre using Acrobat, make sure the font - embedding settings are turned on. Consult your Acrobat manual. For anything else there are - limitations: If you want to use one of my fonts as your main, text font youre pretty much - out of luck unless you explore a font embedding tool such as WEFT but I dont recommend it. - To use my fonts as headings or titles, use image creation software such as The Gimp, Photoshop, Paint Shop Pro, Pixia etc. Save the images as GIF files and place - them on your web page. Theres a lot more to it than can be explained here but there are - countless books available on web page design. -
    • -
    -
      -
    • Q: How can I make these fonts bigger? -
    • -
    • A: All my fonts are infinitely scalable; the limitations are in your software. A common - problem is scaling fonts in Microsoft Word. If you choose Format / Font you can type in any - number you like under size. -
    • -
    -
      -
    • Q: Are these fonts really free? -
    • -
    • A: Yes they are. Some fonts such as Neuropol have expanded font families available - for sale at www.typodermic.com but the version you - downloaded at Larabie Fonts is free. -
    • -
    -
      -
    • Q: Your licence agreement states that the fonts cant be altered. Does that mean I cant - mess around with your fonts in Photoshop/Illustrator/Publisher etc? -
    • -
    • A: Those license restrictions refer to altering the actual fonts themselves, not what you - make with them. As long as you dont alter the font files in font creation software such as - FontLab or Fontographer youre free to create anything you like with them. -
    • -
    -
      -
    • Q: Can I use your fonts in a logo? -
    • -
    • A: Yes. But check with a lawyer if youre not sure. Its okay with me if you use it but - do so at your own risk. -
    • -
    -
      -
    • Q: Can I send you a sample of the nifty thing I created with your fonts? -
    • -
    • A: Of course. Check www.larabiefonts.com/donation.html for my - current email or mailing address. -
    • -
    -
      -
    • Q: Can you make a custom font for me? -
    • -
    • A: Possibly. Check typodermic.com/custom.html for details. Keep in mind - that making fonts is my full-time job so no freebies. -
    • -
    - -
      -
    • Q: I want to sell rubber stamp alphabets, alphabet punches or stencil alphabets using - your font designs. -
    • -
    • A: Contact me first at www.larabiefonts.com/email.html. -
    • -
    -
      -
    • Q: My software wont let me embed one of your fonts. -
    • -
    • A: You may have an old version of one of my fonts. Uninstall it and install a current - version on Larabie Fonts. -
    • -
    -
      -
    • Q: Can you help me find a font? -
    • -
    • A: I really dont have the time but if you send a donation, I can give it a try. If not. - post your question on my font forum: www.larabiefonts.com/info.html. -
    • -
    -

    - LARABIE FONTS END-USER LICENSE AGREEMENT FOR SOFTWARE PRODUCTS -

    -

    - SOFTWARE PRODUCT LICENSE -

    -

    - The SOFTWARE PRODUCT is protected by copyright laws and International copyright treaties, as - well as other intellectual property laws and treaties. The SOFTWARE PRODUCT is licensed, not - sold. -

    -
    - 1. GRANT OF LICENSE. This document grants you the following rights: -
    -

    - - Installation and Use. You may install and use an unlimited number of copies of the SOFTWARE - PRODUCT. You may copy and distribute unlimited copies of the SOFTWARE PRODUCT as you receive - them, in any medium, provided that you publish on each copy an appropriate copyright notice. - Keep intact all the notices that refer to this License and give any other recipients of the - fonts a copy of this License along with the fonts. -

    -
    - 2. DESCRIPTION OF OTHER RIGHTS AND LIMITATIONS. -
    -

    - - You may modify your copy or copies of the SOFTWARE PRODUCT or any portion of it, provided - that you also meet all of these rules: -

    -

    - a) Do not alter in any way alphanumeric characters (A-Z, a-z, 1-9) contained in the font. An - exception is converting between formats, here is allowed the nominal distortion that occurs - during conversion from second order to third order quadratic curves (TrueType to Postscript) - and vice versa. -

    -

    - b) Extra characters may be added; here it is allowed to use curves (shapes) from alphanumeric - characters in fonts under same license. -

    -

    - c) It is allowed to modify and remove analpahbetics (punctuation, special characters, - ligatures and symbols). -

    -

    - d) The original font name must be retained but can be augmented. (ie. a Font named Blue - Highway can be renamed Blue Highway Cyrillic or Blue Highway ANSI, etc.) -

    -

    - e) Character mapping may be altered. -

    -

    - f) If the kerning information is altered or discarded it must be stated in the user notes or - documentation. -

    -

    - g) All modifications must be released under this license. -

    -

    - -

    LIMITED WARRANTY NO WARRANTIES. Larabie Fonts expressly disclaims any warranty for the - SOFTWARE PRODUCT. The SOFTWARE PRODUCT and any related documentation is provided "as is" - without warranty of any kind, either express or implied, including, without limitation, the - implied warranties or merchantability, fitness for a particular purpose, or non-infringement. - The entire risk arising out of use or performance of the SOFTWARE PRODUCT remains with you. -

    - -

    -

    - NO LIABILITY FOR CONSEQUENTIAL DAMAGES. In no event shall Larabie Fonts be liable for any - damages whatsoever (including, without limitation, damages for loss of business profits, - business interruption, loss of business information, or any other pecuniary loss) arising out - of the use of or inability to use this product, even if Larabie Fonts has been advised of the - possibility of such damages. -

    -
    - 3. MISCELLANEOUS -
    -

    - Should you have any questions concerning this document, or if you desire to contact Larabie - Fonts for any reason, please email www.larabiefonts.com/email.html. -

    - - \ No newline at end of file diff --git a/html/forums/inc/class_captcha.php b/html/forums/inc/class_captcha.php deleted file mode 100644 index 82d727a..0000000 --- a/html/forums/inc/class_captcha.php +++ /dev/null @@ -1,467 +0,0 @@ -type = $mybb->settings['captchaimage']; - - $args = array( - 'this' => &$this, - 'build' => &$build, - 'template' => &$template, - ); - - $plugins->run_hooks('captcha_build_start', $args); - - // Prepare the build template - if($template) - { - $this->captcha_template = $template; - - if($this->type == 2) - { - $this->captcha_template .= "_recaptcha"; - } - else if($this->type == 4){ - $this->captcha_template .= "_nocaptcha"; - } - } - - // Work on which CAPTCHA we've got installed - if($this->type == 2 && $mybb->settings['captchapublickey'] && $mybb->settings['captchaprivatekey']) - { - // We want to use reCAPTCHA, set the server options - $this->server = "//www.google.com/recaptcha/api"; - $this->verify_server = "www.google.com"; - - if($build == true) - { - $this->build_recaptcha(); - } - } - else if($this->type == 4 && $mybb->settings['captchapublickey'] && $mybb->settings['captchaprivatekey']) - { - // We want to use reCAPTCHA, set the server options - $this->server = "//www.google.com/recaptcha/api.js"; - $this->verify_server = "https://www.google.com/recaptcha/api/siteverify"; - - if($build == true) - { - $this->build_recaptcha(); - } - } - else if($this->type == 1) - { - if(!function_exists("imagecreatefrompng")) - { - // We want to use the default CAPTCHA, but it's not installed - return; - } - else if($build == true) - { - $this->build_captcha(); - } - } - - $plugins->run_hooks('captcha_build_end', $args); - } - - /** - * @param bool $return Not used - */ - function build_captcha($return = false) - { - global $db, $lang, $templates, $theme, $mybb; - - // This will build a MyBB CAPTCHA - $randomstr = random_str(5); - $imagehash = md5(random_str(12)); - - $insert_array = array( - "imagehash" => $imagehash, - "imagestring" => $randomstr, - "dateline" => TIME_NOW - ); - - $db->insert_query("captcha", $insert_array); - eval("\$this->html = \"".$templates->get($this->captcha_template)."\";"); - //eval("\$this->html = \"".$templates->get("member_register_regimage")."\";"); - } - - function build_recaptcha() - { - global $lang, $mybb, $templates; - - // This will build a reCAPTCHA - $server = $this->server; - $public_key = $mybb->settings['captchapublickey']; - - eval("\$this->html = \"".$templates->get($this->captcha_template, 1, 0)."\";"); - //eval("\$this->html = \"".$templates->get("member_register_regimage_recaptcha")."\";"); - } - - /** - * @return string - */ - function build_hidden_captcha() - { - global $db, $mybb, $templates; - - $field = array(); - - if($this->type == 1) - { - // Names - $hash = "imagehash"; - $string = "imagestring"; - - // Values - $field['hash'] = $db->escape_string($mybb->input['imagehash']); - $field['string'] = $db->escape_string($mybb->input['imagestring']); - } - else if($this->type == 2) - { - // Names - $hash = "recaptcha_challenge_field"; - $string = "recaptcha_response_field"; - - // Values - $field['hash'] = $mybb->input['recaptcha_challenge_field']; - $field['string'] = $mybb->input['recaptcha_response_field']; - } - else if($this->type == 3) - { - // Are You a Human can't be built as a hidden captcha - return ''; - } - - eval("\$this->html = \"".$templates->get("post_captcha_hidden")."\";"); - return $this->html; - } - - /** - * @return bool - */ - function validate_captcha() - { - global $db, $lang, $mybb, $session, $plugins; - - $plugins->run_hooks('captcha_validate_start', $this); - - if($this->type == 1) - { - // We have a normal CAPTCHA to handle - $imagehash = $db->escape_string($mybb->input['imagehash']); - $imagestring = $db->escape_string(my_strtolower($mybb->input['imagestring'])); - - switch($db->type) - { - case 'mysql': - case 'mysqli': - $field = 'imagestring'; - break; - default: - $field = 'LOWER(imagestring)'; - break; - } - - $query = $db->simple_select("captcha", "*", "imagehash = '{$imagehash}' AND {$field} = '{$imagestring}'"); - $imgcheck = $db->fetch_array($query); - - if(!$imgcheck) - { - $this->set_error($lang->invalid_captcha_verify); - $db->delete_query("captcha", "imagehash = '{$imagehash}'"); - } - } - elseif($this->type == 2) - { - $challenge = $mybb->input['recaptcha_challenge_field']; - $response = $mybb->input['recaptcha_response_field']; - - if(!$challenge || strlen($challenge) == 0 || !$response || strlen($response) == 0) - { - $this->set_error($lang->invalid_captcha); - } - else - { - // We have a reCAPTCHA to handle - $data = $this->_qsencode(array( - 'privatekey' => $mybb->settings['captchaprivatekey'], - 'remoteip' => $session->ipaddress, - 'challenge' => $challenge, - 'response' => $response - )); - - // Contact Google and see if our reCAPTCHA was successful - $http_request = "POST /recaptcha/api/verify HTTP/1.0\r\n"; - $http_request .= "Host: $this->verify_server\r\n"; - $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; - $http_request .= "Content-Length: ".strlen($data)."\r\n"; - $http_request .= "User-Agent: reCAPTCHA/PHP\r\n"; - $http_request .= "\r\n"; - $http_request .= $data; - - $fs = @fsockopen($this->verify_server, 80, $errno, $errstr, 10); - - if($fs == false) - { - $this->set_error($lang->invalid_captcha_transmit); - } - else - { - // We connected, but is it correct? - fwrite($fs, $http_request); - - while(!feof($fs)) - { - $response .= fgets($fs, 1160); - } - - fclose($fs); - - $response = explode("\r\n\r\n", $response, 2); - $answer = explode("\n", $response[1]); - - if(trim($answer[0]) != 'true') - { - // We got it wrong! Oh no... - $this->set_error($lang->invalid_captcha_verify); - } - } - } - } - elseif($this->type == 4) - { - $response = $mybb->input['g-recaptcha-response']; - if(!$response || strlen($response) == 0) - { - $this->set_error($lang->invalid_nocaptcha); - } - else - { - // We have a noCAPTCHA to handle - // Contact Google and see if our reCAPTCHA was successful - $response = fetch_remote_file($this->verify_server, array( - 'secret' => $mybb->settings['captchaprivatekey'], - 'remoteip' => $session->ipaddress, - 'response' => $response - )); - - if($response == false) - { - $this->set_error($lang->invalid_nocaptcha_transmit); - } - else - { - $answer = json_decode($response, true); - - if($answer['success'] != 'true') - { - // We got it wrong! Oh no... - $this->set_error($lang->invalid_nocaptcha); - } - } - } - } - - $plugins->run_hooks('captcha_validate_end', $this); - - if(count($this->errors) > 0) - { - return false; - } - else - { - return true; - } - } - - function invalidate_captcha() - { - global $db, $mybb, $plugins; - - if($this->type == 1) - { - // We have a normal CAPTCHA to handle - $imagehash = $db->escape_string($mybb->input['imagehash']); - if($imagehash) - { - $db->delete_query("captcha", "imagehash = '{$imagehash}'"); - } - } - // Not necessary for reCAPTCHA or Are You a Human - - $plugins->run_hooks('captcha_invalidate_end', $this); - } - - /** - * Add an error to the error array. - * - * @param string $error - * @param string $data - */ - function set_error($error, $data='') - { - $this->errors[$error] = array( - "error_code" => $error, - "data" => $data - ); - } - - /** - * Returns the error(s) that occurred when handling data - * in a format that MyBB can handle. - * - * @return array An array of errors in a MyBB format. - */ - function get_errors() - { - global $lang; - - $errors = array(); - foreach($this->errors as $error) - { - $lang_string = $error['error_code']; - - if(!$lang_string) - { - if($lang->invalid_captcha_verify) - { - $lang_string = 'invalid_captcha_verify'; - } - else - { - $lang_string = 'unknown_error'; - } - } - - if(!isset($lang->$lang_string)) - { - $errors[] = $error['error_code']; - continue; - } - - if(!empty($error['data']) && !is_array($error['data'])) - { - $error['data'] = array($error['data']); - } - - if(is_array($error['data'])) - { - array_unshift($error['data'], $lang->$lang_string); - $errors[] = call_user_func_array(array($lang, "sprintf"), $error['data']); - } - else - { - $errors[] = $lang->$lang_string; - } - } - - return $errors; - } - - /** - * @param array $data - * - * @return string - */ - private function _qsencode($data) - { - $req = ''; - foreach($data as $key => $value) - { - $req .= $key.'='.urlencode(stripslashes($value)).'&'; - } - - $req = substr($req, 0, (strlen($req) - 1)); - - return $req; - } -} diff --git a/html/forums/inc/class_core.php b/html/forums/inc/class_core.php deleted file mode 100644 index c5743c9..0000000 --- a/html/forums/inc/class_core.php +++ /dev/null @@ -1,625 +0,0 @@ - array( - "tid", "pid", "uid", - "eid", "pmid", "fid", - "aid", "rid", "sid", - "vid", "cid", "bid", - "hid", "gid", "mid", - "wid", "lid", "iid", - "did", "qid", "id" - ), - "pos" => array( - "page", "perpage" - ), - "a-z" => array( - "sortby", "order" - ) - ); - - /** - * Variables that are to be ignored from cleansing process - * - * @var array - */ - public $ignore_clean_variables = array(); - - /** - * Using built in shutdown functionality provided by register_shutdown_function for < PHP 5? - * - * @var bool - */ - public $use_shutdown = true; - - /** - * Debug mode? - * - * @var bool - */ - public $debug_mode = false; - - /** - * Binary database fields need to be handled differently - * - * @var array - */ - public $binary_fields = array( - 'adminlog' => array('ipaddress' => true), - 'adminsessions' => array('ip' => true), - 'maillogs' => array('ipaddress' => true), - 'moderatorlog' => array('ipaddress' => true), - 'posts' => array('ipaddress' => true), - 'privatemessages' => array('ipaddress' => true), - 'searchlog' => array('ipaddress' => true), - 'sessions' => array('ip' => true), - 'threadratings' => array('ipaddress' => true), - 'users' => array('regip' => true, 'lastip' => true), - 'spamlog' => array('ipaddress' => true), - ); - - /** - * The cache instance to use. - * - * @var datacache - */ - public $cache; - - /** - * The base URL to assets. - * - * @var string - */ - public $asset_url = null; - /** - * String input constant for use with get_input(). - * - * @see get_input - */ - const INPUT_STRING = 0; - /** - * Integer input constant for use with get_input(). - * - * @see get_input - */ - const INPUT_INT = 1; - /** - * Array input constant for use with get_input(). - * - * @see get_input - */ - const INPUT_ARRAY = 2; - /** - * Float input constant for use with get_input(). - * - * @see get_input - */ - const INPUT_FLOAT = 3; - /** - * Boolean input constant for use with get_input(). - * - * @see get_input - */ - const INPUT_BOOL = 4; - - /** - * Constructor of class. - */ - function __construct() - { - // Set up MyBB - $protected = array("_GET", "_POST", "_SERVER", "_COOKIE", "_FILES", "_ENV", "GLOBALS"); - foreach($protected as $var) - { - if(isset($_POST[$var]) || isset($_GET[$var]) || isset($_COOKIE[$var]) || isset($_FILES[$var])) - { - die("Hacking attempt"); - } - } - - if(defined("IGNORE_CLEAN_VARS")) - { - if(!is_array(IGNORE_CLEAN_VARS)) - { - $this->ignore_clean_variables = array(IGNORE_CLEAN_VARS); - } - else - { - $this->ignore_clean_variables = IGNORE_CLEAN_VARS; - } - } - - // Determine Magic Quotes Status (< PHP 6.0) - if(version_compare(PHP_VERSION, '6.0', '<')) - { - if(@get_magic_quotes_gpc()) - { - $this->magicquotes = 1; - $this->strip_slashes_array($_POST); - $this->strip_slashes_array($_GET); - $this->strip_slashes_array($_COOKIE); - } - @set_magic_quotes_runtime(0); - @ini_set("magic_quotes_gpc", 0); - @ini_set("magic_quotes_runtime", 0); - } - - // Determine input - $this->parse_incoming($_GET); - $this->parse_incoming($_POST); - - if($_SERVER['REQUEST_METHOD'] == "POST") - { - $this->request_method = "post"; - } - else if($_SERVER['REQUEST_METHOD'] == "GET") - { - $this->request_method = "get"; - } - - // If we've got register globals on, then kill them too - if(@ini_get("register_globals") == 1) - { - $this->unset_globals($_POST); - $this->unset_globals($_GET); - $this->unset_globals($_FILES); - $this->unset_globals($_COOKIE); - } - $this->clean_input(); - - $safe_mode_status = @ini_get("safe_mode"); - if($safe_mode_status == 1 || strtolower($safe_mode_status) == 'on') - { - $this->safemode = true; - } - - // Are we running on a development server? - if(isset($_SERVER['MYBB_DEV_MODE']) && $_SERVER['MYBB_DEV_MODE'] == 1) - { - $this->dev_mode = 1; - } - - // Are we running in debug mode? - if(isset($this->input['debug']) && $this->input['debug'] == 1) - { - $this->debug_mode = true; - } - - if(isset($this->input['action']) && $this->input['action'] == "mybb_logo") - { - require_once dirname(__FILE__)."/mybb_group.php"; - output_logo(); - } - - if(isset($this->input['intcheck']) && $this->input['intcheck'] == 1) - { - die("MYBB"); - } - } - - /** - * Parses the incoming variables. - * - * @param array $array The array of incoming variables. - */ - function parse_incoming($array) - { - if(!is_array($array)) - { - return; - } - - foreach($array as $key => $val) - { - $this->input[$key] = $val; - } - } - - /** - * Parses the incoming cookies - * - */ - function parse_cookies() - { - if(!is_array($_COOKIE)) - { - return; - } - - $prefix_length = strlen($this->settings['cookieprefix']); - - foreach($_COOKIE as $key => $val) - { - if($prefix_length && substr($key, 0, $prefix_length) == $this->settings['cookieprefix']) - { - $key = substr($key, $prefix_length); - - // Fixes conflicts with one board having a prefix and another that doesn't on the same domain - // Gives priority to our cookies over others (overwrites them) - if($this->cookies[$key]) - { - unset($this->cookies[$key]); - } - } - - if(empty($this->cookies[$key])) - { - $this->cookies[$key] = $val; - } - } - } - - /** - * Strips slashes out of a given array. - * - * @param array $array The array to strip. - */ - function strip_slashes_array(&$array) - { - foreach($array as $key => $val) - { - if(is_array($array[$key])) - { - $this->strip_slashes_array($array[$key]); - } - else - { - $array[$key] = stripslashes($array[$key]); - } - } - } - - /** - * Unsets globals from a specific array. - * - * @param array $array The array to unset from. - */ - function unset_globals($array) - { - if(!is_array($array)) - { - return; - } - - foreach(array_keys($array) as $key) - { - unset($GLOBALS[$key]); - unset($GLOBALS[$key]); // Double unset to circumvent the zend_hash_del_key_or_index hole in PHP <4.4.3 and <5.1.4 - } - } - - /** - * Cleans predefined input variables. - * - */ - function clean_input() - { - foreach($this->clean_variables as $type => $variables) - { - foreach($variables as $var) - { - // If this variable is in the ignored array, skip and move to next. - if(in_array($var, $this->ignore_clean_variables)) - { - continue; - } - - if(isset($this->input[$var])) - { - switch($type) - { - case "int": - $this->input[$var] = $this->get_input($var, MyBB::INPUT_INT); - break; - case "a-z": - $this->input[$var] = preg_replace("#[^a-z\.\-_]#i", "", $this->get_input($var)); - break; - case "pos": - if(($this->input[$var] < 0 && $var != "page") || ($var == "page" && $this->input[$var] != "last" && $this->input[$var] < 0)) - $this->input[$var] = 0; - break; - } - } - } - } - } - - /** - * Checks the input data type before usage. - * - * @param string $name Variable name ($mybb->input) - * @param int $type The type of the variable to get. Should be one of MyBB::INPUT_INT, MyBB::INPUT_ARRAY or MyBB::INPUT_STRING. - * - * @return int|float|array|string Checked data. Type depending on $type - */ - function get_input($name, $type = MyBB::INPUT_STRING) - { - switch($type) - { - case MyBB::INPUT_ARRAY: - if(!isset($this->input[$name]) || !is_array($this->input[$name])) - { - return array(); - } - return $this->input[$name]; - case MyBB::INPUT_INT: - if(!isset($this->input[$name]) || !is_numeric($this->input[$name])) - { - return 0; - } - return (int)$this->input[$name]; - case MyBB::INPUT_FLOAT: - if(!isset($this->input[$name]) || !is_numeric($this->input[$name])) - { - return 0.0; - } - return (float)$this->input[$name]; - case MyBB::INPUT_BOOL: - if(!isset($this->input[$name]) || !is_scalar($this->input[$name])) - { - return false; - } - return (bool)$this->input[$name]; - default: - if(!isset($this->input[$name]) || !is_scalar($this->input[$name])) - { - return ''; - } - return $this->input[$name]; - } - } - - /** - * Get the path to an asset using the CDN URL if configured. - * - * @param string $path The path to the file. - * @param bool $use_cdn Whether to use the configured CDN options. - * - * @return string The complete URL to the asset. - */ - public function get_asset_url($path = '', $use_cdn = true) - { - $path = (string) $path; - $path = ltrim($path, '/'); - - if(substr($path, 0, 4) != 'http') - { - if(substr($path, 0, 2) == './') - { - $path = substr($path, 2); - } - - if($use_cdn && $this->settings['usecdn'] && !empty($this->settings['cdnurl'])) - { - $base_path = rtrim($this->settings['cdnurl'], '/'); - } - else - { - $base_path = rtrim($this->settings['bburl'], '/'); - } - - $url = $base_path; - - if(!empty($path)) - { - $url = $base_path . '/' . $path; - } - } - else - { - $url = $path; - } - - return $url; - } - - /** - * Triggers a generic error. - * - * @param string $code The error code. - */ - function trigger_generic_error($code) - { - global $error_handler; - - switch($code) - { - case "cache_no_write": - $message = "The data cache directory (cache/) needs to exist and be writable by the web server. Change its permissions so that it is writable (777 on Unix based servers)."; - $error_code = MYBB_CACHE_NO_WRITE; - break; - case "install_directory": - $message = "The install directory (install/) still exists on your server and is not locked. To access MyBB please either remove this directory or create an empty file in it called 'lock'."; - $error_code = MYBB_INSTALL_DIR_EXISTS; - break; - case "board_not_installed": - $message = "Your board has not yet been installed and configured. Please do so before attempting to browse it."; - $error_code = MYBB_NOT_INSTALLED; - break; - case "board_not_upgraded": - $message = "Your board has not yet been upgraded. Please do so before attempting to browse it."; - $error_code = MYBB_NOT_UPGRADED; - break; - case "sql_load_error": - $message = "MyBB was unable to load the SQL extension. Please contact the MyBB Group for support. MyBB Website"; - $error_code = MYBB_SQL_LOAD_ERROR; - break; - case "apc_load_error": - $message = "APC needs to be configured with PHP to use the APC cache support."; - $error_code = MYBB_CACHEHANDLER_LOAD_ERROR; - break; - case "eaccelerator_load_error": - $message = "eAccelerator needs to be configured with PHP to use the eAccelerator cache support."; - $error_code = MYBB_CACHEHANDLER_LOAD_ERROR; - break; - case "memcache_load_error": - $message = "Your server does not have memcache support enabled."; - $error_code = MYBB_CACHEHANDLER_LOAD_ERROR; - break; - case "memcached_load_error": - $message = "Your server does not have memcached support enabled."; - $error_code = MYBB_CACHEHANDLER_LOAD_ERROR; - break; - case "xcache_load_error": - $message = "Xcache needs to be configured with PHP to use the Xcache cache support."; - $error_code = MYBB_CACHEHANDLER_LOAD_ERROR; - break; - default: - $message = "MyBB has experienced an internal error. Please contact the MyBB Group for support. MyBB Website"; - $error_code = MYBB_GENERAL; - } - $error_handler->trigger($message, $error_code); - } - - function __destruct() - { - // Run shutdown function - if(function_exists("run_shutdown")) - { - run_shutdown(); - } - } -} - -/** - * Do this here because the core is used on every MyBB page - */ - -$grouppermignore = array("gid", "type", "title", "description", "namestyle", "usertitle", "stars", "starimage", "image"); -$groupzerogreater = array("pmquota", "maxpmrecipients", "maxreputationsday", "attachquota", "maxemails", "maxwarningsday", "maxposts", "edittimelimit", "canusesigxposts", "maxreputationsperuser", "maxreputationsperthread", "emailfloodtime"); -$displaygroupfields = array("title", "description", "namestyle", "usertitle", "stars", "starimage", "image"); - -// These are fields in the usergroups table that are also forum permission specific. -$fpermfields = array( - 'canview', - 'canviewthreads', - 'candlattachments', - 'canpostthreads', - 'canpostreplys', - 'canpostattachments', - 'canratethreads', - 'caneditposts', - 'candeleteposts', - 'candeletethreads', - 'caneditattachments', - 'canviewdeletionnotice', - 'modposts', - 'modthreads', - 'modattachments', - 'mod_edit_posts', - 'canpostpolls', - 'canvotepolls', - 'cansearch' -); diff --git a/html/forums/inc/class_custommoderation.php b/html/forums/inc/class_custommoderation.php deleted file mode 100644 index 7516ef7..0000000 --- a/html/forums/inc/class_custommoderation.php +++ /dev/null @@ -1,496 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/** - * Used to execute a custom moderation tool - * - */ - -class CustomModeration extends Moderation -{ - /** - * Get info on a tool - * - * @param int $tool_id Tool ID - * @return array|bool Returns tool data (tid, type, name, description) in an array, otherwise boolean false. - */ - function tool_info($tool_id) - { - global $db; - - // Get tool info - $query = $db->simple_select("modtools", "*", 'tid="'.(int)$tool_id.'"'); - $tool = $db->fetch_array($query); - if(!$tool['tid']) - { - return false; - } - else - { - return $tool; - } - } - - /** - * Execute Custom Moderation Tool - * - * @param int $tool_id Tool ID - * @param int|array Thread ID(s) - * @param int|array Post ID(s) - * @return string 'forum' or 'default' indicating where to redirect - */ - function execute($tool_id, $tids=0, $pids=0) - { - global $db; - - // Get tool info - $query = $db->simple_select("modtools", '*', 'tid="'.(int)$tool_id.'"'); - $tool = $db->fetch_array($query); - if(!$tool['tid']) - { - return false; - } - - // Format single tid and pid - if(!is_array($tids)) - { - $tids = array($tids); - } - if(!is_array($pids)) - { - $pids = array($pids); - } - - // Unserialize custom moderation - $post_options = my_unserialize($tool['postoptions']); - $thread_options = my_unserialize($tool['threadoptions']); - - // If the tool type is a post tool, then execute the post moderation - $deleted_thread = 0; - if($tool['type'] == 'p') - { - $deleted_thread = $this->execute_post_moderation($post_options, $pids, $tids); - } - // Always execute thead moderation - $this->execute_thread_moderation($thread_options, $tids); - - // If the thread is deleted, indicate to the calling script to redirect to the forum, and not the nonexistant thread - if($thread_options['deletethread'] == 1 || $deleted_thread === 1) - { - return 'forum'; - } - return 'default'; - } - - /** - * Execute Inline Post Moderation - * - * @param array $post_options Moderation information - * @param array $pids Post IDs - * @param array|int $tid Thread IDs (in order of dateline ascending). Only the first one will be used - * @return boolean true - */ - function execute_post_moderation($post_options, $pids, $tid) - { - global $db, $mybb, $lang; - - if(is_array($tid)) - { - $tid = (int)$tid[0]; // There's only 1 thread when doing inline post moderation - // The thread chosen is the first thread in the array of tids. - // It is recommended that this be the tid of the oldest post - } - - // Get the information about thread - $thread = get_thread($tid); - - // If deleting posts, only do that - if($post_options['deleteposts'] == 1) - { - foreach($pids as $pid) - { - $this->delete_post($pid); - } - - $delete_tids = array(); - $imploded_pids = implode(",", array_map("intval", $pids)); - $query = $db->simple_select("threads", "tid", "firstpost IN ({$imploded_pids})"); - while($threadid = $db->fetch_field($query, "tid")) - { - $delete_tids[] = $threadid; - } - if(!empty($delete_tids)) - { - foreach($delete_tids as $delete_tid) - { - $this->delete_thread($delete_tid); - } - // return true here so the code in execute() above knows to redirect to the forum - return true; - } - } - else - { - if($post_options['mergeposts'] == 1) // Merge posts - { - $this->merge_posts($pids); - } - - if($post_options['approveposts'] == 'approve') // Approve posts - { - $this->approve_posts($pids); - } - elseif($post_options['approveposts'] == 'unapprove') // Unapprove posts - { - $this->unapprove_posts($pids); - } - elseif($post_options['approveposts'] == 'toggle') // Toggle post visibility - { - $this->toggle_post_visibility($pids); - } - - if($post_options['softdeleteposts'] == 'softdelete') // Soft delete posts - { - $this->soft_delete_posts($pids); - } - elseif($post_options['softdeleteposts'] == 'restore') // Restore posts - { - $this->restore_posts($pids); - } - elseif($post_options['softdeleteposts'] == 'toggle') // Toggle post visibility - { - $this->toggle_post_softdelete($pids); - } - - if($post_options['splitposts'] > 0 || $post_options['splitposts'] == -2) // Split posts - { - $query = $db->simple_select("posts", "COUNT(*) AS totalposts", "tid='{$tid}'"); - $count = $db->fetch_array($query); - - if($count['totalposts'] == 1) - { - error($lang->error_cantsplitonepost); - } - - if($count['totalposts'] == count($pids)) - { - error($lang->error_cantsplitall); - } - - if($post_options['splitposts'] == -2) - { - $post_options['splitposts'] = $thread['fid']; - } - if(empty($post_options['splitpostsnewsubject'])) - { - // Enter in a subject if a predefined one does not exist. - $post_options['splitpostsnewsubject'] = "{$lang->split_thread_subject} {$thread['subject']}"; - } - $new_subject = str_ireplace('{subject}', $thread['subject'], $post_options['splitpostsnewsubject']); - $new_tid = $this->split_posts($pids, $tid, $post_options['splitposts'], $new_subject); - if($post_options['splitpostsclose'] == 'close') // Close new thread - { - $this->close_threads($new_tid); - } - if($post_options['splitpostsstick'] == 'stick') // Stick new thread - { - $this->stick_threads($new_tid); - } - if($post_options['splitpostsunapprove'] == 'unapprove') // Unapprove new thread - { - $this->unapprove_threads($new_tid, $thread['fid']); - } - if($post_options['splitthreadprefix'] != '0') - { - $this->apply_thread_prefix($new_tid, $post_options['splitthreadprefix']); // Add thread prefix to new thread - } - if(!empty($post_options['splitpostsaddreply'])) // Add reply to new thread - { - require_once MYBB_ROOT."inc/datahandlers/post.php"; - $posthandler = new PostDataHandler("insert"); - - if(empty($post_options['splitpostsreplysubject'])) - { - $post_options['splitpostsreplysubject'] = 'RE: '.$new_subject; - } - else - { - $post_options['splitpostsreplysubject'] = str_ireplace('{username}', $mybb->user['username'], $post_options['splitpostsreplysubject']); - $post_options['splitpostsreplysubject'] = str_ireplace('{subject}', $new_subject, $post_options['splitpostsreplysubject']); - } - - // Set the post data that came from the input to the $post array. - $post = array( - "tid" => $new_tid, - "fid" => $post_options['splitposts'], - "subject" => $post_options['splitpostsreplysubject'], - "uid" => $mybb->user['uid'], - "username" => $mybb->user['username'], - "message" => $post_options['splitpostsaddreply'], - "ipaddress" => my_inet_pton(get_ip()), - ); - // Set up the post options from the input. - $post['options'] = array( - "signature" => 1, - "emailnotify" => 0, - "disablesmilies" => 0 - ); - - $posthandler->set_data($post); - - if($posthandler->validate_post($post)) - { - $posthandler->insert_post($post); - } - } - } - } - return true; - } - - /** - * Execute Normal and Inline Thread Moderation - * - * @param array $thread_options Moderation information - * @param array Thread IDs. Only the first one will be used, but it needs to be an array - * @return boolean true - */ - function execute_thread_moderation($thread_options, $tids) - { - global $db, $mybb; - - $tid = (int)$tids[0]; // Take the first thread to get thread data from - $query = $db->simple_select("threads", 'fid', "tid='$tid'"); - $thread = $db->fetch_array($query); - - // If deleting threads, only do that - if($thread_options['deletethread'] == 1) - { - foreach($tids as $tid) - { - $this->delete_thread($tid); - } - } - else - { - if($thread_options['mergethreads'] == 1 && count($tids) > 1) // Merge Threads (ugly temp code until find better fix) - { - $tid_list = implode(',', $tids); - $options = array('order_by' => 'dateline', 'order_dir' => 'DESC'); - $query = $db->simple_select("threads", 'tid, subject', "tid IN ($tid_list)", $options); // Select threads from newest to oldest - $last_tid = 0; - while($tid = $db->fetch_array($query)) - { - if($last_tid != 0) - { - $this->merge_threads($last_tid, $tid['tid'], $tid['subject']); // And keep merging them until we get down to one thread. - } - $last_tid = $tid['tid']; - } - } - if($thread_options['deletepoll'] == 1) // Delete poll - { - foreach($tids as $tid) - { - $this->delete_poll($tid); - } - } - if($thread_options['removeredirects'] == 1) // Remove redirects - { - foreach($tids as $tid) - { - $this->remove_redirects($tid); - } - } - - if($thread_options['removesubscriptions'] == 1) // Remove thread subscriptions - { - $this->remove_thread_subscriptions($tids, true); - } - - if($thread_options['approvethread'] == 'approve') // Approve thread - { - $this->approve_threads($tids, $thread['fid']); - } - elseif($thread_options['approvethread'] == 'unapprove') // Unapprove thread - { - $this->unapprove_threads($tids, $thread['fid']); - } - elseif($thread_options['approvethread'] == 'toggle') // Toggle thread visibility - { - $this->toggle_thread_visibility($tids, $thread['fid']); - } - - if($thread_options['softdeletethread'] == 'softdelete') // Soft delete thread - { - $this->soft_delete_threads($tids); - } - elseif($thread_options['softdeletethread'] == 'restore') // Restore thread - { - $this->restore_threads($tids); - } - elseif($thread_options['softdeletethread'] == 'toggle') // Toggle thread visibility - { - $this->toggle_thread_softdelete($tids); - } - - if($thread_options['openthread'] == 'open') // Open thread - { - $this->open_threads($tids); - } - elseif($thread_options['openthread'] == 'close') // Close thread - { - $this->close_threads($tids); - } - elseif($thread_options['openthread'] == 'toggle') // Toggle thread visibility - { - $this->toggle_thread_status($tids); - } - - if($thread_options['stickthread'] == 'stick') // Stick thread - { - $this->stick_threads($tids); - } - elseif($thread_options['stickthread'] == 'unstick') // Unstick thread - { - $this->unstick_threads($tids); - } - elseif($thread_options['stickthread'] == 'toggle') // Toggle thread importance - { - $this->toggle_thread_importance($tids); - } - - if($thread_options['threadprefix'] != '-1') - { - $this->apply_thread_prefix($tids, $thread_options['threadprefix']); // Update thread prefix - } - - if(my_strtolower(trim($thread_options['newsubject'])) != '{subject}') // Update thread subjects - { - $this->change_thread_subject($tids, $thread_options['newsubject']); - } - if(!empty($thread_options['addreply'])) // Add reply to thread - { - $tid_list = implode(',', $tids); - $query = $db->simple_select("threads", 'uid, fid, subject, tid, firstpost, closed', "tid IN ($tid_list) AND closed NOT LIKE 'moved|%'"); - require_once MYBB_ROOT."inc/datahandlers/post.php"; - - // Loop threads adding a reply to each one - while($thread = $db->fetch_array($query)) - { - $posthandler = new PostDataHandler("insert"); - - if(empty($thread_options['replysubject'])) - { - $new_subject = 'RE: '.$thread['subject']; - } - else - { - $new_subject = str_ireplace('{username}', $mybb->user['username'], $thread_options['replysubject']); - $new_subject = str_ireplace('{subject}', $thread['subject'], $new_subject); - } - - // Set the post data that came from the input to the $post array. - $post = array( - "tid" => $thread['tid'], - "replyto" => $thread['firstpost'], - "fid" => $thread['fid'], - "subject" => $new_subject, - "uid" => $mybb->user['uid'], - "username" => $mybb->user['username'], - "message" => $thread_options['addreply'], - "ipaddress" => my_inet_pton(get_ip()), - ); - - // Set up the post options from the input. - $post['options'] = array( - "signature" => 1, - "emailnotify" => 0, - "disablesmilies" => 0 - ); - - if($thread['closed'] == 1) - { - // Keep this thread closed - $post['modoptions']['closethread'] = 1; - } - - $posthandler->set_data($post); - if($posthandler->validate_post($post)) - { - $posthandler->insert_post($post); - } - } - } - if($thread_options['movethread'] > 0 && $thread_options['movethread'] != $thread['fid']) // Move thread - { - if($thread_options['movethreadredirect'] == 1) // Move Thread with redirect - { - $time = TIME_NOW + ($thread_options['movethreadredirectexpire'] * 86400); - foreach($tids as $tid) - { - $this->move_thread($tid, $thread_options['movethread'], 'redirect', $time); - } - } - else // Normal move - { - $this->move_threads($tids, $thread_options['movethread']); - } - } - if($thread_options['copythread'] > 0 || $thread_options['copythread'] == -2) // Copy thread - { - if($thread_options['copythread'] == -2) - { - $thread_options['copythread'] = $thread['fid']; - } - foreach($tids as $tid) - { - $new_tid = $this->move_thread($tid, $thread_options['copythread'], 'copy'); - } - } - if(!empty($thread_options['recountrebuild'])) - { - require_once MYBB_ROOT.'/inc/functions_rebuild.php'; - - foreach($tids as $tid) - { - rebuild_thread_counters($tid); - } - } - } - - // Do we have a PM subject and PM message? - if(isset($thread_options['pm_subject']) && $thread_options['pm_subject'] != '' && isset($thread_options['pm_message']) && $thread_options['pm_message'] != '') - { - $tid_list = implode(',', $tids); - - // For each thread, we send a PM to the author - $query = $db->simple_select("threads", 'uid', "tid IN ($tid_list)"); - while($uid = $db->fetch_field($query, 'uid')) - { - // Let's send our PM - $pm = array( - 'subject' => $thread_options['pm_subject'], - 'message' => $thread_options['pm_message'], - 'touid' => $uid - ); - send_pm($pm, $mybb->user['uid'], 1); - } - } - - return true; - } -} diff --git a/html/forums/inc/class_datacache.php b/html/forums/inc/class_datacache.php deleted file mode 100644 index 074eb51..0000000 --- a/html/forums/inc/class_datacache.php +++ /dev/null @@ -1,1338 +0,0 @@ -config['cache_store']) - { - // Disk cache - case "files": - require_once MYBB_ROOT."/inc/cachehandlers/disk.php"; - $this->handler = new diskCacheHandler(); - break; - // Memcache cache - case "memcache": - require_once MYBB_ROOT."/inc/cachehandlers/memcache.php"; - $this->handler = new memcacheCacheHandler(); - break; - // Memcached cache - case "memcached": - require_once MYBB_ROOT."/inc/cachehandlers/memcached.php"; - $this->handler = new memcachedCacheHandler(); - break; - // eAccelerator cache - case "eaccelerator": - require_once MYBB_ROOT."/inc/cachehandlers/eaccelerator.php"; - $this->handler = new eacceleratorCacheHandler(); - break; - // Xcache cache - case "xcache": - require_once MYBB_ROOT."/inc/cachehandlers/xcache.php"; - $this->handler = new xcacheCacheHandler(); - break; - // APC cache - case "apc": - require_once MYBB_ROOT."/inc/cachehandlers/apc.php"; - $this->handler = new apcCacheHandler(); - break; - } - - if($this->handler instanceof CacheHandlerInterface) - { - if(!$this->handler->connect()) - { - $this->handler = null; - } - } - else - { - // Database cache - $query = $db->simple_select("datacache", "title,cache"); - while($data = $db->fetch_array($query)) - { - $this->cache[$data['title']] = unserialize($data['cache']); - } - } - } - - /** - * Read cache from files or db. - * - * @param string $name The cache component to read. - * @param boolean $hard If true, cannot be overwritten during script execution. - * @return mixed - */ - function read($name, $hard=false) - { - global $db, $mybb; - - // Already have this cache and we're not doing a hard refresh? Return cached copy - if(isset($this->cache[$name]) && $hard == false) - { - return $this->cache[$name]; - } - // If we're not hard refreshing, and this cache doesn't exist, return false - // It would have been loaded pre-global if it did exist anyway... - else if($hard == false && !($this->handler instanceof CacheHandlerInterface)) - { - return false; - } - - if($this->handler instanceof CacheHandlerInterface) - { - get_execution_time(); - - $data = $this->handler->fetch($name); - - $call_time = get_execution_time(); - $this->call_time += $call_time; - $this->call_count++; - - if($mybb->debug_mode) - { - $hit = true; - if($data === false) - { - $hit = false; - } - $this->debug_call('read:'.$name, $call_time, $hit); - } - - // No data returned - cache gone bad? - if($data === false) - { - // Fetch from database - $query = $db->simple_select("datacache", "title,cache", "title='".$db->escape_string($name)."'"); - $cache_data = $db->fetch_array($query); - $data = unserialize($cache_data['cache']); - - // Update cache for handler - get_execution_time(); - - $hit = $this->handler->put($name, $data); - - $call_time = get_execution_time(); - $this->call_time += $call_time; - $this->call_count++; - - if($mybb->debug_mode) - { - $this->debug_call('set:'.$name, $call_time, $hit); - } - } - } - // Else, using internal database cache - else - { - $query = $db->simple_select("datacache", "title,cache", "title='$name'"); - $cache_data = $db->fetch_array($query); - - if(!$cache_data['title']) - { - $data = false; - } - else - { - $data = unserialize($cache_data['cache']); - } - } - - // Cache locally - $this->cache[$name] = $data; - - if($data !== false) - { - return $data; - } - else - { - return false; - } - } - - /** - * Update cache contents. - * - * @param string $name The cache content identifier. - * @param string $contents The cache content. - */ - function update($name, $contents) - { - global $db, $mybb; - - $this->cache[$name] = $contents; - - // We ALWAYS keep a running copy in the db just incase we need it - $dbcontents = $db->escape_string(serialize($contents)); - - $replace_array = array( - "title" => $db->escape_string($name), - "cache" => $dbcontents - ); - $db->replace_query("datacache", $replace_array, "", false); - - // Do we have a cache handler we're using? - if($this->handler instanceof CacheHandlerInterface) - { - get_execution_time(); - - $hit = $this->handler->put($name, $contents); - - $call_time = get_execution_time(); - $this->call_time += $call_time; - $this->call_count++; - - if($mybb->debug_mode) - { - $this->debug_call('update:'.$name, $call_time, $hit); - } - } - } - - /** - * Delete cache contents. - * Originally from frostschutz's PluginLibrary - * github.com/frostschutz - * - * @param string $name Cache name or title - * @param boolean $greedy To delete a cache starting with name_ - */ - function delete($name, $greedy = false) - { - global $db, $mybb, $cache; - - // Prepare for database query. - $dbname = $db->escape_string($name); - $where = "title = '{$dbname}'"; - - // Delete on-demand or handler cache - if($this->handler instanceof CacheHandlerInterface) - { - get_execution_time(); - - $hit = $this->handler->delete($name); - - $call_time = get_execution_time(); - $this->call_time += $call_time; - $this->call_count++; - - if($mybb->debug_mode) - { - $this->debug_call('delete:'.$name, $call_time, $hit); - } - } - - // Greedy? - if($greedy) - { - $name .= '_'; - $names = array(); - $keys = array_keys($cache->cache); - - foreach($keys as $key) - { - if(strpos($key, $name) === 0) - { - $names[$key] = 0; - } - } - - $ldbname = strtr($dbname, - array( - '%' => '=%', - '=' => '==', - '_' => '=_' - ) - ); - - $where .= " OR title LIKE '{$ldbname}=_%' ESCAPE '='"; - - if($this->handler instanceof CacheHandlerInterface) - { - $query = $db->simple_select("datacache", "title", $where); - - while($row = $db->fetch_array($query)) - { - $names[$row['title']] = 0; - } - - // ...from the filesystem... - $start = strlen(MYBB_ROOT."cache/"); - foreach((array)@glob(MYBB_ROOT."cache/{$name}*.php") as $filename) - { - if($filename) - { - $filename = substr($filename, $start, strlen($filename)-4-$start); - $names[$filename] = 0; - } - } - - foreach($names as $key => $val) - { - get_execution_time(); - - $hit = $this->handler->delete($key); - - $call_time = get_execution_time(); - $this->call_time += $call_time; - $this->call_count++; - - if($mybb->debug_mode) - { - $this->debug_call('delete:'.$name, $call_time, $hit); - } - } - } - } - - // Delete database cache - $db->delete_query("datacache", $where); - } - - /** - * Debug a cache call to a non-database cache handler - * - * @param string $string The cache key - * @param string $qtime The time it took to perform the call. - * @param boolean $hit Hit or miss status - */ - function debug_call($string, $qtime, $hit) - { - global $mybb, $plugins; - - $debug_extra = ''; - if($plugins->current_hook) - { - $debug_extra = "
    (Plugin Hook: {$plugins->current_hook})
    "; - } - - if($hit) - { - $hit_status = 'HIT'; - } - else - { - $hit_status = 'MISS'; - } - - $cache_data = explode(':', $string); - $cache_method = $cache_data[0]; - $cache_key = $cache_data[1]; - - $this->cache_debug = " - - - - - - - - - -
    {$debug_extra}
    #{$this->call_count} - ".ucfirst($cache_method)." Call
    ({$mybb->config['cache_store']}) [{$hit_status}] ".htmlspecialchars_uni($cache_key)."
    Call Time: ".format_time_duration($qtime)."
    -
    \n"; - - $this->calllist[$this->call_count]['key'] = $string; - $this->calllist[$this->call_count]['time'] = $qtime; - } - - /** - * Select the size of the cache - * - * @param string $name The name of the cache - * @return integer the size of the cache - */ - function size_of($name='') - { - global $db; - - if($this->handler instanceof CacheHandlerInterface) - { - $size = $this->handler->size_of($name); - if(!$size) - { - if($name) - { - $query = $db->simple_select("datacache", "cache", "title='{$name}'"); - return strlen($db->fetch_field($query, "cache")); - } - else - { - return $db->fetch_size("datacache"); - } - } - else - { - return $size; - } - } - // Using MySQL as cache - else - { - if($name) - { - $query = $db->simple_select("datacache", "cache", "title='{$name}'"); - return strlen($db->fetch_field($query, "cache")); - } - else - { - return $db->fetch_size("datacache"); - } - } - } - - /** - * Update the MyBB version in the cache. - * - */ - function update_version() - { - global $mybb; - - $version = array( - "version" => $mybb->version, - "version_code" => $mybb->version_code - ); - - $this->update("version", $version); - } - - /** - * Update the attachment type cache. - * - */ - function update_attachtypes() - { - global $db; - - $types = array(); - - $query = $db->simple_select('attachtypes', '*', 'enabled=1'); - while($type = $db->fetch_array($query)) - { - $type['extension'] = my_strtolower($type['extension']); - $types[$type['extension']] = $type; - } - - $this->update("attachtypes", $types); - } - - /** - * Update the smilies cache. - * - */ - function update_smilies() - { - global $db; - - $smilies = array(); - - $query = $db->simple_select("smilies", "*", "", array('order_by' => 'disporder', 'order_dir' => 'ASC')); - while($smilie = $db->fetch_array($query)) - { - $smilies[$smilie['sid']] = $smilie; - } - - $this->update("smilies", $smilies); - } - - /** - * Update the posticon cache. - * - */ - function update_posticons() - { - global $db; - - $icons = array(); - - $query = $db->simple_select("icons", "iid, name, path"); - while($icon = $db->fetch_array($query)) - { - $icons[$icon['iid']] = $icon; - } - - $this->update("posticons", $icons); - } - - /** - * Update the badwords cache. - * - */ - function update_badwords() - { - global $db; - - $badwords = array(); - - $query = $db->simple_select("badwords", "*"); - while($badword = $db->fetch_array($query)) - { - $badwords[$badword['bid']] = $badword; - } - - $this->update("badwords", $badwords); - } - - /** - * Update the usergroups cache. - * - */ - function update_usergroups() - { - global $db; - - $query = $db->simple_select("usergroups"); - - $gs = array(); - while($g = $db->fetch_array($query)) - { - $gs[$g['gid']] = $g; - } - - $this->update("usergroups", $gs); - } - - /** - * Update the forum permissions cache. - * - * @return bool When failed, returns false. - */ - function update_forumpermissions() - { - global $forum_cache, $db; - - $this->built_forum_permissions = array(0); - - // Get our forum list - cache_forums(true); - if(!is_array($forum_cache)) - { - return false; - } - - reset($forum_cache); - $fcache = array(); - - // Resort in to the structure we require - foreach($forum_cache as $fid => $forum) - { - $this->forum_permissions_forum_cache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; - } - - // Sort children - foreach($fcache as $pid => $value) - { - ksort($fcache[$pid]); - } - ksort($fcache); - - // Fetch forum permissions from the database - $query = $db->simple_select("forumpermissions"); - while($forum_permission = $db->fetch_array($query)) - { - $this->forum_permissions[$forum_permission['fid']][$forum_permission['gid']] = $forum_permission; - } - - $this->build_forum_permissions(); - $this->update("forumpermissions", $this->built_forum_permissions); - - return true; - } - - /** - * Build the forum permissions array - * - * @access private - * @param array $permissions An optional permissions array. - * @param int $pid An optional permission id. - */ - private function build_forum_permissions($permissions=array(), $pid=0) - { - $usergroups = array_keys($this->read("usergroups", true)); - if($this->forum_permissions_forum_cache[$pid]) - { - foreach($this->forum_permissions_forum_cache[$pid] as $main) - { - foreach($main as $forum) - { - $perms = $permissions; - foreach($usergroups as $gid) - { - if($this->forum_permissions[$forum['fid']][$gid]) - { - $perms[$gid] = $this->forum_permissions[$forum['fid']][$gid]; - } - if($perms[$gid]) - { - $perms[$gid]['fid'] = $forum['fid']; - $this->built_forum_permissions[$forum['fid']][$gid] = $perms[$gid]; - } - } - $this->build_forum_permissions($perms, $forum['fid']); - } - } - } - } - - /** - * Update the stats cache (kept for the sake of being able to rebuild this cache via the cache interface) - * - */ - function update_stats() - { - require_once MYBB_ROOT."inc/functions_rebuild.php"; - rebuild_stats(); - } - - /** - * Update the statistics cache - * - */ - function update_statistics() - { - global $db; - - $query = $db->simple_select('users', 'uid, username, referrals', 'referrals>0', array('order_by' => 'referrals', 'order_dir' => 'DESC', 'limit' => 1)); - $topreferrer = $db->fetch_array($query); - - $timesearch = TIME_NOW - 86400; - switch($db->type) - { - case 'pgsql': - $group_by = $db->build_fields_string('users', 'u.'); - break; - default: - $group_by = 'p.uid'; - break; - } - - $query = $db->query(' - SELECT u.uid, u.username, COUNT(pid) AS poststoday - FROM '.TABLE_PREFIX.'posts p - LEFT JOIN '.TABLE_PREFIX.'users u ON (p.uid=u.uid) - WHERE p.dateline>'.$timesearch.' - GROUP BY '.$group_by.' ORDER BY poststoday DESC - LIMIT 1 - '); - $topposter = $db->fetch_array($query); - - $query = $db->simple_select('users', 'COUNT(uid) AS posters', 'postnum>0'); - $posters = $db->fetch_field($query, 'posters'); - - $statistics = array( - 'time' => TIME_NOW, - 'top_referrer' => (array)$topreferrer, - 'top_poster' => (array)$topposter, - 'posters' => $posters - ); - - $this->update('statistics', $statistics); - } - - /** - * Update the moderators cache. - * - * @return bool Returns false on failure - */ - function update_moderators() - { - global $forum_cache, $db; - - $this->built_moderators = array(0); - - // Get our forum list - cache_forums(true); - if(!is_array($forum_cache)) - { - return false; - } - - reset($forum_cache); - $fcache = array(); - - // Resort in to the structure we require - foreach($forum_cache as $fid => $forum) - { - $this->moderators_forum_cache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; - } - - // Sort children - foreach($fcache as $pid => $value) - { - ksort($fcache[$pid]); - } - ksort($fcache); - - $this->moderators = array(); - - // Fetch moderators from the database - $query = $db->query(" - SELECT m.*, u.username, u.usergroup, u.displaygroup - FROM ".TABLE_PREFIX."moderators m - LEFT JOIN ".TABLE_PREFIX."users u ON (m.id=u.uid) - WHERE m.isgroup = '0' - ORDER BY u.username - "); - while($moderator = $db->fetch_array($query)) - { - $this->moderators[$moderator['fid']]['users'][$moderator['id']] = $moderator; - } - - if(!function_exists("sort_moderators_by_usernames")) - { - function sort_moderators_by_usernames($a, $b) - { - return strcasecmp($a['username'], $b['username']); - } - } - - //Fetch moderating usergroups from the database - $query = $db->query(" - SELECT m.*, u.title - FROM ".TABLE_PREFIX."moderators m - LEFT JOIN ".TABLE_PREFIX."usergroups u ON (m.id=u.gid) - WHERE m.isgroup = '1' - ORDER BY u.title - "); - while($moderator = $db->fetch_array($query)) - { - $this->moderators[$moderator['fid']]['usergroups'][$moderator['id']] = $moderator; - } - - if(is_array($this->moderators)) - { - foreach(array_keys($this->moderators) as $fid) - { - uasort($this->moderators[$fid], 'sort_moderators_by_usernames'); - } - } - - $this->build_moderators(); - - $this->update("moderators", $this->built_moderators); - - return true; - } - - /** - * Update the users awaiting activation cache. - * - */ - function update_awaitingactivation() - { - global $db; - - $query = $db->simple_select('users', 'COUNT(uid) AS awaitingusers', 'usergroup=\'5\''); - $awaitingusers = (int)$db->fetch_field($query, 'awaitingusers'); - - $data = array( - 'users' => $awaitingusers, - 'time' => TIME_NOW - ); - - $this->update('awaitingactivation', $data); - } - - /** - * Build the moderators array - * - * @access private - * @param array $moderators An optional moderators array (moderators of the parent forum for example). - * @param int $pid An optional parent ID. - */ - private function build_moderators($moderators=array(), $pid=0) - { - if(isset($this->moderators_forum_cache[$pid])) - { - foreach($this->moderators_forum_cache[$pid] as $main) - { - foreach($main as $forum) - { - $forum_mods = ''; - if(count($moderators)) - { - $forum_mods = $moderators; - } - // Append - local settings override that of a parent - array_merge works here - if(isset($this->moderators[$forum['fid']])) - { - if(is_array($forum_mods) && count($forum_mods)) - { - $forum_mods = array_merge($forum_mods, $this->moderators[$forum['fid']]); - } - else - { - $forum_mods = $this->moderators[$forum['fid']]; - } - } - $this->built_moderators[$forum['fid']] = $forum_mods; - $this->build_moderators($forum_mods, $forum['fid']); - } - } - } - } - - /** - * Update the forums cache. - * - */ - function update_forums() - { - global $db; - - $forums = array(); - - // Things we don't want to cache - $exclude = array("unapprovedthreads", "unapprovedposts", "threads", "posts", "lastpost", "lastposter", "lastposttid", "lastposteruid", "lastpostsubject", "deletedthreads", "deletedposts"); - - $query = $db->simple_select("forums", "*", "", array('order_by' => 'pid,disporder')); - while($forum = $db->fetch_array($query)) - { - foreach($forum as $key => $val) - { - if(in_array($key, $exclude)) - { - unset($forum[$key]); - } - } - $forums[$forum['fid']] = $forum; - } - - $this->update("forums", $forums); - } - - /** - * Update usertitles cache. - * - */ - function update_usertitles() - { - global $db; - - $usertitles = array(); - $query = $db->simple_select("usertitles", "utid, posts, title, stars, starimage", "", array('order_by' => 'posts', 'order_dir' => 'DESC')); - while($usertitle = $db->fetch_array($query)) - { - $usertitles[] = $usertitle; - } - - $this->update("usertitles", $usertitles); - } - - /** - * Update reported content cache. - * - */ - function update_reportedcontent() - { - global $db, $mybb; - - $query = $db->simple_select("reportedcontent", "COUNT(rid) AS unreadcount", "reportstatus='0'"); - $num = $db->fetch_array($query); - - $query = $db->simple_select("reportedcontent", "COUNT(rid) AS reportcount"); - $total = $db->fetch_array($query); - - $query = $db->simple_select("reportedcontent", "dateline", "reportstatus='0'", array('order_by' => 'dateline', 'order_dir' => 'DESC')); - $latest = $db->fetch_array($query); - - $reports = array( - "unread" => $num['unreadcount'], - "total" => $total['reportcount'], - "lastdateline" => $latest['dateline'] - ); - - $this->update("reportedcontent", $reports); - } - - /** - * Update mycode cache. - * - */ - function update_mycode() - { - global $db; - - $mycodes = array(); - $query = $db->simple_select("mycode", "regex, replacement", "active=1", array('order_by' => 'parseorder')); - while($mycode = $db->fetch_array($query)) - { - $mycodes[] = $mycode; - } - - $this->update("mycode", $mycodes); - } - - /** - * Update the mailqueue cache - * - * @param int $last_run - * @param int $lock_time - */ - function update_mailqueue($last_run=0, $lock_time=0) - { - global $db; - - $query = $db->simple_select("mailqueue", "COUNT(*) AS queue_size"); - $queue_size = $db->fetch_field($query, "queue_size"); - - $mailqueue = $this->read("mailqueue"); - if(!is_array($mailqueue)) - { - $mailqueue = array(); - } - $mailqueue['queue_size'] = $queue_size; - if($last_run > 0) - { - $mailqueue['last_run'] = $last_run; - } - $mailqueue['locked'] = $lock_time; - - $this->update("mailqueue", $mailqueue); - } - - /** - * Update update_check cache (dummy function used by upgrade/install scripts) - */ - function update_update_check() - { - $update_cache = array( - "dateline" => TIME_NOW - ); - - $this->update("update_check", $update_cache); - } - - /** - * Update default_theme cache - */ - function update_default_theme() - { - global $db; - - $query = $db->simple_select("themes", "name, tid, properties, stylesheets", "def='1'", array('limit' => 1)); - $theme = $db->fetch_array($query); - $this->update("default_theme", $theme); - } - - /** - * Updates the tasks cache saving the next run time - */ - function update_tasks() - { - global $db; - - $query = $db->simple_select("tasks", "nextrun", "enabled=1", array("order_by" => "nextrun", "order_dir" => "asc", "limit" => 1)); - $next_task = $db->fetch_array($query); - - $task_cache = $this->read("tasks"); - if(!is_array($task_cache)) - { - $task_cache = array(); - } - $task_cache['nextrun'] = $next_task['nextrun']; - - if(!$task_cache['nextrun']) - { - $task_cache['nextrun'] = TIME_NOW+3600; - } - - $this->update("tasks", $task_cache); - } - - /** - * Updates the banned IPs cache - */ - function update_bannedips() - { - global $db; - - $banned_ips = array(); - $query = $db->simple_select("banfilters", "fid,filter", "type=1"); - while($banned_ip = $db->fetch_array($query)) - { - $banned_ips[$banned_ip['fid']] = $banned_ip; - } - $this->update("bannedips", $banned_ips); - } - - /** - * Updates the banned emails cache - */ - function update_bannedemails() - { - global $db; - - $banned_emails = array(); - $query = $db->simple_select("banfilters", "fid, filter", "type = '3'"); - - while($banned_email = $db->fetch_array($query)) - { - $banned_emails[$banned_email['fid']] = $banned_email; - } - - $this->update("bannedemails", $banned_emails); - } - - /** - * Updates the search engine spiders cache - */ - function update_spiders() - { - global $db; - - $spiders = array(); - $query = $db->simple_select("spiders", "sid, name, useragent, usergroup", "", array("order_by" => "LENGTH(useragent)", "order_dir" => "DESC")); - while($spider = $db->fetch_array($query)) - { - $spiders[$spider['sid']] = $spider; - } - $this->update("spiders", $spiders); - } - - function update_most_replied_threads() - { - global $db, $mybb; - - $threads = array(); - - $query = $db->simple_select("threads", "tid, subject, replies, fid, uid", "visible='1'", array('order_by' => 'replies', 'order_dir' => 'DESC', 'limit_start' => 0, 'limit' => $mybb->settings['statslimit'])); - while($thread = $db->fetch_array($query)) - { - $threads[] = $thread; - } - - $this->update("most_replied_threads", $threads); - } - - function update_most_viewed_threads() - { - global $db, $mybb; - - $threads = array(); - - $query = $db->simple_select("threads", "tid, subject, views, fid, uid", "visible='1'", array('order_by' => 'views', 'order_dir' => 'DESC', 'limit_start' => 0, 'limit' => $mybb->settings['statslimit'])); - while($thread = $db->fetch_array($query)) - { - $threads[] = $thread; - } - - $this->update("most_viewed_threads", $threads); - } - - function update_banned() - { - global $db; - - $bans = array(); - - $query = $db->simple_select("banned"); - while($ban = $db->fetch_array($query)) - { - $bans[$ban['uid']] = $ban; - } - - $this->update("banned", $bans); - } - - function update_birthdays() - { - global $db; - - $birthdays = array(); - - // Get today, yesterday, and tomorrow's time (for different timezones) - $bdaytime = TIME_NOW; - $bdaydate = my_date("j-n", $bdaytime, '', 0); - $bdaydatetomorrow = my_date("j-n", ($bdaytime+86400), '', 0); - $bdaydateyesterday = my_date("j-n", ($bdaytime-86400), '', 0); - - $query = $db->simple_select("users", "uid, username, usergroup, displaygroup, birthday, birthdayprivacy", "birthday LIKE '$bdaydate-%' OR birthday LIKE '$bdaydateyesterday-%' OR birthday LIKE '$bdaydatetomorrow-%'"); - while($bday = $db->fetch_array($query)) - { - // Pop off the year from the birthday because we don't need it. - $bday['bday'] = explode('-', $bday['birthday']); - array_pop($bday['bday']); - $bday['bday'] = implode('-', $bday['bday']); - - if($bday['birthdayprivacy'] != 'all') - { - ++$birthdays[$bday['bday']]['hiddencount']; - continue; - } - - // We don't need any excess caleries in the cache - unset($bday['birthdayprivacy']); - - $birthdays[$bday['bday']]['users'][] = $bday; - } - - $this->update("birthdays", $birthdays); - } - - function update_groupleaders() - { - global $db; - - $groupleaders = array(); - - $query = $db->simple_select("groupleaders"); - while($groupleader = $db->fetch_array($query)) - { - $groupleaders[$groupleader['uid']][] = $groupleader; - } - - $this->update("groupleaders", $groupleaders); - } - - function update_threadprefixes() - { - global $db; - - $prefixes = array(); - $query = $db->simple_select("threadprefixes", "*", "", array('order_by' => 'prefix', 'order_dir' => 'ASC')); - - while($prefix = $db->fetch_array($query)) - { - $prefixes[$prefix['pid']] = $prefix; - } - - $this->update("threadprefixes", $prefixes); - } - - function update_forumsdisplay() - { - global $db; - - $fd_statistics = array(); - - $time = TIME_NOW; // Look for announcements that don't end, or that are ending some time in the future - $query = $db->simple_select("announcements", "fid", "enddate = '0' OR enddate > '{$time}'", array("order_by" => "aid")); - - if($db->num_rows($query)) - { - while($forum = $db->fetch_array($query)) - { - if(!isset($fd_statistics[$forum['fid']]['announcements'])) - { - $fd_statistics[$forum['fid']]['announcements'] = 1; - } - } - } - - // Do we have any mod tools to use in our forums? - $query = $db->simple_select("modtools", "forums, tid", '', array("order_by" => "tid")); - - if($db->num_rows($query)) - { - unset($forum); - while($tool = $db->fetch_array($query)) - { - $forums = explode(",", $tool['forums']); - - foreach($forums as $forum) - { - if(!$forum) - { - $forum = -1; - } - - if(!isset($fd_statistics[$forum]['modtools'])) - { - $fd_statistics[$forum]['modtools'] = 1; - } - } - } - } - - $this->update("forumsdisplay", $fd_statistics); - } - - /** - * Update profile fields cache. - * - */ - function update_profilefields() - { - global $db; - - $fields = array(); - $query = $db->simple_select("profilefields", "*", "", array('order_by' => 'disporder')); - while($field = $db->fetch_array($query)) - { - $fields[] = $field; - } - - $this->update("profilefields", $fields); - } - - /** - * Update the report reasons cache. - * - */ - function update_reportreasons($no_plugins = false) - { - global $db; - - $content_types = array('post', 'profile', 'reputation'); - if(!$no_plugins) - { - global $plugins; - $content_types = $plugins->run_hooks("report_content_types", $content_types); - } - - $reasons = array(); - - $query = $db->simple_select("reportreasons", "*", "", array('order_by' => 'disporder')); - while($reason = $db->fetch_array($query)) - { - if($reason['appliesto'] == 'all') - { - foreach($content_types as $content) - { - $reasons[$content][] = array( - 'rid' => $reason['rid'], - 'title' => $reason['title'], - 'extra' => $reason['extra'], - ); - } - } - elseif($reason['appliesto'] != '') - { - $appliesto = explode(",", $reason['appliesto']); - foreach($appliesto as $content) - { - $reasons[$content][] = array( - 'rid' => $reason['rid'], - 'title' => $reason['title'], - 'extra' => $reason['extra'], - ); - } - } - } - - $this->update("reportreasons", $reasons); - } - - /* Other, extra functions for reloading caches if we just changed to another cache extension (i.e. from db -> xcache) */ - function reload_mostonline() - { - global $db; - - $query = $db->simple_select("datacache", "title,cache", "title='mostonline'"); - $this->update("mostonline", unserialize($db->fetch_field($query, "cache"))); - } - - function reload_plugins() - { - global $db; - - $query = $db->simple_select("datacache", "title,cache", "title='plugins'"); - $this->update("plugins", unserialize($db->fetch_field($query, "cache"))); - } - - function reload_last_backup() - { - global $db; - - $query = $db->simple_select("datacache", "title,cache", "title='last_backup'"); - $this->update("last_backup", unserialize($db->fetch_field($query, "cache"))); - } - - function reload_internal_settings() - { - global $db; - - $query = $db->simple_select("datacache", "title,cache", "title='internal_settings'"); - $this->update("internal_settings", unserialize($db->fetch_field($query, "cache"))); - } - - function reload_version_history() - { - global $db; - - $query = $db->simple_select("datacache", "title,cache", "title='version_history'"); - $this->update("version_history", unserialize($db->fetch_field($query, "cache"))); - } - - function reload_modnotes() - { - global $db; - - $query = $db->simple_select("datacache", "title,cache", "title='modnotes'"); - $this->update("modnotes", unserialize($db->fetch_field($query, "cache"))); - } - - function reload_adminnotes() - { - global $db; - - $query = $db->simple_select("datacache", "title,cache", "title='adminnotes'"); - $this->update("adminnotes", unserialize($db->fetch_field($query, "cache"))); - } - - function reload_mybb_credits() - { - admin_redirect('index.php?module=home-credits&fetch_new=-2'); - } -} diff --git a/html/forums/inc/class_error.php b/html/forums/inc/class_error.php deleted file mode 100644 index 5abe51b..0000000 --- a/html/forums/inc/class_error.php +++ /dev/null @@ -1,623 +0,0 @@ - 'Error', - E_WARNING => 'Warning', - E_PARSE => 'Parsing Error', - E_NOTICE => 'Notice', - E_CORE_ERROR => 'Core Error', - E_CORE_WARNING => 'Core Warning', - E_COMPILE_ERROR => 'Compile Error', - E_COMPILE_WARNING => 'Compile Warning', - E_DEPRECATED => 'Deprecated Warning', - E_USER_ERROR => 'User Error', - E_USER_WARNING => 'User Warning', - E_USER_NOTICE => 'User Notice', - E_USER_DEPRECATED => 'User Deprecated Warning', - E_STRICT => 'Runtime Notice', - E_RECOVERABLE_ERROR => 'Catchable Fatal Error', - MYBB_SQL => 'MyBB SQL Error', - MYBB_TEMPLATE => 'MyBB Template Error', - MYBB_GENERAL => 'MyBB Error', - MYBB_NOT_INSTALLED => 'MyBB Error', - MYBB_NOT_UPGRADED => 'MyBB Error', - MYBB_INSTALL_DIR_EXISTS => 'MyBB Error', - MYBB_SQL_LOAD_ERROR => 'MyBB Error', - MYBB_CACHE_NO_WRITE => 'MyBB Error', - MYBB_CACHEHANDLER_LOAD_ERROR => 'MyBB Error', - ); - - /** - * Array of MyBB error types - * - * @var array - */ - public $mybb_error_types = array( - MYBB_SQL, - MYBB_TEMPLATE, - MYBB_GENERAL, - MYBB_NOT_INSTALLED, - MYBB_NOT_UPGRADED, - MYBB_INSTALL_DIR_EXISTS, - MYBB_SQL_LOAD_ERROR, - MYBB_CACHE_NO_WRITE, - MYBB_CACHEHANDLER_LOAD_ERROR, - ); - - /** - * Array of all of the error types to ignore - * - * @var array - */ - public $ignore_types = array( - E_DEPRECATED, - E_NOTICE, - E_USER_NOTICE, - E_STRICT - ); - - /** - * String of all the warnings collected - * - * @var string - */ - public $warnings = ""; - - /** - * Is MyBB in an errornous state? (Have we received an error?) - * - * @var boolean - */ - public $has_errors = false; - - /** - * Initializes the error handler - * - */ - function __construct() - { - // Lets set the error handler in here so we can just do $handler = new errorHandler() and be all set up. - $error_types = E_ALL; - foreach($this->ignore_types as $bit) - { - $error_types = $error_types & ~$bit; - } - error_reporting($error_types); - set_error_handler(array(&$this, "error"), $error_types); - } - - /** - * Parses a error for processing. - * - * @param string $type The error type (i.e. E_ERROR, E_FATAL) - * @param string $message The error message - * @param string $file The error file - * @param integer $line The error line - * @return boolean True if parsing was a success, otherwise assume a error - */ - function error($type, $message, $file=null, $line=0) - { - global $mybb; - - // Error reporting turned off (either globally or by @ before erroring statement) - if(error_reporting() == 0) - { - return true; - } - - if(in_array($type, $this->ignore_types)) - { - return true; - } - - $file = str_replace(MYBB_ROOT, "", $file); - - $this->has_errors = true; - - // For some reason in the installer this setting is set to "<" - $accepted_error_types = array('both', 'error', 'warning', 'none'); - if(!in_array($mybb->settings['errortypemedium'], $accepted_error_types)) - { - $mybb->settings['errortypemedium'] = "both"; - } - - if(defined("IN_TASK")) - { - global $task; - - require_once MYBB_ROOT."inc/functions_task.php"; - - $filestr = ''; - if($file) - { - $filestr = " - Line: $line - File: $file"; - } - - add_task_log($task, "{$this->error_types[$type]} - [$type] ".var_export($message, true)."{$filestr}"); - } - - // Saving error to log file. - if($mybb->settings['errorlogmedium'] == "log" || $mybb->settings['errorlogmedium'] == "both") - { - $this->log_error($type, $message, $file, $line); - } - - // Are we emailing the Admin a copy? - if($mybb->settings['errorlogmedium'] == "mail" || $mybb->settings['errorlogmedium'] == "both") - { - $this->email_error($type, $message, $file, $line); - } - - // SQL Error - if($type == MYBB_SQL) - { - $this->output_error($type, $message, $file, $line); - } - else - { - // Do we have a PHP error? - if(my_strpos(my_strtolower($this->error_types[$type]), 'warning') === false) - { - $this->output_error($type, $message, $file, $line); - } - // PHP Error - else - { - if($mybb->settings['errortypemedium'] == "none" || $mybb->settings['errortypemedium'] == "error") - { - echo "
    MyBB Internal: One or more warnings occurred. Please contact your administrator for assistance.
    "; - } - else - { - global $templates; - - $warning = "{$this->error_types[$type]} [$type] $message - Line: $line - File: $file PHP ".PHP_VERSION." (".PHP_OS.")
    \n"; - if(is_object($templates) && method_exists($templates, "get") && !defined("IN_ADMINCP")) - { - $this->warnings .= $warning; - $this->warnings .= $this->generate_backtrace(); - } - else - { - echo "
    {$warning}".$this->generate_backtrace()."
    "; - } - } - } - } - - return true; - } - - /** - * Returns all the warnings - * - * @return string|bool The warnings or false if no warnings exist - */ - function show_warnings() - { - global $lang, $templates; - - if(empty($this->warnings)) - { - return false; - } - - // Incase a template fails and we're receiving a blank page. - if(MANUAL_WARNINGS) - { - echo $this->warnings."
    "; - } - - if(!$lang->warnings) - { - $lang->warnings = "The following warnings occurred:"; - } - - $template_exists = false; - - if(!is_object($templates) || !method_exists($templates, 'get')) - { - if(@file_exists(MYBB_ROOT."inc/class_templates.php")) - { - @require_once MYBB_ROOT."inc/class_templates.php"; - $templates = new templates; - $template_exists = true; - } - } - else - { - $template_exists = true; - } - - $warning = ''; - if($template_exists == true) - { - eval("\$warning = \"".$templates->get("php_warnings")."\";"); - } - - return $warning; - } - - /** - * Triggers a user created error - * Example: $error_handler->trigger("Some Warning", E_USER_ERROR); - * - * @param string $message Message - * @param string|int $type Type - */ - function trigger($message="", $type=E_USER_ERROR) - { - global $lang; - - if(!$message) - { - $message = $lang->unknown_user_trigger; - } - - if(in_array($type, $this->mybb_error_types)) - { - $this->error($type, $message); - } - else - { - trigger_error($message, $type); - } - } - - /** - * Logs the error in the specified error log file. - * - * @param string $type Warning type - * @param string $message Warning message - * @param string $file Warning file - * @param integer $line Warning line - */ - function log_error($type, $message, $file, $line) - { - global $mybb; - - if($type == MYBB_SQL) - { - $message = "SQL Error: {$message['error_no']} - {$message['error']}\nQuery: {$message['query']}"; - } - - // Do not log something that might be executable - $message = str_replace('\n"; - $error_data .= "\t".TIME_NOW."\n"; - $error_data .= "\t\n"; - $error_data .= "\t".$line."\n"; - $error_data .= "\t".$type."\n"; - $error_data .= "\t".$this->error_types[$type]."\n"; - $error_data .= "\t".$message."\n"; - $error_data .= "\n\n"; - - if(trim($mybb->settings['errorloglocation']) != "") - { - @error_log($error_data, 3, $mybb->settings['errorloglocation']); - } - else - { - @error_log($error_data, 0); - } - } - - /** - * Emails the error in the specified error log file. - * - * @param string $type Warning type - * @param string $message Warning message - * @param string $file Warning file - * @param integer $line Warning line - * @return bool returns false if no admin email is set - */ - function email_error($type, $message, $file, $line) - { - global $mybb; - - if(!$mybb->settings['adminemail']) - { - return false; - } - - if($type == MYBB_SQL) - { - $message = "SQL Error: {$message['error_no']} - {$message['error']}\nQuery: {$message['query']}"; - } - - $message = "Your copy of MyBB running on {$mybb->settings['bbname']} ({$mybb->settings['bburl']}) has experienced an error. Details of the error include:\n---\nType: $type\nFile: $file (Line no. $line)\nMessage\n$message"; - - @my_mail($mybb->settings['adminemail'], "MyBB error on {$mybb->settings['bbname']}", $message, $mybb->settings['adminemail']); - - return true; - } - - /** - * @param string $type - * @param string $message - * @param string $file - * @param int $line - */ - function output_error($type, $message, $file, $line) - { - global $mybb, $parser, $lang; - - if(!$mybb->settings['bbname']) - { - $mybb->settings['bbname'] = "MyBB"; - } - - if($type == MYBB_SQL) - { - $title = "MyBB SQL Error"; - $error_message = "

    MyBB has experienced an internal SQL error and cannot continue.

    "; - if($mybb->settings['errortypemedium'] == "both" || $mybb->settings['errortypemedium'] == "error" || defined("IN_INSTALL") || defined("IN_UPGRADE")) - { - $message['query'] = htmlspecialchars_uni($message['query']); - $message['error'] = htmlspecialchars_uni($message['error']); - $error_message .= "
    \n"; - $error_message .= "
    SQL Error:
    \n
    {$message['error_no']} - {$message['error']}
    \n"; - if($message['query'] != "") - { - $error_message .= "
    Query:
    \n
    {$message['query']}
    \n"; - } - $error_message .= "
    \n"; - } - } - else - { - $title = "MyBB Internal Error"; - $error_message = "

    MyBB has experienced an internal error and cannot continue.

    "; - if($mybb->settings['errortypemedium'] == "both" || $mybb->settings['errortypemedium'] == "error" || defined("IN_INSTALL") || defined("IN_UPGRADE")) - { - $error_message .= "
    \n"; - $error_message .= "
    Error Type:
    \n
    {$this->error_types[$type]} ($type)
    \n"; - $error_message .= "
    Error Message:
    \n
    {$message}
    \n"; - if(!empty($file)) - { - $error_message .= "
    Location:
    File: {$file}
    Line: {$line}
    \n"; - if(!@preg_match('#config\.php|settings\.php#', $file) && @file_exists($file)) - { - $code_pre = @file($file); - - $code = ""; - - if(isset($code_pre[$line-4])) - { - $code .= $line-3 . ". ".$code_pre[$line-4]; - } - - if(isset($code_pre[$line-3])) - { - $code .= $line-2 . ". ".$code_pre[$line-3]; - } - - if(isset($code_pre[$line-2])) - { - $code .= $line-1 . ". ".$code_pre[$line-2]; - } - - $code .= $line . ". ".$code_pre[$line-1]; // The actual line. - - if(isset($code_pre[$line])) - { - $code .= $line+1 . ". ".$code_pre[$line]; - } - - if(isset($code_pre[$line+1])) - { - $code .= $line+2 . ". ".$code_pre[$line+1]; - } - - if(isset($code_pre[$line+2])) - { - $code .= $line+3 . ". ".$code_pre[$line+2]; - } - - unset($code_pre); - - $parser_exists = false; - - if(!is_object($parser) || !method_exists($parser, 'mycode_parse_php')) - { - if(@file_exists(MYBB_ROOT."inc/class_parser.php")) - { - @require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - $parser_exists = true; - } - } - else - { - $parser_exists = true; - } - - if($parser_exists) - { - $code = $parser->mycode_parse_php($code, true); - } - else - { - $code = @nl2br($code); - } - - $error_message .= "
    Code:
    {$code}
    \n"; - } - } - $backtrace = $this->generate_backtrace(); - if($backtrace && !in_array($type, $this->mybb_error_types)) - { - $error_message .= "
    Backtrace:
    {$backtrace}
    \n"; - } - $error_message .= "
    \n"; - } - } - - if(isset($lang->settings['charset'])) - { - $charset = $lang->settings['charset']; - } - else - { - $charset = 'UTF-8'; - } - - if(!headers_sent() && !defined("IN_INSTALL") && !defined("IN_UPGRADE")) - { - @header('HTTP/1.1 503 Service Temporarily Unavailable'); - @header('Status: 503 Service Temporarily Unavailable'); - @header('Retry-After: 1800'); - @header("Content-type: text/html; charset={$charset}"); - $file_name = htmlspecialchars_uni(basename($_SERVER['SCRIPT_FILENAME'])); - - echo << - - - - {$mybb->settings['bbname']} - Internal Error - - - -
    - - -
    -

    {$title}

    - -
    - {$error_message} - -
    -
    -
    - - -EOF; - } - else - { - echo << - #mybb_error_content { border: 1px solid #026CB1; background: #fff; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } - #mybb_error_content a:link { color: #026CB1; text-decoration: none; } - #mybb_error_content a:visited { color: #026CB1; text-decoration: none; } - #mybb_error_content a:hover, a:active { color: #000; text-decoration: underline; } - #mybb_error_content h2 { font-size: 12px; padding: 4px; background: #026CB1; color: #fff; margin: 0; border-bottom: none; } - #mybb_error_error { padding: 6px; } - #mybb_error_footer { font-size: 12px; border-top: 1px dotted #DDDDDD; padding-top: 10px; } - #mybb_error_content dt { font-weight: bold; } - -
    -

    {$title}

    -
    - {$error_message} - -
    -
    -EOF; - } - exit(1); - } - - /** - * Generates a backtrace if the server supports it. - * - * @return string The generated backtrace - */ - function generate_backtrace() - { - $backtrace = ''; - if(function_exists("debug_backtrace")) - { - $trace = debug_backtrace(); - $backtrace = "\n"; - $backtrace .= "\n"; - $backtrace .= "\n"; - $backtrace .= "\n"; - $backtrace .= "\n"; - $backtrace .= "\n\n"; - - // Strip off this function from trace - array_shift($trace); - - foreach($trace as $call) - { - if(empty($call['file'])) $call['file'] = "[PHP]"; - if(empty($call['line'])) $call['line'] = " "; - if(!empty($call['class'])) $call['function'] = $call['class'].$call['type'].$call['function']; - $call['file'] = str_replace(MYBB_ROOT, "/", $call['file']); - $backtrace .= "\n"; - $backtrace .= "\n"; - $backtrace .= "\n"; - $backtrace .= "\n"; - $backtrace .= "\n"; - } - $backtrace .= "
    FileLineFunction
    {$call['file']}{$call['line']}{$call['function']}
    \n"; - } - return $backtrace; - } -} diff --git a/html/forums/inc/class_feedgeneration.php b/html/forums/inc/class_feedgeneration.php deleted file mode 100644 index a6b4f76..0000000 --- a/html/forums/inc/class_feedgeneration.php +++ /dev/null @@ -1,224 +0,0 @@ -feed_format = 'atom1.0'; - } - else - { - $this->feed_format = 'rss2.0'; - } - } - - /** - * Sets the channel information for the RSS feed. - * - * @param array $channel The channel information - */ - function set_channel($channel) - { - $this->channel = $channel; - } - - /** - * Adds an item to the RSS feed. - * - * @param array $item The item. - */ - function add_item($item) - { - $this->items[] = $item; - } - - /** - * Generate and echo XML for the feed. - * - */ - function generate_feed() - { - global $lang; - - // First, add the feed metadata. - switch($this->feed_format) - { - // Ouput an Atom 1.0 formatted feed. - case "atom1.0": - $this->channel['date'] = gmdate("Y-m-d\TH:i:s\Z", $this->channel['date']); - $this->xml .= "settings['charset']}\"?>\n"; - $this->xml .= "\n"; - $this->xml .= "\t<![CDATA[".$this->sanitize_content($this->channel['title'])."]]>\n"; - $this->xml .= "\tsanitize_content($this->channel['description'])."]]>\n"; - $this->xml .= "\tchannel['link']}syndication.php\"/>\n"; - $this->xml .= "\t{$this->channel['link']}\n"; - $this->xml .= "\tchannel['link']}\"/>\n"; - $this->xml .= "\t{$this->channel['date']}\n"; - $this->xml .= "\tMyBB\n"; - break; - // The default is the RSS 2.0 format. - default: - $this->channel['date'] = gmdate("D, d M Y H:i:s O", $this->channel['date']); - $this->xml .= "settings['charset']}\"?>\n"; - $this->xml .= "\n"; - $this->xml .= "\t\n"; - $this->xml .= "\t\t<![CDATA[".$this->sanitize_content($this->channel['title'])."]]>\n"; - $this->xml .= "\t\t".$this->channel['link']."\n"; - $this->xml .= "\t\tsanitize_content($this->channel['description'])."]]>\n"; - $this->xml .= "\t\t".$this->channel['date']."\n"; - $this->xml .= "\t\tMyBB\n"; - } - - // Now loop through all of the items and add them to the feed XML. - foreach($this->items as $item) - { - if(!$item['date']) - { - $item['date'] = TIME_NOW; - } - switch($this->feed_format) - { - // Output Atom 1.0 format feed. - case "atom1.0": - $item['date'] = date("Y-m-d\TH:i:s\Z", $item['date']); - $this->xml .= "\t\n"; - if(!empty($item['author'])) - { - $this->xml .= "\t\t\n"; - $this->xml .= "\t\t\tsanitize_content($item['author'])."]]>\n"; - $this->xml .= "\t\t\n"; - } - $this->xml .= "\t\t{$item['date']}\n"; - if(empty($item['updated'])) - { - $item['updated'] = $item['date']; - } - else - { - $item['updated'] = date("Y-m-d\TH:i:s\Z", $item['updated']); - } - $this->xml .= "\t\t{$item['updated']}\n"; - $this->xml .= "\t\t\n"; - $this->xml .= "\t\t{$item['link']}\n"; - $this->xml .= "\t\t<![CDATA[".$this->sanitize_content($item['title'])."]]>\n"; - $this->xml .= "\t\tsanitize_content($item['description'])."]]>\n"; - $this->xml .= "\t\tfalse\n"; - $this->xml .= "\t\n"; - break; - - // The default is the RSS 2.0 format. - default: - $item['date'] = date("D, d M Y H:i:s O", $item['date']); - $this->xml .= "\t\t\n"; - $this->xml .= "\t\t\t<![CDATA[".$this->sanitize_content($item['title'])."]]>\n"; - $this->xml .= "\t\t\t".$item['link']."\n"; - $this->xml .= "\t\t\t".$item['date']."\n"; - if(!empty($item['author'])) - { - $this->xml .= "\t\t\tsanitize_content($item['author'])."]]>\n"; - } - $this->xml .= "\t\t\t".$item['link']."\n"; - $this->xml .= "\t\t\t\n"; - $this->xml .= "\t\t\t\n"; - $this->xml .= "\t\t\n"; - break; - } - } - - // Now, neatly end the feed XML. - switch($this->feed_format) - { - case "atom1.0": - $this->xml .= ""; - break; - default: - $this->xml .= "\t\n"; - $this->xml .= ""; - } - } - - /** - * Sanitize content suitable for RSS feeds. - * - * @param string $string The string we wish to sanitize. - * @return string The cleaned string. - */ - function sanitize_content($content) - { - $content = preg_replace("#&[^\s]([^\#])(?![a-z1-4]{1,10});#i", "&$1", $content); - $content = str_replace("]]>", "]]]]>", $content); - - return $content; - } - - /** - * Output the feed XML. - */ - function output_feed() - { - global $lang; - // Send an appropriate header to the browser. - switch($this->feed_format) - { - case "atom1.0": - header("Content-Type: application/atom+xml; charset=\"{$lang->settings['charset']}\""); - break; - default: - header("Content-Type: text/xml; charset=\"{$lang->settings['charset']}\""); - } - - // Output the feed XML. If the feed hasn't been generated, do so. - if($this->xml) - { - echo $this->xml; - } - else - { - $this->generate_feed(); - echo $this->xml; - } - } -} diff --git a/html/forums/inc/class_feedparser.php b/html/forums/inc/class_feedparser.php deleted file mode 100644 index b1833f1..0000000 --- a/html/forums/inc/class_feedparser.php +++ /dev/null @@ -1,242 +0,0 @@ -")+1 !== strlen($contents)) - { - $contents = substr($contents, 0, strrpos($contents, ">")+1); - } - - // Could not load the feed, return an error - if(!$contents) - { - $this->error = "invalid_file"; - return false; - } - - // Parse the feed and get the tree - $parser = new XMLParser($contents); - $tree = $parser->get_tree(); - - // If the feed is invalid, throw back an error - if($tree == false) - { - $this->error = "invalid_feed_xml"; - return false; - } - - // Change array key names to lower case - $tree = $this->keys_to_lowercase($tree); - - // This is an RSS feed, parse it - if(array_key_exists("rss", $tree)) - { - $this->parse_rss($tree['rss']); - } - - // We don't know how to parse this feed - else - { - $this->error = "unknown_feed_type"; - return false; - } - - return true; - } - - /** - * Parses an XML structure in the format of an RSS feed - * - * @param array $feed_contents PHP XML parser structure - * @return boolean true - */ - function parse_rss($feed_contents) - { - foreach(array('title', 'link', 'description', 'pubdate') as $value) - { - if(!isset($feed_contents['channel'][$value]['value'])) - { - $feed_contents['channel'][$value]['value'] = ''; - } - } - - // Fetch channel information from the parsed feed - $this->channel = array( - "title" => $feed_contents['channel']['title']['value'], - "link" => $feed_contents['channel']['link']['value'], - "description" => $feed_contents['channel']['description']['value'], - "date" => $feed_contents['channel']['pubdate']['value'], - "date_timestamp" => $this->get_rss_timestamp($feed_contents['channel']['pubdate']['value']) - ); - - // The XML parser does not create a multidimensional array of items if there is one item, so fake it - if(!array_key_exists("0", $feed_contents['channel']['item'])) - { - $feed_contents['channel']['item'] = array($feed_contents['channel']['item']); - } - - // Loop through each of the items in the feed - foreach($feed_contents['channel']['item'] as $feed_item) - { - // Here is a nice long stretch of code for parsing items, we do it this way because most elements are optional in an - // item and we only want to assign what we have. - - $item = array(); - - - // Set the item title if we have it - if(array_key_exists("title", $feed_item)) - { - $item['title'] = $feed_item['title']['value']; - } - - if(array_key_exists("description", $feed_item)) - { - $item['description'] = $feed_item['description']['value']; - } - - if(array_key_exists("link", $feed_item)) - { - $item['link'] = $feed_item['link']['value']; - } - - // If we have a pub date, store it and attempt to generate a unix timestamp from it - if(array_key_exists("pubdate", $feed_item)) - { - $item['date'] = $feed_item['pubdate']['value']; - $item['date_timestamp'] = $this->get_rss_timestamp($item['date']); - } - - // If we have a GUID - if(array_key_exists("guid", $feed_item)) - { - $item['guid'] = $feed_item['guid']['value']; - } - // Otherwise, attempt to generate one from the link and item title - else - { - $item['guid'] = md5($item['link'].$item['title']); - } - - // If we have some content, set it - if(array_key_exists("content:encoded", $feed_item)) - { - $item['content'] = $feed_item['content:encoded']['value']; - } - else if(array_key_exists("content", $feed_item)) - { - $item['content'] = $feed_item['content']['value']; - } - - // We have a DC based creator, set it - if(array_key_exists("dc:creator", $feed_item)) - { - $item['author'] = $feed_item['dc:creator']['value']; - } - // Otherwise, attempt to use the author if we have it - else if(array_key_exists("author", $feed_item)) - { - $item['author'] = $feed_item['author']['value']; - } - - // Assign the item to our list of items - $this->items[] = $item; - } - return true; - } - - /** - * Convert all array keys within an array to lowercase - * - * @param array $array The array to be converted - * @return array The converted array - */ - function keys_to_lowercase($array) - { - $new_array = array(); - foreach($array as $key => $value) - { - $new_key = strtolower($key); - if(is_array($value)) - { - $new_array[$new_key] = $this->keys_to_lowercase($value); - } - else - { - $new_array[$new_key] = $value; - } - } - return $new_array; - } - - /** - * Converts an RSS date stamp in to a unix timestamp - * - * @param string $date The RSS date - * @return integer The unix timestamp (if successful), 0 if unsuccessful - */ - function get_rss_timestamp($date) - { - $stamp = strtotime($date); - if($stamp <= 0) - { - if(preg_match("#\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2}#", $date, $result)) - { - $date = str_replace(array("T", "+"), array(" ", " +"), $date); - $date[23] = ""; - } - $stamp = strtotime($date); - } - return $stamp; - } -} diff --git a/html/forums/inc/class_graph.php b/html/forums/inc/class_graph.php deleted file mode 100644 index f686e66..0000000 --- a/html/forums/inc/class_graph.php +++ /dev/null @@ -1,337 +0,0 @@ -= 2, create base image - if(gd_version() >= 2) - { - $this->im = imagecreatetruecolor($this->img_width, $this->img_height); - } - else - { - $this->im = imagecreate($this->img_width, $this->img_height); - } - - // No GD support, die. - if(!$this->im) - { - return; - } - - if(function_exists("imageantialias")) - { - imageantialias($this->im, true); - } - - // Fill the background - imagefill($this->im, 0, 0, $this->color(239, 239, 239)); - - // Create our internal working graph box - $inside_end_x = $this->inside_x+$this->inside_width; - $inside_end_y = $this->inside_y+$this->inside_height; - $this->image_create_rectangle($this->inside_x, $this->inside_y, $inside_end_x, $inside_end_y, 4, $this->color(254, 254, 254)); - - // Draw our three lines inside our internal working graph area - for($i = 1; $i < 4; ++$i) - { - $y_value = $this->inside_y+(($this->inside_height/4)*$i); - imageline($this->im, $this->inside_x, $y_value, $inside_end_x, $y_value, $this->color(185, 185, 185)); - } - } - - /** - * Select and allocate a color to the internal image resource - * - * @param integer $red The red value - * @param integer $green The green value - * @param integer $blue The blue value - * @return integer A color identifier - */ - private function color($red, $green, $blue) - { - return imagecolorallocate($this->im, $red, $green, $blue); - } - - /** - * Creates a filled rectangle with optional rounded corners - * - * @param integer $x1 The initial x value - * @param integer $y1 The initial y value - * @param integer $x2 The ending x value - * @param integer $y2 The ending y value - * @param integer $radius The optional radius - * @param integer $color The optional rectangle color (defaults to black) - */ - private function image_create_rectangle($x1, $y1, $x2, $y2, $radius=1, $color=null) - { - if($color == null) - { - $color = $this->color(0, 0, 0); - } - - // Draw our rectangle - imagefilledrectangle($this->im, $x1, $y1+$radius, $x2, $y2-$radius, $color); - imagefilledrectangle($this->im, $x1+$radius, $y1, $x2-$radius, $y2, $color); - - if($radius > 0) - { - $diameter = $radius*2; - - // Now draw our four corners on the rectangle - imagefilledellipse($this->im, $x1+$radius, $y1+$radius, $diameter, $diameter, $color); - imagefilledellipse($this->im, $x1+$radius, $y2-$radius, $diameter, $diameter, $color); - imagefilledellipse($this->im, $x2-$radius, $y2-$radius, $diameter, $diameter, $color); - imagefilledellipse($this->im, $x2-$radius, $y1+$radius, $diameter, $diameter, $color); - } - } - - /** - * Creates a nicer thick line for angled lines - * - * @param integer $x1 The initial x value - * @param integer $y1 The initial y value - * @param integer $x2 The ending x value - * @param integer $y2 The ending y value - * @param integer $color The optional rectangle color (defaults to black) - * @param integer $thick The optional thickness (defaults to 1) - * @return int - */ - private function imagelinethick($x1, $y1, $x2, $y2, $color, $thick = 1) - { - if($thick == 1) - { - return imageline($this->im, $x1, $y1, $x2, $y2, $color); - } - - $t = $thick / 2 - 0.5; - if($x1 == $x2 || $y1 == $y2) - { - return imagefilledrectangle($this->im, round(min($x1, $x2) - $t), round(min($y1, $y2) - $t), round(max($x1, $x2) + $t), round(max($y1, $y2) + $t), $color); - } - - $k = ($y2 - $y1) / ($x2 - $x1); //y = kx + q - $a = $t / sqrt(1 + pow($k, 2)); - $points = array( - round($x1 - (1+$k)*$a), round($y1 + (1-$k)*$a), - round($x1 - (1-$k)*$a), round($y1 - (1+$k)*$a), - round($x2 + (1+$k)*$a), round($y2 - (1-$k)*$a), - round($x2 + (1-$k)*$a), round($y2 + (1+$k)*$a), - ); - imagefilledpolygon($this->im, $points, 4, $color); - - return imagepolygon($this->im, $points, 4, $color); - } - - /** - * Adds an array of x, y points to the internal points array - * - * @param array $points The array of x, y points to add - */ - public function add_points($points) - { - $this->points = array_merge($this->points, $points); - } - - /** - * Adds an array of x labels to the internal labels array - * - * @param array $labels The array of x labels to add - */ - public function add_x_labels($labels) - { - $this->x_labels = array_merge($this->x_labels, $labels); - } - - /** - * Sets a bottom label - * - * @param string $label The bottom label to set - */ - public function set_bottom_label($label) - { - $this->bottom_label = $label; - } - - /** - * Renders the graph to memory - * - */ - public function render() - { - // Get our max's and min's - $asorted = $this->points; - sort($asorted, SORT_NUMERIC); - $min = $asorted[0]; - $max = $asorted[count($asorted)-1]; - - // Scale based on how many points we need to shove into 930 pixels of width - $x_delta = $this->inside_width/count($this->points); - - // Scale our y axis to 220 pixels - $y_scale_factor = ($max-$min)/$this->inside_height; - - // Get our Y initial - $y_initial = $this->inside_y+$this->inside_height; - - // Get our scale for finding our points of reference to place our x axis labels - $x_label_scale = ceil(count($this->points)/20); - $x_label_points = array(); - $next_y_scaled = 0; - - foreach($this->points as $x => $y) - { - if(($x_label_scale == 0 || (($x+1) % $x_label_scale) == 0) && $x != 0) - { - $x_label_points[] = $x; - - imagedashedline($this->im, $this->inside_x+($x_delta*$x), 30, $this->inside_x+($x_delta*$x), $y_initial, $this->color(185, 185, 185)); - - imagefilledellipse($this->im, $this->inside_x+($x_delta*$x), $y_initial-$next_y_scaled+0.5, 8, 8, $this->color(84, 92, 209)); - } - - // Look ahead to find our next point, if there is one - if(!array_key_exists($x+1, $this->points)) - { - break; - } - $next_y = $this->points[$x+1]; - - if($y_scale_factor == 0) - { - $y_scaled = $next_y_scaled = 0; - } - else - { - $y_scaled = ($y-$min)/$y_scale_factor; - $next_y_scaled = ($next_y-$min)/$y_scale_factor; - } - - // Draw our line - $this->imagelinethick($this->inside_x+($x_delta*$x), $y_initial-$y_scaled, $this->inside_x+($x_delta*($x+1)), $y_initial-$next_y_scaled, $this->color(84, 92, 209), 3); - } - - // Draw our x labels - foreach($x_label_points as $x) - { - $label = $this->x_labels[$x]; - $text_width = imagefontwidth(2)*strlen($label); - $x = $this->inside_x+($x_delta*$x)-($text_width/2); - - imagestring($this->im, 2, $x, $y_initial+5, $label, $this->color(0, 0, 0)); - } - - // Draw our bottom label - imagestring($this->im, 2, ($this->img_width / 2), $y_initial+25, $this->bottom_label, $this->color(0, 0, 0)); - - if($max > 4) - { - // Draw our y labels - for($i = 1; $i < 4; ++$i) - { - $y_value = $this->inside_y+(($this->inside_height/4)*$i); - imagestring($this->im, 2, 5, $y_value-7, my_number_format(round($min+(($max-$min)/4)*(4-$i))), $this->color(0, 0, 0)); - } - } - imagestring($this->im, 2, 5, $this->inside_y+$this->inside_height-7, my_number_format($min), $this->color(0, 0, 0)); - imagestring($this->im, 2, 5, $this->inside_y-7, my_number_format($max), $this->color(0, 0, 0)); - } - - /** - * Outputs the graph to the screen in PNG format - * - */ - public function output() - { - // Output the image - header("Content-type: image/png"); - imagepng($this->im); - imagedestroy($this->im); - exit; - } -} - diff --git a/html/forums/inc/class_language.php b/html/forums/inc/class_language.php deleted file mode 100644 index a864a96..0000000 --- a/html/forums/inc/class_language.php +++ /dev/null @@ -1,242 +0,0 @@ -path = $path; - } - - /** - * Check if a specific language exists. - * - * @param string $language The language to check for. - * @return boolean True when exists, false when does not exist. - */ - function language_exists($language) - { - $language = preg_replace("#[^a-z0-9\-_]#i", "", $language); - if(file_exists($this->path."/".$language.".php")) - { - return true; - } - else - { - return false; - } - } - - /** - * Set the language for an area. - * - * @param string $language The language to use. - * @param string $area The area to set the language for. - */ - function set_language($language="english", $area="user") - { - global $mybb; - - $language = preg_replace("#[^a-z0-9\-_]#i", "", $language); - - // Default language is English. - if($language == "") - { - $language = "english"; - } - - // Check if the language exists. - if(!$this->language_exists($language)) - { - die("Language $language ($this->path/$language) is not installed"); - } - - $this->language = $language; - require $this->path."/".$language.".php"; - $this->settings = $langinfo; - - // Load the admin language files as well, if needed. - if($area == "admin") - { - if(!is_dir($this->path."/".$language."/{$area}")) - { - if(!is_dir($this->path."/".$mybb->settings['cplanguage']."/{$area}")) - { - if(!is_dir($this->path."/english/{$area}")) - { - die("Your forum does not contain an Administration set. Please reupload the english language administration pack."); - } - else - { - $language = "english"; - } - } - else - { - $language = $mybb->settings['cplanguage']; - } - } - $this->language = $language."/{$area}"; - $this->fallback = $this->fallback."/{$area}"; - } - } - - /** - * Load the language variables for a section. - * - * @param string $section The section name. - * @param boolean $isdatahandler Is this a datahandler? - * @param boolean $supress_error supress the error if the file doesn't exist? - */ - function load($section, $isdatahandler=false, $supress_error=false) - { - // Assign language variables. - // Datahandlers are never in admin lang directory. - if($isdatahandler === true) - { - $lfile = $this->path."/".str_replace('/admin', '', $this->language)."/".$section.".lang.php"; - } - else - { - $lfile = $this->path."/".$this->language."/".$section.".lang.php"; - } - - if(file_exists($lfile)) - { - require_once $lfile; - } - elseif(file_exists($this->path."/".$this->fallback."/".$section.".lang.php")) - { - require_once $this->path."/".$this->fallback."/".$section.".lang.php"; - } - else - { - if($supress_error != true) - { - die("$lfile does not exist"); - } - } - - // We must unite and protect our language variables! - $lang_keys_ignore = array('language', 'path', 'settings'); - - if(isset($l) && is_array($l)) - { - foreach($l as $key => $val) - { - if((empty($this->$key) || $this->$key != $val) && !in_array($key, $lang_keys_ignore)) - { - $this->$key = $val; - } - } - } - } - - /** - * @param string $string - * - * @return string - */ - function sprintf($string) - { - $arg_list = func_get_args(); - $num_args = count($arg_list); - - for($i = 1; $i < $num_args; $i++) - { - $string = str_replace('{'.$i.'}', $arg_list[$i], $string); - } - - return $string; - } - - /** - * Get the language variables for a section. - * - * @param boolean $admin Admin variables when true, user when false. - * @return array The language variables. - */ - function get_languages($admin=false) - { - $dir = @opendir($this->path); - while($lang = readdir($dir)) - { - $ext = my_strtolower(get_extension($lang)); - if($lang != "." && $lang != ".." && $ext == "php") - { - $lname = str_replace(".".$ext, "", $lang); - require $this->path."/".$lang; - if(!$admin || ($admin && $langinfo['admin'])) - { - $languages[$lname] = $langinfo['name']; - } - } - } - @ksort($languages); - return $languages; - } - - /** - * Parse contents for language variables. - * - * @param string $contents The contents to parse. - * @return string The parsed contents. - */ - function parse($contents) - { - $contents = preg_replace_callback("##", array($this, 'parse_replace'), $contents); - return $contents; - } - - /** - * Replace content with language variable. - * - * @param array $matches Matches. - * @return string Language variable. - */ - function parse_replace($matches) - { - return $this->{$matches[1]}; - } -} diff --git a/html/forums/inc/class_mailhandler.php b/html/forums/inc/class_mailhandler.php deleted file mode 100644 index ee6bd3f..0000000 --- a/html/forums/inc/class_mailhandler.php +++ /dev/null @@ -1,437 +0,0 @@ -settings['returnemail'])) - { - $email = $mybb->settings['returnemail']; - } - else - { - $email = $mybb->settings['adminemail']; - } - - return $email; - } - - /** - * Builds the whole mail. - * To be used by the different email classes later. - * - * @param string $to to email. - * @param string $subject subject of email. - * @param string $message message of email. - * @param string $from from email. - * @param string $charset charset of email. - * @param string $headers headers of email. - * @param string $format format of the email (HTML, plain text, or both?). - * @param string $message_text plain text version of the email. - * @param string $return_email the return email address. - */ - function build_message($to, $subject, $message, $from="", $charset="", $headers="", $format="text", $message_text="", $return_email="") - { - global $parser, $lang, $mybb; - - $this->message = ''; - $this->headers = $headers; - - if($from) - { - $this->from = $from; - } - else - { - if($mybb->settings['mail_handler'] == 'smtp') - { - $this->from = $this->get_from_email(); - } - else - { - $this->from = '"'.$this->utf8_encode($mybb->settings['bbname']).'"'; - $this->from .= " <".$this->get_from_email().">"; - } - } - - if($return_email) - { - $this->return_email = $return_email; - } - else - { - $this->return_email = ""; - $this->return_email = $this->get_from_email(); - } - - $this->set_to($to); - $this->set_subject($subject); - - if($charset) - { - $this->set_charset($charset); - } - - $this->parse_format = $format; - $this->set_common_headers(); - $this->set_message($message, $message_text); - } - - /** - * Sets the charset. - * - * @param string $charset charset - */ - function set_charset($charset) - { - global $lang; - - if(empty($charset)) - { - $this->charset = $lang->settings['charset']; - } - else - { - $this->charset = $charset; - } - } - - /** - * Sets and formats the email message. - * - * @param string $message message - * @param string $message_text - */ - function set_message($message, $message_text="") - { - $message = $this->cleanup_crlf($message); - - if($message_text) - { - $message_text = $this->cleanup_crlf($message_text); - } - - if($this->parse_format == "html" || $this->parse_format == "both") - { - $this->set_html_headers($message, $message_text); - } - else - { - $this->message = $message; - $this->set_plain_headers(); - } - } - - /** - * Sets and formats the email subject. - * - * @param string $subject - */ - function set_subject($subject) - { - $this->orig_subject = $this->cleanup($subject); - $this->subject = $this->utf8_encode($this->orig_subject); - } - - /** - * Sets and formats the recipient address. - * - * @param string $to - */ - function set_to($to) - { - $to = $this->cleanup($to); - - $this->to = $this->cleanup($to); - } - - /** - * Sets the plain headers, text/plain - */ - function set_plain_headers() - { - $this->headers .= "Content-Type: text/plain; charset={$this->charset}{$this->delimiter}"; - } - - /** - * Sets the alternative headers, text/html and text/plain. - * - * @param string $message - * @param string $message_text - */ - function set_html_headers($message, $message_text="") - { - if(!$message_text && $this->parse_format == 'both') - { - $message_text = strip_tags($message); - } - - if($this->parse_format == 'both') - { - $mime_boundary = "=_NextPart".md5(TIME_NOW); - - $this->headers .= "Content-Type: multipart/alternative; boundary=\"{$mime_boundary}\"{$this->delimiter}"; - $this->message = "This is a multi-part message in MIME format.{$this->delimiter}{$this->delimiter}"; - - $this->message .= "--{$mime_boundary}{$this->delimiter}"; - $this->message .= "Content-Type: text/plain; charset=\"{$this->charset}\"{$this->delimiter}"; - $this->message .= "Content-Transfer-Encoding: 8bit{$this->delimiter}{$this->delimiter}"; - $this->message .= $message_text."{$this->delimiter}{$this->delimiter}"; - - $this->message .= "--{$mime_boundary}{$this->delimiter}"; - - $this->message .= "Content-Type: text/html; charset=\"{$this->charset}\"{$this->delimiter}"; - $this->message .= "Content-Transfer-Encoding: 8bit{$this->delimiter}{$this->delimiter}"; - $this->message .= $message."{$this->delimiter}{$this->delimiter}"; - - $this->message .= "--{$mime_boundary}--{$this->delimiter}{$this->delimiter}"; - } - else - { - $this->headers .= "Content-Type: text/html; charset=\"{$this->charset}\"{$this->delimiter}"; - $this->headers .= "Content-Transfer-Encoding: 8bit{$this->delimiter}{$this->delimiter}"; - $this->message = $message."{$this->delimiter}{$this->delimiter}"; - } - } - - /** - * Sets the common headers. - */ - function set_common_headers() - { - global $mybb; - - // Build mail headers - $this->headers .= "From: {$this->from}{$this->delimiter}"; - - if($this->return_email) - { - $this->headers .= "Return-Path: {$this->return_email}{$this->delimiter}"; - $this->headers .= "Reply-To: {$this->return_email}{$this->delimiter}"; - } - - if(isset($_SERVER['SERVER_NAME'])) - { - $http_host = $_SERVER['SERVER_NAME']; - } - else if(isset($_SERVER['HTTP_HOST'])) - { - $http_host = $_SERVER['HTTP_HOST']; - } - else - { - $http_host = "unknown.local"; - } - - $msg_id = md5(uniqid(TIME_NOW, true)) . "@" . $http_host; - - if($mybb->settings['mail_message_id']) - { - $this->headers .= "Message-ID: <{$msg_id}>{$this->delimiter}"; - } - $this->headers .= "Content-Transfer-Encoding: 8bit{$this->delimiter}"; - $this->headers .= "X-Priority: 3{$this->delimiter}"; - $this->headers .= "X-Mailer: MyBB{$this->delimiter}"; - $this->headers .= "MIME-Version: 1.0{$this->delimiter}"; - } - - /** - * Log a fatal error message to the database. - * - * @param string $error The error message - */ - function fatal_error($error) - { - global $db; - - $mail_error = array( - "subject" => $db->escape_string($this->orig_subject), - "message" => $db->escape_string($this->message), - "toaddress" => $db->escape_string($this->to), - "fromaddress" => $db->escape_string($this->from), - "dateline" => TIME_NOW, - "error" => $db->escape_string($error), - "smtperror" => $db->escape_string($this->data), - "smtpcode" => (int)$this->code - ); - $db->insert_query("mailerrors", $mail_error); - - // Another neat feature would be the ability to notify the site administrator via email - but wait, with email down, how do we do that? How about private message and hope the admin checks their PMs? - } - - /** - * Rids pesky characters from subjects, recipients, from addresses etc (prevents mail injection too) - * - * @param string $string The string being checked - * @return string The cleaned string - */ - function cleanup($string) - { - $string = str_replace(array("\r", "\n", "\r\n"), "", $string); - $string = trim($string); - return $string; - } - - /** - * Converts message text to suit the correct delimiter - * See dev.mybb.com/issues/1735 (Jorge Oliveira) - * - * @param string $text The text being converted - * @return string The converted string - */ - function cleanup_crlf($text) - { - $text = str_replace("\r\n", "\n", $text); - $text = str_replace("\r", "\n", $text); - $text = str_replace("\n", "\r\n", $text); - - return $text; - } - - /** - * Encode a string based on the character set enabled. Used to encode subjects - * and recipients in email messages going out so that they show up correctly - * in email clients. - * - * @param string $string The string to be encoded. - * @return string The encoded string. - */ - function utf8_encode($string) - { - if(strtolower($this->charset) == 'utf-8' && preg_match('/[^\x20-\x7E]/', $string)) - { - $chunk_size = 47; // Derived from floor((75 - strlen("=?UTF-8?B??=")) * 0.75); - $len = strlen($string); - $output = ''; - $pos = 0; - - while($pos < $len) - { - $newpos = min($pos + $chunk_size, $len); - - while(ord($string[$newpos]) >= 0x80 && ord($string[$newpos]) < 0xC0) - { - // Reduce len until it's safe to split UTF-8. - $newpos--; - } - - $chunk = substr($string, $pos, $newpos - $pos); - $pos = $newpos; - - $output .= " =?UTF-8?B?".base64_encode($chunk)."?=\n"; - } - return trim($output); - } - return $string; - } -} diff --git a/html/forums/inc/class_moderation.php b/html/forums/inc/class_moderation.php deleted file mode 100644 index 0c8835f..0000000 --- a/html/forums/inc/class_moderation.php +++ /dev/null @@ -1,3773 +0,0 @@ -run_hooks("class_moderation_close_threads", $tids); - - $tid_list = implode(',', $tids); - - $openthread = array( - "closed" => 1, - ); - $db->update_query("threads", $openthread, "tid IN ($tid_list) AND closed NOT LIKE 'moved|%'"); - - return true; - } - - /** - * Open one or more threads - * - * @param array|int $tids Thread ID(s) - * @return boolean - */ - - function open_threads($tids) - { - global $db, $plugins; - - if(!is_array($tids)) - { - $tids = array($tids); - } - - if(empty($tids)) - { - return false; - } - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $plugins->run_hooks("class_moderation_open_threads", $tids); - - $tid_list = implode(',', $tids); - - $closethread = array( - "closed" => 0, - ); - $db->update_query("threads", $closethread, "tid IN ($tid_list)"); - - return true; - } - - /** - * Stick one or more threads - * - * @param array|int $tids Thread ID(s) - * @return boolean - */ - function stick_threads($tids) - { - global $db, $plugins; - - if(!is_array($tids)) - { - $tids = array($tids); - } - - if(empty($tids)) - { - return false; - } - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $plugins->run_hooks("class_moderation_stick_threads", $tids); - - $tid_list = implode(',', $tids); - - $stickthread = array( - "sticky" => 1, - ); - $db->update_query("threads", $stickthread, "tid IN ($tid_list)"); - - return true; - } - - /** - * Unstick one or more thread - * - * @param array|int $tids Thread ID(s) - * @return boolean - */ - function unstick_threads($tids) - { - global $db, $plugins; - - if(!is_array($tids)) - { - $tids = array($tids); - } - - if(empty($tids)) - { - return false; - } - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $plugins->run_hooks("class_moderation_unstick_threads", $tids); - - $tid_list = implode(',', $tids); - - $unstickthread = array( - "sticky" => 0, - ); - $db->update_query("threads", $unstickthread, "tid IN ($tid_list)"); - - return true; - } - - /** - * Remove redirects that redirect to the specified thread - * - * @param int $tid Thread ID of the thread - * @return boolean - */ - function remove_redirects($tid) - { - global $db, $plugins; - - $plugins->run_hooks("class_moderation_remove_redirects", $tid); - - // Delete the redirects - $tid = (int)$tid; - if(empty($tid)) - { - return false; - } - - $query = $db->simple_select('threads', 'tid', "closed='moved|$tid'"); - while($redirect_tid = $db->fetch_field($query, 'tid')) - { - $this->delete_thread($redirect_tid); - } - - return true; - } - - /** - * Delete a thread - * - * @param int $tid Thread ID of the thread - * @return boolean - */ - function delete_thread($tid) - { - global $db, $cache, $plugins; - - $tid = (int)$tid; - - $plugins->run_hooks("class_moderation_delete_thread_start", $tid); - - $thread = get_thread($tid); - if(!$thread) - { - return false; - } - $forum = get_forum($thread['fid']); - - $userposts = array(); - - // Find the pid, uid, visibility, and forum post count status - $query = $db->simple_select('posts', 'pid, uid, visible', "tid='{$tid}'"); - $pids = array(); - $num_unapproved_posts = $num_approved_posts = $num_deleted_posts = 0; - while($post = $db->fetch_array($query)) - { - $pids[] = $post['pid']; - - if(!function_exists("remove_attachments")) - { - require_once MYBB_ROOT."inc/functions_upload.php"; - } - - // Remove attachments - remove_attachments($post['pid']); - - // If the post is unapproved, count it! - if(($post['visible'] == 0 && $thread['visible'] != -1) || $thread['visible'] == 0) - { - $num_unapproved_posts++; - } - elseif($post['visible'] == -1 || $thread['visible'] == -1) - { - $num_deleted_posts++; - } - else - { - $num_approved_posts++; - - // Count the post counts for each user to be subtracted - if($forum['usepostcounts'] != 0) - { - if(!isset($userposts[$post['uid']]['num_posts'])) - { - $userposts[$post['uid']]['num_posts'] = 0; - } - ++$userposts[$post['uid']]['num_posts']; - } - } - } - - if($forum['usethreadcounts'] != 0 && substr($thread['closed'], 0, 6) != 'moved|') - { - if(!isset($userposts[$thread['uid']]['num_threads'])) - { - $userposts[$thread['uid']]['num_threads'] = 0; - } - ++$userposts[$thread['uid']]['num_threads']; - } - - // Remove post count from users - if($thread['visible'] == 1) - { - if(!empty($userposts)) - { - foreach($userposts as $uid => $subtract) - { - $update_array = array( - "postnum" => "-{$subtract['num_posts']}", - "threadnum" => "-{$subtract['num_threads']}", - ); - update_user_counters($uid, $update_array); - } - } - } - // Delete posts and their attachments - if(!empty($pids)) - { - $pids = implode(',', $pids); - $db->delete_query("posts", "pid IN ($pids)"); - $db->delete_query("attachments", "pid IN ($pids)"); - $db->delete_query("reportedcontent", "id IN ($pids) AND (type = 'post' OR type = '')"); - } - - // Delete threads, redirects, subscriptions, polls, and poll votes - $db->delete_query("threads", "tid='$tid'"); - $query = $db->simple_select('threads', 'tid', "closed='moved|$tid'"); - while($redirect_tid = $db->fetch_field($query, 'tid')) - { - $this->delete_thread($redirect_tid); - } - $db->delete_query("threadsubscriptions", "tid='$tid'"); - $db->delete_query("polls", "tid='$tid'"); - $db->delete_query("pollvotes", "pid='".$thread['poll']."'"); - $db->delete_query("threadsread", "tid='$tid'"); - $db->delete_query("threadratings", "tid='$tid'"); - - $updated_counters = array( - "posts" => "-{$num_approved_posts}", - "unapprovedposts" => "-{$num_unapproved_posts}", - "deletedposts" => "-{$num_deleted_posts}" - ); - - if($thread['visible'] == 1) - { - $updated_counters['threads'] = -1; - } - elseif($thread['visible'] == -1) - { - $updated_counters['deletedthreads'] = -1; - } - else - { - $updated_counters['unapprovedthreads'] = -1; - } - - if(strpos($thread['closed'], 'moved|') !== false) - { - // Redirect - if($thread['visible'] == 1) - { - $updated_counters['posts'] = -1; - } - elseif($thread['visible'] == -1) - { - $updated_counters['deletedposts'] = -1; - } - else - { - $updated_counters['unapprovedposts'] = -1; - } - } - - // Update forum count - update_forum_counters($thread['fid'], $updated_counters); - update_forum_lastpost($thread['fid']); - mark_reports($tid, 'thread'); - - $plugins->run_hooks("class_moderation_delete_thread", $tid); - - return true; - } - - /** - * Delete a poll - * - * @param int $pid Poll id - * @return boolean - */ - function delete_poll($pid) - { - global $db, $plugins; - - $pid = (int)$pid; - - if(empty($pid)) - { - return false; - } - - $plugins->run_hooks("class_moderation_delete_poll", $pid); - - $db->delete_query("polls", "pid='$pid'"); - $db->delete_query("pollvotes", "pid='$pid'"); - $pollarray = array( - 'poll' => '0', - ); - $db->update_query("threads", $pollarray, "poll='$pid'"); - - return true; - } - - /** - * Approve one or more threads - * - * @param array|int $tids Thread ID(s) - * @return boolean - */ - function approve_threads($tids) - { - global $db, $cache, $plugins; - - if(!is_array($tids)) - { - $tids = array($tids); - } - - if(empty($tids)) - { - return false; - } - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $tid_list = $forum_counters = $user_counters = $posts_to_approve = array(); - - foreach($tids as $tid) - { - $thread = get_thread($tid); - if(!$thread || $thread['visible'] == 1 || $thread['visible'] == -1) - { - continue; - } - $tid_list[] = $thread['tid']; - - $forum = get_forum($thread['fid']); - - if(!isset($forum_counters[$forum['fid']])) - { - $forum_counters[$forum['fid']] = array( - 'num_posts' => 0, - 'num_threads' => 0, - 'num_deleted_posts' => 0, - 'num_unapproved_posts' => 0 - ); - } - - if(!isset($user_counters[$thread['uid']])) - { - $user_counters[$thread['uid']] = array( - 'num_posts' => 0, - 'num_threads' => 0 - ); - } - - ++$forum_counters[$forum['fid']]['num_threads']; - $forum_counters[$forum['fid']]['num_posts'] += $thread['replies']+1; // Remove implied visible from count - $forum_counters[$forum['fid']]['num_deleted_posts'] += $thread['deletedposts']; - $forum_counters[$forum['fid']]['num_unapproved_posts'] += $thread['deletedposts']+$thread['replies']+1; - - if($forum['usepostcounts'] != 0) - { - // On approving thread restore user post counts - $query = $db->simple_select("posts", "COUNT(pid) as posts, uid", "tid='{$tid}' AND (visible='1' OR pid='{$thread['firstpost']}') AND uid > 0 GROUP BY uid"); - while($counter = $db->fetch_array($query)) - { - $user_counters[$counter['uid']]['num_posts'] += $counter['posts']; - } - } - - if($forum['usethreadcounts'] != 0 && substr($thread['closed'], 0, 6) != 'moved|') - { - ++$user_counters[$thread['uid']]['num_threads']; - } - - $posts_to_approve[] = $thread['firstpost']; - } - - if(!empty($tid_list)) - { - $tid_moved_list = ""; - $comma = ""; - foreach($tid_list as $tid) - { - $tid_moved_list .= "{$comma}'moved|{$tid}'"; - $comma = ","; - } - $tid_list = implode(',', $tid_list); - $approve = array( - "visible" => 1 - ); - $db->update_query("threads", $approve, "tid IN ($tid_list)"); - // Approve redirects, too - $redirect_tids = array(); - $query = $db->simple_select('threads', 'tid', "closed IN ({$tid_moved_list})"); - while($redirect_tid = $db->fetch_field($query, 'tid')) - { - $redirect_tids[] = $redirect_tid; - } - if(!empty($redirect_tids)) - { - $this->approve_threads($redirect_tids); - } - if(!empty($posts_to_approve)) - { - $db->update_query("posts", $approve, "pid IN (".implode(',', $posts_to_approve).")"); - } - - $plugins->run_hooks("class_moderation_approve_threads", $tids); - - if(!empty($forum_counters)) - { - foreach($forum_counters as $fid => $counters) - { - // Update stats - $update_array = array( - "threads" => "+{$counters['num_threads']}", - "unapprovedthreads" => "-{$counters['num_threads']}", - "posts" => "+{$counters['num_posts']}", - "unapprovedposts" => "-{$counters['num_unapproved_posts']}", - "deletedposts" => "+{$counters['num_deleted_posts']}" - ); - update_forum_counters($fid, $update_array); - update_forum_lastpost($fid); - } - } - - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counters) - { - $update_array = array( - "postnum" => "+{$counters['num_posts']}", - "threadnum" => "+{$counters['num_threads']}", - ); - update_user_counters($uid, $update_array); - } - } - } - return true; - } - - /** - * Unapprove one or more threads - * - * @param array|int $tids Thread ID(s) - * @return boolean - */ - function unapprove_threads($tids) - { - global $db, $cache, $plugins; - - if(!is_array($tids)) - { - $tids = array($tids); - } - - if(empty($tids)) - { - return false; - } - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $tid_list = implode(',', $tids); - $tid_moved_list = ""; - $comma = ""; - foreach($tids as $tid) - { - $tid_moved_list .= "{$comma}'moved|{$tid}'"; - $comma = ","; - } - - $forum_counters = $user_counters = $posts_to_unapprove = array(); - - foreach($tids as $tid) - { - $thread = get_thread($tid); - $forum = get_forum($thread['fid']); - - if($thread['visible'] == 1 || $thread['visible'] == -1) - { - if(!isset($forum_counters[$forum['fid']])) - { - $forum_counters[$forum['fid']] = array( - 'num_threads' => 0, - 'num_posts' => 0, - 'num_unapprovedthreads' => 0, - 'num_unapprovedposts' => 0, - 'num_deletedthreads' => 0, - 'num_deletedposts' => 0 - ); - } - - if(!isset($user_counters[$thread['uid']])) - { - $user_counters[$thread['uid']] = array( - 'num_posts' => 0, - 'num_threads' => 0 - ); - } - - ++$forum_counters[$forum['fid']]['num_unapprovedthreads']; - $forum_counters[$forum['fid']]['num_unapprovedposts'] += $thread['replies']+$thread['deletedposts']+1; - - if($thread['visible'] == 1) - { - ++$forum_counters[$forum['fid']]['num_threads']; - $forum_counters[$forum['fid']]['num_posts'] += $thread['replies']+1; // Add implied invisible to count - $forum_counters[$forum['fid']]['num_deletedposts'] += $thread['deletedposts']; - } - else - { - ++$forum_counters[$forum['fid']]['num_deletedthreads']; - $forum_counters[$forum['fid']]['num_deletedposts'] += $thread['replies']+$thread['unapprovedposts']+$thread['deletedposts']+1; // Add implied invisible to count - $forum_counters[$forum['fid']]['num_unapprovedposts'] += $thread['unapprovedposts']; - } - - // On unapproving thread update user post counts - if($thread['visible'] == 1 && $forum['usepostcounts'] != 0) - { - $query = $db->simple_select("posts", "COUNT(pid) AS posts, uid", "tid='{$tid}' AND (visible='1' OR pid='{$thread['firstpost']}') AND uid > 0 GROUP BY uid"); - while($counter = $db->fetch_array($query)) - { - $user_counters[$counter['uid']]['num_posts'] += $counter['posts']; - } - } - - if($thread['visible'] == 1 && $forum['usethreadcounts'] != 0 && substr($thread['closed'], 0, 6) != 'moved|') - { - ++$user_counters[$thread['uid']]['num_threads']; - } - - } - $posts_to_unapprove[] = $thread['firstpost']; - } - - $approve = array( - "visible" => 0 - ); - $db->update_query("threads", $approve, "tid IN ($tid_list)"); - // Unapprove redirects, too - $redirect_tids = array(); - $query = $db->simple_select('threads', 'tid', "closed IN ({$tid_moved_list})"); - while($redirect_tid = $db->fetch_field($query, 'tid')) - { - $redirect_tids[] = $redirect_tid; - } - if(!empty($redirect_tids)) - { - $this->unapprove_threads($redirect_tids); - } - if(!empty($posts_to_unapprove)) - { - $db->update_query("posts", $approve, "pid IN (".implode(',', $posts_to_unapprove).")"); - } - - $plugins->run_hooks("class_moderation_unapprove_threads", $tids); - - if(!empty($forum_counters)) - { - foreach($forum_counters as $fid => $counters) - { - // Update stats - $update_array = array( - "threads" => "-{$counters['num_threads']}", - "unapprovedthreads" => "+{$counters['num_unapprovedthreads']}", - "posts" => "-{$counters['num_posts']}", - "unapprovedposts" => "+{$counters['num_unapprovedposts']}", - "deletedthreads" => "-{$counters['num_deletedthreads']}", - "deletedposts" => "-{$counters['num_deletedposts']}" - ); - update_forum_counters($fid, $update_array); - update_forum_lastpost($fid); - } - } - - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counters) - { - $update_array = array( - "postnum" => "-{$counters['num_posts']}", - "threadnum" => "-{$counters['num_threads']}", - ); - update_user_counters($uid, $update_array); - } - } - - return true; - } - - /** - * Delete a specific post - * - * @param int $pid Post ID - * @return boolean - */ - function delete_post($pid) - { - global $db, $cache, $plugins; - - $pid = $plugins->run_hooks("class_moderation_delete_post_start", $pid); - // Get pid, uid, fid, tid, visibility, forum post count status of post - $pid = (int)$pid; - $query = $db->query(" - SELECT p.pid, p.uid, p.fid, p.tid, p.visible, t.visible as threadvisible - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.pid='$pid' - "); - $post = $db->fetch_array($query); - if(!$post) - { - return false; - } - - $forum = get_forum($post['fid']); - // If post counts enabled in this forum and it hasn't already been unapproved, remove 1 - if($forum['usepostcounts'] != 0 && $post['visible'] != -1 && $post['visible'] != 0 && $post['threadvisible'] != 0 && $post['threadvisible'] != -1) - { - update_user_counters($post['uid'], array('postnum' => "-1")); - } - - if(!function_exists("remove_attachments")) - { - require MYBB_ROOT."inc/functions_upload.php"; - } - - // Remove attachments - remove_attachments($pid); - - // Delete the post - $db->delete_query("posts", "pid='$pid'"); - - // Remove any reports attached to this post - $db->delete_query("reportedcontent", "id='{$pid}' AND (type = 'post' OR type = '')"); - - // Update unapproved post count - if($post['visible'] == 0) - { - $update_array = array( - "unapprovedposts" => "-1" - ); - } - elseif($post['visible'] == -1) - { - $update_array = array( - "deletedposts" => "-1" - ); - } - else - { - $update_array = array( - "replies" => "-1" - ); - } - - $plugins->run_hooks("class_moderation_delete_post", $post['pid']); - - update_thread_counters($post['tid'], $update_array); - update_last_post($post['tid']); - - // Update unapproved post count - if(($post['visible'] == 0 && $post['threadvisible'] != -1) || $post['threadvisible'] == 0) - { - $update_array = array( - "unapprovedposts" => "-1" - ); - } - elseif($post['visible'] == -1 || $post['threadvisible'] == -1) - { - $update_array = array( - "deletedposts" => "-1" - ); - } - else - { - $update_array = array( - "posts" => "-1" - ); - } - - update_forum_counters($post['fid'], $update_array); - update_forum_lastpost($post['fid']); - - return true; - } - - /** - * Merge posts within thread - * - * @param array $pids Post IDs to be merged - * @param int $tid Thread ID (Set to 0 if posts from multiple threads are selected) - * @return int ID of the post into which all other posts are merged - */ - function merge_posts($pids, $tid=0, $sep="new_line") - { - global $db, $plugins; - - // Make sure we only have valid values - $pids = array_map('intval', $pids); - - if(empty($pids) || count($pids) < 2) - { - return false; - } - - $pidin = implode(',', $pids); - $attachment_count = 0; - - $first = 1; - // Get the messages to be merged - $query = $db->query(" - SELECT p.pid, p.uid, p.fid, p.tid, p.visible, p.message, t.visible AS threadvisible, t.replies AS threadreplies, t.firstpost AS threadfirstpost, t.unapprovedposts AS threadunapprovedposts, COUNT(a.aid) AS attachmentcount - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."attachments a ON (a.pid=p.pid AND a.visible=1) - WHERE p.pid IN($pidin) - GROUP BY p.pid - ORDER BY p.dateline ASC - "); - $message = ''; - $threads = $forum_counters = $thread_counters = $user_counters = array(); - while($post = $db->fetch_array($query)) - { - $threads[$post['tid']] = $post['tid']; - if(!isset($thread_counters[$post['tid']])) - { - $thread_counters[$post['tid']] = array( - 'replies' => 0, - 'unapprovedposts' => 0, - 'deletedposts' => 0, - 'attachmentcount' => 0 - ); - } - if($first == 1) - { // all posts will be merged into this one - $masterpid = $post['pid']; - $message = $post['message']; - $fid = $post['fid']; - $mastertid = $post['tid']; - $first = 0; - $visible = $post['visible']; - } - else - { - // these are the selected posts - if($sep == "new_line") - { - $message .= "\n\n {$post['message']}"; - } - else - { - $message .= "[hr]{$post['message']}"; - } - - if(!isset($forum_counters[$post['fid']])) - { - $forum_counters[$post['fid']] = array( - 'num_posts' => 0, - 'unapprovedposts' => 0, - 'deletedposts' => 0 - ); - } - - if($post['visible'] == 1) - { - --$thread_counters[$post['tid']]['replies']; - $forum = get_forum($post['fid']); - if(!isset($user_counters[$post['uid']])) - { - $user_counters[$post['uid']] = array( - 'num_posts' => 0, - 'num_threads' => 0 - ); - } - // Subtract 1 from user's post count - if($forum['usepostcounts'] != 0 && $post['threadvisible'] == 1) - { - // Update post count of the user of the merged posts - --$user_counters[$post['uid']]['num_posts']; - } - if($post['threadfirstpost'] == $post['pid'] && $forum['usethreadcounts'] != 0 && $post['threadvisible'] == 1) - { - --$user_counters[$post['uid']]['num_threads']; - } - $thread_counters[$post['tid']]['attachmentcount'] -= $post['attachmentcount']; - } - elseif($post['visible'] == 0) - { - // Subtract 1 unapproved post from post's thread - --$thread_counters[$post['tid']]['unapprovedposts']; - } - elseif($post['visible'] == -1) - { - // Subtract 1 deleted post from post's thread - --$thread_counters[$post['tid']]['deletedposts']; - } - - // Subtract 1 post from post's forum - if($post['threadvisible'] == 1 && $post['visible'] == 1) - { - --$forum_counters[$post['fid']]['num_posts']; - } - elseif($post['threadvisible'] == 0 || ($post['visible'] == 0 && $post['threadvisible'] != -1)) - { - --$forum_counters[$post['fid']]['unapprovedposts']; - } - else - { - --$forum_counters[$post['fid']]['deletedposts']; - } - - // Add attachment count to thread - if($visible == 1) - { - $thread_counters[$mastertid]['attachmentcount'] += $post['attachmentcount']; - } - } - } - - // Update the message - $mergepost = array( - "message" => $db->escape_string($message), - ); - $db->update_query("posts", $mergepost, "pid = '{$masterpid}'"); - - // Delete the extra posts - $db->delete_query("posts", "pid IN({$pidin}) AND pid != '{$masterpid}'"); - - // Update pid for attachments - $mergepost2 = array( - "pid" => $masterpid, - ); - $db->update_query("attachments", $mergepost2, "pid IN({$pidin})"); - - // If the first post of a thread is merged out, the first should be updated - $query = $db->simple_select("threads", "tid, uid, fid, visible", "firstpost IN({$pidin}) AND firstpost != '{$masterpid}'"); - while($thread = $db->fetch_array($query)) - { - // In some cases the first post of a thread changes - // Therefore resync the visible field to make sure they're the same if they're not - $query = $db->simple_select("posts", "pid, uid, visible", "tid='{$thread['tid']}'", array('order_by' => 'dateline', 'order_dir' => 'asc', 'limit' => 1)); - $new_firstpost = $db->fetch_array($query); - if($thread['visible'] != $new_firstpost['visible']) - { - $db->update_query("posts", array('visible' => $thread['visible']), "pid='{$new_firstpost['pid']}'"); - // Correct counters - if($new_firstpost['visible'] == 1) - { - --$thread_counters[$thread['tid']]['replies']; - } - elseif($new_firstpost['visible'] == -1) - { - --$thread_counters[$thread['tid']]['deletedposts']; - } - else - { - --$thread_counters[$thread['tid']]['unapprovedposts']; - } - if($thread['visible'] == 1) - { - ++$thread_counters[$thread['tid']]['replies']; - } - elseif($thread['visible'] == -1) - { - ++$thread_counters[$thread['tid']]['deletedposts']; - } - else - { - ++$thread_counters[$thread['tid']]['unapprovedposts']; - } - } - - if($new_firstpost['uid'] != $thread['uid'] && $forum['usethreadcounts'] != 0 && $thread['visible'] == 1) - { - if(!isset($user_counters[$new_firstpost['uid']])) - { - $user_counters[$new_firstpost['uid']] = array( - 'num_posts' => 0, - 'num_threads' => 0 - ); - } - ++$user_counters[$new_firstpost['uid']]['num_threads']; - } - update_first_post($thread['tid']); - } - - $arguments = array("pids" => $pids, "tid" => $tid); - $plugins->run_hooks("class_moderation_merge_posts", $arguments); - - if(!empty($thread_counters)) - { - foreach($thread_counters as $tid => $counters) - { - $counters = array( - 'replies' => signed($counters['replies']), - 'unapprovedposts' => signed($counters['unapprovedposts']), - 'deletedposts' => signed($counters['deletedposts']), - 'attachmentcount' => signed($counters['attachmentcount']) - ); - update_thread_counters($tid, $counters); - update_last_post($tid); - } - } - - if(!empty($forum_counters)) - { - foreach($forum_counters as $fid => $counters) - { - $updated_forum_stats = array( - 'posts' => signed($counters['num_posts']), - 'unapprovedposts' => signed($counters['unapprovedposts']), - 'deletedposts' => signed($counters['deletedposts']) - ); - update_forum_counters($fid, $updated_forum_stats); - update_forum_lastpost($fid); - } - } - - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counters) - { - $update_array = array( - "postnum" => "+{$counters['num_posts']}", - "threadnum" => "+{$counters['num_threads']}" - ); - update_user_counters($uid, $update_array); - } - } - - return $masterpid; - } - - /** - * Move/copy thread - * - * @param int $tid Thread to be moved - * @param int $new_fid Destination forum - * @param string $method Method of movement (redirect, copy, move) - * @param int $redirect_expire Expiry timestamp for redirect - * @return int Thread ID - */ - function move_thread($tid, $new_fid, $method="redirect", $redirect_expire=0) - { - global $db, $plugins; - - // Get thread info - $tid = (int)$tid; - $new_fid = (int)$new_fid; - $redirect_expire = (int)$redirect_expire; - - $thread = get_thread($tid, true); - - $newforum = get_forum($new_fid); - if(!$thread || !$newforum) - { - return false; - } - $fid = $thread['fid']; - $forum = get_forum($fid); - - $num_threads = $num_unapproved_threads = $num_posts = $num_unapproved_posts = $num_deleted_posts = $num_deleted_threads = 0; - - if($thread['visible'] == 1) - { - $num_threads++; - $num_posts = $thread['replies']+1; - $num_unapproved_posts = $thread['unapprovedposts']; - $num_deleted_posts = $thread['deletedposts']; - } - elseif($thread['visible'] == -1) - { - $num_deleted_threads++; - // Implied forum deleted count for deleted threads - $num_deleted_posts = $thread['replies']+$thread['deletedposts']+$thread['unapprovedposts']+1; - } - else - { - $num_unapproved_threads++; - // Implied forum unapproved count for unapproved threads - $num_unapproved_posts = $thread['replies']+$thread['unapprovedposts']+$thread['deletedposts']+1; - } - - switch($method) - { - case "redirect": // move (and leave redirect) thread - $arguments = array("tid" => $tid, "new_fid" => $new_fid); - $plugins->run_hooks("class_moderation_move_thread_redirect", $arguments); - - $query = $db->simple_select('threads', 'tid', "closed='moved|$tid' AND fid='$new_fid'"); - while($redirect_tid = $db->fetch_field($query, 'tid')) - { - $this->delete_thread($redirect_tid); - } - $changefid = array( - "fid" => $new_fid, - ); - $db->update_query("threads", $changefid, "tid='$tid'"); - $db->update_query("posts", $changefid, "tid='$tid'"); - - // If the thread has a prefix and the destination forum doesn't accept that prefix, remove the prefix - if($thread['prefix'] != 0) - { - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(','||forums||',' LIKE '%,$new_fid,%' OR forums='-1') AND pid='".$thread['prefix']."'"); - break; - default: - $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(CONCAT(',',forums,',') LIKE '%,$new_fid,%' OR forums='-1') AND pid='".$thread['prefix']."'"); - } - if($db->fetch_field($query, "num_prefixes") == 0) - { - $sqlarray = array( - "prefix" => 0, - ); - $db->update_query("threads", $sqlarray, "tid='$tid'"); - } - } - - $threadarray = array( - "fid" => $thread['fid'], - "subject" => $db->escape_string($thread['subject']), - "icon" => $thread['icon'], - "uid" => $thread['uid'], - "username" => $db->escape_string($thread['username']), - "dateline" => $thread['dateline'], - "lastpost" => $thread['lastpost'], - "lastposteruid" => $thread['lastposteruid'], - "lastposter" => $db->escape_string($thread['lastposter']), - "views" => 0, - "replies" => 0, - "closed" => "moved|$tid", - "sticky" => $thread['sticky'], - "visible" => (int)$thread['visible'], - "notes" => '' - ); - $redirect_tid = $db->insert_query("threads", $threadarray); - if($redirect_expire) - { - $this->expire_thread($redirect_tid, $redirect_expire); - } - - // If we're moving back to a forum where we left a redirect, delete the rediect - $query = $db->simple_select("threads", "tid", "closed LIKE 'moved|".(int)$tid."' AND fid='".(int)$new_fid."'"); - while($redirect_tid = $db->fetch_field($query, 'tid')) - { - $this->delete_thread($redirect_tid); - } - break; - case "copy":// copy thread - - $threadarray = array( - "fid" => $new_fid, - "subject" => $db->escape_string($thread['subject']), - "icon" => $thread['icon'], - "uid" => $thread['uid'], - "username" => $db->escape_string($thread['username']), - "dateline" => $thread['dateline'], - "firstpost" => 0, - "lastpost" => $thread['lastpost'], - "lastposteruid" => $thread['lastposteruid'], - "lastposter" => $db->escape_string($thread['lastposter']), - "views" => $thread['views'], - "replies" => $thread['replies'], - "closed" => $thread['closed'], - "sticky" => $thread['sticky'], - "visible" => (int)$thread['visible'], - "unapprovedposts" => $thread['unapprovedposts'], - "deletedposts" => $thread['deletedposts'], - "attachmentcount" => $thread['attachmentcount'], - "prefix" => $thread['prefix'], - "notes" => '' - ); - - $arguments = array("tid" => $tid, "new_fid" => $new_fid); - $plugins->run_hooks("class_moderation_copy_thread", $arguments); - - // If the thread has a prefix and the destination forum doesn't accept that prefix, don't copy the prefix - if($threadarray['prefix'] != 0) - { - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(','||forums||',' LIKE '%,$new_fid,%' OR forums='-1') AND pid='".$thread['prefix']."'"); - break; - default: - $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(CONCAT(',',forums,',') LIKE '%,$new_fid,%' OR forums='-1') AND pid='".$thread['prefix']."'"); - } - if($db->fetch_field($query, "num_prefixes") == 0) - { - $threadarray['prefix'] = 0; - } - } - - $newtid = $db->insert_query("threads", $threadarray); - - if($thread['poll'] != 0) - { - $query = $db->simple_select("polls", "*", "tid = '{$thread['tid']}'"); - $poll = $db->fetch_array($query); - - $poll_array = array( - 'tid' => $newtid, - 'question' => $db->escape_string($poll['question']), - 'dateline' => $poll['dateline'], - 'options' => $db->escape_string($poll['options']), - 'votes' => $poll['votes'], - 'numoptions' => $poll['numoptions'], - 'numvotes' => $poll['numvotes'], - 'timeout' => $poll['timeout'], - 'closed' => $poll['closed'], - 'multiple' => $poll['multiple'], - 'public' => $poll['public'] - ); - $new_pid = $db->insert_query("polls", $poll_array); - - $query = $db->simple_select("pollvotes", "*", "pid = '{$poll['pid']}'"); - while($pollvote = $db->fetch_array($query)) - { - $pollvote_array = array( - 'pid' => $new_pid, - 'uid' => $pollvote['uid'], - 'voteoption' => $pollvote['voteoption'], - 'dateline' => $pollvote['dateline'], - ); - $db->insert_query("pollvotes", $pollvote_array); - } - - $db->update_query("threads", array('poll' => $new_pid), "tid='{$newtid}'"); - } - - $query = $db->simple_select("posts", "*", "tid = '{$thread['tid']}'"); - while($post = $db->fetch_array($query)) - { - $post_array = array( - 'tid' => $newtid, - 'fid' => $new_fid, - 'subject' => $db->escape_string($post['subject']), - 'icon' => $post['icon'], - 'uid' => $post['uid'], - 'username' => $db->escape_string($post['username']), - 'dateline' => $post['dateline'], - 'ipaddress' => $db->escape_binary($post['ipaddress']), - 'includesig' => $post['includesig'], - 'smilieoff' => $post['smilieoff'], - 'edituid' => $post['edituid'], - 'edittime' => $post['edittime'], - 'visible' => $post['visible'], - 'message' => $db->escape_string($post['message']), - ); - $pid = $db->insert_query("posts", $post_array); - - // Properly set our new firstpost in our new thread - if($thread['firstpost'] == $post['pid']) - { - $db->update_query("threads", array('firstpost' => $pid), "tid='{$newtid}'"); - } - - // Insert attachments for this post - $query2 = $db->simple_select("attachments", "*", "pid = '{$post['pid']}'"); - while($attachment = $db->fetch_array($query2)) - { - $attachment_array = array( - 'pid' => $pid, - 'uid' => $attachment['uid'], - 'filename' => $db->escape_string($attachment['filename']), - 'filetype' => $db->escape_string($attachment['filetype']), - 'filesize' => $attachment['filesize'], - 'attachname' => $db->escape_string($attachment['attachname']), - 'downloads' => $attachment['downloads'], - 'visible' => $attachment['visible'], - 'thumbnail' => $db->escape_string($attachment['thumbnail']) - ); - $new_aid = $db->insert_query("attachments", $attachment_array); - - $post['message'] = str_replace("[attachment={$attachment['aid']}]", "[attachment={$new_aid}]", $post['message']); - } - - if(strpos($post['message'], "[attachment=") !== false) - { - $db->update_query("posts", array('message' => $db->escape_string($post['message'])), "pid='{$pid}'"); - } - } - - update_thread_data($newtid); - - $the_thread = $newtid; - break; - default: - case "move": // plain move thread - $arguments = array("tid" => $tid, "new_fid" => $new_fid); - $plugins->run_hooks("class_moderation_move_simple", $arguments); - - $sqlarray = array( - "fid" => $new_fid, - ); - $db->update_query("threads", $sqlarray, "tid='$tid'"); - $db->update_query("posts", $sqlarray, "tid='$tid'"); - - // If the thread has a prefix and the destination forum doesn't accept that prefix, remove the prefix - if($thread['prefix'] != 0) - { - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(','||forums||',' LIKE '%,$new_fid,%' OR forums='-1') AND pid='".$thread['prefix']."'"); - break; - default: - $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(CONCAT(',',forums,',') LIKE '%,$new_fid,%' OR forums='-1') AND pid='".$thread['prefix']."'"); - } - if($db->fetch_field($query, "num_prefixes") == 0) - { - $sqlarray = array( - "prefix" => 0, - ); - $db->update_query("threads", $sqlarray, "tid='$tid'"); - } - } - - // If we're moving back to a forum where we left a redirect, delete the rediect - $query = $db->simple_select("threads", "tid", "closed LIKE 'moved|".(int)$tid."' AND fid='".(int)$new_fid."'"); - while($redirect_tid = $db->fetch_field($query, 'tid')) - { - $this->delete_thread($redirect_tid); - } - break; - } - - // Do post and thread count changes if changing between countable and non-countable forums - $query = $db->query(" - SELECT COUNT(p.pid) AS posts, u.uid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.tid='$tid' AND p.visible=1 - GROUP BY u.uid - ORDER BY posts DESC - "); - while($posters = $db->fetch_array($query)) - { - $pcount = 0; - if($forum['usepostcounts'] == 1 && $method != 'copy' && $newforum['usepostcounts'] == 0 && $thread['visible'] == 1) - { - $pcount -= $posters['posts']; - } - if(($forum['usepostcounts'] == 0 || $method == 'copy') && $newforum['usepostcounts'] == 1 && $thread['visible'] == 1) - { - $pcount += $posters['posts']; - } - - if($pcount > 0) - { - update_user_counters($posters['uid'], array('postnum' => "+$pcount")); - } - elseif($pcount < 0) - { - update_user_counters($posters['uid'], array('postnum' => $pcount)); - } - } - - if($forum['usethreadcounts'] == 1 && $method != 'copy' && $newforum['usethreadcounts'] == 0 && $thread['visible'] == 1) - { - update_user_counters($thread['uid'], array('threadnum' => "-1")); - } - elseif(($forum['usethreadcounts'] == 0 || $method == 'copy') && $newforum['usethreadcounts'] == 1 && $thread['visible'] == 1) - { - update_user_counters($thread['uid'], array('threadnum' => "+1")); - } - - // Update forum counts - $update_array = array( - "threads" => "+{$num_threads}", - "unapprovedthreads" => "+{$num_unapproved_threads}", - "posts" => "+{$num_posts}", - "unapprovedposts" => "+{$num_unapproved_posts}", - "deletedthreads" => "+{$num_deleted_threads}", - "deletedposts" => "+{$num_deleted_posts}" - ); - update_forum_counters($new_fid, $update_array); - update_forum_lastpost($new_fid); - - if($method != "copy") - { - // The redirect needs to be counted, too - if($method == "redirect") - { - if($thread['visible'] == -1) - { - --$num_deleted_threads; - --$num_deleted_posts; - } - elseif($thread['visible'] == 0) - { - --$num_unapproved_threads; - --$num_unapproved_posts; - } - else - { - --$num_threads; - --$num_posts; - } - } - $update_array = array( - "threads" => "-{$num_threads}", - "unapprovedthreads" => "-{$num_unapproved_threads}", - "posts" => "-{$num_posts}", - "unapprovedposts" => "-{$num_unapproved_posts}", - "deletedthreads" => "-{$num_deleted_threads}", - "deletedposts" => "-{$num_deleted_posts}" - ); - update_forum_counters($fid, $update_array); - update_forum_lastpost($fid); - } - - if(isset($newtid)) - { - return $newtid; - } - else - { - // Remove thread subscriptions for the users who no longer have permission to view the thread - $this->remove_thread_subscriptions($tid, false, $new_fid); - - return $tid; - } - } - - /** - * Merge one thread into another - * - * @param int $mergetid Thread that will be merged into destination - * @param int $tid Destination thread - * @param string $subject New thread subject - * @return boolean - */ - function merge_threads($mergetid, $tid, $subject) - { - global $db, $mybb, $mergethread, $thread, $plugins, $cache; - - $mergetid = (int)$mergetid; - $tid = (int)$tid; - - if(!isset($mergethread['tid']) || $mergethread['tid'] != $mergetid) - { - $mergethread = get_thread($mergetid); - } - if(!isset($thread['tid']) || $thread['tid'] != $tid) - { - $thread = get_thread($tid); - } - - if(!$mergethread || !$thread) - { - return false; - } - - $forum_cache = $cache->read('forums'); - - $threadarray = array(); - if(!$thread['poll'] && $mergethread['poll']) - { - $threadarray['poll'] = $mergethread['poll']; - $sqlarray = array( - "tid" => $tid, - ); - $db->update_query("polls", $sqlarray, "tid='".(int)$mergethread['tid']."'"); - } - // Both the old and the new thread have polls? Remove one - elseif($mergethread['poll']) - { - $db->delete_query("polls", "pid='{$mergethread['poll']}'"); - $db->delete_query("pollvotes", "pid='{$mergethread['poll']}'"); - } - - $subject = $db->escape_string($subject); - $threadarray['subject'] = $subject; - - $user_posts = array(); - if($thread['visible'] != $mergethread['visible'] || $forum_cache[$thread['fid']]['usepostcounts'] != $forum_cache[$mergethread['fid']]['usepostcounts']) - { - $query = $db->query(" - SELECT uid, COUNT(pid) AS postnum - FROM ".TABLE_PREFIX."posts - WHERE tid='{$mergetid}' AND visible=1 - GROUP BY uid - "); - while($post = $db->fetch_array($query)) - { - // Update user counters - if($mergethread['visible'] == 1 && $forum_cache[$mergethread['fid']]['usepostcounts'] == 1) - { - $user_posts[$post['uid']]['postnum'] -= $post['postnum']; - } - elseif($thread['visible'] == 1 && $forum_cache[$thread['fid']]['usepostcounts'] == 1) - { - $user_posts[$post['uid']]['postnum'] += $post['postnum']; - } - } - } - - $sqlarray = array( - "tid" => $tid, - "fid" => $thread['fid'], - "replyto" => 0, - ); - $db->update_query("posts", $sqlarray, "tid='{$mergetid}'"); - - $sqlarray = array( - "closed" => "moved|{$tid}", - ); - $db->update_query("threads", $sqlarray, "closed='moved|{$mergetid}'"); - $sqlarray = array( - "tid" => $tid, - ); - - // Update the thread ratings - $new_numrating = $thread['numratings'] + $mergethread['numratings']; - $new_threadrating = $thread['totalratings'] + $mergethread['totalratings']; - - $threadarray["numratings"] = $new_numrating; - $threadarray["totalratings"] = $new_threadrating; - $db->update_query("threads", $threadarray, "tid = '{$tid}'"); - - // Check if we have a thread subscription already for our new thread - $subscriptions = array(); - - $query = $db->simple_select("threadsubscriptions", "tid, uid", "tid='{$mergetid}' OR tid='{$tid}'"); - while($subscription = $db->fetch_array($query)) - { - if(!isset($subscriptions[$subscription['tid']])) - { - $subscriptions[$subscription['tid']] = array(); - } - $subscriptions[$subscription['tid']][] = $subscription['uid']; - } - - // Update any subscriptions for the merged thread - if(!empty($subscriptions[$mergetid])) - { - $update_users = array(); - foreach($subscriptions[$mergetid] as $user) - { - if(!isset($subscriptions[$tid]) || !in_array($user, $subscriptions[$tid])) - { - // User doesn't have a $tid subscription - $update_users[] = $user; - } - } - - if(!empty($update_users)) - { - $update_array = array( - "tid" => $tid - ); - - $update_users = implode(",", $update_users); - $db->update_query("threadsubscriptions", $update_array, "tid = '{$mergetid}' AND uid IN ({$update_users})"); - } - } - - // Remove source thread subscriptions - $db->delete_query("threadsubscriptions", "tid = '{$mergetid}'"); - - $arguments = array("mergetid" => $mergetid, "tid" => $tid, "subject" => $subject); - $plugins->run_hooks("class_moderation_merge_threads", $arguments); - - $this->delete_thread($mergetid); - - // Add the former first post - if($mergethread['visible'] == 1) - { - ++$mergethread['replies']; - } - elseif($mergethread['visible'] == -1) - { - ++$mergethread['deletedposts']; - } - else - { - ++$mergethread['unapprovedposts']; - } - - // In some cases the thread we may be merging with may cause us to have a new firstpost if it is an older thread - // Therefore resync the visible field to make sure they're the same if they're not - $query = $db->simple_select("posts", "pid, uid, visible", "tid='{$tid}'", array('order_by' => 'dateline', 'order_dir' => 'asc', 'limit' => 1)); - $new_firstpost = $db->fetch_array($query); - if($thread['visible'] != $new_firstpost['visible']) - { - $db->update_query("posts", array('visible' => $thread['visible']), "pid='{$new_firstpost['pid']}'"); - if($new_firstpost['visible'] == 1 && $forum_cache[$thread['fid']]['usepostcounts'] == 1) - { - --$user_posts[$post['uid']]['postnum']; - } - elseif($thread['visible'] == 1 && $forum_cache[$thread['fid']]['usepostcounts'] == 1) - { - ++$user_posts[$post['uid']]['postnum']; - } - } - // Update first post if needed - if($new_firstpost['pid'] != $thread['firstpost']) - { - update_first_post($thread['tid']); - } - - // Update thread count if thread has a new firstpost and is visible - if($thread['uid'] != $new_firstpost['uid'] && $thread['visible'] == 1 && $forum_cache[$thread['fid']]['usethreadcounts'] == 1) - { - if(!isset($user_posts[$thread['uid']]['threadnum'])) - { - $user_posts[$thread['uid']]['threadnum'] = 0; - } - --$user_posts[$thread['uid']]['threadnum']; - if(!isset($user_posts[$new_firstpost['uid']]['threadnum'])) - { - $user_posts[$new_firstpost['uid']]['threadnum'] = 0; - } - ++$user_posts[$new_firstpost['uid']]['threadnum']; - } - - // Thread is not in current forum - if($mergethread['fid'] != $thread['fid']) - { - // If new thread is unapproved, implied counter comes in to effect - if($thread['visible'] == 0) - { - $updated_stats = array( - "unapprovedposts" => '+'.($mergethread['replies']+$mergethread['unapprovedposts']+$mergethread['deletedposts']) - ); - } - elseif($thread['visible'] == -1) - { - $updated_stats = array( - "deletedposts" => '+'.($mergethread['replies']+$mergethread['deletedposts']+$mergethread['unapprovedposts']) - ); - } - else - { - $updated_stats = array( - "posts" => "+{$mergethread['replies']}", - "unapprovedposts" => "+{$mergethread['unapprovedposts']}", - "deletedposts" => "+{$mergethread['deletedposts']}" - ); - } - update_forum_counters($thread['fid'], $updated_stats); - - // If old thread is unapproved, implied counter comes in to effect - if($mergethread['visible'] == 0) - { - $updated_stats = array( - "unapprovedposts" => '-'.($mergethread['replies']+$mergethread['unapprovedposts']+$mergethread['deletedposts']) - ); - } - elseif($mergethread['visible'] == -1) - { - $updated_stats = array( - "deletedposts" => '-'.($mergethread['replies']+$mergethread['deletedposts']+$mergethread['unapprovedposts']) - ); - } - else - { - $updated_stats = array( - "posts" => "-{$mergethread['replies']}", - "unapprovedposts" => "-{$mergethread['unapprovedposts']}", - "deletedposts" => "-{$mergethread['deletedposts']}" - ); - } - update_forum_counters($mergethread['fid'], $updated_stats); - update_forum_lastpost($mergethread['fid']); - } - // Visibility changed - elseif($mergethread['visible'] != $thread['visible']) - { - $updated_stats = array( - 'posts' => 0, - 'unapprovedposts' => 0, - 'deletedposts' => 0 - ); - - // If old thread is unapproved, implied counter comes in to effect - if($mergethread['visible'] == 0) - { - $updated_stats['unapprovedposts'] -= $mergethread['replies']+$mergethread['deletedposts']; - $updated_stats['posts'] += $mergethread['replies']; - $updated_stats['deletedposts'] += $mergethread['deletedposts']; - } - elseif($mergethread['visible'] == -1) - { - $updated_stats['deletedposts'] -= $mergethread['replies']+$mergethread['unapprovedposts']; - $updated_stats['posts'] += $mergethread['replies']; - $updated_stats['unapprovedposts'] += $mergethread['unapprovedposts']; - } - - // If new thread is unapproved, implied counter comes in to effect - if($thread['visible'] == 0) - { - $updated_stats['unapprovedposts'] += $mergethread['replies']+$mergethread['deletedposts']; - $updated_stats['posts'] -= $mergethread['replies']; - $updated_stats['deletedposts'] -= $mergethread['deletedposts']; - } - elseif($thread['visible'] == -1) - { - $updated_stats['deletedposts'] += $mergethread['replies']+$mergethread['unapprovedposts']; - $updated_stats['posts'] -= $mergethread['replies']; - $updated_stats['unapprovedposts'] -= $mergethread['unapprovedposts']; - } - - $new_stats = array(); - if($updated_stats['posts'] < 0) - { - $new_stats['posts'] = $updated_stats['posts']; - } - elseif($updated_stats['posts'] > 0) - { - $new_stats['posts'] = "+{$updated_stats['posts']}"; - } - - if($updated_stats['unapprovedposts'] < 0) - { - $new_stats['unapprovedposts'] = $updated_stats['unapprovedposts']; - } - elseif($updated_stats['unapprovedposts'] > 0) - { - $new_stats['unapprovedposts'] = "+{$updated_stats['unapprovedposts']}"; - } - - if($updated_stats['deletedposts'] < 0) - { - $new_stats['deletedposts'] = $updated_stats['deletedposts']; - } - elseif($updated_stats['deletedposts'] > 0) - { - $new_stats['deletedposts'] = "+{$updated_stats['deletedposts']}"; - } - - if(!empty($new_stats)) - { - update_forum_counters($mergethread['fid'], $new_stats); - update_forum_lastpost($mergethread['fid']); - } - } - - if($thread['visible'] != $new_firstpost['visible']) - { - // Correct counters - if($new_firstpost['visible'] == 1) - { - --$mergethread['replies']; - } - elseif($new_firstpost['visible'] == -1) - { - --$mergethread['deletedposts']; - } - else - { - --$mergethread['unapprovedposts']; - } - if($thread['visible'] == 1) - { - ++$mergethread['replies']; - } - elseif($thread['visible'] == -1) - { - ++$mergethread['deletedposts']; - } - else - { - ++$mergethread['unapprovedposts']; - } - } - - // Update user counters - foreach($user_posts as $uid => $counters) - { - $update_array = array( - "postnum" => "+{$counters['postnum']}", - "threadnum" => "+{$counters['threadnum']}", - ); - update_user_counters($uid, $update_array); - } - - $updated_stats = array( - "replies" => "+{$mergethread['replies']}", - "attachmentcount" => "+{$mergethread['attachmentcount']}", - "unapprovedposts" => "+{$mergethread['unapprovedposts']}", - "deletedposts" => "+{$mergethread['unapprovedposts']}", - "deletedposts" => "+{$mergethread['deletedposts']}" - ); - update_thread_counters($tid, $updated_stats); - update_last_post($tid); - - // Forum last post has to be updated after thread - update_forum_lastpost($thread['fid']); - return true; - } - - /** - * Split posts into a new/existing thread - * - * @param array $pids PIDs of posts to split - * @param int $tid Original thread ID (this is only used as a base for the new - * thread; it can be set to 0 when the posts specified are coming from more - * than 1 thread) - * @param int $moveto Destination forum - * @param string $newsubject New thread subject - * @param int $destination_tid TID if moving into existing thread - * @return int|bool New thread ID or false on failure - */ - function split_posts($pids, $tid, $moveto, $newsubject, $destination_tid=0) - { - global $db, $thread, $plugins, $cache; - - $tid = (int)$tid; - $moveto = (int)$moveto; - $newtid = (int)$destination_tid; - - // Make sure we only have valid values - $pids = array_map('intval', $pids); - - $pids_list = implode(',', $pids); - - // Get forum infos - $forum_cache = $cache->read('forums'); - - if(empty($pids) || !$forum_cache[$moveto]) - { - return false; - } - - // Get the first split post - $query = $db->simple_select('posts', 'pid,uid,visible,icon,username,dateline', 'pid IN ('.$pids_list.')', array('order_by' => 'dateline', 'order_dir' => 'asc', 'limit' => 1)); - - $post_info = $db->fetch_array($query); - - $visible = $post_info['visible']; - - $forum_counters[$moveto] = array( - 'threads' => 0, - 'deletedthreads' => 0, - 'unapprovedthreads' => 0, - 'posts' => 0, - 'unapprovedposts' => 0, - 'deletedposts' => 0 - ); - - if($destination_tid == 0) - { - // Splitting into a new thread - // Create the new thread - $newsubject = $db->escape_string($newsubject); - $newthread = array( - "fid" => $moveto, - "subject" => $newsubject, - "icon" => (int)$post_info['icon'], - "uid" => (int)$post_info['uid'], - "username" => $db->escape_string($post_info['username']), - "dateline" => (int)$post_info['dateline'], - "firstpost" => $post_info['pid'], - "lastpost" => 0, - "lastposter" => '', - "visible" => (int)$visible, - "notes" => '' - ); - $newtid = $db->insert_query("threads", $newthread); - - if($visible == 1) - { - ++$forum_counters[$moveto]['threads']; - if(!isset($user_counters[$newthread['uid']])) - { - $user_counters[$newthread['uid']] = array( - 'postnum' => 0, - 'threadnum' => 0 - ); - } - ++$user_counters[$newthread['uid']]['threadnum']; - } - elseif($visible == -1) - { - ++$forum_counters[$moveto]['deletedthreads']; - } - else - { - // Unapproved thread? - ++$forum_counters[$moveto]['unapprovedthreads']; - } - } - else - { - $newthread = get_thread($newtid); - if(!$newthread) - { - return false; - } - $moveto = $newthread['fid']; - } - - // Get selected posts before moving forums to keep old fid - $original_posts_query = $db->query(" - SELECT p.pid, p.tid, p.fid, p.visible, p.uid, p.dateline, t.visible as threadvisible, t.firstpost, COUNT(a.aid) as postattachmentcount - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (p.tid=t.tid) - LEFT JOIN ".TABLE_PREFIX."attachments a ON (a.pid=p.pid AND a.visible=1) - WHERE p.pid IN ($pids_list) - GROUP BY p.pid - "); - - // Move the selected posts over - $sqlarray = array( - "tid" => $newtid, - "fid" => $moveto, - "replyto" => 0 - ); - $db->update_query("posts", $sqlarray, "pid IN ($pids_list)"); - - $thread_counters[$newtid] = array( - 'replies' => 0, - 'unapprovedposts' => 0, - 'deletedposts' => 0, - 'attachmentcount' => 0 - ); - - // Get posts being merged - while($post = $db->fetch_array($original_posts_query)) - { - if(!isset($thread_counters[$post['tid']])) - { - $thread_counters[$post['tid']] = array( - 'replies' => 0, - 'unapprovedposts' => 0, - 'deletedposts' => 0, - 'attachmentcount' => 0 - ); - } - if(!isset($forum_counters[$post['fid']])) - { - $forum_counters[$post['fid']] = array( - 'posts' => 0, - 'unapprovedposts' => 0, - 'deletedposts' => 0 - ); - } - if(!isset($user_counters[$post['uid']])) - { - $user_counters[$post['uid']] = array( - 'postnum' => 0, - 'threadnum' => 0 - ); - } - if($post['visible'] == 1) - { - // Modify users' post counts - if($post['threadvisible'] == 1 && $forum_cache[$post['fid']]['usepostcounts'] == 1 && ($forum_cache[$moveto]['usepostcounts'] == 0 || $newthread['visible'] != 1)) - { - // Moving into a forum that doesn't count post counts - --$user_counters[$post['uid']]['postnum']; - } - - // Subtract 1 from the old thread's replies - --$thread_counters[$post['tid']]['replies']; - } - elseif($post['visible'] == 0) - { - // Unapproved post - // Subtract 1 from the old thread's unapproved posts - --$thread_counters[$post['tid']]['unapprovedposts']; - } - elseif($post['visible'] == -1) - { - // Soft deleted post - // Subtract 1 from the old thread's deleted posts - --$thread_counters[$post['tid']]['deletedposts']; - } - - // Subtract 1 from the old forum's posts - if($post['threadvisible'] == 1 && $post['visible'] == 1) - { - --$forum_counters[$post['fid']]['posts']; - } - elseif($post['threadvisible'] == 0 || ($post['visible'] == 0 && $post['threadvisible'] == 1)) - { - --$forum_counters[$post['fid']]['unapprovedposts']; - } - else - { - --$forum_counters[$post['fid']]['deletedposts']; - } - - // Subtract attachment counts from old thread and add to new thread (which are counted regardless of post or attachment unapproval at time of coding) - $thread_counters[$post['tid']]['attachmentcount'] -= $post['postattachmentcount']; - $thread_counters[$newtid]['attachmentcount'] += $post['postattachmentcount']; - - if($post['firstpost'] == $post['pid']) - { - // In some cases the first post of a thread changes - // Therefore resync the visible field to make sure they're the same if they're not - $query = $db->simple_select("posts", "pid, visible, uid", "tid='{$post['tid']}'", array('order_by' => 'dateline', 'order_dir' => 'asc', 'limit' => 1)); - $new_firstpost = $db->fetch_array($query); - - if(!isset($user_counters[$new_firstpost['uid']])) - { - $user_counters[$new_firstpost['uid']] = array( - 'postnum' => 0, - 'threadnum' => 0 - ); - } - - // Update post counters if visibility changes - if($post['threadvisible'] != $new_firstpost['visible']) - { - $db->update_query("posts", array('visible' => $post['threadvisible']), "pid='{$new_firstpost['pid']}'"); - // Subtract new first post - if($new_firstpost['visible'] == 1) - { - --$thread_counters[$post['tid']]['replies']; - if($post['threadvisible'] == 1 && $forum_cache[$post['fid']]['usepostcounts'] == 1) - { - --$user_counters[$new_firstpost['uid']]['postnum']; - } - } - elseif($new_firstpost['visible'] == -1) - { - --$thread_counters[$post['tid']]['deletedposts']; - } - else - { - --$thread_counters[$post['tid']]['unapprovedposts']; - } - if($post['threadvisible'] == 0 || ($new_firstpost['visible'] == 0 && $post['threadvisible'] == 1)) - { - --$forum_counters[$post['fid']]['unapprovedposts']; - } - else - { - --$forum_counters[$post['fid']]['deletedposts']; - } - - // Add old first post - if($post['threadvisible'] == 1) - { - ++$thread_counters[$post['tid']]['replies']; - ++$forum_counters[$post['fid']]['posts']; - if($forum_cache[$post['fid']]['usepostcounts'] == 1) - { - ++$user_counters[$new_firstpost['uid']]['postnum']; - } - } - elseif($post['threadvisible'] == -1) - { - ++$thread_counters[$post['tid']]['deletedposts']; - ++$forum_counters[$post['fid']]['deletedposts']; - } - else - { - ++$thread_counters[$post['tid']]['unapprovedposts']; - ++$forum_counters[$post['fid']]['unapprovedposts']; - } - } - - // Update user thread counter if thread opener changes - if($post['threadvisible'] == 1 && $forum_cache[$post['fid']]['usethreadcounts'] == 1 && $post['uid'] != $new_firstpost['uid']) - { - // Subtract thread from old thread opener - --$user_counters[$post['uid']]['threadnum']; - // Add thread to new thread opener - ++$user_counters[$new_firstpost['uid']]['threadnum']; - } - update_first_post($post['tid']); - } - - // This is the new first post of an existing thread? - if($post['pid'] == $post_info['pid'] && $post['dateline'] < $newthread['dateline']) - { - // Update post counters if visibility changes - if($post['visible'] != $newthread['visible']) - { - $db->update_query("posts", array('visible' => $newthread['visible']), "pid='{$post['pid']}'"); - - // This is needed to update the forum counters correctly - $post['visible'] = $newthread['visible']; - } - - // Update user thread counter if thread opener changes - if($newthread['visible'] == 1 && $forum_cache[$newthread['fid']]['usethreadcounts'] == 1 && $post['uid'] != $newthread['uid']) - { - // Add thread to new thread opener - ++$user_counters[$post['uid']]['threadnum']; - if(!isset($user_counters[$newthread['uid']])) - { - $user_counters[$newthread['uid']] = array( - 'postnum' => 0, - 'threadnum' => 0 - ); - } - // Subtract thread from old thread opener - --$user_counters[$newthread['uid']]['threadnum']; - } - update_first_post($newtid); - } - - if($post['visible'] == 1) - { - // Modify users' post counts - if($newthread['visible'] == 1 && ($forum_cache[$post['fid']]['usepostcounts'] == 0 || $post['threadvisible'] != 1) && $forum_cache[$moveto]['usepostcounts'] == 1) - { - // Moving into a forum that does count post counts - ++$user_counters[$post['uid']]['postnum']; - } - - // Add 1 to the new thread's replies - ++$thread_counters[$newtid]['replies']; - } - elseif($post['visible'] == 0) - { - // Unapproved post - // Add 1 to the new thread's unapproved posts - ++$thread_counters[$newtid]['unapprovedposts']; - } - elseif($post['visible'] == -1) - { - // Soft deleted post - // Add 1 to the new thread's deleted posts - ++$thread_counters[$newtid]['deletedposts']; - } - - // Add 1 to the new forum's posts - if($newthread['visible'] == 1 && $post['visible'] == 1) - { - ++$forum_counters[$moveto]['posts']; - } - elseif($newthread['visible'] == 0 || ($post['visible'] == 0 && $newthread['visible'] == 1)) - { - ++$forum_counters[$moveto]['unapprovedposts']; - } - else - { - ++$forum_counters[$moveto]['deletedposts']; - } - } - - if($destination_tid == 0 && $newthread['visible'] == 1) - { - // If splitting into a new thread, subtract one from the thread's reply count to compensate for the original post - --$thread_counters[$newtid]['replies']; - } - elseif($destination_tid == 0 && $newthread['visible'] == 0) - { - // If splitting into a new thread, subtract one from the thread's reply count to compensate for the original post - --$thread_counters[$newtid]['unapprovedposts']; - } - elseif($destination_tid == 0 && $newthread['visible'] == -1) - { - // If splitting into a new thread, subtract one from the thread's reply count to compensate for the original post - --$thread_counters[$newtid]['deletedposts']; - } - - $arguments = array("pids" => $pids, "tid" => $tid, "moveto" => $moveto, "newsubject" => $newsubject, "destination_tid" => $destination_tid); - $plugins->run_hooks("class_moderation_split_posts", $arguments); - - // Update user post counts - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counters) - { - foreach($counters as $key => $counter) - { - if($counter >= 0) - { - $counters[$key] = "+{$counter}"; // add the addition operator for query - } - } - update_user_counters($uid, $counters); - } - } - - // Update thread counters - if(is_array($thread_counters)) - { - foreach($thread_counters as $tid => $counters) - { - if($tid == $newtid) - { - // Update the subject of the first post in the new thread - $query = $db->simple_select("posts", "pid", "tid='$newtid'", array('order_by' => 'dateline', 'limit' => 1)); - $newthread = $db->fetch_array($query); - $sqlarray = array( - "subject" => $newsubject, - "replyto" => 0 - ); - $db->update_query("posts", $sqlarray, "pid='{$newthread['pid']}'"); - } - else - { - // Update the subject of the first post in the old thread - $query = $db->query(" - SELECT p.pid, t.subject - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (p.tid=t.tid) - WHERE p.tid='{$tid}' - ORDER BY p.dateline ASC - LIMIT 1 - "); - $oldthread = $db->fetch_array($query); - $sqlarray = array( - "subject" => $db->escape_string($oldthread['subject']), - "replyto" => 0 - ); - $db->update_query("posts", $sqlarray, "pid='{$oldthread['pid']}'"); - } - - foreach($counters as $key => $counter) - { - if($counter >= 0) - { - $counters[$key] = "+{$counter}"; - } - } - update_thread_counters($tid, $counters); - update_last_post($tid); - } - } - - // Update forum counters - if(!empty($forum_counters)) - { - foreach($forum_counters as $fid => $counters) - { - foreach($counters as $key => $counter) - { - if($counter >= 0) - { - $counters[$key] = "+{$counter}"; - } - } - update_forum_counters($fid, $counters); - update_forum_lastpost($fid); - } - } - - return $newtid; - } - - /** - * Move multiple threads to new forum - * - * @param array $tids Thread IDs - * @param int $moveto Destination forum - * @return boolean - */ - function move_threads($tids, $moveto) - { - global $db, $plugins; - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $tid_list = implode(',', $tids); - - $moveto = (int)$moveto; - - $newforum = get_forum($moveto); - - if(empty($tids) || !$newforum) - { - return false; - } - - $total_posts = $total_unapproved_posts = $total_deleted_posts = $total_threads = $total_unapproved_threads = $total_deleted_threads = 0; - $forum_counters = $user_counters = array(); - $query = $db->simple_select("threads", "fid, visible, replies, unapprovedposts, deletedposts, tid, uid", "tid IN ($tid_list)"); - while($thread = $db->fetch_array($query)) - { - $forum = get_forum($thread['fid']); - - if(!isset($forum_counters[$thread['fid']])) - { - $forum_counters[$thread['fid']] = array( - 'posts' => 0, - 'threads' => 0, - 'unapprovedposts' => 0, - 'unapprovedthreads' => 0, - 'deletedthreads' => 0, - 'deletedposts' => 0 - ); - } - - if(!isset($user_counters[$thread['uid']])) - { - $user_counters[$thread['uid']] = array( - 'num_posts' => 0, - 'num_threads' => 0 - ); - } - - if($thread['visible'] == 1) - { - $total_posts += $thread['replies']+1; - $total_unapproved_posts += $thread['unapprovedposts']; - $total_deleted_posts += $thread['deletedposts']; - $forum_counters[$thread['fid']]['posts'] += $thread['replies']+1; - $forum_counters[$thread['fid']]['unapprovedposts'] += $thread['unapprovedposts']; - $forum_counters[$thread['fid']]['deletedposts'] += $thread['deletedposts']; - - $forum_counters[$thread['fid']]['threads']++; - ++$total_threads; - - if($newforum['usethreadcounts'] == 1 && $forum['usethreadcounts'] == 0) - { - ++$user_counters[$thread['uid']]['num_threads']; - } - else if($newforum['usethreadcounts'] == 0 && $forum['usethreadcounts'] == 1) - { - --$user_counters[$thread['uid']]['num_threads']; - } - - $query1 = $db->query(" - SELECT COUNT(p.pid) AS posts, u.uid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.tid = '{$thread['tid']}' AND p.visible=1 - GROUP BY u.uid - ORDER BY posts DESC - "); - while($posters = $db->fetch_array($query1)) - { - if(!isset($user_counters[$posters['uid']])) - { - $user_counters[$posters['uid']] = array( - 'num_posts' => 0, - 'num_threads' => 0 - ); - } - - if($newforum['usepostcounts'] != 0 && $forum['usepostcounts'] == 0) - { - $user_counters[$posters['uid']]['num_posts'] += $posters['posts']; - } - else if($newforum['usepostcounts'] == 0 && $forum['usepostcounts'] != 0) - { - $user_counters[$posters['uid']]['num_posts'] -= $posters['posts']; - } - } - } - elseif($thread['visible'] == -1) - { - $total_deleted_posts += $thread['replies']+$thread['unapprovedposts']+$thread['deletedposts']+1; - - $forum_counters[$thread['fid']]['deletedposts'] += $thread['replies']+$thread['unapprovedposts']+$thread['deletedposts']+1; // Implied deleted posts counter for deleted threads - - $forum_counters[$thread['fid']]['deletedthreads']++; - ++$total_deleted_threads; - } - else - { - $total_unapproved_posts += $thread['replies']+$thread['unapprovedposts']+$thread['deletedposts']+1; - - $forum_counters[$thread['fid']]['unapprovedposts'] += $thread['replies']+$thread['unapprovedposts']+$thread['deletedposts']+1; // Implied unapproved posts counter for unapproved threads - - $forum_counters[$thread['fid']]['unapprovedthreads']++; - ++$total_unapproved_threads; - } - - // Remove old redirects - $redirects_query = $db->simple_select('threads', 'tid', "closed='moved|{$thread['tid']}' AND fid='$moveto'"); - while($redirect_tid = $db->fetch_field($redirects_query, 'tid')) - { - $this->delete_thread($redirect_tid); - } - } - - $sqlarray = array( - "fid" => $moveto, - ); - $db->update_query("threads", $sqlarray, "tid IN ($tid_list)"); - $db->update_query("posts", $sqlarray, "tid IN ($tid_list)"); - - // If any of the thread has a prefix and the destination forum doesn't accept that prefix, remove the prefix - $query = $db->simple_select("threads", "tid, prefix", "tid IN ($tid_list) AND prefix != 0"); - while($thread = $db->fetch_array($query)) - { - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(','||forums||',' LIKE '%,$moveto,%' OR forums='-1') AND pid='".$thread['prefix']."'"); - break; - default: - $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(CONCAT(',',forums,',') LIKE '%,$moveto,%' OR forums='-1') AND pid='".$thread['prefix']."'"); - } - if($db->fetch_field($query, "num_prefixes") == 0) - { - $sqlarray = array( - "prefix" => 0, - ); - $db->update_query("threads", $sqlarray, "tid = '{$thread['tid']}'"); - } - } - - $arguments = array("tids" => $tids, "moveto" => $moveto); - $plugins->run_hooks("class_moderation_move_threads", $arguments); - - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counters) - { - $update_array = array( - "postnum" => "+{$counters['num_posts']}", - "threadnum" => "+{$counters['num_threads']}", - ); - update_user_counters($uid, $update_array); - } - } - - if(is_array($forum_counters)) - { - foreach($forum_counters as $fid => $counter) - { - $updated_count = array( - 'posts' => "-{$counter['posts']}", - 'threads' => "-{$counter['threads']}", - 'unapprovedposts' => "-{$counter['unapprovedposts']}", - 'unapprovedthreads' => "-{$counter['unapprovedthreads']}", - 'deletedposts' => "-{$counter['deletedposts']}", - 'deletedthreads' => "-{$counter['deletedthreads']}" - - ); - update_forum_counters($fid, $updated_count); - update_forum_lastpost($fid); - } - } - - $updated_count = array( - "threads" => "+{$total_threads}", - "unapprovedthreads" => "+{$total_unapproved_threads}", - "posts" => "+{$total_posts}", - "unapprovedposts" => "+{$total_unapproved_posts}", - 'deletedposts' => "+{$total_deleted_posts}", - "deletedthreads" => "+{$total_deleted_threads}" - ); - - update_forum_counters($moveto, $updated_count); - update_forum_lastpost($moveto); - - // Remove thread subscriptions for the users who no longer have permission to view the thread - $this->remove_thread_subscriptions($tid_list, false, $moveto); - - return true; - } - - /** - * Approve multiple posts - * - * @param array $pids PIDs - * @return boolean - */ - function approve_posts($pids) - { - global $db, $cache, $plugins; - - $num_posts = 0; - - if(empty($pids)) - { - return false; - } - - // Make sure we only have valid values - $pids = array_map('intval', $pids); - - $pid_list = implode(',', $pids); - $pids = $threads_to_update = array(); - - // Make visible - $approve = array( - "visible" => 1, - ); - - // We have three cases we deal with in these code segments: - // 1) We're approving specific unapproved posts - // 1.1) if the thread is approved - // 1.2) if the thread is unapproved - // 2) We're approving the firstpost of the thread, therefore approving the thread itself - // 3) We're doing both 1 and 2 - $query = $db->query(" - SELECT p.tid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.pid IN ($pid_list) AND p.visible = '0' AND t.firstpost = p.pid AND t.visible = 0 - "); - while($post = $db->fetch_array($query)) - { - // This is the first post in the thread so we're approving the whole thread. - $threads_to_update[] = $post['tid']; - } - - if(!empty($threads_to_update)) - { - $this->approve_threads($threads_to_update); - } - - $thread_counters = $forum_counters = $user_counters = array(); - - $query = $db->query(" - SELECT p.pid, p.tid, p.fid, p.uid, t.visible AS threadvisible - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.pid IN ($pid_list) AND p.visible = '0' AND t.firstpost != p.pid - "); - while($post = $db->fetch_array($query)) - { - $pids[] = $post['pid']; - - if(!isset($thread_counters[$post['tid']])) - { - $thread_counters[$post['tid']] = array( - 'replies' => 0 - ); - } - - ++$thread_counters[$post['tid']]['replies']; - - // If the thread of this post is unapproved then we've already taken into account this counter as implied. - // Updating it again would cause it to double count - if($post['threadvisible'] == 1) - { - if(!isset($forum_counters[$post['fid']])) - { - $forum_counters[$post['fid']] = array( - 'num_posts' => 0 - ); - } - ++$forum_counters[$post['fid']]['num_posts']; - } - - $forum = get_forum($post['fid']); - - // If post counts enabled in this forum and the thread is approved, add 1 - if($forum['usepostcounts'] != 0 && $post['threadvisible'] == 1) - { - if(!isset($user_counters[$post['uid']])) - { - $user_counters[$post['uid']] = 0; - } - ++$user_counters[$post['uid']]; - } - } - - if(empty($pids) && empty($threads_to_update)) - { - return false; - } - - if(!empty($pids)) - { - $where = "pid IN (".implode(',', $pids).")"; - $db->update_query("posts", $approve, $where); - } - - $plugins->run_hooks("class_moderation_approve_posts", $pids); - - if(!empty($thread_counters)) - { - foreach($thread_counters as $tid => $counters) - { - $counters_update = array( - "unapprovedposts" => "-".$counters['replies'], - "replies" => "+".$counters['replies'] - ); - update_thread_counters($tid, $counters_update); - update_last_post($tid); - } - } - - if(!empty($forum_counters)) - { - foreach($forum_counters as $fid => $counters) - { - $updated_forum_stats = array( - 'posts' => "+{$counters['num_posts']}", - 'unapprovedposts' => "-{$counters['num_posts']}", - ); - update_forum_counters($fid, $updated_forum_stats); - update_forum_lastpost($fid); - } - } - - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counter) - { - update_user_counters($uid, array('postnum' => "+{$counter}")); - } - } - - return true; - } - - /** - * Unapprove multiple posts - * - * @param array $pids PIDs - * @return boolean - */ - function unapprove_posts($pids) - { - global $db, $cache, $plugins; - - if(empty($pids)) - { - return false; - } - - // Make sure we only have valid values - $pids = array_map('intval', $pids); - - $pid_list = implode(',', $pids); - $pids = $threads_to_update = array(); - - // Make invisible - $approve = array( - "visible" => 0, - ); - - // We have three cases we deal with in these code segments: - // 1) We're unapproving specific approved posts - // 1.1) if the thread is approved - // 1.2) if the thread is unapproved - // 1.3) if the thread is deleted - // 2) We're unapproving the firstpost of the thread, therefore unapproving the thread itself - // 3) We're doing both 1 and 2 - $query = $db->query(" - SELECT p.tid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.pid IN ($pid_list) AND p.visible IN (-1,1) AND t.firstpost = p.pid AND t.visible IN (-1,1) - "); - while($post = $db->fetch_array($query)) - { - // This is the first post in the thread so we're unapproving the whole thread. - $threads_to_update[] = $post['tid']; - } - - if(!empty($threads_to_update)) - { - $this->unapprove_threads($threads_to_update); - } - - $thread_counters = $forum_counters = $user_counters = array(); - - $query = $db->query(" - SELECT p.pid, p.tid, p.visible, p.fid, p.uid, t.visible AS threadvisible - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.pid IN ($pid_list) AND p.visible IN (-1,1) AND t.firstpost != p.pid - "); - while($post = $db->fetch_array($query)) - { - $pids[] = $post['pid']; - - if(!isset($thread_counters[$post['tid']])) - { - $thread_counters[$post['tid']] = array( - 'replies' => 0, - 'unapprovedposts' => 0, - 'deletedposts' => 0 - ); - } - - ++$thread_counters[$post['tid']]['unapprovedposts']; - if($post['visible'] == 1) - { - ++$thread_counters[$post['tid']]['replies']; - } - else - { - ++$thread_counters[$post['tid']]['deletedposts']; - } - - if(!isset($forum_counters[$post['fid']])) - { - $forum_counters[$post['fid']] = array( - 'num_posts' => 0, - 'num_unapproved_posts' => 0, - 'num_deleted_posts' => 0 - ); - } - - // If the thread of this post is unapproved then we've already taken into account this counter as implied. - // Updating it again would cause it to double count - if($post['threadvisible'] != 0) - { - ++$forum_counters[$post['fid']]['num_unapproved_posts']; - if($post['visible'] == 1) - { - ++$forum_counters[$post['fid']]['num_posts']; - } - else - { - ++$forum_counters[$post['fid']]['num_deleted_posts']; - } - } - - $forum = get_forum($post['fid']); - - // If post counts enabled in this forum and the thread is approved, subtract 1 - if($forum['usepostcounts'] != 0 && $post['visible'] == 1 && $post['threadvisible'] == 1) - { - if(!isset($user_counters[$post['uid']])) - { - $user_counters[$post['uid']] = 0; - } - --$user_counters[$post['uid']]; - } - } - - if(empty($pids) && empty($threads_to_update)) - { - return false; - } - - if(!empty($pids)) - { - $where = "pid IN (".implode(',', $pids).")"; - $db->update_query("posts", $approve, $where); - } - - $plugins->run_hooks("class_moderation_unapprove_posts", $pids); - - if(!empty($thread_counters)) - { - foreach($thread_counters as $tid => $counters) - { - $counters_update = array( - "unapprovedposts" => "+".$counters['unapprovedposts'], - "replies" => "-".$counters['replies'], - "deletedposts" => "-".$counters['deletedposts'] - ); - - update_thread_counters($tid, $counters_update); - update_last_post($tid); - } - } - - if(!empty($forum_counters)) - { - foreach($forum_counters as $fid => $counters) - { - $updated_forum_stats = array( - 'posts' => "-{$counters['num_posts']}", - 'unapprovedposts' => "+{$counters['num_unapproved_posts']}", - 'deletedposts' => "-{$counters['num_deleted_posts']}" - ); - update_forum_counters($fid, $updated_forum_stats); - update_forum_lastpost($fid); - } - } - - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counter) - { - update_user_counters($uid, array('postnum' => "{$counter}")); - } - } - - return true; - } - - /** - * Change thread subject - * - * @param int|array $tids Thread ID(s) - * @param string $format Format of new subject (with {subject}) - * @return boolean - */ - function change_thread_subject($tids, $format) - { - global $db, $mybb, $plugins; - - // Get tids into list - if(!is_array($tids)) - { - $tids = array($tids); - } - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - if(empty($tids)) - { - return false; - } - - $tid_list = implode(',', $tids); - - // Get original subject - $query = $db->simple_select("threads", "subject, tid", "tid IN ($tid_list)"); - while($thread = $db->fetch_array($query)) - { - // Update threads and first posts with new subject - $subject = str_replace('{username}', $mybb->user['username'], $format); - $subject = str_replace('{subject}', $thread['subject'], $subject); - $new_subject = array( - "subject" => $db->escape_string($subject) - ); - $db->update_query("threads", $new_subject, "tid='{$thread['tid']}'"); - $db->update_query("posts", $new_subject, "tid='{$thread['tid']}' AND replyto='0'"); - } - - $arguments = array("tids" => $tids, "format" => $format); - $plugins->run_hooks("class_moderation_change_thread_subject", $arguments); - - return true; - } - - /** - * Add thread expiry - * - * @param int $tid Thread ID - * @param int $deletetime Timestamp when the thread is deleted - * @return boolean - */ - function expire_thread($tid, $deletetime) - { - global $db, $plugins; - - $tid = (int)$tid; - - if(empty($tid)) - { - return false; - } - - $update_thread = array( - "deletetime" => (int)$deletetime - ); - $db->update_query("threads", $update_thread, "tid='{$tid}'"); - - $arguments = array("tid" => $tid, "deletetime" => $deletetime); - $plugins->run_hooks("class_moderation_expire_thread", $arguments); - - return true; - } - - /** - * Toggle post visibility (approved/unapproved) - * - * @param array $pids Post IDs - * @return boolean true - */ - function toggle_post_visibility($pids) - { - global $db; - - // Make sure we only have valid values - $pids = array_map('intval', $pids); - - $pid_list = implode(',', $pids); - $query = $db->simple_select("posts", 'pid, visible', "pid IN ($pid_list)"); - while($post = $db->fetch_array($query)) - { - if($post['visible'] != 0) - { - $unapprove[] = $post['pid']; - } - else - { - $approve[] = $post['pid']; - } - } - if(is_array($unapprove)) - { - $this->unapprove_posts($unapprove); - } - if(is_array($approve)) - { - $this->approve_posts($approve); - } - return true; - } - - /** - * Toggle post visibility (deleted/restored) - * - * @param array $pids Post IDs - * @return boolean true - */ - function toggle_post_softdelete($pids) - { - global $db; - - // Make sure we only have valid values - $pids = array_map('intval', $pids); - - $pid_list = implode(',', $pids); - $query = $db->simple_select("posts", 'pid, visible', "pid IN ($pid_list)"); - while($post = $db->fetch_array($query)) - { - if($post['visible'] != -1) - { - $delete[] = $post['pid']; - } - else - { - $restore[] = $post['pid']; - } - } - if(is_array($delete)) - { - $this->soft_delete_posts($delete); - } - if(is_array($restore)) - { - $this->restore_posts($restore); - } - return true; - } - - /** - * Toggle thread visibility (approved/unapproved) - * - * @param array $tids Thread IDs - * @param int $fid Forum ID - * @return boolean true - */ - function toggle_thread_visibility($tids, $fid) - { - global $db; - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - $fid = (int)$fid; - - $tid_list = implode(',', $tids); - $query = $db->simple_select("threads", 'tid, visible', "tid IN ($tid_list)"); - while($thread = $db->fetch_array($query)) - { - if($thread['visible'] != 0) - { - $unapprove[] = $thread['tid']; - } - else - { - $approve[] = $thread['tid']; - } - } - if(is_array($unapprove)) - { - $this->unapprove_threads($unapprove, $fid); - } - if(is_array($approve)) - { - $this->approve_threads($approve, $fid); - } - return true; - } - - /** - * Toggle thread visibility (deleted/restored) - * - * @param array $tids Thread IDs - * @return boolean true - */ - function toggle_thread_softdelete($tids) - { - global $db; - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $tid_list = implode(',', $tids); - $query = $db->simple_select("threads", 'tid, visible', "tid IN ($tid_list)"); - while($thread = $db->fetch_array($query)) - { - if($thread['visible'] != -1) - { - $delete[] = $thread['tid']; - } - else - { - $restore[] = $thread['tid']; - } - } - if(is_array($delete)) - { - $this->soft_delete_threads($delete); - } - if(is_array($restore)) - { - $this->restore_threads($restore); - } - return true; - } - - /** - * Toggle threads open/closed - * - * @param array $tids Thread IDs - * @return boolean true - */ - function toggle_thread_status($tids) - { - global $db; - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $tid_list = implode(',', $tids); - $query = $db->simple_select("threads", 'tid, closed', "tid IN ($tid_list)"); - while($thread = $db->fetch_array($query)) - { - if($thread['closed'] == 1) - { - $open[] = $thread['tid']; - } - elseif($thread['closed'] == 0) - { - $close[] = $thread['tid']; - } - } - if(is_array($open)) - { - $this->open_threads($open); - } - if(is_array($close)) - { - $this->close_threads($close); - } - return true; - } - - /** - * Toggle threads stick/unstick - * - * @param array $tids Thread IDs - * @return boolean true - */ - function toggle_thread_importance($tids) - { - global $db; - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $stick = array(); - $unstick = array(); - - $tid_list = implode(',', $tids); - $query = $db->simple_select("threads", 'tid, sticky', "tid IN ($tid_list)"); - while($thread = $db->fetch_array($query)) - { - if($thread['sticky'] == 0) - { - $stick[] = $thread['tid']; - } - elseif($thread['sticky'] == 1) - { - $unstick[] = $thread['tid']; - } - } - if(!empty($stick)) - { - $this->stick_threads($stick); - } - if(!empty($unstick)) - { - $this->unstick_threads($unstick); - } - return true; - } - - /** - * Remove thread subscriptions (from one or multiple threads in the same forum) - * - * @param int|array $tids Thread ID, or an array of thread IDs from the same forum. - * @param boolean $all True (default) to delete all subscriptions, false to only delete subscriptions from users with no permission to read the thread - * @param int $fid (Only applies if $all is false) The forum ID of the thread - * @return boolean - */ - function remove_thread_subscriptions($tids, $all = true, $fid = 0) - { - global $db, $plugins; - - // Format thread IDs - if(!is_array($tids)) - { - $tids = array($tids); - } - - if(empty($tids)) - { - return false; - } - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - $fid = (int)$fid; - - $tids_csv = implode(',', $tids); - - // Delete only subscriptions from users who no longer have permission to read the thread. - if(!$all) - { - // Get groups that cannot view the forum or its threads - $forum_parentlist = get_parent_list($fid); - $query = $db->simple_select("forumpermissions", "gid", "fid IN ({$forum_parentlist}) AND (canview=0 OR canviewthreads=0)"); - $groups = array(); - $additional_groups = ''; - while($group = $db->fetch_array($query)) - { - $groups[] = $group['gid']; - switch($db->type) - { - case "pgsql": - case "sqlite": - $additional_groups .= " OR ','||u.additionalgroups||',' LIKE ',{$group['gid']},'"; - break; - default: - $additional_groups .= " OR CONCAT(',',u.additionalgroups,',') LIKE ',{$group['gid']},'"; - } - } - // If there are groups found, delete subscriptions from users in these groups - if(count($groups) > 0) - { - $groups_csv = implode(',', $groups); - $query = $db->query(" - SELECT s.tid, u.uid - FROM ".TABLE_PREFIX."threadsubscriptions s - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=s.uid) - WHERE s.tid IN ({$tids_csv}) - AND (u.usergroup IN ({$groups_csv}){$additional_groups}) - "); - while($subscription = $db->fetch_array($query)) - { - $db->delete_query("threadsubscriptions", "uid='{$subscription['uid']}' AND tid='{$subscription['tid']}'"); - } - } - } - // Delete all subscriptions of this thread - else - { - $db->delete_query("threadsubscriptions", "tid IN ({$tids_csv})"); - } - - $arguments = array("tids" => $tids, "all" => $all, "fid" => $fid); - $plugins->run_hooks("class_moderation_remove_thread_subscriptions", $arguments); - - return true; - } - - /** - * Apply a thread prefix (to one or multiple threads in the same forum) - * - * @param int|array $tids Thread ID, or an array of thread IDs from the same forum. - * @param int $prefix Prefix ID to apply to the threads - * @return bool - */ - function apply_thread_prefix($tids, $prefix = 0) - { - global $db, $plugins; - - // Format thread IDs - if(!is_array($tids)) - { - $tids = array($tids); - } - - if(empty($tids)) - { - return false; - } - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - $tids_csv = implode(',', $tids); - - $update_thread = array('prefix' => (int)$prefix); - $db->update_query('threads', $update_thread, "tid IN ({$tids_csv})"); - - $arguments = array('tids' => $tids, 'prefix' => $prefix); - - $plugins->run_hooks('class_moderation_apply_thread_prefix', $arguments); - - return true; - } - - /** - * Soft delete multiple posts - * - * @param array $pids PIDs - * @return boolean - */ - function soft_delete_posts($pids) - { - global $db, $cache, $plugins; - - if(empty($pids)) - { - return false; - } - - // Make sure we only have valid values - $pids = array_map('intval', $pids); - - $pid_list = implode(',', $pids); - $pids = $threads_to_update = array(); - - // Make invisible - $update = array( - "visible" => -1, - ); - - // We have three cases we deal with in these code segments: - // 1) We're deleting specific approved posts - // 1.1) if the thread is approved - // 1.2) if the thread is unapproved - // 1.3) if the thread is deleted - // 2) We're deleting the firstpost of the thread, therefore deleting the thread itself - // 3) We're doing both 1 and 2 - $query = $db->query(" - SELECT p.tid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.pid IN ($pid_list) AND p.visible IN (0,1) AND t.firstpost = p.pid AND t.visible IN (0,1) - "); - while($post = $db->fetch_array($query)) - { - // This is the first post in the thread so we're deleting the whole thread. - $threads_to_update[] = $post['tid']; - } - - if(!empty($threads_to_update)) - { - $this->soft_delete_threads($threads_to_update); - } - - $thread_counters = $forum_counters = $user_counters = array(); - - $query = $db->query(" - SELECT p.pid, p.tid, p.visible, f.fid, f.usepostcounts, p.uid, t.visible AS threadvisible - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) - WHERE p.pid IN ($pid_list) AND p.visible IN (0,1) AND t.firstpost != p.pid - "); - while($post = $db->fetch_array($query)) - { - $pids[] = $post['pid']; - - if(!isset($thread_counters[$post['tid']])) - { - $thread_counters[$post['tid']] = array( - 'replies' => 0, - 'unapprovedposts' => 0, - 'deletedposts' => 0 - ); - } - - ++$thread_counters[$post['tid']]['deletedposts']; - if($post['visible'] == 1) - { - ++$thread_counters[$post['tid']]['replies']; - } - else - { - ++$thread_counters[$post['tid']]['unapprovedposts']; - } - - if(!isset($forum_counters[$post['fid']])) - { - $forum_counters[$post['fid']] = array( - 'num_posts' => 0, - 'num_unapproved_posts' => 0, - 'num_deleted_posts' => 0 - ); - } - - // If the thread of this post is deleted then we've already taken into account this counter as implied. - // Updating it again would cause it to double count - if($post['threadvisible'] == 1) - { - ++$forum_counters[$post['fid']]['num_deleted_posts']; - if($post['visible'] == 1) - { - ++$forum_counters[$post['fid']]['num_posts']; - } - else - { - ++$forum_counters[$post['fid']]['num_unapproved_posts']; - } - } - - // If post counts enabled in this forum and the thread is approved, subtract 1 - if($post['usepostcounts'] != 0 && $post['threadvisible'] == 1 && $post['visible'] == 1) - { - if(!isset($user_counters[$post['uid']])) - { - $user_counters[$post['uid']] = 0; - } - --$user_counters[$post['uid']]; - } - } - - if(empty($pids) && empty($threads_to_update)) - { - return false; - } - - if(!empty($pids)) - { - $where = "pid IN (".implode(',', $pids).")"; - $db->update_query("posts", $update, $where); - mark_reports($pids, "posts"); - } - - $plugins->run_hooks("class_moderation_soft_delete_posts", $pids); - - if(is_array($thread_counters)) - { - foreach($thread_counters as $tid => $counters) - { - $counters_update = array( - "unapprovedposts" => "-".$counters['unapprovedposts'], - "replies" => "-".$counters['replies'], - "deletedposts" => "+".$counters['deletedposts'] - ); - - update_thread_counters($tid, $counters_update); - update_last_post($tid); - } - } - - if(is_array($forum_counters)) - { - foreach($forum_counters as $fid => $counters) - { - $updated_forum_stats = array( - 'posts' => "-{$counters['num_posts']}", - 'unapprovedposts' => "-{$counters['num_unapproved_posts']}", - 'deletedposts' => "+{$counters['num_deleted_posts']}" - ); - update_forum_counters($fid, $updated_forum_stats); - update_forum_lastpost($fid); - } - } - - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counter) - { - update_user_counters($uid, array('postnum' => "{$counter}")); - } - } - - return true; - } - - /** - * Restore multiple posts - * - * @param array $pids PIDs - * @return boolean - */ - function restore_posts($pids) - { - global $db, $cache, $plugins; - - $num_posts = 0; - - if(empty($pids)) - { - return false; - } - - // Make sure we only have valid values - $pids = array_map('intval', $pids); - - $pid_list = implode(',', $pids); - $pids = $threads_to_update = array(); - - // Make visible - $update = array( - "visible" => 1, - ); - - // We have three cases we deal with in these code segments: - // 1) We're approving specific restored posts - // 1.1) if the thread is deleted - // 1.2) if the thread is restored - // 2) We're restoring the firstpost of the thread, therefore restoring the thread itself - // 3) We're doing both 1 and 2 - $query = $db->query(" - SELECT p.tid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.pid IN ($pid_list) AND p.visible = '-1' AND t.firstpost = p.pid AND t.visible = -1 - "); - while($post = $db->fetch_array($query)) - { - // This is the first post in the thread so we're approving the whole thread. - $threads_to_update[] = $post['tid']; - } - - if(!empty($threads_to_update)) - { - $this->restore_threads($threads_to_update); - } - - $thread_counters = $forum_counters = $user_counters = array(); - - $query = $db->query(" - SELECT p.pid, p.tid, f.fid, f.usepostcounts, p.uid, t.visible AS threadvisible - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) - WHERE p.pid IN ($pid_list) AND p.visible = '-1' AND t.firstpost != p.pid - "); - while($post = $db->fetch_array($query)) - { - $pids[] = $post['pid']; - - if(!isset($thread_counters[$post['tid']])) - { - $thread_counters[$post['tid']] = array( - 'replies' => 0 - ); - } - - ++$thread_counters[$post['tid']]['replies']; - - // If the thread of this post is deleted then we've already taken into account this counter as implied. - // Updating it again would cause it to double count - if($post['threadvisible'] == 1) - { - if(!isset($forum_counters[$post['fid']])) - { - $forum_counters[$post['fid']] = array( - 'num_posts' => 0 - ); - } - ++$forum_counters[$post['fid']]['num_posts']; - } - - // If post counts enabled in this forum and the thread is approved, add 1 - if($post['usepostcounts'] != 0 && $post['threadvisible'] == 1) - { - if(!isset($user_counters[$post['uid']])) - { - $user_counters[$post['uid']] = 0; - } - ++$user_counters[$post['uid']]; - - } - } - - if(empty($pids) && empty($threads_to_update)) - { - return false; - } - - if(!empty($pids)) - { - $where = "pid IN (".implode(',', $pids).")"; - $db->update_query("posts", $update, $where); - } - - $plugins->run_hooks("class_moderation_restore_posts", $pids); - - if(is_array($thread_counters)) - { - foreach($thread_counters as $tid => $counters) - { - $counters_update = array( - "deletedposts" => "-".$counters['replies'], - "replies" => "+".$counters['replies'] - ); - update_thread_counters($tid, $counters_update); - update_last_post($tid); - } - } - - if(is_array($forum_counters)) - { - foreach($forum_counters as $fid => $counters) - { - $updated_forum_stats = array( - 'posts' => "+{$counters['num_posts']}", - 'deletedposts' => "-{$counters['num_posts']}" - ); - update_forum_counters($fid, $updated_forum_stats); - update_forum_lastpost($fid); - } - } - - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counter) - { - update_user_counters($uid, array('postnum' => "+{$counter}")); - } - } - - return true; - } - - /** - * Restore one or more threads - * - * @param array|int $tids Thread ID(s) - * @return boolean true - */ - function restore_threads($tids) - { - global $db, $cache, $plugins; - - if(!is_array($tids)) - { - $tids = array($tids); - } - - if(empty($tids)) - { - return false; - } - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $tid_list = $forum_counters = $user_counters = $posts_to_restore = array(); - - foreach($tids as $tid) - { - $thread = get_thread($tid); - if(!$thread || $thread['visible'] != -1) - { - continue; - } - $tid_list[] = $thread['tid']; - - $forum = get_forum($thread['fid']); - - if(!isset($forum_counters[$forum['fid']])) - { - $forum_counters[$forum['fid']] = array( - 'num_posts' => 0, - 'num_threads' => 0, - 'num_deleted_posts' => 0, - 'num_unapproved_posts' => 0 - ); - } - - if(!isset($user_counters[$thread['uid']])) - { - $user_counters[$thread['uid']] = array( - 'num_posts' => 0, - 'num_threads' => 0 - ); - } - - ++$forum_counters[$forum['fid']]['num_threads']; - $forum_counters[$forum['fid']]['num_posts'] += $thread['replies']+1; // Remove implied visible from count - $forum_counters[$forum['fid']]['num_deleted_posts'] += $thread['replies']+$thread['unapprovedposts']+1; - $forum_counters[$forum['fid']]['num_unapproved_posts'] += $thread['unapprovedposts']; - - if($forum['usepostcounts'] != 0) - { - // On approving thread restore user post counts - $query = $db->simple_select("posts", "COUNT(pid) as posts, uid", "tid='{$tid}' AND (visible='1' OR pid='{$thread['firstpost']}') AND uid > 0 GROUP BY uid"); - while($counter = $db->fetch_array($query)) - { - if(!isset($user_counters[$counter['uid']]['num_posts'])) - { - $user_counters[$counter['uid']]['num_posts'] = 0; - } - $user_counters[$counter['uid']]['num_posts'] += $counter['posts']; - } - } - - if($forum['usethreadcounts'] != 0 && substr($thread['closed'], 0, 6) != 'moved|') - { - ++$user_counters[$thread['uid']]['num_threads']; - } - - $posts_to_restore[] = $thread['firstpost']; - } - - if(!empty($tid_list)) - { - $tid_moved_list = ""; - $comma = ""; - foreach($tid_list as $tid) - { - $tid_moved_list .= "{$comma}'moved|{$tid}'"; - $comma = ","; - } - $tid_list = implode(',', $tid_list); - $update = array( - "visible" => 1 - ); - $db->update_query("threads", $update, "tid IN ($tid_list)"); - // Restore redirects, too - $redirect_tids = array(); - $query = $db->simple_select('threads', 'tid', "closed IN ({$tid_moved_list})"); - while($redirect_tid = $db->fetch_field($query, 'tid')) - { - $redirect_tids[] = $redirect_tid; - } - if(!empty($redirect_tids)) - { - $this->restore_threads($redirect_tids); - } - if(!empty($posts_to_restore)) - { - $db->update_query("posts", $update, "pid IN (".implode(',', $posts_to_restore).")"); - } - - $plugins->run_hooks("class_moderation_restore_threads", $tids); - - if(is_array($forum_counters)) - { - foreach($forum_counters as $fid => $counters) - { - // Update stats - $update_array = array( - "threads" => "+{$counters['num_threads']}", - "posts" => "+{$counters['num_posts']}", - "unapprovedposts" => "+{$counters['num_unapproved_posts']}", - "deletedposts" => "-{$counters['num_deleted_posts']}", - "deletedthreads" => "-{$counters['num_threads']}" - ); - update_forum_counters($fid, $update_array); - update_forum_lastpost($fid); - } - } - - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counters) - { - $update_array = array( - "postnum" => "+{$counters['num_posts']}", - "threadnum" => "+{$counters['num_threads']}", - ); - update_user_counters($uid, $update_array); - } - } - } - return true; - } - - /** - * Soft delete one or more threads - * - * @param array|int Thread ID(s) - * @return boolean - */ - function soft_delete_threads($tids) - { - global $db, $cache, $plugins; - - if(!is_array($tids)) - { - $tids = array($tids); - } - - if(empty($tids)) - { - return false; - } - - // Make sure we only have valid values - $tids = array_map('intval', $tids); - - $tid_list = implode(',', $tids); - $tid_moved_list = ""; - $comma = ""; - foreach($tids as $tid) - { - $tid_moved_list .= "{$comma}'moved|{$tid}'"; - $comma = ","; - } - - $forum_counters = $user_counters = $posts_to_delete = array(); - - foreach($tids as $tid) - { - $thread = get_thread($tid); - $forum = get_forum($thread['fid']); - - if($thread['visible'] == 1 || $thread['visible'] == 0) - { - if(!isset($forum_counters[$forum['fid']])) - { - $forum_counters[$forum['fid']] = array( - 'num_posts' => 0, - 'num_threads' => 0, - 'num_deleted_threads' => 0, - 'num_deleted_posts' => 0, - 'unapproved_threads' => 0, - 'unapproved_posts' => 0 - ); - } - - if(!isset($user_counters[$thread['uid']])) - { - $user_counters[$thread['uid']] = array( - 'num_posts' => 0, - 'num_threads' => 0 - ); - } - - ++$forum_counters[$forum['fid']]['num_deleted_threads']; - $forum_counters[$forum['fid']]['num_deleted_posts'] += $thread['replies']+$thread['unapprovedposts']+1; - - if($thread['visible'] == 1) - { - ++$forum_counters[$forum['fid']]['num_threads']; - $forum_counters[$forum['fid']]['num_posts'] += $thread['replies']+1; // Add implied invisible to count - $forum_counters[$forum['fid']]['unapproved_posts'] += $thread['unapprovedposts']; - } - else - { - ++$forum_counters[$forum['fid']]['unapproved_threads']; - $forum_counters[$forum['fid']]['unapproved_posts'] += $thread['replies']+$thread['deletedposts']+$thread['unapprovedposts']+1; // Add implied invisible to count - $forum_counters[$forum['fid']]['num_deleted_posts'] += $thread['deletedposts']; - } - - // On unapproving thread update user post counts - if($thread['visible'] == 1 && $forum['usepostcounts'] != 0) - { - $query = $db->simple_select("posts", "COUNT(pid) AS posts, uid", "tid='{$tid}' AND (visible='1' OR pid='{$thread['firstpost']}') AND uid > 0 GROUP BY uid"); - while($counter = $db->fetch_array($query)) - { - if(!isset($user_counters[$counter['uid']]['num_posts'])) - { - $user_counters[$counter['uid']]['num_posts'] = 0; - } - $user_counters[$counter['uid']]['num_posts'] += $counter['posts']; - } - } - - if($thread['visible'] == 1 && $forum['usethreadcounts'] != 0 && substr($thread['closed'], 0, 6) != 'moved|') - { - ++$user_counters[$thread['uid']]['num_threads']; - } - } - $posts_to_delete[] = $thread['firstpost']; - } - - $update = array( - "visible" => -1 - ); - $db->update_query("threads", $update, "tid IN ($tid_list)"); - // Soft delete redirects, too - $redirect_tids = array(); - $query = $db->simple_select('threads', 'tid', "closed IN ({$tid_moved_list})"); - - mark_reports($tids, "threads"); - - while($redirect_tid = $db->fetch_field($query, 'tid')) - { - $redirect_tids[] = $redirect_tid; - } - if(!empty($redirect_tids)) - { - $this->soft_delete_threads($redirect_tids); - } - if(!empty($posts_to_delete)) - { - $db->update_query("posts", $update, "pid IN (".implode(',', $posts_to_delete).")"); - } - - $plugins->run_hooks("class_moderation_soft_delete_threads", $tids); - - if(is_array($forum_counters)) - { - foreach($forum_counters as $fid => $counters) - { - // Update stats - $update_array = array( - "threads" => "-{$counters['num_threads']}", - "unapprovedthreads" => "-{$counters['unapproved_threads']}", - "posts" => "-{$counters['num_posts']}", - "unapprovedposts" => "-{$counters['unapproved_posts']}", - "deletedposts" => "+{$counters['num_deleted_posts']}", - "deletedthreads" => "+{$counters['num_deleted_threads']}" - ); - update_forum_counters($fid, $update_array); - update_forum_lastpost($fid); - } - } - - if(!empty($user_counters)) - { - foreach($user_counters as $uid => $counters) - { - $update_array = array( - "postnum" => "-{$counters['num_posts']}", - "threadnum" => "-{$counters['num_threads']}", - ); - update_user_counters($uid, $update_array); - } - } - - return true; - } -} diff --git a/html/forums/inc/class_parser.php b/html/forums/inc/class_parser.php deleted file mode 100644 index 22c70d7..0000000 --- a/html/forums/inc/class_parser.php +++ /dev/null @@ -1,1728 +0,0 @@ - with clear: both be added at the end of the parsed message - * - * @access public - * @var boolean - */ - public $clear_needed = false; - - /** - * Parses a message with the specified options. - * - * @param string $message The message to be parsed. - * @param array $options Array of yes/no options - allow_html,filter_badwords,allow_mycode,allow_smilies,nl2br,me_username,filter_cdata. - * @return string The parsed message. - */ - function parse_message($message, $options=array()) - { - global $plugins, $mybb; - - $this->clear_needed = false; - - // Set base URL for parsing smilies - $this->base_url = $mybb->settings['bburl']; - - if($this->base_url != "") - { - if(my_substr($this->base_url, my_strlen($this->base_url) -1) != "/") - { - $this->base_url = $this->base_url."/"; - } - } - - // Set the options - $this->options = $options; - - $message = $plugins->run_hooks("parse_message_start", $message); - - // Get rid of carriage returns for they are the workings of the devil - $message = str_replace("\r", "", $message); - - // Filter bad words if requested. - if(!empty($this->options['filter_badwords'])) - { - $message = $this->parse_badwords($message); - } - - // Filter CDATA tags if requested (syndication.php). - if(!empty($this->options['filter_cdata'])) - { - $message = $this->parse_cdata($message); - } - - // If MyCode needs to be replaced, first filter out [code] and [php] tags. - if(!empty($this->options['allow_mycode']) && $mybb->settings['allowcodemycode'] == 1) - { - // This code is reserved and could break codes - $message = str_replace("\n", "\n", $message); - - preg_match_all("#\[(code|php)\](.*?)\[/\\1\](\r\n?|\n?)#si", $message, $code_matches, PREG_SET_ORDER); - $message = preg_replace("#\[(code|php)\](.*?)\[/\\1\](\r\n?|\n?)#si", "\n", $message); - } - - if(empty($this->options['allow_html'])) - { - $message = $this->parse_html($message); - $message = str_replace("<mybb-code>\n", "\n", $message); - } - else - { - // Replace base, meta,script and style tags in our post - these are > dangerous < - $message = preg_replace('#<(/?)(base|meta|script|style)([^>]*)>#i', '<$1$2$3>', $message); - $message = $this->fix_javascript($message); - - $find = array("
    \n", "
    \n"); - $replace = array("\n", "\n"); - $message = str_replace($find, $replace, $message); - } - - // Replace "me" code and slaps if we have a username - if(!empty($this->options['me_username']) && $mybb->settings['allowmemycode'] == 1) - { - global $lang; - - $message = preg_replace('#(>|^|\r|\n)/me ([^\r\n<]*)#i', "\\1* {$this->options['me_username']} \\2", $message); - $message = preg_replace('#(>|^|\r|\n)/slap ([^\r\n<]*)#i', "\\1* {$this->options['me_username']} {$lang->slaps} \\2 {$lang->with_trout}", $message); - } - - // If we can, parse smilies - if(!empty($this->options['allow_smilies'])) - { - $message = $this->parse_smilies($message, $this->options['allow_html']); - } - - // Replace MyCode if requested. - if(!empty($this->options['allow_mycode'])) - { - $message = $this->parse_mycode($message); - } - - // Parse Highlights - if(!empty($this->options['highlight'])) - { - $message = $this->highlight_message($message, $this->options['highlight']); - } - - // Run plugin hooks - $message = $plugins->run_hooks("parse_message", $message); - - if(!empty($this->options['allow_mycode'])) - { - // Now that we're done, if we split up any code tags, parse them and glue it all back together - if(count($code_matches) > 0) - { - foreach($code_matches as $text) - { - if(my_strtolower($text[1]) == "code") - { - // Fix up HTML inside the code tags so it is clean - $text[2] = $this->parse_html($text[2]); - - $code = $this->mycode_parse_code($text[2]); - } - elseif(my_strtolower($text[1]) == "php") - { - $code = $this->mycode_parse_php($text[2]); - } - $message = preg_replace("#\\n?#", $code, $message, 1); - } - } - } - - if(!isset($this->options['nl2br']) || $this->options['nl2br'] != 0) - { - $message = nl2br($message); - // Fix up new lines and block level elements - $message = preg_replace("#(]*>)\s*
    #i", "$1", $message); - $message = preg_replace("#( )+(]*>)#i", "$2", $message); - } - - if($this->clear_needed) - { - $message .= '
    '; - } - - $message = $plugins->run_hooks("parse_message_end", $message); - - return $message; - } - - /** - * Converts HTML in a message to their specific entities whilst allowing unicode characters. - * - * @param string $message The message to be parsed. - * @return string The formatted message. - */ - function parse_html($message) - { - $message = preg_replace("#&(?!\#[0-9]+;)#si", "&", $message); // fix & but allow unicode - $message = str_replace("<","<",$message); - $message = str_replace(">",">",$message); - return $message; - } - - /** - * Generates a cache of MyCode, both standard and custom. - * - * @access private - */ - function cache_mycode() - { - global $cache, $lang, $mybb; - $this->mycode_cache = array(); - - $standard_mycode = $callback_mycode = $nestable_mycode = array(); - $standard_count = $callback_count = $nestable_count = 0; - - if($mybb->settings['allowbasicmycode'] == 1) - { - $standard_mycode['b']['regex'] = "#\[b\](.*?)\[/b\]#si"; - $standard_mycode['b']['replacement'] = "$1"; - - $standard_mycode['u']['regex'] = "#\[u\](.*?)\[/u\]#si"; - $standard_mycode['u']['replacement'] = "$1"; - - $standard_mycode['i']['regex'] = "#\[i\](.*?)\[/i\]#si"; - $standard_mycode['i']['replacement'] = "$1"; - - $standard_mycode['s']['regex'] = "#\[s\](.*?)\[/s\]#si"; - $standard_mycode['s']['replacement'] = "$1"; - - $standard_mycode['hr']['regex'] = "#\[hr\]#si"; - $standard_mycode['hr']['replacement'] = "
    "; - - ++$standard_count; - } - - if($mybb->settings['allowsymbolmycode'] == 1) - { - $standard_mycode['copy']['regex'] = "#\(c\)#i"; - $standard_mycode['copy']['replacement'] = "©"; - - $standard_mycode['tm']['regex'] = "#\(tm\)#i"; - $standard_mycode['tm']['replacement'] = "™"; - - $standard_mycode['reg']['regex'] = "#\(r\)#i"; - $standard_mycode['reg']['replacement'] = "®"; - - ++$standard_count; - } - - if($mybb->settings['allowlinkmycode'] == 1) - { - $callback_mycode['url_simple']['regex'] = "#\[url\]((?!javascript)[a-z]+?://)([^\r\n\"<]+?)\[/url\]#si"; - $callback_mycode['url_simple']['replacement'] = array($this, 'mycode_parse_url_callback1'); - - $callback_mycode['url_simple2']['regex'] = "#\[url\]((?!javascript:)[^\r\n\"<]+?)\[/url\]#i"; - $callback_mycode['url_simple2']['replacement'] = array($this, 'mycode_parse_url_callback2'); - - $callback_mycode['url_complex']['regex'] = "#\[url=((?!javascript)[a-z]+?://)([^\r\n\"<]+?)\](.+?)\[/url\]#si"; - $callback_mycode['url_complex']['replacement'] = array($this, 'mycode_parse_url_callback1'); - - $callback_mycode['url_complex2']['regex'] = "#\[url=((?!javascript:)[^\r\n\"<]+?)\](.+?)\[/url\]#si"; - $callback_mycode['url_complex2']['replacement'] = array($this, 'mycode_parse_url_callback2'); - - ++$callback_count; - } - - if($mybb->settings['allowemailmycode'] == 1) - { - $callback_mycode['email_simple']['regex'] = "#\[email\]((?:[a-zA-Z0-9-_\+\.]+?)@[a-zA-Z0-9-]+\.[a-zA-Z0-9\.-]+(?:\?.*?)?)\[/email\]#i"; - $callback_mycode['email_simple']['replacement'] = array($this, 'mycode_parse_email_callback'); - - $callback_mycode['email_complex']['regex'] = "#\[email=((?:[a-zA-Z0-9-_\+\.]+?)@[a-zA-Z0-9-]+\.[a-zA-Z0-9\.-]+(?:\?.*?)?)\](.*?)\[/email\]#i"; - $callback_mycode['email_complex']['replacement'] = array($this, 'mycode_parse_email_callback'); - - ++$callback_count; - } - - if($mybb->settings['allowcolormycode'] == 1) - { - $nestable_mycode['color']['regex'] = "#\[color=([a-zA-Z]*|\#?[\da-fA-F]{3}|\#?[\da-fA-F]{6})](.*?)\[/color\]#si"; - $nestable_mycode['color']['replacement'] = "$2"; - - ++$nestable_count; - } - - if($mybb->settings['allowsizemycode'] == 1) - { - $nestable_mycode['size']['regex'] = "#\[size=(xx-small|x-small|small|medium|large|x-large|xx-large)\](.*?)\[/size\]#si"; - $nestable_mycode['size']['replacement'] = "$2"; - - $callback_mycode['size_int']['regex'] = "#\[size=([0-9\+\-]+?)\](.*?)\[/size\]#si"; - $callback_mycode['size_int']['replacement'] = array($this, 'mycode_handle_size_callback'); - - ++$nestable_count; - ++$callback_count; - } - - if($mybb->settings['allowfontmycode'] == 1) - { - $nestable_mycode['font']['regex'] = "#\[font=([a-z0-9 ,\-_'\"]+)\](.*?)\[/font\]#si"; - $nestable_mycode['font']['replacement'] = "$2"; - - ++$nestable_count; - } - - if($mybb->settings['allowalignmycode'] == 1) - { - $nestable_mycode['align']['regex'] = "#\[align=(left|center|right|justify)\](.*?)\[/align\]#si"; - $nestable_mycode['align']['replacement'] = "
    $2
    "; - - ++$nestable_count; - } - - $custom_mycode = $cache->read("mycode"); - - // If there is custom MyCode, load it. - if(is_array($custom_mycode)) - { - foreach($custom_mycode as $key => $mycode) - { - $mycode['regex'] = str_replace("\x0", "", $mycode['regex']); - $custom_mycode[$key]['regex'] = "#".$mycode['regex']."#si"; - - ++$standard_count; - } - $mycode = array_merge($standard_mycode, $custom_mycode); - } - else - { - $mycode = $standard_mycode; - } - - // Assign the MyCode to the cache. - foreach($mycode as $code) - { - $this->mycode_cache['standard']['find'][] = $code['regex']; - $this->mycode_cache['standard']['replacement'][] = $code['replacement']; - } - - // Assign the nestable MyCode to the cache. - foreach($nestable_mycode as $code) - { - $this->mycode_cache['nestable'][] = array('find' => $code['regex'], 'replacement' => $code['replacement']); - } - - // Assign the nestable MyCode to the cache. - foreach($callback_mycode as $code) - { - $this->mycode_cache['callback'][] = array('find' => $code['regex'], 'replacement' => $code['replacement']); - } - - $this->mycode_cache['standard_count'] = $standard_count; - $this->mycode_cache['callback_count'] = $callback_count; - $this->mycode_cache['nestable_count'] = $nestable_count; - } - - /** - * Parses MyCode tags in a specific message with the specified options. - * - * @param string $message The message to be parsed. - * @param array $options Array of options in yes/no format. Options are allow_imgcode. - * @return string The parsed message. - */ - function parse_mycode($message, $options=array()) - { - global $lang, $mybb; - - if(empty($this->options)) - { - $this->options = $options; - } - - // Cache the MyCode globally if needed. - if($this->mycode_cache == 0) - { - $this->cache_mycode(); - } - - // Parse quotes first - $message = $this->mycode_parse_quotes($message); - - $message = $this->mycode_auto_url($message); - - $message = str_replace('$', '$', $message); - - // Replace the rest - if($this->mycode_cache['standard_count'] > 0) - { - $message = preg_replace($this->mycode_cache['standard']['find'], $this->mycode_cache['standard']['replacement'], $message); - } - - if($this->mycode_cache['callback_count'] > 0) - { - foreach($this->mycode_cache['callback'] as $replace) - { - $message = preg_replace_callback($replace['find'], $replace['replacement'], $message); - } - } - - // Replace the nestable mycode's - if($this->mycode_cache['nestable_count'] > 0) - { - foreach($this->mycode_cache['nestable'] as $mycode) - { - while(preg_match($mycode['find'], $message)) - { - $message = preg_replace($mycode['find'], $mycode['replacement'], $message); - } - } - } - - // Reset list cache - if($mybb->settings['allowlistmycode'] == 1) - { - $this->list_elements = array(); - $this->list_count = 0; - - // Find all lists - $message = preg_replace_callback("#(\[list(=(a|A|i|I|1))?\]|\[/list\])#si", array($this, 'mycode_prepare_list'), $message); - - // Replace all lists - for($i = $this->list_count; $i > 0; $i--) - { - // Ignores missing end tags - $message = preg_replace_callback("#\s?\[list(=(a|A|i|I|1))?&{$i}\](.*?)(\[/list&{$i}\]|$)(\r\n?|\n?)#si", array($this, 'mycode_parse_list_callback'), $message, 1); - } - } - - // Convert images when allowed. - if(!empty($this->options['allow_imgcode'])) - { - $message = preg_replace_callback("#\[img\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback1'), $message); - $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback2'), $message); - $message = preg_replace_callback("#\[img align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback3'), $message); - $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*) align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback4'), $message); - } - else - { - $message = preg_replace_callback("#\[img\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback1'), $message); - $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback2'), $message); - $message = preg_replace_callback("#\[img align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback3'), $message); - $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*) align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback4'), $message); - } - - // Convert videos when allow. - if(!empty($this->options['allow_videocode'])) - { - $message = preg_replace_callback("#\[video=(.*?)\](.*?)\[/video\]#i", array($this, 'mycode_parse_video_callback'), $message); - } - else - { - $message = preg_replace_callback("#\[video=(.*?)\](.*?)\[/video\]#i", array($this, 'mycode_parse_video_disabled_callback'), $message); - } - - return $message; - } - - /** - * Generates a cache of smilies - * - * @access private - */ - function cache_smilies() - { - global $cache, $mybb, $theme, $templates; - $this->smilies_cache = array(); - - $smilies = $cache->read("smilies"); - if(is_array($smilies)) - { - $extra_class = $onclick = ''; - foreach($smilies as $sid => $smilie) - { - $smilie['find'] = explode("\n", $smilie['find']); - $smilie['image'] = str_replace("{theme}", $theme['imgdir'], $smilie['image']); - $smilie['image'] = htmlspecialchars_uni($mybb->get_asset_url($smilie['image'])); - $smilie['name'] = htmlspecialchars_uni($smilie['name']); - - foreach($smilie['find'] as $s) - { - $s = $this->parse_html($s); - eval("\$smilie_template = \"".$templates->get("smilie", 1, 0)."\";"); - $this->smilies_cache[$s] = $smilie_template; - // workaround for smilies starting with ; - if($s[0] == ";") - { - $this->smilies_cache += array( - "&$s" => "&$s", - "<$s" => "<$s", - ">$s" => ">$s", - ); - } - } - } - } - } - - /** - * Parses smilie code in the specified message. - * - * @param string $message $message The message being parsed. - * @param int $allow_html not used - * @return string The parsed message. - */ - function parse_smilies($message, $allow_html=0) - { - if($this->smilies_cache == 0) - { - $this->cache_smilies(); - } - - // No smilies? - if(!count($this->smilies_cache)) - { - return $message; - } - - // First we take out any of the tags we don't want parsed between (url= etc) - preg_match_all("#\[(url(=[^\]]*)?\]|quote=([^\]]*)?\])|(http|ftp)(s|)://[^\s]*#i", $message, $bad_matches, PREG_PATTERN_ORDER); - if(count($bad_matches[0]) > 0) - { - $message = preg_replace("#\[(url(=[^\]]*)?\]|quote=([^\]]*)?\])|(http|ftp)(s|)://[^\s]*#si", "", $message); - } - - $message = strtr($message, $this->smilies_cache); - - // If we matched any tags previously, swap them back in - if(count($bad_matches[0]) > 0) - { - $message = explode("", $message); - $i = 0; - foreach($bad_matches[0] as $match) - { - $message[$i] .= $match; - $i++; - } - $message = implode("", $message); - } - - return $message; - } - - /** - * Generates a cache of badwords filters. - * - * @access private - */ - function cache_badwords() - { - global $cache; - $this->badwords_cache = array(); - $this->badwords_cache = $cache->read("badwords"); - } - - /** - * Parses a list of filtered/badwords in the specified message. - * - * @param string $message The message to be parsed. - * @param array $options Array of parser options in yes/no format. - * @return string The parsed message. - */ - function parse_badwords($message, $options=array()) - { - if(empty($this->options)) - { - $this->options = $options; - } - - if($this->badwords_cache == 0) - { - $this->cache_badwords(); - } - if(is_array($this->badwords_cache)) - { - reset($this->badwords_cache); - foreach($this->badwords_cache as $bid => $badword) - { - if(!$badword['replacement']) - { - $badword['replacement'] = "*****"; - } - - // Take into account the position offset for our last replacement. - $badword['badword'] = str_replace('\*', '([a-zA-Z0-9_]{1})', preg_quote($badword['badword'], "#")); - - // Ensure we run the replacement enough times but not recursively (i.e. not while(preg_match..)) - $message = preg_replace("#(^|\W)".$badword['badword']."(?=\W|$)#i", '\1'.$badword['replacement'], $message); - } - } - if(!empty($this->options['strip_tags'])) - { - $message = strip_tags($message); - } - return $message; - } - - /** - * Resolves nested CDATA tags in the specified message. - * - * @param string $message The message to be parsed. - * @return string The parsed message. - */ - function parse_cdata($message) - { - $message = str_replace(']]>', ']]]]>', $message); - - return $message; - } - - /** - * Attempts to move any javascript references in the specified message. - * - * @param string The message to be parsed. - * @return string The parsed message. - */ - function fix_javascript($message) - { - $js_array = array( - "#(&\#(0*)106;?|&\#(0*)74;?|&\#x(0*)4a;?|&\#x(0*)6a;?|j)((&\#(0*)97;?|&\#(0*)65;?|a)(&\#(0*)118;?|&\#(0*)86;?|v)(&\#(0*)97;?|&\#(0*)65;?|a)(\s)?(&\#(0*)115;?|&\#(0*)83;?|s)(&\#(0*)99;?|&\#(0*)67;?|c)(&\#(0*)114;?|&\#(0*)82;?|r)(&\#(0*)105;?|&\#(0*)73;?|i)(&\#112;?|&\#(0*)80;?|p)(&\#(0*)116;?|&\#(0*)84;?|t)(&\#(0*)58;?|\:))#i", - "#([\s\"']on)([a-z]+\s*=)#i", - ); - - // Add invisible white space - $message = preg_replace($js_array, "$1\xE2\x80\x8C$2$6", $message); - - return $message; - } - - /** - * Handles fontsize. - * - * @param int $size The original size. - * @param string $text The text within a size tag. - * @return string The parsed text. - */ - function mycode_handle_size($size, $text) - { - global $templates; - - $size = (int)$size; - - if($size < 1) - { - $size = 1; - } - - if($size > 50) - { - $size = 50; - } - - $text = str_replace("\'", "'", $text); - - eval("\$mycode_size = \"".$templates->get("mycode_size_int", 1, 0)."\";"); - return $mycode_size; - } - - /** - * Handles fontsize. - * - * @param array $matches Matches. - * @return string The parsed text. - */ - function mycode_handle_size_callback($matches) - { - return $this->mycode_handle_size($matches[1], $matches[2]); - } - - /** - * Parses quote MyCode. - * - * @param string $message The message to be parsed - * @param boolean $text_only Are we formatting as text? - * @return string The parsed message. - */ - function mycode_parse_quotes($message, $text_only=false) - { - global $lang, $templates, $theme, $mybb; - - // Assign pattern and replace values. - $pattern = "#\[quote\](.*?)\[\/quote\](\r\n?|\n?)#si"; - $pattern_callback = "#\[quote=([\"']|"|)(.*?)(?:\\1)(.*?)(?:[\"']|")?\](.*?)\[/quote\](\r\n?|\n?)#si"; - - if($text_only == false) - { - $replace = "
    $lang->quote$1
    \n"; - $replace_callback = array($this, 'mycode_parse_post_quotes_callback1'); - } - else - { - $replace = "\n{$lang->quote}\n--\n$1\n--\n"; - $replace_callback = array($this, 'mycode_parse_post_quotes_callback2'); - } - - do - { - // preg_replace has erased the message? Restore it... - $previous_message = $message; - $message = preg_replace($pattern, $replace, $message, -1, $count); - $message = preg_replace_callback($pattern_callback, $replace_callback, $message, -1, $count_callback); - if(!$message) - { - $message = $previous_message; - break; - } - } while($count || $count_callback); - - if($text_only == false) - { - $find = array( - "#(\r\n*|\n*)<\/cite>(\r\n*|\n*)#", - "#(\r\n*|\n*)<\/blockquote>#" - ); - - $replace = array( - "
    ", - "" - ); - $message = preg_replace($find, $replace, $message); - } - return $message; - } - - /** - * Parses quotes with post id and/or dateline. - * - * @param string $message The message to be parsed - * @param string $username The username to be parsed - * @param boolean $text_only Are we formatting as text? - * @return string The parsed message. - */ - function mycode_parse_post_quotes($message, $username, $text_only=false) - { - global $lang, $templates, $theme, $mybb; - - $linkback = $date = ""; - - $message = trim($message); - $message = preg_replace("#(^|$)#i", "", $message); - - if(!$message) - { - return ''; - } - - $username .= "'"; - $delete_quote = true; - - preg_match("#pid=(?:"|\"|')?([0-9]+)[\"']?(?:"|\"|')?#i", $username, $match); - if((int)$match[1]) - { - $pid = (int)$match[1]; - $url = $mybb->settings['bburl']."/".get_post_link($pid)."#pid$pid"; - if(defined("IN_ARCHIVE")) - { - $linkback = " [ -> ]"; - } - else - { - eval("\$linkback = \" ".$templates->get("postbit_gotopost", 1, 0)."\";"); - } - - $username = preg_replace("#(?:"|\"|')? pid=(?:"|\"|')?[0-9]+[\"']?(?:"|\"|')?#i", '', $username); - $delete_quote = false; - } - - unset($match); - preg_match("#dateline=(?:"|\"|')?([0-9]+)(?:"|\"|')?#i", $username, $match); - if((int)$match[1]) - { - if($match[1] < TIME_NOW) - { - $postdate = my_date('relative', (int)$match[1]); - $date = " ({$postdate})"; - } - $username = preg_replace("#(?:"|\"|')? dateline=(?:"|\"|')?[0-9]+(?:"|\"|')?#i", '', $username); - $delete_quote = false; - } - - if($delete_quote) - { - $username = my_substr($username, 0, my_strlen($username)-1); - } - - if(!empty($this->options['allow_html'])) - { - $username = htmlspecialchars_uni($username); - } - - if($text_only) - { - return "\n{$username} {$lang->wrote}{$date}\n--\n{$message}\n--\n"; - } - else - { - $span = ""; - if(!$delete_quote) - { - $span = "{$date}"; - } - - eval("\$mycode_quote = \"".$templates->get("mycode_quote_post", 1, 0)."\";"); - return $mycode_quote; - } - } - - /** - * Parses quotes with post id and/or dateline. - * - * @param array $matches Matches. - * @return string The parsed message. - */ - function mycode_parse_post_quotes_callback1($matches) - { - return $this->mycode_parse_post_quotes($matches[4],$matches[2].$matches[3]); - } - - /** - * Parses quotes with post id and/or dateline. - * - * @param array $matches Matches. - * @return string The parsed message. - */ - function mycode_parse_post_quotes_callback2($matches) - { - return $this->mycode_parse_post_quotes($matches[4],$matches[2].$matches[3], true); - } - - /** - * Parses code MyCode. - * - * @param string $code The message to be parsed - * @param boolean $text_only Are we formatting as text? - * @return string The parsed message. - */ - function mycode_parse_code($code, $text_only=false) - { - global $lang, $templates; - - if($text_only == true) - { - return "\n{$lang->code}\n--\n{$code}\n--\n"; - } - - // Clean the string before parsing. - $code = preg_replace('#^(\t*)(\n|\r|\0|\x0B| )*#', '\\1', $code); - $code = rtrim($code); - $original = preg_replace('#^\t*#', '', $code); - - if(empty($original)) - { - return; - } - - $code = str_replace('$', '$', $code); - $code = preg_replace('#\$([0-9])#', '\\\$\\1', $code); - $code = str_replace('\\', '\', $code); - $code = str_replace("\t", '    ', $code); - $code = str_replace(" ", '  ', $code); - - eval("\$mycode_code = \"".$templates->get("mycode_code", 1, 0)."\";"); - return $mycode_code; - } - - /** - * Parses code MyCode. - * - * @param array $matches Matches. - * @return string The parsed message. - */ - function mycode_parse_code_callback($matches) - { - return $this->mycode_parse_code($matches[1], true); - } - - /** - * Parses PHP code MyCode. - * - * @param string $str The message to be parsed - * @param boolean $bare_return Whether or not it should return it as pre-wrapped in a div or not. - * @param boolean $text_only Are we formatting as text? - * @return string The parsed message. - */ - function mycode_parse_php($str, $bare_return = false, $text_only = false) - { - global $lang, $templates; - - if($text_only == true) - { - return "\n{$lang->php_code}\n--\n$str\n--\n"; - } - - // Clean the string before parsing except tab spaces. - $str = preg_replace('#^(\t*)(\n|\r|\0|\x0B| )*#', '\\1', $str); - $str = rtrim($str); - - $original = preg_replace('#^\t*#', '', $str); - - if(empty($original)) - { - return; - } - - // See if open and close tags are provided. - $added_open_tag = false; - if(!preg_match("#^\s*<\?#si", $str)) - { - $added_open_tag = true; - $str = "\s*$#si", $str)) - { - $added_end_tag = true; - $str = $str." \n?>"; - } - - $code = @highlight_string($str, true); - - // Do the actual replacing. - $code = preg_replace('#\s*\s*#i', "", $code); - $code = preg_replace("#\s*#", "", $code); - $code = preg_replace("#(\r\n?|\n?)#", "", $code); - $code = str_replace("\\", '\', $code); - $code = str_replace('$', '$', $code); - $code = preg_replace("#&\#([0-9]+);#si", "&#$1;", $code); - - if($added_open_tag) - { - $code = preg_replace("#<\?php( | )(
    ?)#", "", $code); - } - - if($added_end_tag) - { - $code = str_replace("?>", "
    ", $code); - // Wait a minute. It fails highlighting? Stupid highlighter. - $code = str_replace("?>", "", $code); - } - - $code = preg_replace("##", "", $code); - $code = str_replace("", "
    ", $code); - $code = str_replace("", "
    ", $code); - $code = preg_replace("# *$#", "", $code); - - if($bare_return) - { - return $code; - } - - // Send back the code all nice and pretty - eval("\$mycode_php = \"".$templates->get("mycode_php", 1, 0)."\";"); - return $mycode_php; - } - - /** - * Parses PHP code MyCode. - * - * @param array $matches Matches. - * @return string The parsed message. - */ - function mycode_parse_php_callback($matches) - { - return $this->mycode_parse_php($matches[1], false, true); - } - - /** - * Parses URL MyCode. - * - * @param string $url The URL to link to. - * @param string $name The name of the link. - * @return string The built-up link. - */ - function mycode_parse_url($url, $name="") - { - global $templates; - if(!preg_match("#^[a-z0-9]+://#i", $url)) - { - $url = "http://".$url; - } - - if(!empty($this->options['allow_html'])) - { - $url = $this->parse_html($url); - } - - if(!$name) - { - $name = $url; - } - - if($name == $url && (!isset($this->options['shorten_urls']) || !empty($this->options['shorten_urls']))) - { - $name = htmlspecialchars_decode($name); - if(my_strlen($name) > 55) - { - $name = my_substr($name , 0, 40).'...'.my_substr($name , -10); - } - $name = htmlspecialchars_uni($name); - } - - $nofollow = ''; - if(!empty($this->options['nofollow_on'])) - { - $nofollow = " rel=\"nofollow\""; - } - - // Fix some entities in URLs - $entities = array('$' => '%24', '$' => '%24', '^' => '%5E', '`' => '%60', '[' => '%5B', ']' => '%5D', '{' => '%7B', '}' => '%7D', '"' => '%22', '<' => '%3C', '>' => '%3E', ' ' => '%20'); - $url = str_replace(array_keys($entities), array_values($entities), $url); - - $name = preg_replace("#&\#([0-9]+);#si", "&#$1;", $name); // Fix & but allow unicode - - eval("\$mycode_url = \"".$templates->get("mycode_url", 1, 0)."\";"); - return $mycode_url; - } - - /** - * Parses URL MyCode. - * - * @param array $matches Matches. - * @return string The built-up link. - */ - function mycode_parse_url_callback1($matches) - { - if(!isset($matches[3])) - { - $matches[3] = ''; - } - return $this->mycode_parse_url($matches[1].$matches[2], $matches[3]); - } - - /** - * Parses URL MyCode. - * - * @param array $matches Matches. - * @return string The built-up link. - */ - function mycode_parse_url_callback2($matches) - { - if(!isset($matches[2])) - { - $matches[2] = ''; - } - return $this->mycode_parse_url($matches[1], $matches[2]); - } - - /** - * Parses IMG MyCode. - * - * @param string $url The URL to the image - * @param array $dimensions Optional array of dimensions - * @param string $align - * @return string - */ - function mycode_parse_img($url, $dimensions=array(), $align='') - { - global $lang, $templates; - $url = trim($url); - $url = str_replace("\n", "", $url); - $url = str_replace("\r", "", $url); - - if(!empty($this->options['allow_html'])) - { - $url = $this->parse_html($url); - } - - $css_align = ''; - if($align == "right") - { - $css_align = ' style="float: right;"'; - } - else if($align == "left") - { - $css_align = ' style="float: left;"'; - } - - if($align) - { - $this->clear_needed = true; - } - - $alt = basename($url); - $alt = htmlspecialchars_decode($alt); - if(my_strlen($alt) > 55) - { - $alt = my_substr($alt, 0, 40).'...'.my_substr($alt, -10); - } - $alt = htmlspecialchars_uni($alt); - - $alt = $lang->sprintf($lang->posted_image, $alt); - $width = $height = ''; - if(isset($dimensions[0]) && $dimensions[0] > 0 && isset($dimensions[1]) && $dimensions[1] > 0) - { - $width = " width=\"{$dimensions[0]}\""; - $height = " height=\"{$dimensions[1]}\""; - } - - eval("\$mycode_img = \"".$templates->get("mycode_img", 1, 0)."\";"); - return $mycode_img; - } - - /** - * Parses IMG MyCode. - * - * @param array $matches Matches. - * @return string Image code. - */ - function mycode_parse_img_callback1($matches) - { - return $this->mycode_parse_img($matches[2]); - } - - /** - * Parses IMG MyCode. - * - * @param array $matches Matches. - * @return string Image code. - */ - function mycode_parse_img_callback2($matches) - { - return $this->mycode_parse_img($matches[4], array($matches[1], $matches[2])); - } - - /** - * Parses IMG MyCode. - * - * @param array $matches Matches. - * @return string Image code. - */ - function mycode_parse_img_callback3($matches) - { - return $this->mycode_parse_img($matches[3], array(), $matches[1]); - } - - /** - * Parses IMG MyCode. - * - * @param array $matches Matches. - * @return string Image code. - */ - function mycode_parse_img_callback4($matches) - { - return $this->mycode_parse_img($matches[5], array($matches[1], $matches[2]), $matches[3]); - } - - /** - * Parses IMG MyCode disabled. - * - * @param string $url The URL to the image - * @return string - */ - function mycode_parse_img_disabled($url) - { - global $lang; - $url = trim($url); - $url = str_replace("\n", "", $url); - $url = str_replace("\r", "", $url); - $url = str_replace("\'", "'", $url); - - $image = $lang->sprintf($lang->posted_image, $this->mycode_parse_url($url)); - return $image; - } - - /** - * Parses IMG MyCode disabled. - * - * @param array $matches Matches. - * @return string Image code. - */ - function mycode_parse_img_disabled_callback1($matches) - { - return $this->mycode_parse_img_disabled($matches[2]); - } - - /** - * Parses IMG MyCode disabled. - * - * @param array $matches Matches. - * @return string Image code. - */ - function mycode_parse_img_disabled_callback2($matches) - { - return $this->mycode_parse_img_disabled($matches[4]); - } - - /** - * Parses IMG MyCode disabled. - * - * @param array $matches Matches. - * @return string Image code. - */ - function mycode_parse_img_disabled_callback3($matches) - { - return $this->mycode_parse_img_disabled($matches[3]); - } - - /** - * Parses IMG MyCode disabled. - * - * @param array $matches Matches. - * @return string Image code. - */ - function mycode_parse_img_disabled_callback4($matches) - { - return $this->mycode_parse_img_disabled($matches[5]); - } - - /** - * Parses email MyCode. - * - * @param string $email The email address to link to. - * @param string $name The name for the link. - * @return string The built-up email link. - */ - function mycode_parse_email($email, $name="") - { - global $templates; - - if(!$name) - { - $name = $email; - } - if(preg_match("/^([a-zA-Z0-9-_\+\.]+?)@[a-zA-Z0-9-]+\.[a-zA-Z0-9\.-]+$/si", $email)) - { - $email = $email; - } - elseif(preg_match("/^([a-zA-Z0-9-_\+\.]+?)@[a-zA-Z0-9-]+\.[a-zA-Z0-9\.-]+\?(.*?)$/si", $email)) - { - $email = htmlspecialchars_uni($email); - } - - eval("\$mycode_email = \"".$templates->get("mycode_email", 1, 0)."\";"); - return $mycode_email; - } - - /** - * Parses email MyCode. - * - * @param array $matches Matches - * @return string The built-up email link. - */ - function mycode_parse_email_callback($matches) - { - if(!isset($matches[2])) - { - $matches[2] = ''; - } - return $this->mycode_parse_email($matches[1], $matches[2]); - } - - /** - * Parses video MyCode. - * - * @param string $video The video provider. - * @param string $url The video to link to. - * @return string The built-up video code. - */ - function mycode_parse_video($video, $url) - { - global $templates; - - if(empty($video) || empty($url)) - { - return "[video={$video}]{$url}[/video]"; - } - - $parsed_url = @parse_url(urldecode($url)); - if($parsed_url == false) - { - return "[video={$video}]{$url}[/video]"; - } - - $fragments = array(); - if($parsed_url['fragment']) - { - $fragments = explode("&", $parsed_url['fragment']); - } - - $queries = explode("&", $parsed_url['query']); - - $input = array(); - foreach($queries as $query) - { - list($key, $value) = explode("=", $query); - $key = str_replace("amp;", "", $key); - $input[$key] = $value; - } - - $path = explode('/', $parsed_url['path']); - - switch($video) - { - case "dailymotion": - list($id) = explode('_', $path[2], 2); // http://www.dailymotion.com/video/fds123_title-goes-here - break; - case "metacafe": - $id = $path[2]; // http://www.metacafe.com/watch/fds123/title_goes_here/ - $title = htmlspecialchars_uni($path[3]); - break; - case "myspacetv": - $id = $path[4]; // http://www.myspace.com/video/fds/fds/123 - break; - case "facebook": - if(isset($input['v'])) - { - $id = $input['v']; // http://www.facebook.com/video/video.php?v=123 - } - elseif(substr($path[3], 0, 3) == 'vb.') - { - $id = $path[4]; // https://www.facebook.com/fds/videos/vb.123/123/ - } - else - { - $id = $path[3]; // https://www.facebook.com/fds/videos/123/ - } - break; - case "veoh": - $id = $path[2]; // http://www.veoh.com/watch/123 - break; - case "liveleak": - $id = $input['i']; // http://www.liveleak.com/view?i=123 - break; - case "yahoo": - if(isset($path[2])) - { - $id = $path[2]; // http://xy.screen.yahoo.com/fds/fds-123.html - } - else - { - $id = $path[1]; // http://xy.screen.yahoo.com/fds-123.html - } - // Support for localized portals - $domain = explode('.', $parsed_url['host']); - if($domain[0] != 'screen' && preg_match('#^([a-z-]+)$#', $domain[0])) - { - $local = "{$domain[0]}."; - } - else - { - $local = ''; - } - break; - case "vimeo": - if(isset($path[3])) - { - $id = $path[3]; // http://vimeo.com/fds/fds/fds123 - } - else - { - $id = $path[1]; // http://vimeo.com/fds123 - } - break; - case "youtube": - if($fragments[0]) - { - $id = str_replace('!v=', '', $fragments[0]); // http://www.youtube.com/watch#!v=fds123 - } - elseif($input['v']) - { - $id = $input['v']; // http://www.youtube.com/watch?v=fds123 - } - else - { - $id = $path[1]; // http://www.youtu.be/fds123 - } - break; - case "twitch": - if(isset($path[3])) - { - $id = $path[3]; // https://www.twitch.tv/giantbomb/v/100048090 - } - break; - default: - return "[video={$video}]{$url}[/video]"; - } - - if(empty($id)) - { - return "[video={$video}]{$url}[/video]"; - } - - $id = htmlspecialchars_uni($id); - - eval("\$video_code = \"".$templates->get("video_{$video}_embed")."\";"); - return $video_code; - } - - /** - * Parses video MyCode. - * - * @param array $matches Matches. - * @return string The built-up video code. - */ - function mycode_parse_video_callback($matches) - { - return $this->mycode_parse_video($matches[1], $matches[2]); - } - - /** - * Parses video MyCode disabled. - * - * @param string $url The URL to the video - * @return string - */ - function mycode_parse_video_disabled($url) - { - global $lang; - $url = trim($url); - $url = str_replace("\n", "", $url); - $url = str_replace("\r", "", $url); - $url = str_replace("\'", "'", $url); - - $video = $lang->sprintf($lang->posted_video, $this->mycode_parse_url($url)); - return $video; - } - - /** - * Parses video MyCode disabled. - * - * @param array $matches Matches. - * @return string The built-up video code. - */ - function mycode_parse_video_disabled_callback($matches) - { - return $this->mycode_parse_video_disabled($matches[2]); - } - - /** - * Parses URLs automatically. - * - * @param string $message The message to be parsed - * @return string The parsed message. - */ - function mycode_auto_url($message) - { - $message = " ".$message; - // Links should end with slashes, numbers, characters and braces but not with dots, commas or question marks - $message = preg_replace_callback("#([\>\s\(\)])(http|https|ftp|news|irc|ircs|irc6){1}://([^\/\"\s\<\[\.]+\.([^\/\"\s\<\[\.]+\.)*[\w]+(:[0-9]+)?(/([^\"\s<\[]|\[\])*)?([\w\/\)]))#iu", array($this, 'mycode_auto_url_callback'), $message); - $message = preg_replace_callback("#([\>\s\(\)])(www|ftp)\.(([^\/\"\s\<\[\.]+\.)*[\w]+(:[0-9]+)?(/([^\"\s<\[]|\[\])*)?([\w\/\)]))#iu", array($this, 'mycode_auto_url_callback'), $message); - $message = my_substr($message, 1); - - return $message; - } - - /** - * Parses URLs automatically. - * - * @param array $matches Matches - * @return string The parsed message. - */ - function mycode_auto_url_callback($matches) - { - $external = ''; - // Allow links like http://en.wikipedia.org/wiki/PHP_(disambiguation) but detect mismatching braces - while(my_substr($matches[3], -1) == ')') - { - if(substr_count($matches[3], ')') > substr_count($matches[3], '(')) - { - $matches[3] = my_substr($matches[3], 0, -1); - $external = ')'.$external; - } - else - { - break; - } - - // Example: ([...] http://en.wikipedia.org/Example_(disambiguation).) - $last_char = my_substr($matches[3], -1); - while($last_char == '.' || $last_char == ',' || $last_char == '?' || $last_char == '!') - { - $matches[3] = my_substr($matches[3], 0, -1); - $external = $last_char.$external; - $last_char = my_substr($matches[3], -1); - } - } - if($matches[2] == 'www' || $matches[2] == 'ftp') - { - return "{$matches[1]}[url]{$matches[2]}.{$matches[3]}[/url]{$external}"; - } - else - { - return "{$matches[1]}[url]{$matches[2]}://{$matches[3]}[/url]{$external}"; - } - } - - /** - * Parses list MyCode. - * - * @param string $message The message to be parsed - * @param string $type The list type - * @return string The parsed message. - */ - function mycode_parse_list($message, $type="") - { - // No list elements? That's invalid HTML - if(strpos($message, '[*]') === false) - { - $message = "[*]{$message}"; - } - - $message = preg_replace("#[^\S\n\r]*\[\*\]\s*#", "\n
  • ", $message); - $message .= "
  • "; - - if($type) - { - $list = "\n
      $message
    \n"; - } - else - { - $list = "
      $message
    \n"; - } - $list = preg_replace("#<(ol type=\"$type\"|ul)>\s*#", "<$1>", $list); - return $list; - } - - /** - * Parses list MyCode. - * - * @param array $matches Matches - * @return string The parsed message. - */ - function mycode_parse_list_callback($matches) - { - return $this->mycode_parse_list($matches[3], $matches[2]); - } - - /** - * Prepares list MyCode by finding the matching list tags. - * - * @param array $matches Matches - * @return string Temporary replacements. - */ - function mycode_prepare_list($matches) - { - // Append number to identify matching list tags - if(strcasecmp($matches[1], '[/list]') == 0) - { - $count = array_pop($this->list_elements); - if($count !== NULL) - { - return "[/list&{$count}]"; - } - else - { - // No open list tag... - return $matches[0]; - } - } - else - { - ++$this->list_count; - $this->list_elements[] = $this->list_count; - if(!empty($matches[2])) - { - return "[list{$matches[2]}&{$this->list_count}]"; - } - else - { - return "[list&{$this->list_count}]"; - } - } - } - - /** - * Strips smilies from a string - * - * @param string $message The message for smilies to be stripped from - * @return string The message with smilies stripped - */ - function strip_smilies($message) - { - if($this->smilies_cache == 0) - { - $this->cache_smilies(); - } - if(is_array($this->smilies_cache)) - { - $message = str_replace($this->smilies_cache, array_keys($this->smilies_cache), $message); - } - return $message; - } - - /** - * Highlights a string - * - * @param string $message The message to be highligted - * @param string $highlight The highlight keywords - * @return string The message with highlight bbcodes - */ - function highlight_message($message, $highlight) - { - if(empty($this->highlight_cache)) - { - $this->highlight_cache = build_highlight_array($highlight); - } - - if(is_array($this->highlight_cache) && !empty($this->highlight_cache)) - { - $message = preg_replace(array_keys($this->highlight_cache), $this->highlight_cache, $message); - } - - return $message; - } - - /** - * Parses message to plain text equivalents of MyCode. - * - * @param string $message The message to be parsed - * @param array $options - * @return string The parsed message. - */ - function text_parse_message($message, $options=array()) - { - global $plugins; - - if(empty($this->options)) - { - $this->options = $options; - } - - // Filter bad words if requested. - if(!empty($this->options['filter_badwords'])) - { - $message = $this->parse_badwords($message); - } - - // Parse quotes first - $message = $this->mycode_parse_quotes($message, true); - - $message = preg_replace_callback("#\[php\](.*?)\[/php\](\r\n?|\n?)#is", array($this, 'mycode_parse_php_callback'), $message); - $message = preg_replace_callback("#\[code\](.*?)\[/code\](\r\n?|\n?)#is", array($this, 'mycode_parse_code_callback'), $message); - - $find = array( - "#\[(b|u|i|s|url|email|color|img)\](.*?)\[/\\1\]#is", - "#\[img=([1-9][0-9]*)x([1-9][0-9]*)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", - "#\[url=((?!javascript)[a-z]+?://)([^\r\n\"<]+?)\](.+?)\[/url\]#si", - "#\[url=((?!javascript:)[^\r\n\"<&\(\)]+?)\](.+?)\[/url\]#si", - ); - - $replace = array( - "$2", - "$4", - "$3 ($1$2)", - "$2 ($1)", - ); - $message = preg_replace($find, $replace, $message); - - // Replace "me" code and slaps if we have a username - if(!empty($this->options['me_username'])) - { - global $lang; - - $message = preg_replace('#(>|^|\r|\n)/me ([^\r\n<]*)#i', "\\1* {$this->options['me_username']} \\2", $message); - $message = preg_replace('#(>|^|\r|\n)/slap ([^\r\n<]*)#i', "\\1* {$this->options['me_username']} {$lang->slaps} \\2 {$lang->with_trout}", $message); - } - - // Reset list cache - $this->list_elements = array(); - $this->list_count = 0; - - // Find all lists - $message = preg_replace_callback("#(\[list(=(a|A|i|I|1))?\]|\[/list\])#si", array($this, 'mycode_prepare_list'), $message); - - // Replace all lists - for($i = $this->list_count; $i > 0; $i--) - { - // Ignores missing end tags - $message = preg_replace_callback("#\s?\[list(=(a|A|i|I|1))?&{$i}\](.*?)(\[/list&{$i}\]|$)(\r\n?|\n?)#si", array($this, 'mycode_parse_list_callback'), $message, 1); - } - - // Run plugin hooks - $message = $plugins->run_hooks("text_parse_message", $message); - - return $message; - } -} diff --git a/html/forums/inc/class_plugins.php b/html/forums/inc/class_plugins.php deleted file mode 100644 index 3cb492d..0000000 --- a/html/forums/inc/class_plugins.php +++ /dev/null @@ -1,245 +0,0 @@ -read("plugins"); - if(!empty($plugin_list['active']) && is_array($plugin_list['active'])) - { - foreach($plugin_list['active'] as $plugin) - { - if($plugin != "" && file_exists(MYBB_ROOT."inc/plugins/".$plugin.".php")) - { - require_once MYBB_ROOT."inc/plugins/".$plugin.".php"; - } - } - } - } - - /** - * Add a hook onto which a plugin can be attached. - * - * @param string $hook The hook name. - * @param array|string $function The function of this hook. - * @param int $priority The priority this hook has. - * @param string $file The optional file belonging to this hook. - * @return boolean Whether the hook was added. - */ - function add_hook($hook, $function, $priority=10, $file="") - { - if(is_array($function)) - { - if(!count($function) == 2) - { // must be an array of two items! - return false; - } - - if(is_string($function[0])) - { // Static class method - $method_representation = sprintf('%s::%s', $function[0], $function[1]); - } - elseif(is_object($function[0])) - { // Instance class method - $method_representation = sprintf('%s->%s', get_class($function[0]), $function[1]); - } - else - { // Unknown array type - return false; - } - - // Check to see if we already have this hook running at this priority - if(!empty($this->hooks[$hook][$priority][$method_representation]) && is_array($this->hooks[$hook][$priority][$method_representation])) - { - return true; - } - - // Add the hook - $this->hooks[$hook][$priority][$method_representation] = array( - 'class_method' => $function, - 'file' => $file - ); - } - else - { - // Check to see if we already have this hook running at this priority - if(!empty($this->hooks[$hook][$priority][$function]) && is_array($this->hooks[$hook][$priority][$function])) - { - return true; - } - - // Add the hook - $this->hooks[$hook][$priority][$function] = array( - 'function' => $function, - 'file' => $file - ); - } - - return true; - } - - /** - * Run the hooks that have plugins. - * - * @param string $hook The name of the hook that is run. - * @param mixed $arguments The argument for the hook that is run. The passed value MUST be a variable - * @return mixed The arguments for the hook. - */ - function run_hooks($hook, &$arguments="") - { - if(!isset($this->hooks[$hook]) || !is_array($this->hooks[$hook])) - { - return $arguments; - } - $this->current_hook = $hook; - ksort($this->hooks[$hook]); - foreach($this->hooks[$hook] as $priority => $hooks) - { - if(is_array($hooks)) - { - foreach($hooks as $key => $hook) - { - if($hook['file']) - { - require_once $hook['file']; - } - - if(array_key_exists('class_method', $hook)) - { - $return_args = call_user_func_array($hook['class_method'], array(&$arguments)); - } - else - { - $func = $hook['function']; - - $return_args = $func($arguments); - } - - if($return_args) - { - $arguments = $return_args; - } - } - } - } - $this->current_hook = ''; - - return $arguments; - } - - /** - * Remove a specific hook. - * - * @param string $hook The name of the hook. - * @param array|string $function The function of the hook. - * @param string $file The filename of the plugin. - * @param int $priority The priority of the hook. - * @return bool Whether the hook was removed successfully. - */ - function remove_hook($hook, $function, $file="", $priority=10) - { - if(is_array($function)) - { - if(is_string($function[0])) - { // Static class method - $method_representation = sprintf('%s::%s', $function[0], $function[1]); - } - elseif(is_object($function[0])) - { // Instance class method - $method_representation = sprintf('%s->%s', get_class($function[0]), $function[1]); - } - else - { // Unknown array type - return false; - } - - if(!isset($this->hooks[$hook][$priority][$method_representation])) - { - return true; - } - unset($this->hooks[$hook][$priority][$method_representation]); - } - else - { - // Check to see if we don't already have this hook running at this priority - if(!isset($this->hooks[$hook][$priority][$function])) - { - return true; - } - unset($this->hooks[$hook][$priority][$function]); - } - - return true; - } - - /** - * Establishes if a particular plugin is compatible with this version of MyBB. - * - * @param string $plugin The name of the plugin. - * @return boolean TRUE if compatible, FALSE if incompatible. - */ - function is_compatible($plugin) - { - global $mybb; - - // Ignore potentially missing plugins. - if(!file_exists(MYBB_ROOT."inc/plugins/".$plugin.".php")) - { - return true; - } - - require_once MYBB_ROOT."inc/plugins/".$plugin.".php"; - - $info_func = "{$plugin}_info"; - if(!function_exists($info_func)) - { - return false; - } - $plugin_info = $info_func(); - - // No compatibility set or compatibility = * - assume compatible - if(!$plugin_info['compatibility'] || $plugin_info['compatibility'] == "*") - { - return true; - } - $compatibility = explode(",", $plugin_info['compatibility']); - foreach($compatibility as $version) - { - $version = trim($version); - $version = str_replace("*", ".+", preg_quote($version)); - $version = str_replace("\.+", ".+", $version); - if(preg_match("#{$version}#i", $mybb->version_code)) - { - return true; - } - } - - // Nothing matches - return false; - } -} - diff --git a/html/forums/inc/class_session.php b/html/forums/inc/class_session.php deleted file mode 100644 index faa585e..0000000 --- a/html/forums/inc/class_session.php +++ /dev/null @@ -1,570 +0,0 @@ -ipaddress = get_ip(); - $this->packedip = my_inet_pton($this->ipaddress); - - // Find out the user agent. - $this->useragent = $_SERVER['HTTP_USER_AGENT']; - - // Attempt to find a session id in the cookies. - if(isset($mybb->cookies['sid']) && !defined('IN_UPGRADE')) - { - $sid = $db->escape_string($mybb->cookies['sid']); - // Load the session - $query = $db->simple_select("sessions", "*", "sid='{$sid}' AND ip=".$db->escape_binary($this->packedip)); - $session = $db->fetch_array($query); - if($session['sid']) - { - $this->sid = $session['sid']; - } - } - - // If we have a valid session id and user id, load that users session. - if(!empty($mybb->cookies['mybbuser'])) - { - $logon = explode("_", $mybb->cookies['mybbuser'], 2); - $this->load_user($logon[0], $logon[1]); - } - - // If no user still, then we have a guest. - if(!isset($mybb->user['uid'])) - { - // Detect if this guest is a search engine spider. (bots don't get a cookied session ID so we first see if that's set) - if(!$this->sid) - { - $spiders = $cache->read("spiders"); - if(is_array($spiders)) - { - foreach($spiders as $spider) - { - if(my_strpos(my_strtolower($this->useragent), my_strtolower($spider['useragent'])) !== false) - { - $this->load_spider($spider['sid']); - } - } - } - } - - // Still nothing? JUST A GUEST! - if(!$this->is_spider) - { - $this->load_guest(); - } - } - - // As a token of our appreciation for getting this far (and they aren't a spider), give the user a cookie - if($this->sid && (!isset($mybb->cookies['sid']) || $mybb->cookies['sid'] != $this->sid) && $this->is_spider != true) - { - my_setcookie("sid", $this->sid, -1, true); - } - } - - /** - * Load a user via the user credentials. - * - * @param int $uid The user id. - * @param string $loginkey The user's loginkey. - * @return bool - */ - function load_user($uid, $loginkey='') - { - global $mybb, $db, $time, $lang, $mybbgroups, $cache; - - // Read the banned cache - $bannedcache = $cache->read("banned"); - - // If the banned cache doesn't exist, update it and re-read it - if(!is_array($bannedcache)) - { - $cache->update_banned(); - $bannedcache = $cache->read("banned"); - } - - $uid = (int)$uid; - $query = $db->query(" - SELECT u.*, f.* - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - WHERE u.uid='$uid' - LIMIT 1 - "); - $mybb->user = $db->fetch_array($query); - - if(!empty($bannedcache[$uid])) - { - $banned_user = $bannedcache[$uid]; - $mybb->user['bandate'] = $banned_user['dateline']; - $mybb->user['banlifted'] = $banned_user['lifted']; - $mybb->user['banoldgroup'] = $banned_user['oldgroup']; - $mybb->user['banolddisplaygroup'] = $banned_user['olddisplaygroup']; - $mybb->user['banoldadditionalgroups'] = $banned_user['oldadditionalgroups']; - } - - // Check the password if we're not using a session - if(empty($loginkey) || $loginkey !== $mybb->user['loginkey'] || !$mybb->user['uid']) - { - unset($mybb->user); - $this->uid = 0; - return false; - } - $this->uid = $mybb->user['uid']; - - // Set the logout key for this user - $mybb->user['logoutkey'] = md5($mybb->user['loginkey']); - - // Sort out the private message count for this user. - if(($mybb->user['totalpms'] == -1 || $mybb->user['unreadpms'] == -1) && $mybb->settings['enablepms'] != 0) // Forced recount - { - $update = 0; - if($mybb->user['totalpms'] == -1) - { - $update += 1; - } - if($mybb->user['unreadpms'] == -1) - { - $update += 2; - } - - require_once MYBB_ROOT."inc/functions_user.php"; - $pmcount = update_pm_count('', $update); - if(is_array($pmcount)) - { - $mybb->user = array_merge($mybb->user, $pmcount); - } - } - $mybb->user['pms_total'] = $mybb->user['totalpms']; - $mybb->user['pms_unread'] = $mybb->user['unreadpms']; - - if($mybb->user['lastip'] != $this->packedip && array_key_exists('lastip', $mybb->user) && !defined('IN_UPGRADE')) - { - $lastip_add = ", lastip=".$db->escape_binary($this->packedip); - } - else - { - $lastip_add = ''; - } - - // If the last visit was over 900 seconds (session time out) ago then update lastvisit. - $time = TIME_NOW; - if($time - $mybb->user['lastactive'] > 900) - { - $db->shutdown_query("UPDATE ".TABLE_PREFIX."users SET lastvisit='{$mybb->user['lastactive']}', lastactive='$time'{$lastip_add} WHERE uid='{$mybb->user['uid']}'"); - $mybb->user['lastvisit'] = $mybb->user['lastactive']; - require_once MYBB_ROOT."inc/functions_user.php"; - update_pm_count('', 2); - } - else - { - $timespent = TIME_NOW - $mybb->user['lastactive']; - $db->shutdown_query("UPDATE ".TABLE_PREFIX."users SET lastactive='$time', timeonline=timeonline+$timespent{$lastip_add} WHERE uid='{$mybb->user['uid']}'"); - } - - // Sort out the language and forum preferences. - if($mybb->user['language'] && $lang->language_exists($mybb->user['language'])) - { - $mybb->settings['bblanguage'] = $mybb->user['language']; - } - if($mybb->user['dateformat'] != 0 && $mybb->user['dateformat'] != '') - { - global $date_formats; - if($date_formats[$mybb->user['dateformat']]) - { - $mybb->settings['dateformat'] = $date_formats[$mybb->user['dateformat']]; - } - } - - // Choose time format. - if($mybb->user['timeformat'] != 0 && $mybb->user['timeformat'] != '') - { - global $time_formats; - if($time_formats[$mybb->user['timeformat']]) - { - $mybb->settings['timeformat'] = $time_formats[$mybb->user['timeformat']]; - } - } - - // Find out the threads per page preference. - if($mybb->user['tpp']) - { - $mybb->settings['threadsperpage'] = $mybb->user['tpp']; - } - - // Find out the posts per page preference. - if($mybb->user['ppp']) - { - $mybb->settings['postsperpage'] = $mybb->user['ppp']; - } - - // Does this user prefer posts in classic mode? - if($mybb->user['classicpostbit']) - { - $mybb->settings['postlayout'] = 'classic'; - } - else - { - $mybb->settings['postlayout'] = 'horizontal'; - } - - // Check if this user is currently banned and if we have to lift it. - if(!empty($mybb->user['bandate']) && (isset($mybb->user['banlifted']) && !empty($mybb->user['banlifted'])) && $mybb->user['banlifted'] < $time) // hmmm...bad user... how did you get banned =/ - { - // must have been good.. bans up :D - $db->shutdown_query("UPDATE ".TABLE_PREFIX."users SET usergroup='".(int)$mybb->user['banoldgroup']."', additionalgroups='".$mybb->user['banoldadditionalgroups']."', displaygroup='".(int)$mybb->user['banolddisplaygroup']."' WHERE uid='".$mybb->user['uid']."'"); - $db->shutdown_query("DELETE FROM ".TABLE_PREFIX."banned WHERE uid='".$mybb->user['uid']."'"); - // we better do this..otherwise they have dodgy permissions - $mybb->user['usergroup'] = $mybb->user['banoldgroup']; - $mybb->user['displaygroup'] = $mybb->user['banolddisplaygroup']; - $mybb->user['additionalgroups'] = $mybb->user['banoldadditionalgroups']; - $cache->update_banned(); - - $mybbgroups = $mybb->user['usergroup']; - if($mybb->user['additionalgroups']) - { - $mybbgroups .= ','.$mybb->user['additionalgroups']; - } - } - else if(!empty($mybb->user['bandate']) && (empty($mybb->user['banlifted']) || !empty($mybb->user['banlifted']) && $mybb->user['banlifted'] > $time)) - { - $mybbgroups = $mybb->user['usergroup']; - } - else - { - // Gather a full permission set for this user and the groups they are in. - $mybbgroups = $mybb->user['usergroup']; - if($mybb->user['additionalgroups']) - { - $mybbgroups .= ','.$mybb->user['additionalgroups']; - } - } - - $mybb->usergroup = usergroup_permissions($mybbgroups); - if(!$mybb->user['displaygroup']) - { - $mybb->user['displaygroup'] = $mybb->user['usergroup']; - } - - $mydisplaygroup = usergroup_displaygroup($mybb->user['displaygroup']); - if(is_array($mydisplaygroup)) - { - $mybb->usergroup = array_merge($mybb->usergroup, $mydisplaygroup); - } - - if(!$mybb->user['usertitle']) - { - $mybb->user['usertitle'] = $mybb->usergroup['usertitle']; - } - - // Update or create the session. - if(!defined("NO_ONLINE") && !defined('IN_UPGRADE')) - { - if(!empty($this->sid)) - { - $this->update_session($this->sid, $mybb->user['uid']); - } - else - { - $this->create_session($mybb->user['uid']); - } - } - return true; - } - - /** - * Load a guest user. - * - */ - function load_guest() - { - global $mybb, $time, $db, $lang; - - // Set up some defaults - $time = TIME_NOW; - $mybb->user['usergroup'] = 1; - $mybb->user['username'] = ''; - $mybb->user['uid'] = 0; - $mybbgroups = 1; - $mybb->user['displaygroup'] = 1; - - // Has this user visited before? Lastvisit need updating? - if(isset($mybb->cookies['mybb']['lastvisit'])) - { - if(!isset($mybb->cookies['mybb']['lastactive'])) - { - $mybb->user['lastactive'] = $time; - $mybb->cookies['mybb']['lastactive'] = $mybb->user['lastactive']; - } - else - { - $mybb->user['lastactive'] = (int)$mybb->cookies['mybb']['lastactive']; - } - if($time - $mybb->cookies['mybb']['lastactive'] > 900) - { - my_setcookie("mybb[lastvisit]", $mybb->user['lastactive']); - $mybb->user['lastvisit'] = $mybb->user['lastactive']; - } - else - { - $mybb->user['lastvisit'] = (int)$mybb->cookies['mybb']['lastactive']; - } - } - - // No last visit cookie, create one. - else - { - my_setcookie("mybb[lastvisit]", $time); - $mybb->user['lastvisit'] = $time; - } - - // Update last active cookie. - my_setcookie("mybb[lastactive]", $time); - - // Gather a full permission set for this guest - $mybb->usergroup = usergroup_permissions($mybbgroups); - $mydisplaygroup = usergroup_displaygroup($mybb->user['displaygroup']); - - $mybb->usergroup = array_merge($mybb->usergroup, $mydisplaygroup); - - // Update the online data. - if(!defined("NO_ONLINE") && !defined('IN_UPGRADE')) - { - if(!empty($this->sid)) - { - $this->update_session($this->sid); - } - else - { - $this->create_session(); - } - } - } - - /** - * Load a search engine spider. - * - * @param int $spider_id The ID of the search engine spider - */ - function load_spider($spider_id) - { - global $mybb, $time, $db, $lang; - - // Fetch the spider preferences from the database - $query = $db->simple_select("spiders", "*", "sid='{$spider_id}'"); - $spider = $db->fetch_array($query); - - // Set up some defaults - $time = TIME_NOW; - $this->is_spider = true; - if($spider['usergroup']) - { - $mybb->user['usergroup'] = $spider['usergroup']; - } - else - { - $mybb->user['usergroup'] = 1; - } - $mybb->user['username'] = ''; - $mybb->user['uid'] = 0; - $mybb->user['displaygroup'] = $mybb->user['usergroup']; - - // Set spider language - if($spider['language'] && $lang->language_exists($spider['language'])) - { - $mybb->settings['bblanguage'] = $spider['language']; - } - - // Set spider theme - if($spider['theme']) - { - $mybb->user['style'] = $spider['theme']; - } - - // Gather a full permission set for this spider. - $mybb->usergroup = usergroup_permissions($mybb->user['usergroup']); - $mydisplaygroup = usergroup_displaygroup($mybb->user['displaygroup']); - $mybb->usergroup = array_merge($mybb->usergroup, $mydisplaygroup); - - // Update spider last minute (only do so on two minute intervals - decrease load for quick spiders) - if($spider['lastvisit'] < TIME_NOW-120) - { - $updated_spider = array( - "lastvisit" => TIME_NOW - ); - $db->update_query("spiders", $updated_spider, "sid='{$spider_id}'"); - } - - // Update the online data. - if(!defined("NO_ONLINE") && !defined('IN_UPGRADE')) - { - $this->sid = "bot=".$spider_id; - $this->create_session(); - } - - } - - /** - * Update a user session. - * - * @param int $sid The session id. - * @param int $uid The user id. - */ - function update_session($sid, $uid=0) - { - global $db; - - // Find out what the special locations are. - $speciallocs = $this->get_special_locations(); - if($uid) - { - $onlinedata['uid'] = $uid; - } - else - { - $onlinedata['uid'] = 0; - } - $onlinedata['time'] = TIME_NOW; - - $onlinedata['location'] = $db->escape_string(substr(get_current_location(), 0, 150)); - $onlinedata['useragent'] = $db->escape_string(my_substr($this->useragent, 0, 200)); - - $onlinedata['location1'] = (int)$speciallocs['1']; - $onlinedata['location2'] = (int)$speciallocs['2']; - $onlinedata['nopermission'] = 0; - $sid = $db->escape_string($sid); - - $db->update_query("sessions", $onlinedata, "sid='{$sid}'"); - } - - /** - * Create a new session. - * - * @param int $uid The user id to bind the session to. - */ - function create_session($uid=0) - { - global $db; - $speciallocs = $this->get_special_locations(); - - // If there is a proper uid, delete by uid. - if($uid > 0) - { - $db->delete_query("sessions", "uid='{$uid}'"); - $onlinedata['uid'] = $uid; - } - // Is a spider - delete all other spider references - else if($this->is_spider == true) - { - $db->delete_query("sessions", "sid='{$this->sid}'"); - } - // Else delete by ip. - else - { - $db->delete_query("sessions", "ip=".$db->escape_binary($this->packedip)); - $onlinedata['uid'] = 0; - } - - // If the user is a search enginge spider, ... - if($this->is_spider == true) - { - $onlinedata['sid'] = $this->sid; - } - else - { - $onlinedata['sid'] = md5(random_str(50)); - } - $onlinedata['time'] = TIME_NOW; - $onlinedata['ip'] = $db->escape_binary($this->packedip); - - $onlinedata['location'] = $db->escape_string(substr(get_current_location(), 0, 150)); - $onlinedata['useragent'] = $db->escape_string(my_substr($this->useragent, 0, 200)); - - $onlinedata['location1'] = (int)$speciallocs['1']; - $onlinedata['location2'] = (int)$speciallocs['2']; - $onlinedata['nopermission'] = 0; - $db->replace_query("sessions", $onlinedata, "sid", false); - $this->sid = $onlinedata['sid']; - $this->uid = $onlinedata['uid']; - } - - /** - * Find out the special locations. - * - * @return array Special locations array. - */ - function get_special_locations() - { - global $mybb; - $array = array('1' => '', '2' => ''); - if(preg_match("#forumdisplay.php#", $_SERVER['PHP_SELF']) && $mybb->get_input('fid', MyBB::INPUT_INT) > 0) - { - $array[1] = $mybb->get_input('fid', MyBB::INPUT_INT); - $array[2] = ''; - } - elseif(preg_match("#showthread.php#", $_SERVER['PHP_SELF'])) - { - global $db; - - if($mybb->get_input('tid', MyBB::INPUT_INT) > 0) - { - $array[2] = $mybb->get_input('tid', MyBB::INPUT_INT); - } - - // If there is no tid but a pid, trick the system into thinking there was a tid anyway. - elseif(isset($mybb->input['pid']) && !empty($mybb->input['pid'])) - { - $options = array( - "limit" => 1 - ); - $query = $db->simple_select("posts", "tid", "pid=".$mybb->get_input('pid', MyBB::INPUT_INT), $options); - $post = $db->fetch_array($query); - $array[2] = $post['tid']; - } - - $thread = get_thread($array[2]); - $array[1] = $thread['fid']; - } - return $array; - } -} diff --git a/html/forums/inc/class_stopforumspamchecker.php b/html/forums/inc/class_stopforumspamchecker.php deleted file mode 100644 index 0b9ae72..0000000 --- a/html/forums/inc/class_stopforumspamchecker.php +++ /dev/null @@ -1,204 +0,0 @@ -plugins = $plugins; - $this->min_weighting_before_spam = (double)$min_weighting_before_spam; - $this->check_usernames = (bool)$check_usernames; - $this->check_emails = (bool)$check_emails; - $this->check_ips = (bool)$check_ips; - $this->log_blocks = (bool)$log_blocks; - } - - /** - * Check a user against the 3rd party service to determine whether they are a spammer. - * - * @param string $username The username of the user to check. - * @param string $email The email address of the user to check. - * @param string $ip_address The IP address sof the user to check. - * @return bool Whether the user is considered a spammer or not. - * @throws Exception Thrown when there's an error fetching from the StopForumSpam API or when the data cannot be decoded. - */ - public function is_user_a_spammer($username = '', $email = '', $ip_address = '') - { - $is_spammer = false; - $confidence = 0; - - if(filter_var($email, FILTER_VALIDATE_EMAIL) && filter_var($ip_address, FILTER_VALIDATE_IP)) // Calls to the API with invalid email/ip formats cause issues - { - $username_encoded = urlencode($username); - $email_encoded = urlencode($email); - - $check_url = sprintf(self::STOP_FORUM_SPAM_API_URL_FORMAT, $username_encoded, $email_encoded, $ip_address); - - $result = fetch_remote_file($check_url); - - if($result !== false) - { - $result_json = @json_decode($result); - - if($result_json != null && !isset($result_json->error)) - { - if($this->check_usernames && $result_json->username->appears) - { - $confidence += $result_json->username->confidence; - } - - if($this->check_emails && $result_json->email->appears) - { - $confidence += $result_json->email->confidence; - } - - if($this->check_ips && $result_json->ip->appears) - { - $confidence += $result_json->ip->confidence; - } - - if($confidence > $this->min_weighting_before_spam) - { - $is_spammer = true; - } - } - else - { - throw new Exception('stopforumspam_error_decoding'); - } - } - else - { - throw new Exception('stopforumspam_error_retrieving'); - } - } - - if($this->plugins) - { - $params = array( - 'username' => &$username, - 'email' => &$email, - 'ip_address' => &$ip_address, - 'is_spammer' => &$is_spammer, - 'confidence' => &$confidence, - ); - - $this->plugins->run_hooks('stopforumspam_check_spammer_pre_return', $params); - } - - if($this->log_blocks && $is_spammer) - { - log_spam_block( - $username, $email, $ip_address, array( - 'confidence' => (double)$confidence, - ) - ); - } - - return $is_spammer; - } - - /** - * @param array $sfsSettingsEnabled - * - * @return string - */ - public function getErrorText($sfsSettingsEnabled) - { - global $mybb, $lang; - - foreach($sfsSettingsEnabled as $setting) - { - if($setting == 'stopforumspam_check_usernames' && $mybb->settings[$setting]) - { - $settingsenabled[] = $lang->sfs_error_username; - continue; - } - - if($setting == 'stopforumspam_check_emails' && $mybb->settings[$setting]) - { - $settingsenabled[] = $lang->sfs_error_email; - continue; - } - - if($setting = 'stopforumspam_check_ips' && $mybb->settings[$setting]) - { - $settingsenabled[] = $lang->sfs_error_ip; - continue; - } - } - - if(sizeof($settingsenabled) > 1) - { - $lastsetting = $settingsenabled[sizeof($settingsenabled)-1]; - unset($settingsenabled[sizeof($settingsenabled)-1]); - - $stopforumspamerror = implode($lang->comma, $settingsenabled) . " {$lang->sfs_error_or} " . $lastsetting; - } - else - { - $stopforumspamerror = $settingsenabled[0]; - } - return $stopforumspamerror; - } -} diff --git a/html/forums/inc/class_templates.php b/html/forums/inc/class_templates.php deleted file mode 100644 index 0126591..0000000 --- a/html/forums/inc/class_templates.php +++ /dev/null @@ -1,163 +0,0 @@ - $title) - { - $sql .= " ,'".trim($title)."'"; - } - - $query = $db->simple_select("templates", "title,template", "title IN (''$sql) AND sid IN ('-2','-1','".$theme['templateset']."')", array('order_by' => 'sid', 'order_dir' => 'asc')); - while($template = $db->fetch_array($query)) - { - $this->cache[$template['title']] = $template['template']; - } - } - - /** - * Gets templates. - * - * @param string $title The title of the template to get. - * @param boolean|int $eslashes True if template contents must be escaped, false if not. - * @param boolean|int $htmlcomments True to output HTML comments, false to not output. - * @return string The template HTML. - */ - function get($title, $eslashes=1, $htmlcomments=1) - { - global $db, $theme, $mybb; - - // - // DEVELOPMENT MODE - // - if($mybb->dev_mode == 1) - { - $template = $this->dev_get($title); - if($template !== false) - { - $this->cache[$title] = $template; - } - } - - if(!isset($this->cache[$title])) - { - // Only load master and global templates if template is needed in Admin CP - if(empty($theme['templateset'])) - { - $query = $db->simple_select("templates", "template", "title='".$db->escape_string($title)."' AND sid IN ('-2','-1')", array('order_by' => 'sid', 'order_dir' => 'DESC', 'limit' => 1)); - } - else - { - $query = $db->simple_select("templates", "template", "title='".$db->escape_string($title)."' AND sid IN ('-2','-1','".$theme['templateset']."')", array('order_by' => 'sid', 'order_dir' => 'DESC', 'limit' => 1)); - } - - $gettemplate = $db->fetch_array($query); - if($mybb->debug_mode) - { - $this->uncached_templates[$title] = $title; - } - - if(!$gettemplate) - { - $gettemplate['template'] = ""; - } - - $this->cache[$title] = $gettemplate['template']; - } - $template = $this->cache[$title]; - - if($htmlcomments) - { - if($mybb->settings['tplhtmlcomments'] == 1) - { - $template = "\n{$template}\n"; - } - else - { - $template = "\n{$template}\n"; - } - } - - if($eslashes) - { - $template = str_replace("\\'", "'", addslashes($template)); - } - return $template; - } - - /** - * Prepare a template for rendering to a variable. - * - * @param string $template The name of the template to get. - * @param boolean $eslashes True if template contents must be escaped, false if not. - * @param boolean $htmlcomments True to output HTML comments, false to not output. - * @return string The eval()-ready PHP code for rendering the template - */ - function render($template, $eslashes=true, $htmlcomments=true) - { - return 'return "'.$this->get($template, $eslashes, $htmlcomments).'";'; - } - - /** - * Fetch a template directly from the install/resources/mybb_theme.xml directory if it exists (DEVELOPMENT MODE) - * - * @param string $title - * @return string|bool - */ - function dev_get($title) - { - static $template_xml; - - if(!$template_xml) - { - if(@file_exists(MYBB_ROOT."install/resources/mybb_theme.xml")) - { - $template_xml = simplexml_load_file(MYBB_ROOT."install/resources/mybb_theme.xml"); - } - else - { - return false; - } - } - $res = $template_xml->xpath("//template[@name='{$title}']"); - return $res[0]; - } -} diff --git a/html/forums/inc/class_timers.php b/html/forums/inc/class_timers.php deleted file mode 100644 index 8f31170..0000000 --- a/html/forums/inc/class_timers.php +++ /dev/null @@ -1,133 +0,0 @@ -add(); - } - - /** - * Starts the timer. - * - */ - function add() - { - if(!$this->start) - { - $this->start = microtime(true); - } - } - - /** - * Gets the time for which the timer has run up until this point. - * - * @return string|boolean The formatted time up until now or false when timer is no longer running. - */ - function getTime() - { - if($this->end) // timer has been stopped - { - return $this->totaltime; - } - elseif($this->start && !$this->end) // timer is still going - { - $currenttime = microtime(true); - $totaltime = $currenttime - $this->start; - return $this->format($totaltime); - } - else - { - return false; - } - } - - /** - * Stops the timer. - * - * @return string The formatted total time. - */ - function stop() - { - if($this->start) - { - $this->end = microtime(true); - $totaltime = $this->end - $this->start; - $this->totaltime = $totaltime; - $this->formatted = $this->format($totaltime); - return $this->formatted; - } - return ''; - } - - /** - * Removes the timer. - * - */ - function remove() - { - $this->name = ""; - $this->start = ""; - $this->end = ""; - $this->totaltime = ""; - $this->formatted = ""; - } - - /** - * Formats the timer time in a pretty way. - * - * @param string $string The time string. - * @return string The formatted time string. - */ - function format($string) - { - return number_format($string, 7); - } -} diff --git a/html/forums/inc/class_xml.php b/html/forums/inc/class_xml.php deleted file mode 100644 index a53e516..0000000 --- a/html/forums/inc/class_xml.php +++ /dev/null @@ -1,182 +0,0 @@ -data = $data; - } - - /** - * Build a tree based structure based from the parsed data - * - * @return array The tree based structure - */ - function get_tree() - { - $parser = xml_parser_create(); - xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0); - xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); - if(!xml_parse_into_struct($parser, $this->data, $vals, $index)) - { - return false; - } - - $i = -1; - return $this->get_children($vals, $i); - } - - /** - * Private: Build a completed tag by fetching all child nodes and attributes - * - * @param array $thisvals Array of values from the current tag - * @param array $vals Array of child nodes - * @param int $i Internal counter - * @param string $type Type of tag. Complete is a single line tag with attributes - * @return array Completed tag array - */ - function build_tag($thisvals, $vals, &$i, $type) - { - $tag = array('tag' => $thisvals['tag']); - - if(isset($thisvals['attributes'])) - { - $tag['attributes'] = $thisvals['attributes']; - } - - if($type == "complete") - { - if(isset($thisvals['value'])) - { - $tag['value'] = $thisvals['value']; - } - } - else - { - $tag = array_merge($tag, $this->get_children($vals, $i)); - } - return $tag; - } - - /** - * Fetch the children for from a specific node array - * - * @param array $vals Array of children - * @param int $i Internal counter - * @return array Array of child nodes - */ - function get_children($vals, &$i) - { - $children = array(); - - if($i > -1 && isset($vals[$i]['value'])) - { - $children['value'] = $vals[$i]['value']; - } - - while(++$i < count($vals)) - { - $type = $vals[$i]['type']; - if($type == "cdata") - { - $children['value'] .= $vals[$i]['value']; - } - elseif($type == "complete" || $type == "open") - { - $tag = $this->build_tag($vals[$i], $vals, $i, $type); - if($this->index_numeric) - { - $tag['tag'] = $vals[$i]['tag']; - $children[] = $tag; - } - else - { - $children[$tag['tag']][] = $tag; - } - } - else if($type == "close") - { - break; - } - } - if($this->collapse_dups) - { - foreach($children as $key => $value) - { - if(is_array($value) && (count($value) == 1)) - { - $children[$key] = $value[0]; - } - } - } - return $children; - } -} - -/** - * Kill off unnecessary tags and return a clean array of XML data - * - * @param array $array Array of parsed XML data - * @return array Cleaned array of XML data - */ -function kill_tags($array) -{ - foreach($array as $key => $val) - { - if($key == "tag" || $key == "value") - { - unset($array[$key]); - } - else if(is_array($val)) - { - // kill any nested tag or value indexes - $array[$key] = kill_tags($val); - - // if the array no longer has any key/val sets - // and therefore is at the deepest level, then - // store the string value - if(count($array[$key]) <= 0) - { - $array[$key] = $val['value']; - } - } - } - - return $array; -} diff --git a/html/forums/inc/config.default.php b/html/forums/inc/config.default.php deleted file mode 100644 index e69de29..0000000 diff --git a/html/forums/inc/datahandler.php b/html/forums/inc/datahandler.php deleted file mode 100644 index 69e8144..0000000 --- a/html/forums/inc/datahandler.php +++ /dev/null @@ -1,217 +0,0 @@ -method = $method; - } - - /** - * Sets the data to be used for the data handler - * - * @param array $data The data. - * @return bool - */ - function set_data($data) - { - if(!is_array($data)) - { - return false; - } - $this->data = $data; - return true; - } - - /** - * Add an error to the error array. - * - * @param string $error The error name. - * @param string $data - */ - function set_error($error, $data='') - { - $this->errors[$error] = array( - "error_code" => $error, - "data" => $data - ); - } - - /** - * Returns the error(s) that occurred when handling data. - * - * @return array An array of errors. - */ - function get_errors() - { - return $this->errors; - } - - /** - * Returns the error(s) that occurred when handling data - * in a format that MyBB can handle. - * - * @return array An array of errors in a MyBB format. - */ - function get_friendly_errors() - { - global $lang; - - // Load the language pack we need - if($this->language_file) - { - $lang->load($this->language_file, true); - } - // Prefix all the error codes with the language prefix. - $errors = array(); - foreach($this->errors as $error) - { - $lang_string = $this->language_prefix.'_'.$error['error_code']; - if(!$lang->$lang_string) - { - $errors[] = $error['error_code']; - continue; - } - - if(!empty($error['data']) && !is_array($error['data'])) - { - $error['data'] = array($error['data']); - } - - if(is_array($error['data'])) - { - array_unshift($error['data'], $lang->$lang_string); - $errors[] = call_user_func_array(array($lang, "sprintf"), $error['data']); - } - else - { - $errors[] = $lang->$lang_string; - } - } - return $errors; - } - - /** - * Sets whether or not we are done validating. - * - * @param boolean True when done, false when not done. - */ - function set_validated($validated = true) - { - $this->is_validated = $validated; - } - - /** - * Returns whether or not we are done validating. - * - * @return boolean True when done, false when not done. - */ - function get_validated() - { - if($this->is_validated == true) - { - return true; - } - else - { - return false; - } - } - - /** - * Verifies if yes/no options haven't been modified. - * - * @param array $options The user options array. - * @param string $option The specific option to check. - * @param int|bool $default Optionally specify if the default should be used. - */ - function verify_yesno_option(&$options, $option, $default=1) - { - if($this->method == "insert" || array_key_exists($option, $options)) - { - if(isset($options[$option]) && $options[$option] != $default && $options[$option] != "") - { - if($default == 1) - { - $options[$option] = 0; - } - else - { - $options[$option] = 1; - } - } - else if(@array_key_exists($option, $options) && $options[$option] == '') - { - $options[$option] = 0; - } - else - { - $options[$option] = $default; - } - } - } -} diff --git a/html/forums/inc/datahandlers/event.php b/html/forums/inc/datahandlers/event.php deleted file mode 100644 index 93ef3f0..0000000 --- a/html/forums/inc/datahandlers/event.php +++ /dev/null @@ -1,643 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/** - * Event handling class, provides common structure to handle event data. - * - */ -class EventDataHandler extends DataHandler -{ - /** - * The language file used in the data handler. - * - * @var string - */ - public $language_file = 'datahandler_event'; - - /** - * The prefix for the language variables used in the data handler. - * - * @var string - */ - public $language_prefix = 'eventdata'; - - /** - * Array of data inserted in to an event. - * - * @var array - */ - public $event_insert_data = array(); - - /** - * Array of data used to update an event. - * - * @var array - */ - public $event_update_data = array(); - - /** - * Event ID currently being manipulated by the datahandlers. - * - * @var int - */ - public $eid = 0; - - /** - * Values to be returned after inserting/updating an event. - * - * @var array - */ - public $return_values = array(); - - /** - * Verifies if an event name is valid or not and attempts to fix it - * - * @return boolean True if valid, false if invalid. - */ - function verify_name() - { - $name = &$this->data['name']; - $name = trim($name); - if(!$name) - { - $this->set_error("missing_name"); - return false; - } - return true; - } - - /** - * Verifies if an event description is valid or not and attempts to fix it - * - * @return boolean True if valid, false if invalid. - */ - function verify_description() - { - $description = &$this->data['description']; - $description = trim($description); - if(!$description) - { - $this->set_error("missing_description"); - return false; - } - return true; - } - - /** - * Verifies if an event date is valid or not and attempts to fix it - * - * @return boolean True if valid, false if invalid. - */ - function verify_date() - { - $event = &$this->data; - - // All types of events require a start date - if(!$event['start_date']['day'] || !$event['start_date']['month'] || !$event['start_date']['year']) - { - $this->set_error("invalid_start_date"); - return false; - } - - $event['start_date']['day'] = (int)$event['start_date']['day']; - $event['start_date']['month'] = (int)$event['start_date']['month']; - $event['start_date']['year'] = (int)$event['start_date']['year']; - - if($event['start_date']['day'] > date("t", mktime(0, 0, 0, $event['start_date']['month'], 1, $event['start_date']['year']))) - { - $this->set_error("invalid_start_date"); - return false; - } - - // Calendar events can only be within the next 5 years - if($event['start_date']['year'] > date("Y") + 5) - { - $this->set_error("invalid_start_year"); - return false; - } - - //Check to see if the month is within 1 and 12 - if($event['start_date']['month'] > 12 || $event['start_date']['month'] < 1) - { - $this->set_error("invalid_start_month"); - return false; - } - - // For ranged events, we check the end date & times too - if($event['type'] == "ranged") - { - if(!$event['end_date']['day'] || !$event['end_date']['month'] || !$event['end_date']['year']) - { - $this->set_error("invalid_end_date"); - return false; - } - - $event['end_date']['day'] = (int)$event['end_date']['day']; - $event['end_date']['month'] = (int)$event['end_date']['month']; - $event['end_date']['year'] = (int)$event['end_date']['year']; - - if($event['end_date']['day'] > date("t", mktime(0, 0, 0, $event['end_date']['month'], 1, $event['end_date']['year']))) - { - $this->set_error("invalid_end_date"); - return false; - } - - // Calendar events can only be within the next 5 years - if($event['end_date']['year'] > date("Y") + 5) - { - $this->set_error("invalid_end_year"); - return false; - } - - //Check to see if the month is within 1 and 12 - if($event['end_date']['month'] > 12 || $event['end_date']['month'] < 1) - { - $this->set_error("invalid_end_month"); - return false; - } - - // Validate time input - if($event['start_date']['time'] || $event['end_date']['time']) - { - if(($event['start_date']['time'] && !$event['end_date']['time']) || ($event['end_date']['time'] && !$event['start_date']['time'])) - { - $this->set_error("cant_specify_one_time"); - return false; - } - - // Begin start time validation - $start_time = $this->verify_time($event['start_date']['time']); - if(!is_array($start_time)) - { - $this->set_error("start_time_invalid"); - return false; - } - - // End time validation - $end_time = $this->verify_time($event['end_date']['time']); - if(!is_array($end_time)) - { - $this->set_error("end_time_invalid"); - return false; - } - $event['usingtime'] = 1; - } - else - { - $start_time = array("hour" => 0, "min" => 0); - $end_time = array("hour" => 23, "min" => 59); - $event['usingtime'] = 0; - } - } - - if(array_key_exists('timezone', $event)) - { - $event['timezone'] = (float)$event['timezone']; - if($event['timezone'] > 12 || $event['timezone'] < -12) - { - $this->set_error("invalid_timezone"); - return false; - } - $start_time['hour'] -= $event['timezone']; - $end_time['hour'] -= $event['timezone']; - } - - if(!isset($start_time)) - { - $start_time = array("hour" => 0, "min" => 0); - } - - $start_timestamp = gmmktime($start_time['hour'], $start_time['min'], 0, $event['start_date']['month'], $event['start_date']['day'], $event['start_date']['year']); - - if($event['type'] == "ranged") - { - $end_timestamp = gmmktime($end_time['hour'], $end_time['min'], 0, $event['end_date']['month'], $event['end_date']['day'], $event['end_date']['year']); - - if($end_timestamp <= $start_timestamp) - { - $this->set_error("end_in_past"); - return false; - } - } - - if(!isset($end_timestamp)) - { - $end_timestamp = 0; - } - - // Save our time stamps for saving - $event['starttime'] = $start_timestamp; - $event['endtime'] = $end_timestamp; - - return true; - } - - /** - * @param string $time - * - * @return array|bool - */ - function verify_time($time) - { - preg_match('#^(0?[1-9]|1[012])\s?([:\.]?)\s?([0-5][0-9])?(\s?[ap]m)|([01][0-9]|2[0-3])\s?([:\.])\s?([0-5][0-9])$#i', $time, $matches); - if(count($matches) == 0) - { - return false; - } - - // 24h time - if(count($matches) == 8) - { - $hour = $matches[5]; - $min = $matches[7]; - } - // 12 hour time - else - { - $hour = $matches[1]; - $min = (int)$matches[3]; - $matches[4] = trim($matches[4]); - if(my_strtolower($matches[4]) == "pm" && $hour != 12) - { - $hour += 12; - } - else if(my_strtolower($matches[4]) == "am" && $hour == 12) - { - $hour = 0; - } - } - return array("hour" => $hour, "min" => $min); - } - - /** - * @return bool - */ - function verify_repeats() - { - $event = &$this->data; - - if(!is_array($event['repeats']) || !$event['repeats']['repeats']) - { - return true; - } - - if(!$event['endtime']) - { - $this->set_error("only_ranged_events_repeat"); - return false; - } - - switch($event['repeats']['repeats']) - { - case 1: - $event['repeats']['days'] = (int)$event['repeats']['days']; - if($event['repeats']['days'] <= 0) - { - $this->set_error("invalid_repeat_day_interval"); - return false; - } - case 2: - break; - case 3: - $event['repeats']['weeks'] = (int)$event['repeats']['weeks']; - if($event['repeats']['weeks'] <= 0) - { - $this->set_error("invalid_repeat_week_interval"); - return false; - } - if(count($event['repeats']['days']) == 0) - { - $this->set_error("invalid_repeat_weekly_days"); - return false; - } - asort($event['repeats']['days']); - break; - case 4: - if($event['repeats']['day']) - { - $event['repeats']['day'] = (int)$event['repeats']['day']; - if($event['repeats']['day'] <= 0 || $event['repeats']['day'] > 31) - { - $this->set_error("invalid_repeat_day_interval"); - return false; - } - } - else - { - if($event['repeats']['occurance'] != "last") - { - $event['repeats']['occurance'] = (int)$event['repeats']['occurance']; - } - $event['repeats']['weekday'] = (int)$event['repeats']['weekday']; - } - $event['repeats']['months'] = (int)$event['repeats']['months']; - if($event['repeats']['months'] <= 0 || $event['repeats']['months'] > 12) - { - $this->set_error("invalid_repeat_month_interval"); - return false; - } - break; - case 5: - if($event['repeats']['day']) - { - $event['repeats']['day'] = (int)$event['repeats']['day']; - if($event['repeats']['day'] <= 0 || $event['repeats']['day'] > 31) - { - $this->set_error("invalid_repeat_day_interval"); - return false; - } - } - else - { - if($event['repeats']['occurance'] != "last") - { - $event['repeats']['occurance'] = (int)$event['repeats']['occurance']; - } - $event['repeats']['weekday'] = (int)$event['repeats']['weekday']; - } - $event['repeats']['month'] = (int)$event['repeats']['month']; - if($event['repeats']['month'] <= 0 || $event['repeats']['month'] > 12) - { - $this->set_error("invalid_repeat_month_interval"); - return false; - } - $event['repeats']['years'] = (int)$event['repeats']['years']; - if($event['repeats']['years'] <= 0 || $event['repeats']['years'] > 4) - { - $this->set_error("invalid_repeat_year_interval"); - return false; - } - break; - default: - $event['repeats'] = array(); - } - require_once MYBB_ROOT."inc/functions_calendar.php"; - $event['starttime_user'] = $event['starttime']; - $event['endtime_user'] = $event['endtime']; - $next_occurance = fetch_next_occurance($event, array('start' => $event['starttime'], 'end' => $event['endtime']), $event['starttime'], true); - if($next_occurance > $event['endtime']) - { - $this->set_error("event_wont_occur"); - return false; - } - return true; - } - - /** - * Validate an event. - * - * @return bool - */ - function validate_event() - { - global $plugins; - - $event = &$this->data; - - if($this->method == "insert" || array_key_exists('name', $event)) - { - $this->verify_name(); - } - - if($this->method == "insert" || array_key_exists('description', $event)) - { - $this->verify_description(); - } - - if($this->method == "insert" || array_key_exists('start_date', $event) || array_key_exists('end_date', $event)) - { - $this->verify_date(); - } - - if(($this->method == "insert" && $event['endtime']) || array_key_exists('repeats', $event)) - { - $this->verify_repeats(); - } - - $plugins->run_hooks("datahandler_event_validate", $this); - - // We are done validating, return. - $this->set_validated(true); - if(count($this->get_errors()) > 0) - { - return false; - } - else - { - return true; - } - } - - /** - * Insert an event into the database. - * - * @return array Array of new event details, eid and private. - */ - function insert_event() - { - global $db, $mybb, $plugins; - - // Yes, validating is required. - if(!$this->get_validated()) - { - die("The event needs to be validated before inserting it into the DB."); - } - - if(count($this->get_errors()) > 0) - { - die("The event is not valid."); - } - - $event = &$this->data; - - $query = $db->simple_select("calendars", "*", "cid='".(int)$event['cid']."'"); - $calendar_moderation = $db->fetch_field($query, "moderation"); - if($calendar_moderation == 1 && (int)$event['private'] != 1) - { - $visible = 0; - if($event['uid'] == $mybb->user['uid']) - { - $calendar_permissions = get_calendar_permissions($event['cid']); - if($calendar_permissions['canbypasseventmod'] == 1) - { - $visible = 1; - } - } - } - else - { - $visible = 1; - } - - // Prepare an array for insertion into the database. - $this->event_insert_data = array( - 'cid' => (int)$event['cid'], - 'uid' => (int)$event['uid'], - 'name' => $db->escape_string($event['name']), - 'description' => $db->escape_string($event['description']), - 'visible' => $visible, - 'private' => (int)$event['private'], - 'dateline' => TIME_NOW, - 'starttime' => (int)$event['starttime'], - 'endtime' => (int)$event['endtime'] - ); - - if(isset($event['timezone'])) - { - $this->event_insert_data['timezone'] = $db->escape_string((float)$event['timezone']); - } - - if(isset($event['ignoretimezone'])) - { - $this->event_insert_data['ignoretimezone'] = (int)$event['ignoretimezone']; - } - - if(isset($event['usingtime'])) - { - $this->event_insert_data['usingtime'] = (int)$event['usingtime']; - } - - if(isset($event['repeats'])) - { - $this->event_insert_data['repeats'] = $db->escape_string(my_serialize($event['repeats'])); - } - else - { - $this->event_insert_data['repeats'] = ''; - } - - $plugins->run_hooks("datahandler_event_insert", $this); - - $this->eid = $db->insert_query("events", $this->event_insert_data); - - // Return the event's eid and whether or not it is private. - $this->return_values = array( - 'eid' => $this->eid, - 'private' => $event['private'], - 'visible' => $visible - ); - - $plugins->run_hooks("datahandler_event_insert_end", $this); - - return $this->return_values; - } - - /** - * Updates an event that is already in the database. - * - * @return array - */ - function update_event() - { - global $db, $plugins; - - // Yes, validating is required. - if(!$this->get_validated()) - { - die("The event needs to be validated before inserting it into the DB."); - } - - if(count($this->get_errors()) > 0) - { - die("The event is not valid."); - } - - $event = &$this->data; - - $this->eid = $event['eid']; - - if(isset($event['cid'])) - { - $this->event_update_data['cid'] = $db->escape_string($event['cid']); - } - - if(isset($event['name'])) - { - $this->event_update_data['name'] = $db->escape_string($event['name']); - } - - if(isset($event['description'])) - { - $this->event_update_data['description'] = $db->escape_string($event['description']); - } - - if(isset($event['starttime'])) - { - $this->event_update_data['starttime'] = (int)$event['starttime']; - $this->event_update_data['usingtime'] = (int)$event['usingtime']; - } - - if(isset($event['endtime'])) - { - $this->event_update_data['endtime'] = (int)$event['endtime']; - $this->event_update_data['usingtime'] = (int)$event['usingtime']; - } - else - { - $this->event_update_data['endtime'] = 0; - $this->event_update_data['usingtime'] = 0; - } - - if(isset($event['repeats'])) - { - if(!empty($event['repeats'])) - { - $event['repeats'] = my_serialize($event['repeats']); - } - $this->event_update_data['repeats'] = $db->escape_string($event['repeats']); - } - - if(isset($event['timezone'])) - { - $this->event_update_data['timezone'] = $db->escape_string((float)$event['timezone']); - } - - if(isset($event['ignoretimezone'])) - { - $this->event_update_data['ignoretimezone'] = (int)$event['ignoretimezone']; - } - - if(isset($event['private'])) - { - $this->event_update_data['private'] = (int)$event['private']; - } - - if(isset($event['visible'])) - { - $this->event_update_data['visible'] = $db->escape_string($event['visible']); - } - - if(isset($event['uid'])) - { - $this->event_update_data['uid'] = (int)$event['uid']; - } - - $plugins->run_hooks("datahandler_event_update", $this); - - $db->update_query("events", $this->event_update_data, "eid='".(int)$event['eid']."'"); - - // Return the event's eid and whether or not it is private. - $this->return_values = array( - 'eid' => $event['eid'], - 'private' => $event['private'] - ); - - $plugins->run_hooks("datahandler_event_update_end", $this); - - return $this->return_values; - } -} - diff --git a/html/forums/inc/datahandlers/index.html b/html/forums/inc/datahandlers/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/datahandlers/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/datahandlers/login.php b/html/forums/inc/datahandlers/login.php deleted file mode 100644 index 9012aed..0000000 --- a/html/forums/inc/datahandlers/login.php +++ /dev/null @@ -1,340 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/** - * Login handling class, provides common structure to handle login events. - * - */ -class LoginDataHandler extends DataHandler -{ - /** - * The language file used in the data handler. - * - * @var string - */ - public $language_file = 'datahandler_login'; - - /** - * The prefix for the language variables used in the data handler. - * - * @var string - */ - public $language_prefix = 'logindata'; - - /** - * Array of data used via login events. - * - * @var array - */ - public $login_data = array(); - - /** - * @var bool - */ - public $captcha_verified = true; - - /** - * @var bool|captcha - */ - private $captcha = false; - - /** - * @var int - */ - public $username_method = null; - - /** - * @param int $check_captcha - */ - function verify_attempts($check_captcha = 0) - { - global $db, $mybb; - - $user = &$this->data; - - if($check_captcha) - { - if(!isset($mybb->cookies['loginattempts'])) - { - $mybb->cookies['loginattempts'] = 0; - } - if($mybb->settings['failedcaptchalogincount'] > 0 && ($user['loginattempts'] > $mybb->settings['failedcaptchalogincount'] || (int)$mybb->cookies['loginattempts'] > $mybb->settings['failedcaptchalogincount'])) - { - $this->captcha_verified = false; - $this->verify_captcha(); - } - } - } - - /** - * @return bool - */ - function verify_captcha() - { - global $db, $mybb; - - $user = &$this->data; - - if($user['imagestring'] || $mybb->settings['captchaimage'] != 1) - { - // Check their current captcha input - if correct, hide the captcha input area - require_once MYBB_ROOT.'inc/class_captcha.php'; - $this->captcha = new captcha; - - if($this->captcha->validate_captcha() == false) - { - // CAPTCHA validation failed - foreach($this->captcha->get_errors() as $error) - { - $this->set_error($error); - } - return false; - } - else - { - $this->captcha_verified = true; - return true; - } - } - else if($mybb->input['quick_login'] == 1 && $mybb->input['quick_password'] && $mybb->input['quick_username']) - { - $this->set_error('regimagerequired'); - return false; - } - else - { - $this->set_error('regimageinvalid'); - return false; - } - } - - /** - * @return bool - */ - function verify_username() - { - $this->get_login_data(); - - if(!$this->login_data['uid']) - { - $this->invalid_combination(); - return false; - } - - return true; - } - - /** - * @param bool $strict - * - * @return bool - */ - function verify_password($strict = true) - { - global $db, $mybb, $plugins; - - $this->get_login_data(); - - if(empty($this->login_data['username'])) - { - // Username must be validated to apply a password to - $this->invalid_combination(); - return false; - } - - $args = array( - 'this' => &$this, - 'strict' => &$strict, - ); - - $plugins->run_hooks('datahandler_login_verify_password_start', $args); - - $user = &$this->data; - - if(!$this->login_data['uid'] || $this->login_data['uid'] && !$this->login_data['salt'] && $strict == false) - { - $this->invalid_combination(); - } - - if($strict == true) - { - if(!$this->login_data['salt']) - { - // Generate a salt for this user and assume the password stored in db is a plain md5 password - $password_fields = create_password($this->login_data['password']); - $this->login_data = array_merge($this->login_data, $password_fields); - $db->update_query("users", $password_fields, "uid = '{$this->login_data['uid']}'"); - } - - if(!$this->login_data['loginkey']) - { - $this->login_data['loginkey'] = generate_loginkey(); - - $sql_array = array( - "loginkey" => $this->login_data['loginkey'] - ); - - $db->update_query("users", $sql_array, "uid = '{$this->login_data['uid']}'"); - } - } - - $plugins->run_hooks('datahandler_login_verify_password_end', $args); - - if(!verify_user_password($this->login_data, $user['password'])) - { - $this->invalid_combination(true); - return false; - } - - return true; - } - - /** - * @param bool $show_login_attempts - */ - function invalid_combination($show_login_attempts = false) - { - global $db, $lang, $mybb; - - // Don't show an error when the captcha was wrong! - if(!$this->captcha_verified) - { - return; - } - - $login_text = ''; - if($show_login_attempts) - { - if($mybb->settings['failedlogincount'] != 0 && $mybb->settings['failedlogintext'] == 1) - { - $logins = login_attempt_check(false) + 1; - $login_text = $lang->sprintf($lang->failed_login_again, $mybb->settings['failedlogincount'] - $logins); - } - } - - switch($mybb->settings['username_method']) - { - case 1: - $this->set_error('invalidpwordusernameemail', $login_text); - break; - case 2: - $this->set_error('invalidpwordusernamecombo', $login_text); - break; - default: - $this->set_error('invalidpwordusername', $login_text); - break; - } - } - - function get_login_data() - { - global $db, $settings; - - $user = &$this->data; - - $options = array( - 'fields' => '*', - 'username_method' => (int)$settings['username_method'] - ); - - if($this->username_method !== null) - { - $options['username_method'] = (int)$this->username_method; - } - - $this->login_data = get_user_by_username($user['username'], $options); - } - - /** - * @return bool - */ - function validate_login() - { - global $plugins, $mybb; - - $user = &$this->data; - - $plugins->run_hooks('datahandler_login_validate_start', $this); - - if(!defined('IN_ADMINCP')) - { - $this->verify_attempts($mybb->settings['captchaimage']); - } - - if(array_key_exists('username', $user)) - { - $this->verify_username(); - } - - if(array_key_exists('password', $user)) - { - $this->verify_password(); - } - - $plugins->run_hooks('datahandler_login_validate_end', $this); - - $this->set_validated(true); - if(count($this->get_errors()) > 0) - { - return false; - } - - return true; - } - - /** - * @return bool true - */ - function complete_login() - { - global $plugins, $db, $mybb, $session; - - $user = &$this->login_data; - - $plugins->run_hooks('datahandler_login_complete_start', $this); - - // Login to MyBB - my_setcookie('loginattempts', 1); - my_setcookie("sid", $session->sid, -1, true); - - $ip_address = $db->escape_binary($session->packedip); - $db->delete_query("sessions", "ip = {$ip_address} AND sid != '{$session->sid}'"); - - $newsession = array( - "uid" => $user['uid'], - ); - - $db->update_query("sessions", $newsession, "sid = '{$session->sid}'"); - $db->update_query("users", array("loginattempts" => 1), "uid = '{$user['uid']}'"); - - $remember = null; - if(!isset($mybb->input['remember']) || $mybb->input['remember'] != "yes") - { - $remember = -1; - } - - my_setcookie("mybbuser", $user['uid']."_".$user['loginkey'], $remember, true); - - if($this->captcha !== false) - { - $this->captcha->invalidate_captcha(); - } - - $plugins->run_hooks('datahandler_login_complete_end', $this); - - return true; - } -} diff --git a/html/forums/inc/datahandlers/pm.php b/html/forums/inc/datahandlers/pm.php deleted file mode 100644 index a41e6d2..0000000 --- a/html/forums/inc/datahandlers/pm.php +++ /dev/null @@ -1,755 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/** - * PM handling class, provides common structure to handle private messaging data. - * - */ -class PMDataHandler extends DataHandler -{ - /** - * The language file used in the data handler. - * - * @var string - */ - public $language_file = 'datahandler_pm'; - - /** - * The prefix for the language variables used in the data handler. - * - * @var string - */ - public $language_prefix = 'pmdata'; - - /** - * Array of data inserted in to a private message. - * - * @var array - */ - public $pm_insert_data = array(); - - /** - * Array of data used to update a private message. - * - * @var array - */ - public $pm_update_data = array(); - - /** - * PM ID currently being manipulated by the datahandlers. - * - * @var int - */ - public $pmid = 0; - - /** - * Values to be returned after inserting a PM. - * - * @var array - */ - public $return_values = array(); - - /** - * Verifies a private message subject. - * - * @return boolean True when valid, false when invalid. - */ - function verify_subject() - { - $subject = &$this->data['subject']; - - // Subject is over 85 characters, too long. - if(my_strlen($subject) > 85) - { - $this->set_error("too_long_subject"); - return false; - } - // No subject, apply the default [no subject] - if(!trim_blank_chrs($subject)) - { - $this->set_error("missing_subject"); - return false; - } - return true; - } - - /** - * Verifies if a message for a PM is valid. - * - * @return boolean True when valid, false when invalid. - */ - function verify_message() - { - $message = &$this->data['message']; - - // No message, return an error. - if(trim_blank_chrs($message) == '') - { - $this->set_error("missing_message"); - return false; - } - return true; - } - - /** - * Verifies if the specified sender is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_sender() - { - global $db, $mybb, $lang; - - $pm = &$this->data; - - // Return if we've already validated - if(!empty($pm['sender'])) - { - return true; - } - - // Fetch the senders profile data. - $sender = get_user($pm['fromid']); - - // Collect user permissions for the sender. - $sender_permissions = user_permissions($pm['fromid']); - - // Check if the sender is over their quota or not - if they are, disable draft sending - if(isset($pm['options']['savecopy']) && $pm['options']['savecopy'] != 0 && empty($pm['saveasdraft'])) - { - if($sender_permissions['pmquota'] != "0" && $sender['totalpms'] >= $sender_permissions['pmquota'] && $this->admin_override != true) - { - $pm['options']['savecopy'] = 0; - } - } - - // Assign the sender information to the data. - $pm['sender'] = array( - "uid" => $sender['uid'], - "username" => $sender['username'] - ); - - return true; - } - - /** - * Verifies if an array of recipients for a private message are valid - * - * @return boolean True when valid, false when invalid. - */ - function verify_recipient() - { - global $cache, $db, $mybb, $lang; - - $pm = &$this->data; - - $recipients = array(); - - $invalid_recipients = array(); - // We have our recipient usernames but need to fetch user IDs - if(array_key_exists("to", $pm)) - { - foreach(array("to", "bcc") as $recipient_type) - { - if(!isset($pm[$recipient_type])) - { - $pm[$recipient_type] = array(); - } - if(!is_array($pm[$recipient_type])) - { - $pm[$recipient_type] = array($pm[$recipient_type]); - } - - $pm[$recipient_type] = array_map('trim', $pm[$recipient_type]); - $pm[$recipient_type] = array_filter($pm[$recipient_type]); - - // No recipients? Skip query - if(empty($pm[$recipient_type])) - { - if($recipient_type == 'to' && !$pm['saveasdraft']) - { - $this->set_error("no_recipients"); - return false; - } - continue; - } - - $recipientUsernames = array_map(array($db, 'escape_string'), $pm[$recipient_type]); - $recipientUsernames = "'".implode("','", $recipientUsernames)."'"; - - $query = $db->simple_select('users', '*', 'username IN('.$recipientUsernames.')'); - - $validUsernames = array(); - - while($user = $db->fetch_array($query)) - { - if($recipient_type == "bcc") - { - $user['bcc'] = 1; - } - - $recipients[] = $user; - $validUsernames[] = $user['username']; - } - - foreach($pm[$recipient_type] as $username) - { - if(!in_array($username, $validUsernames)) - { - $invalid_recipients[] = $username; - } - } - } - } - // We have recipient IDs - else - { - foreach(array("toid", "bccid") as $recipient_type) - { - if(!isset($pm[$recipient_type])) - { - $pm[$recipient_type] = array(); - } - if(!is_array($pm[$recipient_type])) - { - $pm[$recipient_type] = array($pm[$recipient_type]); - } - $pm[$recipient_type] = array_map('intval', $pm[$recipient_type]); - $pm[$recipient_type] = array_filter($pm[$recipient_type]); - - // No recipients? Skip query - if(empty($pm[$recipient_type])) - { - if($recipient_type == 'toid' && !$pm['saveasdraft']) - { - $this->set_error("no_recipients"); - return false; - } - continue; - } - - $recipientUids = "'".implode("','", $pm[$recipient_type])."'"; - - $query = $db->simple_select('users', '*', 'uid IN('.$recipientUids.')'); - - $validUids = array(); - - while($user = $db->fetch_array($query)) - { - if($recipient_type == "bccid") - { - $user['bcc'] = 1; - } - - $recipients[] = $user; - $validUids[] = $user['uid']; - } - - foreach($pm[$recipient_type] as $uid) - { - if(!in_array($uid, $validUids)) - { - $invalid_recipients[] = $uid; - } - } - } - } - - // If we have one or more invalid recipients and we're not saving a draft, error - if(count($invalid_recipients) > 0) - { - $invalid_recipients = implode($lang->comma, array_map("htmlspecialchars_uni", $invalid_recipients)); - $this->set_error("invalid_recipients", array($invalid_recipients)); - return false; - } - - $sender_permissions = user_permissions($pm['fromid']); - - // Are we trying to send this message to more users than the permissions allow? - if($sender_permissions['maxpmrecipients'] > 0 && count($recipients) > $sender_permissions['maxpmrecipients'] && $this->admin_override != true) - { - $this->set_error("too_many_recipients", array($sender_permissions['maxpmrecipients'])); - } - - // Now we're done with that we loop through each recipient - foreach($recipients as $user) - { - // Collect group permissions for this recipient. - $recipient_permissions = user_permissions($user['uid']); - - // See if the sender is on the recipients ignore list and that either - // - admin_override is set or - // - sender is an administrator - if($this->admin_override != true && $sender_permissions['canoverridepm'] != 1) - { - if(!empty($user['ignorelist']) && strpos(','.$user['ignorelist'].',', ','.$pm['fromid'].',') !== false) - { - $this->set_error("recipient_is_ignoring", array(htmlspecialchars_uni($user['username']))); - } - - // Is the recipient only allowing private messages from their buddy list? - if($mybb->settings['allowbuddyonly'] == 1 && $user['receivefrombuddy'] == 1 && !empty($user['buddylist']) && strpos(','.$user['buddylist'].',', ','.$pm['fromid'].',') === false) - { - $this->set_error('recipient_has_buddy_only', array(htmlspecialchars_uni($user['username']))); - } - - // Can the recipient actually receive private messages based on their permissions or user setting? - if(($user['receivepms'] == 0 || $recipient_permissions['canusepms'] == 0) && empty($pm['saveasdraft'])) - { - $this->set_error("recipient_pms_disabled", array(htmlspecialchars_uni($user['username']))); - return false; - } - } - - // Check to see if the user has reached their private message quota - if they have, email them. - if($recipient_permissions['pmquota'] != "0" && $user['totalpms'] >= $recipient_permissions['pmquota'] && $recipient_permissions['cancp'] != 1 && $sender_permissions['cancp'] != 1 && empty($pm['saveasdraft']) && !$this->admin_override) - { - if(trim($user['language']) != '' && $lang->language_exists($user['language'])) - { - $uselang = trim($user['language']); - } - elseif($mybb->settings['bblanguage']) - { - $uselang = $mybb->settings['bblanguage']; - } - else - { - $uselang = "english"; - } - if($uselang == $mybb->settings['bblanguage'] || !$uselang) - { - $emailsubject = $lang->emailsubject_reachedpmquota; - $emailmessage = $lang->email_reachedpmquota; - } - else - { - $userlang = new MyLanguage; - $userlang->set_path(MYBB_ROOT."inc/languages"); - $userlang->set_language($uselang); - $userlang->load("messages"); - $emailsubject = $userlang->emailsubject_reachedpmquota; - $emailmessage = $userlang->email_reachedpmquota; - } - $emailmessage = $lang->sprintf($emailmessage, $user['username'], $mybb->settings['bbname'], $mybb->settings['bburl']); - $emailsubject = $lang->sprintf($emailsubject, $mybb->settings['bbname'], $pm['subject']); - - $new_email = array( - "mailto" => $db->escape_string($user['email']), - "mailfrom" => '', - "subject" => $db->escape_string($emailsubject), - "message" => $db->escape_string($emailmessage), - "headers" => '' - ); - - $db->insert_query("mailqueue", $new_email); - $cache->update_mailqueue(); - - if($this->admin_override != true) - { - $this->set_error("recipient_reached_quota", array(htmlspecialchars_uni($user['username']))); - } - } - - // Everything looks good, assign some specifics about the recipient - $pm['recipients'][$user['uid']] = array( - "uid" => $user['uid'], - "username" => $user['username'], - "email" => $user['email'], - "lastactive" => $user['lastactive'], - "pmnotice" => $user['pmnotice'], - "pmnotify" => $user['pmnotify'], - "language" => $user['language'] - ); - - // If this recipient is defined as a BCC recipient, save it - if(isset($user['bcc']) && $user['bcc'] == 1) - { - $pm['recipients'][$user['uid']]['bcc'] = 1; - } - } - return true; - } - - /** - * Verify that the user is not flooding the system. - * - * @return boolean - */ - function verify_pm_flooding() - { - global $mybb, $db; - - $pm = &$this->data; - - // Check if post flooding is enabled within MyBB or if the admin override option is specified. - if($mybb->settings['pmfloodsecs'] > 0 && $pm['fromid'] != 0 && $this->admin_override == false && !is_moderator(0, '', $pm['fromid'])) - { - // Fetch the senders profile data. - $sender = get_user($pm['fromid']); - - // Calculate last post - $query = $db->simple_select("privatemessages", "dateline", "fromid='".$db->escape_string($pm['fromid'])."' AND toid != '0'", array('order_by' => 'dateline', 'order_dir' => 'desc', 'limit' => 1)); - $sender['lastpm'] = $db->fetch_field($query, "dateline"); - - // A little bit of calculation magic and moderator status checking. - if(TIME_NOW-$sender['lastpm'] <= $mybb->settings['pmfloodsecs']) - { - // Oops, user has been flooding - throw back error message. - $time_to_wait = ($mybb->settings['pmfloodsecs'] - (TIME_NOW-$sender['lastpm'])) + 1; - if($time_to_wait == 1) - { - $this->set_error("pm_flooding_one_second"); - } - else - { - $this->set_error("pm_flooding", array($time_to_wait)); - } - return false; - } - } - // All is well that ends well - return true. - return true; - } - - /** - * Verifies if the various 'options' for sending PMs are valid. - * - * @return boolean True when valid, false when invalid. - */ - function verify_options() - { - $options = &$this->data['options']; - - $this->verify_yesno_option($options, 'signature', 1); - $this->verify_yesno_option($options, 'savecopy', 1); - $this->verify_yesno_option($options, 'disablesmilies', 0); - - // Requesting a read receipt? - if(isset($options['readreceipt']) && $options['readreceipt'] == 1) - { - $options['readreceipt'] = 1; - } - else - { - $options['readreceipt'] = 0; - } - return true; - } - - /** - * Validate an entire private message. - * - * @return boolean True when valid, false when invalid. - */ - function validate_pm() - { - global $plugins; - - $pm = &$this->data; - - if(empty($pm['savedraft'])) - { - $this->verify_pm_flooding(); - } - - // Verify all PM assets. - $this->verify_subject(); - - $this->verify_sender(); - - $this->verify_recipient(); - - $this->verify_message(); - - $this->verify_options(); - - $plugins->run_hooks("datahandler_pm_validate", $this); - - // Choose the appropriate folder to save in. - if(!empty($pm['saveasdraft'])) - { - $pm['folder'] = 3; - } - else - { - $pm['folder'] = 1; - } - - // We are done validating, return. - $this->set_validated(true); - if(count($this->get_errors()) > 0) - { - return false; - } - else - { - return true; - } - } - - /** - * Insert a new private message. - * - * @return array Array of PM useful data. - */ - function insert_pm() - { - global $cache, $db, $mybb, $plugins, $lang; - - // Yes, validating is required. - if(!$this->get_validated()) - { - die("The PM needs to be validated before inserting it into the DB."); - } - if(count($this->get_errors()) > 0) - { - die("The PM is not valid."); - } - - // Assign data to common variable - $pm = &$this->data; - - if(empty($pm['pmid'])) - { - $pm['pmid'] = 0; - } - $pm['pmid'] = (int)$pm['pmid']; - - if(empty($pm['icon']) || $pm['icon'] < 0) - { - $pm['icon'] = 0; - } - - $uid = 0; - - if(!is_array($pm['recipients'])) - { - $recipient_list = array(); - } - else - { - // Build recipient list - foreach($pm['recipients'] as $recipient) - { - if(!empty($recipient['bcc'])) - { - $recipient_list['bcc'][] = $recipient['uid']; - } - else - { - $recipient_list['to'][] = $recipient['uid']; - $uid = $recipient['uid']; - } - } - } - - $this->pm_insert_data = array( - 'fromid' => (int)$pm['sender']['uid'], - 'folder' => $pm['folder'], - 'subject' => $db->escape_string($pm['subject']), - 'icon' => (int)$pm['icon'], - 'message' => $db->escape_string($pm['message']), - 'dateline' => TIME_NOW, - 'status' => 0, - 'includesig' => $pm['options']['signature'], - 'smilieoff' => $pm['options']['disablesmilies'], - 'receipt' => (int)$pm['options']['readreceipt'], - 'readtime' => 0, - 'recipients' => $db->escape_string(my_serialize($recipient_list)), - 'ipaddress' => $db->escape_binary($pm['ipaddress']) - ); - - // Check if we're updating a draft or not. - $query = $db->simple_select("privatemessages", "pmid, deletetime", "folder='3' AND uid='".(int)$pm['sender']['uid']."' AND pmid='{$pm['pmid']}'"); - $draftcheck = $db->fetch_array($query); - - // This PM was previously a draft - if($draftcheck['pmid']) - { - if($draftcheck['deletetime']) - { - // This draft was a reply to a PM - $pm['pmid'] = $draftcheck['deletetime']; - $pm['do'] = "reply"; - } - - // Delete the old draft as we no longer need it - $db->delete_query("privatemessages", "pmid='{$draftcheck['pmid']}'"); - } - - // Saving this message as a draft - if(!empty($pm['saveasdraft'])) - { - $this->pm_insert_data['uid'] = $pm['sender']['uid']; - - // If this is a reply, then piggyback into the deletetime to let us know in the future - if($pm['do'] == "reply" || $pm['do'] == "replyall") - { - $this->pm_insert_data['deletetime'] = $pm['pmid']; - } - - $plugins->run_hooks("datahandler_pm_insert_updatedraft", $this); - $db->insert_query("privatemessages", $this->pm_insert_data); - - // If this is a draft, end it here - below deals with complete messages - return array( - "draftsaved" => 1 - ); - } - - $this->pmid = array(); - - // Save a copy of the PM for each of our recipients - foreach($pm['recipients'] as $recipient) - { - // Send email notification of new PM if it is enabled for the recipient - $query = $db->simple_select("privatemessages", "dateline", "uid='".$recipient['uid']."' AND folder='1'", array('order_by' => 'dateline', 'order_dir' => 'desc', 'limit' => 1)); - $lastpm = $db->fetch_array($query); - if($recipient['pmnotify'] == 1 && $recipient['lastactive'] > $lastpm['dateline']) - { - if($recipient['language'] != "" && $lang->language_exists($recipient['language'])) - { - $uselang = $recipient['language']; - } - elseif($mybb->settings['bblanguage']) - { - $uselang = $mybb->settings['bblanguage']; - } - else - { - $uselang = "english"; - } - if($uselang == $mybb->settings['bblanguage'] && !empty($lang->emailsubject_newpm)) - { - $emailsubject = $lang->emailsubject_newpm; - $emailmessage = $lang->email_newpm; - } - else - { - $userlang = new MyLanguage; - $userlang->set_path(MYBB_ROOT."inc/languages"); - $userlang->set_language($uselang); - $userlang->load("messages"); - $emailsubject = $userlang->emailsubject_newpm; - $emailmessage = $userlang->email_newpm; - } - - if(!$pm['sender']['username']) - { - $pm['sender']['username'] = $lang->mybb_engine; - } - - require_once MYBB_ROOT.'inc/class_parser.php'; - $parser = new Postparser; - - $parser_options = array( - 'me_username' => $pm['sender']['username'], - 'filter_badwords' => 1 - ); - - $pm['message'] = $parser->text_parse_message($pm['message'], $parser_options); - - $emailmessage = $lang->sprintf($emailmessage, $recipient['username'], $pm['sender']['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $pm['message']); - $emailsubject = $lang->sprintf($emailsubject, $mybb->settings['bbname'], $pm['subject']); - - $new_email = array( - "mailto" => $db->escape_string($recipient['email']), - "mailfrom" => '', - "subject" => $db->escape_string($emailsubject), - "message" => $db->escape_string($emailmessage), - "headers" => '' - ); - - $db->insert_query("mailqueue", $new_email); - $cache->update_mailqueue(); - } - - $this->pm_insert_data['uid'] = $recipient['uid']; - $this->pm_insert_data['toid'] = $recipient['uid']; - - $plugins->run_hooks("datahandler_pm_insert", $this); - $this->pmid[] = $db->insert_query("privatemessages", $this->pm_insert_data); - - // If PM noices/alerts are on, show! - if($recipient['pmnotice'] == 1) - { - $updated_user = array( - "pmnotice" => 2 - ); - $db->update_query("users", $updated_user, "uid='{$recipient['uid']}'"); - } - - // Update private message count (total, new and unread) for recipient - require_once MYBB_ROOT."/inc/functions_user.php"; - update_pm_count($recipient['uid'], 7, $recipient['lastactive']); - } - - // Are we replying or forwarding an existing PM? - if($pm['pmid']) - { - if($pm['do'] == "reply" || $pm['do'] == "replyall") - { - $sql_array = array( - 'status' => 3, - 'statustime' => TIME_NOW - ); - $db->update_query("privatemessages", $sql_array, "pmid={$pm['pmid']} AND uid={$pm['sender']['uid']}"); - } - elseif($pm['do'] == "forward") - { - $sql_array = array( - 'status' => 4, - 'statustime' => TIME_NOW - ); - $db->update_query("privatemessages", $sql_array, "pmid={$pm['pmid']} AND uid={$pm['sender']['uid']}"); - } - } - - // If we're saving a copy - if($pm['options']['savecopy'] != 0) - { - if(isset($recipient_list['to']) && count($recipient_list['to']) == 1) - { - $this->pm_insert_data['toid'] = $uid; - } - else - { - $this->pm_insert_data['toid'] = 0; - } - $this->pm_insert_data['uid'] = (int)$pm['sender']['uid']; - $this->pm_insert_data['folder'] = 2; - $this->pm_insert_data['status'] = 1; - $this->pm_insert_data['receipt'] = 0; - - $plugins->run_hooks("datahandler_pm_insert_savedcopy", $this); - $db->insert_query("privatemessages", $this->pm_insert_data); - - // Because the sender saved a copy, update their total pm count - require_once MYBB_ROOT."/inc/functions_user.php"; - update_pm_count($pm['sender']['uid'], 1); - } - - // Return back with appropriate data - $this->return_values = array( - "messagesent" => 1, - "pmids" => $this->pmid - ); - - $plugins->run_hooks("datahandler_pm_insert_end", $this); - - return $this->return_values; - } -} diff --git a/html/forums/inc/datahandlers/post.php b/html/forums/inc/datahandlers/post.php deleted file mode 100644 index 6ce60cf..0000000 --- a/html/forums/inc/datahandlers/post.php +++ /dev/null @@ -1,1894 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/* -EXAMPLE USE: - -$post = get from POST data -$thread = get from DB using POST data id - -$postHandler = new postDataHandler(); -if($postHandler->validate_post($post)) -{ - $postHandler->insert_post($post); -} - -*/ - -/** - * Post handling class, provides common structure to handle post data. - * - */ -class PostDataHandler extends DataHandler -{ - /** - * The language file used in the data handler. - * - * @var string - */ - public $language_file = 'datahandler_post'; - - /** - * The prefix for the language variables used in the data handler. - * - * @var string - */ - public $language_prefix = 'postdata'; - - /** - * What are we performing? - * post = New post - * thread = New thread - * edit = Editing a thread or post - * - * @var string - */ - public $action; - - /** - * Array of data inserted in to a post. - * - * @var array - */ - public $post_insert_data = array(); - - /** - * Array of data used to update a post. - * - * @var array - */ - public $post_update_data = array(); - - /** - * Post ID currently being manipulated by the datahandlers. - * - * @var int - */ - public $pid = 0; - - /** - * Array of data inserted in to a thread. - * - * @var array - */ - public $thread_insert_data = array(); - - /** - * Array of data used to update a thread. - * - * @var array - */ - public $thread_update_data = array(); - - /** - * Thread ID currently being manipulated by the datahandlers. - * - * @var int - */ - public $tid = 0; - - /** - * Values to be returned after inserting/updating a post/thread. - * - * @var array - */ - public $return_values = array(); - - /** - * Is this the first post of a thread when editing - * - * @var boolean - */ - public $first_post = false; - - /** - * Verifies the author of a post and fetches the username if necessary. - * - * @return boolean True if the author information is valid, false if invalid. - */ - function verify_author() - { - global $mybb, $lang; - - $post = &$this->data; - - // Don't have a user ID at all - not good (note, a user id of 0 will still work). - if(!isset($post['uid'])) - { - $this->set_error("invalid_user_id"); - return false; - } - // If we have a user id but no username then fetch the username. - else if($post['uid'] > 0 && empty($post['username'])) - { - $user = get_user($post['uid']); - $post['username'] = $user['username']; - } - // if the uid is 0 verify the username - else if($post['uid'] == 0 && $post['username'] != $lang->guest) - { - // Set up user handler - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler(); - - $data_array = array('username' => $post['username']); - $userhandler->set_data($data_array); - - if(!$userhandler->verify_username()) - { - // invalid username - $this->errors = array_merge($this->errors, $userhandler->get_errors()); - return false; - } - - if($userhandler->verify_username_exists()) - { - // username is in use - $this->errors = array_merge($this->errors, $userhandler->get_errors()); - return false; - } - } - - // After all of this, if we still don't have a username, force the username as "Guest" (Note, this is not translatable as it is always a fallback) - if(!$post['username']) - { - $post['username'] = "Guest"; - } - - return true; - } - - /** - * Verifies a post subject. - * - * @return boolean True when valid, false when not valid. - */ - function verify_subject() - { - global $db; - $post = &$this->data; - $subject = &$post['subject']; - $subject = trim_blank_chrs($subject); - - if($this->method == "update" && $post['pid']) - { - // If this is the first post there needs to be a subject, else make it the default one. - if(my_strlen($subject) == 0 && $this->first_post) - { - $this->set_error("firstpost_no_subject"); - return false; - } - elseif(my_strlen($subject) == 0) - { - $thread = get_thread($post['tid']); - $subject = "RE: ".$thread['subject']; - } - } - - // This is a new post - else if($this->action == "post") - { - if(my_strlen($subject) == 0) - { - $thread = get_thread($post['tid']); - $subject = "RE: ".$thread['subject']; - } - } - - // This is a new thread and we require that a subject is present. - else - { - if(my_strlen($subject) == 0) - { - $this->set_error("missing_subject"); - return false; - } - } - - // If post is reply and begins with "RE: ", remove 4 from subject length. - $subject_length = my_strlen($subject); - if($this->action == "post") - { - $position_re = my_strpos($subject, "RE: "); - if($position_re !== false && $position_re == 0) - { - $subject_length = $subject_length - 4; - } - } - - if($subject_length > 85) - { - // Subject is too long - $this->set_error('subject_too_long', my_strlen($subject)); - return false; - } - - // Subject is valid - return true. - return true; - } - - /** - * Verifies a post message. - * - * @return bool - */ - function verify_message() - { - global $mybb; - - $post = &$this->data; - $post['message'] = trim_blank_chrs($post['message']); - - // Do we even have a message at all? - if(my_strlen($post['message']) == 0) - { - $this->set_error("missing_message"); - return false; - } - - // If this board has a maximum message length check if we're over it. Use strlen because SQL limits are in bytes - else if(strlen($post['message']) > $mybb->settings['maxmessagelength'] && $mybb->settings['maxmessagelength'] > 0 && !is_moderator($post['fid'], "", $post['uid'])) - { - $this->set_error("message_too_long", array($mybb->settings['maxmessagelength'], strlen($post['message']))); - return false; - } - - // And if we've got a minimum message length do we meet that requirement too? - else - { - if(!isset($post['fid'])) - { - $post['fid'] = 0; - } - if(!$mybb->settings['mycodemessagelength']) - { - // Check to see of the text is full of MyCode - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - - $message = $parser->text_parse_message($post['message']); - - if(my_strlen($message) < $mybb->settings['minmessagelength'] && $mybb->settings['minmessagelength'] > 0 && !is_moderator($post['fid'], "", $post['uid'])) - { - $this->set_error("message_too_short", array($mybb->settings['minmessagelength'])); - return false; - } - } - else if(my_strlen($post['message']) < $mybb->settings['minmessagelength'] && $mybb->settings['minmessagelength'] > 0 && !is_moderator($post['fid'], "", $post['uid'])) - { - $this->set_error("message_too_short", array($mybb->settings['minmessagelength'])); - return false; - } - } - return true; - } - - /** - * Verifies the specified post options are correct. - * - * @return boolean True - */ - function verify_options() - { - $options = &$this->data['options']; - - // Verify yes/no options. - $this->verify_yesno_option($options, 'signature', 0); - $this->verify_yesno_option($options, 'disablesmilies', 0); - - return true; - } - - /** - * Verify that the user is not flooding the system. - * - * @return boolean - */ - function verify_post_flooding() - { - global $mybb; - - $post = &$this->data; - - // Check if post flooding is enabled within MyBB or if the admin override option is specified. - if($mybb->settings['postfloodcheck'] == 1 && $post['uid'] != 0 && $this->admin_override == false) - { - if($this->verify_post_merge(true) !== true) - { - return true; - } - - // Fetch the user information for this post - used to check their last post date. - $user = get_user($post['uid']); - - // A little bit of calculation magic and moderator status checking. - if(TIME_NOW-$user['lastpost'] <= $mybb->settings['postfloodsecs'] && !is_moderator($post['fid'], "", $user['uid'])) - { - // Oops, user has been flooding - throw back error message. - $time_to_wait = ($mybb->settings['postfloodsecs'] - (TIME_NOW-$user['lastpost'])) + 1; - if($time_to_wait == 1) - { - $this->set_error("post_flooding_one_second"); - } - else - { - $this->set_error("post_flooding", array($time_to_wait)); - } - return false; - } - } - // All is well that ends well - return true. - return true; - } - - /** - * @param bool $simple_mode - * - * @return array|bool - */ - function verify_post_merge($simple_mode=false) - { - global $mybb, $db, $session; - - $post = &$this->data; - - // Are we starting a new thread? - if(empty($post['tid'])) - { - return true; - } - - // Are we even turned on? - if(empty($mybb->settings['postmergemins'])) - { - return true; - } - - // Assign a default separator if none is specified - if(trim($mybb->settings['postmergesep']) == "") - { - $mybb->settings['postmergesep'] = "[hr]"; - } - - // Check to see if this person is in a usergroup that is excluded - if(is_member($mybb->settings['postmergeuignore'], $post['uid'])) - { - return true; - } - - // Select the lastpost and fid information for this thread - $query = $db->simple_select("threads", "lastpost,fid", "lastposteruid='".$post['uid']."' AND tid='".$post['tid']."'", array('limit' => '1')); - $thread = $db->fetch_array($query); - - // Check to see if the same author has posted within the merge post time limit - if(((int)$mybb->settings['postmergemins'] != 0 && trim($mybb->settings['postmergemins']) != "") && (TIME_NOW-$thread['lastpost']) > ((int)$mybb->settings['postmergemins']*60)) - { - return true; - } - - if($mybb->settings['postmergefignore'] == -1) - { - return true; - } - elseif($mybb->settings['postmergefignore'] != '') - { - $fids = explode(',', (string)$mybb->settings['postmergefignore']); - - if(is_array($fids)) - { - foreach($fids as &$fid) - { - $fid = (int)$fid; - } - unset($fid); - - if(in_array($thread['fid'], $fids)) - { - return true; - } - } - } - - if($simple_mode == true) - { - return false; - } - - if($post['uid']) - { - $user_check = "uid='".$post['uid']."'"; - } - else - { - $user_check = "ipaddress=".$db->escape_binary($session->packedip); - } - - $query = $db->simple_select("posts", "pid,message,visible", "{$user_check} AND tid='".$post['tid']."' AND dateline='".$thread['lastpost']."'", array('order_by' => 'pid', 'order_dir' => 'DESC', 'limit' => 1)); - return $db->fetch_array($query); - } - - /** - * Verifies the image count. - * - * @return boolean True when valid, false when not valid. - */ - function verify_image_count() - { - global $mybb, $db; - - $post = &$this->data; - - // Get the permissions of the user who is making this post or thread - $permissions = user_permissions($post['uid']); - - // Fetch the forum this post is being made in - if(!$post['fid']) - { - $query = $db->simple_select('posts', 'fid', "pid = '{$post['pid']}'"); - $post['fid'] = $db->fetch_field($query, 'fid'); - } - $forum = get_forum($post['fid']); - - // Check if this post contains more images than the forum allows - if((!isset($post['savedraft']) || $post['savedraft'] != 1) && $mybb->settings['maxpostimages'] != 0 && $permissions['cancp'] != 1) - { - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - - // Parse the message. - $parser_options = array( - "allow_html" => $forum['allowhtml'], - "allow_mycode" => $forum['allowmycode'], - "allow_imgcode" => $forum['allowimgcode'], - "allow_videocode" => $forum['allowvideocode'], - "filter_badwords" => 1 - ); - - if($post['options']['disablesmilies'] != 1) - { - $parser_options['allow_smilies'] = $forum['allowsmilies']; - } - else - { - $parser_options['allow_smilies'] = 0; - } - - $image_check = $parser->parse_message($post['message'], $parser_options); - - // And count the number of image tags in the message. - $image_count = substr_count($image_check, " $mybb->settings['maxpostimages']) - { - // Throw back a message if over the count with the number of images as well as the maximum number of images per post. - $this->set_error("too_many_images", array(1 => $image_count, 2 => $mybb->settings['maxpostimages'])); - return false; - } - } - - return true; - } - - /** - * Verifies the video count. - * - * @return boolean True when valid, false when not valid. - */ - function verify_video_count() - { - global $mybb, $db; - - $post = &$this->data; - - // Get the permissions of the user who is making this post or thread - $permissions = user_permissions($post['uid']); - - // Check if this post contains more videos than the forum allows - if((!isset($post['savedraft']) || $post['savedraft'] != 1) && $mybb->settings['maxpostvideos'] != 0 && $permissions['cancp'] != 1) - { - // And count the number of video tags in the message. - $video_count = substr_count($post['message'], "[video="); - if($video_count > $mybb->settings['maxpostvideos']) - { - // Throw back a message if over the count with the number of images as well as the maximum number of images per post. - $this->set_error("too_many_videos", array(1 => $video_count, 2 => $mybb->settings['maxpostvideos'])); - return false; - } - } - - return true; - } - - /** - * Verify the reply-to post. - * - * @return boolean True when valid, false when not valid. - */ - function verify_reply_to() - { - global $db; - $post = &$this->data; - - // Check if the post being replied to actually exists in this thread. - if($post['replyto']) - { - $query = $db->simple_select("posts", "pid", "pid='".(int)$post['replyto']."'"); - $valid_post = $db->fetch_array($query); - if(!$valid_post['pid']) - { - $post['replyto'] = 0; - } - else - { - return true; - } - } - - // If this post isn't a reply to a specific post, attach it to the first post. - if(!$post['replyto']) - { - $options = array( - "limit_start" => 0, - "limit" => 1, - "order_by" => "dateline", - "order_dir" => "asc" - ); - $query = $db->simple_select("posts", "pid", "tid='{$post['tid']}'", $options); - $reply_to = $db->fetch_array($query); - $post['replyto'] = $reply_to['pid']; - } - - return true; - } - - /** - * Verify the post icon. - * - * @return boolean True when valid, false when not valid. - */ - function verify_post_icon() - { - global $cache; - - $post = &$this->data; - - $posticons_cache = $cache->read("posticons"); - - // If we don't have a post icon assign it as 0. - if(empty($post['icon']) || !isset($posticons_cache[$post['icon']])) - { - $post['icon'] = 0; - } - return true; - } - - /** - * Verify the dateline. - * - * @return boolean True when valid, false when not valid. - */ - function verify_dateline() - { - $dateline = &$this->data['dateline']; - - // The date has to be numeric and > 0. - if($dateline < 0 || is_numeric($dateline) == false) - { - $dateline = TIME_NOW; - } - } - - /** - * Verify thread prefix. - * - * @return boolean True when valid, false when not valid. - */ - function verify_prefix() - { - $prefix = &$this->data['prefix']; - - // If a valid prefix isn't supplied, don't assign one. - if(empty($prefix)) - { - $prefix = 0; - } - else - { - if(!empty($this->data['tid'])) - { - // Fetch the thread - $thread = get_thread($this->data['tid']); - } - - $prefix_cache = build_prefixes($prefix); - - if(empty($prefix_cache)) - { - $this->set_error('invalid_prefix'); - return false; - } - if($prefix_cache['groups'] != "-1") - { - if(!empty($this->data['edit_uid'])) - { - // Post is being edited - $user = get_user($this->data['edit_uid']); - } - else - { - $user = get_user($this->data['uid']); - } - - if(!is_member($prefix_cache['groups'], array('usergroup' => $user['usergroup'], 'additionalgroups' => $user['additionalgroups'])) && (empty($this->data['tid']) || $prefix != $thread['prefix'])) - { - $this->set_error('invalid_prefix'); - return false; - } - } - if($prefix_cache['forums'] != "-1") - { - // Decide whether this prefix can be used in our forum - $forums = explode(",", $prefix_cache['forums']); - - if(!in_array($this->data['fid'], $forums) && (empty($this->data['tid']) || $prefix != $thread['prefix'])) - { - $this->set_error('invalid_prefix'); - return false; - } - } - } - - // Does this forum require a prefix? - $forum = get_forum($this->data['fid']); - - if($forum['requireprefix'] == 1) - { - $num_prefixes = false; - - // Go through each of our prefixes and decide if there are any possible prefixes to use. - if(!empty($this->data['edit_uid'])) - { - // Post is being edited - $user = get_user($this->data['edit_uid']); - } - else - { - $user = get_user($this->data['uid']); - } - - $prefix_cache = build_prefixes(); - - if(!empty($prefix_cache)) - { - foreach($prefix_cache as $required) - { - if($required['forums'] != "-1") - { - // Decide whether this prefix can be used in our forum - $forums = explode(",", $required['forums']); - - if(!in_array($forum['fid'], $forums)) - { - continue; - } - } - - if(is_member($required['groups'], array('usergroup' => $user['usergroup'], 'additionalgroups' => $user['additionalgroups']))) - { - $num_prefixes = true; - } - } - } - - if($prefix == 0 && $num_prefixes) - { - $this->set_error('require_prefix'); - return false; - } - } - - return true; - } - - /** - * Validate a post. - * - * @return boolean True when valid, false when invalid. - */ - function validate_post() - { - global $mybb, $db, $plugins; - - $post = &$this->data; - $time = TIME_NOW; - - $this->action = "post"; - - if($this->method != "update" && !$post['savedraft']) - { - $this->verify_post_flooding(); - } - - // Are we editing an existing thread or post? - if($this->method == "update") - { - if(empty($post['tid'])) - { - $query = $db->simple_select("posts", "tid", "pid='".(int)$post['pid']."'"); - $post['tid'] = $db->fetch_field($query, "tid"); - } - // Here we determine if we're editing the first post of a thread or not. - $options = array( - "limit" => 1, - "limit_start" => 0, - "order_by" => "dateline", - "order_dir" => "asc" - ); - $query = $db->simple_select("posts", "pid", "tid='".$post['tid']."'", $options); - $first_check = $db->fetch_array($query); - if($first_check['pid'] == $post['pid']) - { - $this->first_post = true; - } - } - - // Verify all post assets. - - if($this->method == "insert" || array_key_exists('uid', $post)) - { - $this->verify_author(); - } - - if($this->method == "insert" || array_key_exists('subject', $post)) - { - $this->verify_subject(); - } - - if($this->method == "insert" || array_key_exists('message', $post)) - { - $this->verify_message(); - $this->verify_image_count(); - $this->verify_video_count(); - } - - if($this->method == "insert" || array_key_exists('dateline', $post)) - { - $this->verify_dateline(); - } - - if($this->method == "insert" || array_key_exists('replyto', $post)) - { - $this->verify_reply_to(); - } - - if($this->method == "insert" || array_key_exists('icon', $post)) - { - $this->verify_post_icon(); - } - - if($this->method == "insert" || array_key_exists('options', $post)) - { - $this->verify_options(); - } - - if($this->method == "update" && $this->first_post) - { - $this->verify_prefix(); - } - - $plugins->run_hooks("datahandler_post_validate_post", $this); - - // We are done validating, return. - $this->set_validated(true); - if(count($this->get_errors()) > 0) - { - return false; - } - else - { - return true; - } - } - - /** - * Insert a post into the database. - * - * @return array Array of new post details, pid and visibility. - */ - function insert_post() - { - global $db, $mybb, $plugins, $cache, $lang; - - $post = &$this->data; - - // Yes, validating is required. - if(!$this->get_validated()) - { - die("The post needs to be validated before inserting it into the DB."); - } - if(count($this->get_errors()) > 0) - { - die("The post is not valid."); - } - - // Fetch the thread - $thread = get_thread($post['tid']); - - $closed = $thread['closed']; - - // This post is being saved as a draft. - if($post['savedraft']) - { - $visible = -2; - } - - // Otherwise this post is being made now and we have a bit to do. - else - { - // Automatic subscription to the thread - if($post['options']['subscriptionmethod'] != "" && $post['uid'] > 0) - { - switch($post['options']['subscriptionmethod']) - { - case "pm": - $notification = 2; - break; - case "email": - $notification = 1; - break; - default: - $notification = 0; - } - - require_once MYBB_ROOT."inc/functions_user.php"; - add_subscribed_thread($post['tid'], $notification, $post['uid']); - } - - // Perform any selected moderation tools. - $ismod = is_moderator($post['fid'], "", $post['uid']); - if($ismod && isset($post['modoptions'])) - { - $lang->load($this->language_file, true); - - $modoptions = $post['modoptions']; - $modlogdata['fid'] = $thread['fid']; - $modlogdata['tid'] = $thread['tid']; - - $modoptions_update = array(); - - // Close the thread. - if(!empty($modoptions['closethread']) && $thread['closed'] != 1 && is_moderator($post['fid'], "canopenclosethreads", $post['uid'])) - { - $modoptions_update['closed'] = $closed = 1; - log_moderator_action($modlogdata, $lang->thread_closed); - } - - // Open the thread. - if(empty($modoptions['closethread']) && $thread['closed'] == 1 && is_moderator($post['fid'], "canopenclosethreads", $post['uid'])) - { - $modoptions_update['closed'] = $closed = 0; - log_moderator_action($modlogdata, $lang->thread_opened); - } - - // Stick the thread. - if(!empty($modoptions['stickthread']) && $thread['sticky'] != 1 && is_moderator($post['fid'], "canstickunstickthreads", $post['uid'])) - { - $modoptions_update['sticky'] = 1; - log_moderator_action($modlogdata, $lang->thread_stuck); - } - - // Unstick the thread. - if(empty($modoptions['stickthread']) && $thread['sticky'] == 1 && is_moderator($post['fid'], "canstickunstickthreads", $post['uid'])) - { - $modoptions_update['sticky'] = 0; - log_moderator_action($modlogdata, $lang->thread_unstuck); - } - - // Execute moderation options. - if($modoptions_update) - { - $db->update_query('threads', $modoptions_update, "tid='{$thread['tid']}'"); - } - } - - // Fetch the forum this post is being made in - $forum = get_forum($post['fid']); - - // Decide on the visibility of this post. - $forumpermissions = forum_permissions($post['fid'], $post['uid']); - if($forumpermissions['modposts'] == 1 && !$ismod) - { - $visible = 0; - } - else - { - $visible = 1; - } - - // Are posts from this user being moderated? Change visibility - if($mybb->user['uid'] == $post['uid'] && $mybb->user['moderateposts'] == 1) - { - $visible = 0; - } - } - - if(!isset($post['pid'])) - { - $post['pid'] = 0; - } - - $post['pid'] = (int)$post['pid']; - $post['uid'] = (int)$post['uid']; - - if($post['pid'] > 0) - { - $query = $db->simple_select("posts", "tid", "pid='{$post['pid']}' AND uid='{$post['uid']}' AND visible='-2'"); - $draft_check = $db->fetch_field($query, "tid"); - } - else - { - $draft_check = false; - } - - if($this->method != "update" && $visible == 1) - { - $double_post = $this->verify_post_merge(); - - // Only combine if they are both invisible (mod queue'd forum) or both visible - if($double_post !== true && $double_post['visible'] == $visible) - { - $this->pid = $double_post['pid']; - - $post['message'] = $double_post['message'] .= "\n".$mybb->settings['postmergesep']."\n".$post['message']; - $update_query = array( - "message" => $db->escape_string($double_post['message']) - ); - $update_query['edituid'] = (int)$post['uid']; - $update_query['edittime'] = TIME_NOW; - $db->update_query("posts", $update_query, "pid='".$double_post['pid']."'"); - - if($draft_check) - { - $db->delete_query("posts", "pid='".$post['pid']."'"); - } - - if($post['posthash']) - { - // Assign any uploaded attachments with the specific posthash to the merged post. - $post['posthash'] = $db->escape_string($post['posthash']); - - $query = $db->simple_select("attachments", "COUNT(aid) AS attachmentcount", "pid='0' AND visible='1' AND posthash='{$post['posthash']}'"); - $attachmentcount = $db->fetch_field($query, "attachmentcount"); - - if($attachmentcount > 0) - { - // Update forum count - update_thread_counters($post['tid'], array('attachmentcount' => "+{$attachmentcount}")); - } - - $attachmentassign = array( - "pid" => $double_post['pid'], - "posthash" => '' - ); - $db->update_query("attachments", $attachmentassign, "posthash='{$post['posthash']}' AND pid='0'"); - } - - // Return the post's pid and whether or not it is visible. - $this->return_values = array( - "pid" => $double_post['pid'], - "visible" => $visible, - "merge" => true - ); - - $plugins->run_hooks("datahandler_post_insert_merge", $this); - - return $this->return_values; - } - } - - if($visible == 1) - { - $now = TIME_NOW; - - // Yes, the value to the lastpost key in this array has single quotes within double quotes. It's not a bug. - $update_array = array( - 'lastpost' => "'{$now}'" - ); - if($forum['usepostcounts'] != 0 && $thread['visible'] == 1) - { - $update_array['postnum'] = 'postnum+1'; - } - - $db->update_query("users", $update_array, "uid='{$post['uid']}'", 1, true); - } - - // Are we updating a post which is already a draft? Perhaps changing it into a visible post? - if($draft_check) - { - // Update a post that is a draft - $this->post_update_data = array( - "subject" => $db->escape_string($post['subject']), - "icon" => (int)$post['icon'], - "uid" => $post['uid'], - "username" => $db->escape_string($post['username']), - "dateline" => (int)$post['dateline'], - "message" => $db->escape_string($post['message']), - "ipaddress" => $db->escape_binary($post['ipaddress']), - "includesig" => $post['options']['signature'], - "smilieoff" => $post['options']['disablesmilies'], - "visible" => $visible - ); - - $plugins->run_hooks("datahandler_post_insert_post", $this); - - $db->update_query("posts", $this->post_update_data, "pid='{$post['pid']}'"); - $this->pid = $post['pid']; - } - else - { - // Insert the post. - $this->post_insert_data = array( - "tid" => (int)$post['tid'], - "replyto" => (int)$post['replyto'], - "fid" => (int)$post['fid'], - "subject" => $db->escape_string($post['subject']), - "icon" => (int)$post['icon'], - "uid" => $post['uid'], - "username" => $db->escape_string($post['username']), - "dateline" => $post['dateline'], - "message" => $db->escape_string($post['message']), - "ipaddress" => $db->escape_binary($post['ipaddress']), - "includesig" => $post['options']['signature'], - "smilieoff" => $post['options']['disablesmilies'], - "visible" => $visible - ); - - $plugins->run_hooks("datahandler_post_insert_post", $this); - - $this->pid = $db->insert_query("posts", $this->post_insert_data); - } - - // Assign any uploaded attachments with the specific posthash to the newly created post. - if($post['posthash']) - { - $post['posthash'] = $db->escape_string($post['posthash']); - $attachmentassign = array( - "pid" => $this->pid, - "posthash" => '' - ); - $db->update_query("attachments", $attachmentassign, "posthash='{$post['posthash']}' AND pid='0'"); - } - - $thread_update = array(); - if($visible == 1 && $thread['visible'] == 1) - { - require_once MYBB_ROOT.'inc/class_parser.php'; - $parser = new Postparser; - - $done_users = array(); - - $subject = $parser->parse_badwords($thread['subject']); - - $parser_options = array( - 'me_username' => $post['username'], - 'filter_badwords' => 1 - ); - - $excerpt = $parser->text_parse_message($post['message'], $parser_options); - $excerpt = my_substr($excerpt, 0, $mybb->settings['subscribeexcerpt']).$lang->emailbit_viewthread; - - // Fetch any users subscribed to this thread receiving instant notification and queue up their subscription notices - $query = $db->query(" - SELECT u.username, u.email, u.uid, u.language, u.loginkey, u.salt, u.regdate, s.notification - FROM ".TABLE_PREFIX."threadsubscriptions s - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=s.uid) - WHERE (s.notification='1' OR s.notification='2') AND s.tid='{$post['tid']}' - AND s.uid != '{$post['uid']}' - AND u.lastactive>'{$thread['lastpost']}' - "); - - $args = array( - 'this' => &$this, - 'done_users' => &$done_users, - 'users' => array() - ); - - while($subscribedmember = $db->fetch_array($query)) - { - if($done_users[$subscribedmember['uid']]) - { - continue; - } - - $args['users'][$subscribedmember['uid']] = (int)$subscribedmember['uid']; - - $done_users[$subscribedmember['uid']] = 1; - - $forumpermissions = forum_permissions($thread['fid'], $subscribedmember['uid']); - if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0) - { - continue; - } - - if($thread['uid'] != $subscribedmember['uid'] && $forumpermissions['canonlyviewownthread'] == 1 && !is_moderator($thread['fid'], "", $subscribedmember['uid'])) - { - // User isn't a moderator or the author of the thread... - continue; - } - - if($subscribedmember['language'] != '' && $lang->language_exists($subscribedmember['language'])) - { - $uselang = $subscribedmember['language']; - } - elseif($mybb->settings['orig_bblanguage']) - { - $uselang = $mybb->settings['orig_bblanguage']; - } - else - { - $uselang = "english"; - } - - if($uselang == $mybb->settings['bblanguage']) - { - if($subscribedmember['notification'] == 1) - { - $emailsubject = $lang->emailsubject_subscription; - $emailmessage = $lang->email_subscription; - } - } - else - { - if($subscribedmember['notification'] == 1) - { - if(!isset($langcache[$uselang]['emailsubject_subscription'])) - { - $userlang = new MyLanguage; - $userlang->set_path(MYBB_ROOT."inc/languages"); - $userlang->set_language($uselang); - $userlang->load("messages"); - $langcache[$uselang]['emailsubject_subscription'] = $userlang->emailsubject_subscription; - $langcache[$uselang]['email_subscription'] = $userlang->email_subscription; - unset($userlang); - } - $emailsubject = $langcache[$uselang]['emailsubject_subscription']; - $emailmessage = $langcache[$uselang]['email_subscription']; - } - } - - if($subscribedmember['notification'] == 1) - { - $emailsubject = $lang->sprintf($emailsubject, $subject); - - $post_code = md5($subscribedmember['loginkey'].$subscribedmember['salt'].$subscribedmember['regdate']); - $emailmessage = $lang->sprintf($emailmessage, $subscribedmember['username'], $post['username'], $mybb->settings['bbname'], $subject, $excerpt, $mybb->settings['bburl'], str_replace("&", "&", get_thread_link($thread['tid'], 0, "newpost")), $thread['tid'], $post_code); - $new_email = array( - "mailto" => $db->escape_string($subscribedmember['email']), - "mailfrom" => '', - "subject" => $db->escape_string($emailsubject), - "message" => $db->escape_string($emailmessage), - "headers" => '' - ); - $db->insert_query("mailqueue", $new_email); - unset($userlang); - $queued_email = 1; - } - elseif($subscribedmember['notification'] == 2) - { - $post_code = md5($subscribedmember['loginkey'].$subscribedmember['salt'].$subscribedmember['regdate']); - $pm = array( - 'subject' => array('pmsubject_subscription', $subject), - 'message' => array('pm_subscription', $subscribedmember['username'], $post['username'], $subject, $excerpt, $mybb->settings['bburl'], str_replace("&", "&", get_thread_link($thread['tid'], 0, "newpost")), $thread['tid'], $post_code), - 'touid' => $subscribedmember['uid'], - 'language' => $subscribedmember['language'], - 'language_file' => 'messages' - ); - send_pm($pm, -1, true); - } - } - - $plugins->run_hooks('datahandler_post_insert_subscribed', $args); - - // Have one or more emails been queued? Update the queue count - if(isset($queued_email) && $queued_email == 1) - { - $cache->update_mailqueue(); - } - - $thread_update = array('replies' => '+1'); - - // Update counters - update_last_post($post['tid']); - update_forum_counters($post['fid'], array("posts" => "+1")); - update_forum_lastpost($thread['fid']); - } - // Post is stuck in moderation queue - else if($visible == 0) - { - // Update the unapproved posts count for the current thread and current forum - $thread_update = array('unapprovedposts' => '+1'); - update_thread_counters($post['tid'], array("unapprovedposts" => "+1")); - update_forum_counters($post['fid'], array("unapprovedposts" => "+1")); - } - else if($thread['visible'] == 0) - { - // Update the unapproved posts count for the current forum - $thread_update = array('replies' => '+1'); - update_forum_counters($post['fid'], array("unapprovedposts" => "+1")); - } - else if($thread['visible'] == -1) - { - // Update the unapproved posts count for the current forum - $thread_update = array('replies' => '+1'); - update_forum_counters($post['fid'], array("deletedposts" => "+1")); - } - - // Update last poster - if($visible == 1 && $thread['visible'] != 1) - { - update_last_post($post['tid']); - } - - $query = $db->simple_select("attachments", "COUNT(aid) AS attachmentcount", "pid='{$this->pid}' AND visible='1'"); - $attachmentcount = $db->fetch_field($query, "attachmentcount"); - if($attachmentcount > 0) - { - $thread_update['attachmentcount'] = "+{$attachmentcount}"; - } - update_thread_counters($post['tid'], $thread_update); - - // Return the post's pid and whether or not it is visible. - $this->return_values = array( - "pid" => $this->pid, - "visible" => $visible, - "closed" => $closed - ); - - $plugins->run_hooks("datahandler_post_insert_post_end", $this); - - return $this->return_values; - } - - /** - * Validate a thread. - * - * @return boolean True when valid, false when invalid. - */ - function validate_thread() - { - global $mybb, $db, $plugins; - - $thread = &$this->data; - - // Validate all thread assets. - - if(!$thread['savedraft']) - { - $this->verify_post_flooding(); - } - - if($this->method == "insert" || array_key_exists('uid', $thread)) - { - $this->verify_author(); - } - - if($this->method == "insert" || array_key_exists('prefix', $thread)) - { - $this->verify_prefix(); - } - - if($this->method == "insert" || array_key_exists('subject', $thread)) - { - $this->verify_subject(); - } - - if($this->method == "insert" || array_key_exists('message', $thread)) - { - $this->verify_message(); - $this->verify_image_count(); - $this->verify_video_count(); - } - - if($this->method == "insert" || array_key_exists('dateline', $thread)) - { - $this->verify_dateline(); - } - - if($this->method == "insert" || array_key_exists('icon', $thread)) - { - $this->verify_post_icon(); - } - - if($this->method == "insert" || array_key_exists('options', $thread)) - { - $this->verify_options(); - } - - $plugins->run_hooks("datahandler_post_validate_thread", $this); - - // We are done validating, return. - $this->set_validated(true); - if(count($this->get_errors()) > 0) - { - return false; - } - else - { - return true; - } - } - - /** - * Insert a thread into the database. - * - * @return array Array of new thread details, tid and visibility. - */ - function insert_thread() - { - global $db, $mybb, $plugins, $cache, $lang; - - // Yes, validating is required. - if(!$this->get_validated()) - { - die("The thread needs to be validated before inserting it into the DB."); - } - if(count($this->get_errors()) > 0) - { - die("The thread is not valid."); - } - - $thread = &$this->data; - - // Fetch the forum this thread is being made in - $forum = get_forum($thread['fid']); - - // This thread is being saved as a draft. - if($thread['savedraft']) - { - $visible = -2; - } - - // Thread is being made now and we have a bit to do. - else - { - $forumpermissions = forum_permissions($thread['fid'], $thread['uid']); - // Decide on the visibility of this post. - if($forumpermissions['modthreads'] == 1 && !is_moderator($thread['fid'], "", $thread['uid'])) - { - $visible = 0; - } - else - { - $visible = 1; - } - - // Are posts from this user being moderated? Change visibility - if($mybb->user['uid'] == $thread['uid'] && $mybb->user['moderateposts'] == 1) - { - $visible = 0; - } - } - - // Have a post ID but not a thread ID - fetch thread ID - if(!empty($thread['pid']) && !$thread['tid']) - { - $query = $db->simple_select("posts", "tid", "pid='{$thread['pid']}"); - $thread['tid'] = $db->fetch_field($query, "tid"); - } - - if(isset($thread['pid']) && $thread['pid'] > 0) - { - $query = $db->simple_select("posts", "pid", "pid='{$thread['pid']}' AND uid='{$thread['uid']}' AND visible='-2'"); - $draft_check = $db->fetch_field($query, "pid"); - } - else - { - $draft_check = false; - } - - // Are we updating a post which is already a draft? Perhaps changing it into a visible post? - if($draft_check) - { - $this->thread_insert_data = array( - "subject" => $db->escape_string($thread['subject']), - "icon" => (int)$thread['icon'], - "username" => $db->escape_string($thread['username']), - "dateline" => (int)$thread['dateline'], - "lastpost" => (int)$thread['dateline'], - "lastposter" => $db->escape_string($thread['username']), - "visible" => $visible - ); - - $plugins->run_hooks("datahandler_post_insert_thread", $this); - - $db->update_query("threads", $this->thread_insert_data, "tid='{$thread['tid']}'"); - - $this->post_insert_data = array( - "subject" => $db->escape_string($thread['subject']), - "icon" => (int)$thread['icon'], - "username" => $db->escape_string($thread['username']), - "dateline" => (int)$thread['dateline'], - "message" => $db->escape_string($thread['message']), - "ipaddress" => $db->escape_binary(my_inet_pton(get_ip())), - "includesig" => $thread['options']['signature'], - "smilieoff" => $thread['options']['disablesmilies'], - "visible" => $visible - ); - $plugins->run_hooks("datahandler_post_insert_thread_post", $this); - - $db->update_query("posts", $this->post_insert_data, "pid='{$thread['pid']}'"); - $this->tid = $thread['tid']; - $this->pid = $thread['pid']; - } - - // Inserting a new thread into the database. - else - { - $this->thread_insert_data = array( - "fid" => $thread['fid'], - "subject" => $db->escape_string($thread['subject']), - "prefix" => (int)$thread['prefix'], - "icon" => (int)$thread['icon'], - "uid" => $thread['uid'], - "username" => $db->escape_string($thread['username']), - "dateline" => (int)$thread['dateline'], - "lastpost" => (int)$thread['dateline'], - "lastposter" => $db->escape_string($thread['username']), - "lastposteruid" => $thread['uid'], - "views" => 0, - "replies" => 0, - "visible" => $visible, - "notes" => '' - ); - - $plugins->run_hooks("datahandler_post_insert_thread", $this); - - $this->tid = $db->insert_query("threads", $this->thread_insert_data); - - $this->post_insert_data = array( - "tid" => $this->tid, - "fid" => $thread['fid'], - "subject" => $db->escape_string($thread['subject']), - "icon" => (int)$thread['icon'], - "uid" => $thread['uid'], - "username" => $db->escape_string($thread['username']), - "dateline" => (int)$thread['dateline'], - "message" => $db->escape_string($thread['message']), - "ipaddress" => $db->escape_binary(my_inet_pton(get_ip())), - "includesig" => $thread['options']['signature'], - "smilieoff" => $thread['options']['disablesmilies'], - "visible" => $visible - ); - $plugins->run_hooks("datahandler_post_insert_thread_post", $this); - - $this->pid = $db->insert_query("posts", $this->post_insert_data); - - // Now that we have the post id for this first post, update the threads table. - $firstpostup = array("firstpost" => $this->pid); - $db->update_query("threads", $firstpostup, "tid='{$this->tid}'"); - } - - // If we're not saving a draft there are some things we need to check now - if(!$thread['savedraft']) - { - if($thread['options']['subscriptionmethod'] != "" && $thread['uid'] > 0) - { - switch($thread['options']['subscriptionmethod']) - { - case "pm": - $notification = 2; - break; - case "email": - $notification = 1; - break; - default: - $notification = 0; - } - - require_once MYBB_ROOT."inc/functions_user.php"; - add_subscribed_thread($this->tid, $notification, $thread['uid']); - } - - // Perform any selected moderation tools. - if(is_moderator($thread['fid'], "", $thread['uid']) && isset($thread['modoptions'])) - { - $lang->load($this->language_file, true); - - $modoptions = $thread['modoptions']; - $modlogdata['fid'] = $thread['fid']; - if(isset($thread['tid'])) - { - $modlogdata['tid'] = $thread['tid']; - } - - $modoptions_update = array(); - - // Close the thread. - if(!empty($modoptions['closethread']) && is_moderator($thread['fid'], "canopenclosethreads", $thread['uid'])) - { - $modoptions_update['closed'] = 1; - log_moderator_action($modlogdata, $lang->thread_closed); - } - - // Stick the thread. - if(!empty($modoptions['stickthread']) && is_moderator($thread['fid'], "canstickunstickthreads", $thread['uid'])) - { - $modoptions_update['sticky'] = 1; - log_moderator_action($modlogdata, $lang->thread_stuck); - } - - // Execute moderation options. - if($modoptions_update) - { - $db->update_query('threads', $modoptions_update, "tid='{$this->tid}'"); - } - } - if($visible == 1) - { - // If we have a registered user then update their post count and last post times. - if($thread['uid'] > 0) - { - $user = get_user($thread['uid']); - $update_query = array(); - // Only update the lastpost column of the user if the date of the thread is newer than their last post. - if($thread['dateline'] > $user['lastpost']) - { - // Yes this has a single quote within a double quote. It's not a bug. - $update_query['lastpost'] = "'{$thread['dateline']}'"; - } - // Update the post count if this forum allows post counts to be tracked - if($forum['usepostcounts'] != 0) - { - $update_query['postnum'] = "postnum+1"; - } - if($forum['usethreadcounts'] != 0) - { - $update_query['threadnum'] = 'threadnum+1'; - } - - // Only update the table if we need to. - if(!empty($update_query)) - { - $db->update_query("users", $update_query, "uid='{$thread['uid']}'", 1, true); - } - } - - if(!isset($forum['lastpost'])) - { - $forum['lastpost'] = 0; - } - - $done_users = array(); - - // Queue up any forum subscription notices to users who are subscribed to this forum. - $excerpt = my_substr($thread['message'], 0, $mybb->settings['subscribeexcerpt']).$lang->emailbit_viewthread; - - // Parse badwords - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - $excerpt = $parser->parse_badwords($excerpt); - - $query = $db->query(" - SELECT u.username, u.email, u.uid, u.language, u.loginkey, u.salt, u.regdate - FROM ".TABLE_PREFIX."forumsubscriptions fs - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=fs.uid) - LEFT JOIN ".TABLE_PREFIX."usergroups g ON (g.gid=u.usergroup) - WHERE fs.fid='".(int)$thread['fid']."' - AND fs.uid != '".(int)$thread['uid']."' - AND u.lastactive > '{$forum['lastpost']}' - AND g.isbannedgroup != 1 - "); - while($subscribedmember = $db->fetch_array($query)) - { - if($done_users[$subscribedmember['uid']]) - { - continue; - } - $done_users[$subscribedmember['uid']] = 1; - - $forumpermissions = forum_permissions($thread['fid'], $subscribedmember['uid']); - if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0) - { - continue; - } - - if(!is_moderator($thread['fid'], "", $subscribedmember['uid']) && $forumpermissions['canonlyviewownthreads'] == 1) - { - // In a 'view own only' forum and not a moderator - continue; - } - - // Determine the language pack we'll be using to send this email in and load it if it isn't already. - if($subscribedmember['language'] != '' && $lang->language_exists($subscribedmember['language'])) - { - $uselang = $subscribedmember['language']; - } - else if($mybb->settings['bblanguage']) - { - $uselang = $mybb->settings['bblanguage']; - } - else - { - $uselang = "english"; - } - - if($uselang == $mybb->settings['bblanguage']) - { - $emailsubject = $lang->emailsubject_forumsubscription; - $emailmessage = $lang->email_forumsubscription; - } - else - { - if(!isset($langcache[$uselang]['emailsubject_forumsubscription'])) - { - $userlang = new MyLanguage; - $userlang->set_path(MYBB_ROOT."inc/languages"); - $userlang->set_language($uselang); - $userlang->load("messages"); - $langcache[$uselang]['emailsubject_forumsubscription'] = $userlang->emailsubject_forumsubscription; - $langcache[$uselang]['email_forumsubscription'] = $userlang->email_forumsubscription; - unset($userlang); - } - $emailsubject = $langcache[$uselang]['emailsubject_forumsubscription']; - $emailmessage = $langcache[$uselang]['email_forumsubscription']; - } - $emailsubject = $lang->sprintf($emailsubject, $forum['name']); - - $post_code = md5($subscribedmember['loginkey'].$subscribedmember['salt'].$subscribedmember['regdate']); - $emailmessage = $lang->sprintf($emailmessage, $subscribedmember['username'], $thread['username'], $forum['name'], $mybb->settings['bbname'], $thread['subject'], $excerpt, $mybb->settings['bburl'], get_thread_link($this->tid), $thread['fid'], $post_code); - $new_email = array( - "mailto" => $db->escape_string($subscribedmember['email']), - "mailfrom" => '', - "subject" => $db->escape_string($emailsubject), - "message" => $db->escape_string($emailmessage), - "headers" => '' - ); - $db->insert_query("mailqueue", $new_email); - unset($userlang); - $queued_email = 1; - } - // Have one or more emails been queued? Update the queue count - if(isset($queued_email) && $queued_email == 1) - { - $cache->update_mailqueue(); - } - } - } - - // Assign any uploaded attachments with the specific posthash to the newly created post. - if($thread['posthash']) - { - $thread['posthash'] = $db->escape_string($thread['posthash']); - $attachmentassign = array( - "pid" => $this->pid, - "posthash" => '' - ); - $db->update_query("attachments", $attachmentassign, "posthash='{$thread['posthash']}' AND pid='0'"); - } - - if($visible == 1) - { - update_last_post($this->tid); - update_forum_counters($thread['fid'], array("threads" => "+1", "posts" => "+1")); - update_forum_lastpost($thread['fid']); - } - else if($visible == 0) - { - update_forum_counters($thread['fid'], array("unapprovedthreads" => "+1", "unapprovedposts" => "+1")); - } - - $query = $db->simple_select("attachments", "COUNT(aid) AS attachmentcount", "pid='{$this->pid}' AND visible='1'"); - $attachmentcount = $db->fetch_field($query, "attachmentcount"); - if($attachmentcount > 0) - { - update_thread_counters($this->tid, array("attachmentcount" => "+{$attachmentcount}")); - } - - // Return the post's pid and whether or not it is visible. - $this->return_values = array( - "pid" => $this->pid, - "tid" => $this->tid, - "visible" => $visible - ); - - $plugins->run_hooks("datahandler_post_insert_thread_end", $this); - - return $this->return_values; - } - - /** - * Updates a post that is already in the database. - * - * @return array - */ - function update_post() - { - global $db, $mybb, $plugins; - - // Yes, validating is required. - if($this->get_validated() != true) - { - die("The post needs to be validated before inserting it into the DB."); - } - if(count($this->get_errors()) > 0) - { - die("The post is not valid."); - } - - $post = &$this->data; - - $post['pid'] = (int)$post['pid']; - - $existing_post = get_post($post['pid']); - $post['tid'] = $existing_post['tid']; - $post['fid'] = $existing_post['fid']; - - $forum = get_forum($post['fid']); - $forumpermissions = forum_permissions($post['fid'], $post['uid']); - - // Decide on the visibility of this post. - $ismod = is_moderator($post['fid'], "", $post['uid']); - - // Keep visibility for unapproved and deleted posts - if($existing_post['visible'] == 0) - { - $visible = 0; - } - elseif($existing_post['visible'] == -1) - { - $visible = -1; - } - elseif($forumpermissions['mod_edit_posts'] == 1 && !$ismod) - { - $visible = 0; - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation; - $moderation->unapprove_posts(array($post['pid'])); - } - else - { - $visible = 1; - } - - // Update the thread details that might have been changed first. - if($this->first_post) - { - $this->tid = $post['tid']; - - if(isset($post['prefix'])) - { - $this->thread_update_data['prefix'] = (int)$post['prefix']; - } - - if(isset($post['subject'])) - { - $this->thread_update_data['subject'] = $db->escape_string($post['subject']); - } - - if(isset($post['icon'])) - { - $this->thread_update_data['icon'] = (int)$post['icon']; - } - if(count($this->thread_update_data) > 0) - { - $plugins->run_hooks("datahandler_post_update_thread", $this); - - $db->update_query("threads", $this->thread_update_data, "tid='".(int)$post['tid']."'"); - } - } - - // Prepare array for post updating. - - $this->pid = $post['pid']; - - if(isset($post['subject'])) - { - $this->post_update_data['subject'] = $db->escape_string($post['subject']); - } - - if(isset($post['message'])) - { - $this->post_update_data['message'] = $db->escape_string($post['message']); - } - - if(isset($post['editreason']) && trim($post['editreason']) != '') - { - $this->post_update_data['editreason'] = $db->escape_string(trim($post['editreason'])); - } - - if(isset($post['icon'])) - { - $this->post_update_data['icon'] = (int)$post['icon']; - } - - if(isset($post['options'])) - { - if(isset($post['options']['disablesmilies'])) - { - $this->post_update_data['smilieoff'] = $db->escape_string($post['options']['disablesmilies']); - } - if(isset($post['options']['signature'])) - { - $this->post_update_data['includesig'] = $db->escape_string($post['options']['signature']); - } - } - - // If we need to show the edited by, let's do so. - if(($mybb->settings['showeditedby'] == 1 && !is_moderator($post['fid'], "caneditposts", $post['edit_uid'])) || ($mybb->settings['showeditedbyadmin'] == 1 && is_moderator($post['fid'], "caneditposts", $post['edit_uid']))) - { - $this->post_update_data['edituid'] = (int)$post['edit_uid']; - $this->post_update_data['edittime'] = TIME_NOW; - } - - $plugins->run_hooks("datahandler_post_update", $this); - - $db->update_query("posts", $this->post_update_data, "pid='".(int)$post['pid']."'"); - - // Automatic subscription to the thread - if($post['options']['subscriptionmethod'] != "" && $post['uid'] > 0) - { - switch($post['options']['subscriptionmethod']) - { - case "pm": - $notification = 2; - break; - case "email": - $notification = 1; - break; - default: - $notification = 0; - } - require_once MYBB_ROOT."inc/functions_user.php"; - add_subscribed_thread($post['tid'], $notification, $post['uid']); - } - else - { - $db->delete_query("threadsubscriptions", "uid='".(int)$post['uid']."' AND tid='".(int)$post['tid']."'"); - } - - update_forum_lastpost($post['fid']); - update_last_post($post['tid']); - - // Return the thread's first post id and whether or not it is visible. - $this->return_values = array( - 'visible' => $visible, - 'first_post' => $this->first_post - ); - - $plugins->run_hooks("datahandler_post_update_end", $this); - - return $this->return_values; - } -} \ No newline at end of file diff --git a/html/forums/inc/datahandlers/user.php b/html/forums/inc/datahandlers/user.php deleted file mode 100644 index 940e089..0000000 --- a/html/forums/inc/datahandlers/user.php +++ /dev/null @@ -1,1854 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/** - * User handling class, provides common structure to handle user data. - * - */ -class UserDataHandler extends DataHandler -{ - /** - * The language file used in the data handler. - * - * @var string - */ - public $language_file = 'datahandler_user'; - - /** - * The prefix for the language variables used in the data handler. - * - * @var string - */ - public $language_prefix = 'userdata'; - - /** - * Array of data inserted in to a user. - * - * @var array - */ - public $user_insert_data = array(); - - /** - * Array of data used to update a user. - * - * @var array - */ - public $user_update_data = array(); - - /** - * User ID currently being manipulated by the datahandlers. - * - * @var int - */ - public $uid = 0; - - /** - * Values to be returned after inserting/deleting an user. - * - * @var array - */ - public $return_values = array(); - - /** - * @var array - */ - var $delete_uids = array(); - - /** - * @var int - */ - var $deleted_users = 0; - - /** - * Verifies if a username is valid or invalid. - * - * @return boolean True when valid, false when invalid. - */ - function verify_username() - { - global $mybb; - - $username = &$this->data['username']; - require_once MYBB_ROOT.'inc/functions_user.php'; - - // Fix bad characters - $username = trim_blank_chrs($username); - $username = str_replace(array(unichr(160), unichr(173), unichr(0xCA), dec_to_utf8(8238), dec_to_utf8(8237), dec_to_utf8(8203)), array(" ", "-", "", "", "", ""), $username); - - // Remove multiple spaces from the username - $username = preg_replace("#\s{2,}#", " ", $username); - - // Check if the username is not empty. - if($username == '') - { - $this->set_error('missing_username'); - return false; - } - - // Check if the username belongs to the list of banned usernames. - if(is_banned_username($username, true)) - { - $this->set_error('banned_username'); - return false; - } - - // Check for certain characters in username (<, >, &, commas and slashes) - if(strpos($username, "<") !== false || strpos($username, ">") !== false || strpos($username, "&") !== false || my_strpos($username, "\\") !== false || strpos($username, ";") !== false || strpos($username, ",") !== false || !validate_utf8_string($username, false, false)) - { - $this->set_error("bad_characters_username"); - return false; - } - - // Check if the username is of the correct length. - if(($mybb->settings['maxnamelength'] != 0 && my_strlen($username) > $mybb->settings['maxnamelength']) || ($mybb->settings['minnamelength'] != 0 && my_strlen($username) < $mybb->settings['minnamelength'])) - { - $this->set_error('invalid_username_length', array($mybb->settings['minnamelength'], $mybb->settings['maxnamelength'])); - return false; - } - - return true; - } - - /** - * Verifies if a usertitle is valid or invalid. - * - * @return boolean True when valid, false when invalid. - */ - function verify_usertitle() - { - global $mybb; - - $usertitle = &$this->data['usertitle']; - - // Check if the usertitle is of the correct length. - if($mybb->settings['customtitlemaxlength'] != 0 && my_strlen($usertitle) > $mybb->settings['customtitlemaxlength']) - { - $this->set_error('invalid_usertitle_length', $mybb->settings['customtitlemaxlength']); - return false; - } - - return true; - } - - /** - * Verifies if a username is already in use or not. - * - * @return boolean False when the username is not in use, true when it is. - */ - function verify_username_exists() - { - $username = &$this->data['username']; - - $user = get_user_by_username(trim($username)); - - if(!empty($this->data['uid']) && !empty($user['uid']) && $user['uid'] == $this->data['uid']) - { - unset($user); - } - - if(!empty($user['uid'])) - { - $this->set_error("username_exists", array($username)); - return true; - } - - return false; - } - - /** - * Verifies if a new password is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_password() - { - global $mybb; - - $user = &$this->data; - - // Always check for the length of the password. - if(my_strlen($user['password']) < $mybb->settings['minpasswordlength'] || my_strlen($user['password']) > $mybb->settings['maxpasswordlength']) - { - $this->set_error('invalid_password_length', array($mybb->settings['minpasswordlength'], $mybb->settings['maxpasswordlength'])); - return false; - } - - // Has the user tried to use their email address or username as a password? - if($user['email'] === $user['password'] || $user['username'] === $user['password']) - { - $this->set_error('bad_password_security'); - return false; - } - - // See if the board has "require complex passwords" enabled. - if($mybb->settings['requirecomplexpasswords'] == 1) - { - // Complex passwords required, do some extra checks. - // First, see if there is one or more complex character(s) in the password. - if(!preg_match("/^.*(?=.{".$mybb->settings['minpasswordlength'].",})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/", $user['password'])) - { - $this->set_error('no_complex_characters', array($mybb->settings['minpasswordlength'])); - return false; - } - } - - // If we have a "password2" check if they both match - if(isset($user['password2']) && $user['password'] !== $user['password2']) - { - $this->set_error("passwords_dont_match"); - return false; - } - - // Generate the user login key - $user['loginkey'] = generate_loginkey(); - - // Combine the password and salt - $password_fields = create_password($user['password'], false, $user); - $user = array_merge($user, $password_fields); - - return true; - } - - /** - * Verifies usergroup selections and other group details. - * - * @return boolean True when valid, false when invalid. - */ - function verify_usergroup() - { - return true; - } - /** - * Verifies if an email address is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_email() - { - global $mybb; - - $user = &$this->data; - - // Check if an email address has actually been entered. - if(trim_blank_chrs($user['email']) == '') - { - $this->set_error('missing_email'); - return false; - } - - // Check if this is a proper email address. - if(!validate_email_format($user['email'])) - { - $this->set_error('invalid_email_format'); - return false; - } - - // Check banned emails - if(is_banned_email($user['email'], true)) - { - $this->set_error('banned_email'); - return false; - } - - // Check signed up emails - // Ignore the ACP because the Merge System sometimes produces users with duplicate email addresses (Not A Bug) - if($mybb->settings['allowmultipleemails'] == 0 && !defined("IN_ADMINCP")) - { - $uid = 0; - if(isset($user['uid'])) - { - $uid = $user['uid']; - } - if(email_already_in_use($user['email'], $uid)) - { - $this->set_error('email_already_in_use'); - return false; - } - } - - // If we have an "email2", verify it matches the existing email - if(isset($user['email2']) && $user['email'] != $user['email2']) - { - $this->set_error("emails_dont_match"); - return false; - } - - return true; - } - - /** - * Verifies if a website is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_website() - { - $website = &$this->data['website']; - - if(!empty($website) && !my_validate_url($website)) - { - $website = 'http://'.$website; - } - - if(!empty($website) && !my_validate_url($website)) - { - $this->set_error('invalid_website'); - return false; - } - - return true; - } - - /** - * Verifies if an ICQ number is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_icq() - { - $icq = &$this->data['icq']; - - if($icq != '' && !is_numeric($icq)) - { - $this->set_error("invalid_icq_number"); - return false; - } - $icq = (int)$icq; - return true; - } - - /** - * Verifies if a birthday is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_birthday() - { - global $mybb; - - $user = &$this->data; - $birthday = &$user['birthday']; - - if(!is_array($birthday)) - { - return true; - } - - // Sanitize any input we have - $birthday['day'] = (int)$birthday['day']; - $birthday['month'] = (int)$birthday['month']; - $birthday['year'] = (int)$birthday['year']; - - // Error if a day and month exists, and the birthday day and range is not in range - if($birthday['day'] != 0 || $birthday['month'] != 0) - { - if($birthday['day'] < 1 || $birthday['day'] > 31 || $birthday['month'] < 1 || $birthday['month'] > 12 || ($birthday['month'] == 2 && $birthday['day'] > 29)) - { - $this->set_error("invalid_birthday"); - return false; - } - } - - // Check if the day actually exists. - $months = get_bdays($birthday['year']); - if($birthday['month'] != 0 && $birthday['day'] > $months[$birthday['month']-1]) - { - $this->set_error("invalid_birthday"); - return false; - } - - // Error if a year exists and the year is out of range - if($birthday['year'] != 0 && ($birthday['year'] < (date("Y")-100)) || $birthday['year'] > date("Y")) - { - $this->set_error("invalid_birthday"); - return false; - } - else if($birthday['year'] == date("Y")) - { - // Error if birth date is in future - if($birthday['month'] > date("m") || ($birthday['month'] == date("m") && $birthday['day'] > date("d"))) - { - $this->set_error("invalid_birthday"); - return false; - } - } - - // Error if COPPA is on, and the user hasn't verified their age / under 13 - if($mybb->settings['coppa'] == "enabled" && ($birthday['year'] == 0 || !$birthday['year'])) - { - $this->set_error("invalid_birthday_coppa"); - return false; - } - elseif(($mybb->settings['coppa'] == "deny" && $birthday['year'] > (date("Y")-13)) && !is_moderator()) - { - $this->set_error("invalid_birthday_coppa2"); - return false; - } - - // Make the user's birthday field - if($birthday['year'] != 0) - { - // If the year is specified, put together a d-m-y string - $user['bday'] = $birthday['day']."-".$birthday['month']."-".$birthday['year']; - } - elseif($birthday['day'] && $birthday['month']) - { - // If only a day and month are specified, put together a d-m string - $user['bday'] = $birthday['day']."-".$birthday['month']."-"; - } - else - { - // No field is specified, so return an empty string for an unknown birthday - $user['bday'] = ''; - } - return true; - } - - /** - * Verifies if the birthday privacy option is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_birthday_privacy() - { - $birthdayprivacy = &$this->data['birthdayprivacy']; - $accepted = array( - 'none', - 'age', - 'all'); - - if(!in_array($birthdayprivacy, $accepted)) - { - $this->set_error("invalid_birthday_privacy"); - return false; - } - return true; - } - - /** - * Verifies if the post count field is filled in correctly. - * - * @return boolean True when valid, false when invalid. - */ - function verify_postnum() - { - $user = &$this->data; - - if(isset($user['postnum']) && $user['postnum'] < 0) - { - $this->set_error("invalid_postnum"); - return false; - } - - return true; - } - - /** - * Verifies if the thread count field is filled in correctly. - * - * @return boolean True when valid, false when invalid. - */ - function verify_threadnum() - { - $user = &$this->data; - - if(isset($user['threadnum']) && $user['threadnum'] < 0) - { - $this->set_error("invalid_threadnum"); - return false; - } - - return true; - } - - /** - * Verifies if a profile fields are filled in correctly. - * - * @return boolean True when valid, false when invalid. - */ - function verify_profile_fields() - { - global $db, $cache; - - $user = &$this->data; - $profile_fields = &$this->data['profile_fields']; - - // Loop through profile fields checking if they exist or not and are filled in. - - // Fetch all profile fields first. - $pfcache = $cache->read('profilefields'); - - if(is_array($pfcache)) - { - // Then loop through the profile fields. - foreach($pfcache as $profilefield) - { - if(isset($this->data['profile_fields_editable']) || isset($this->data['registration']) && ($profilefield['required'] == 1 || $profilefield['registration'] == 1)) - { - $profilefield['editableby'] = -1; - } - - if(!is_member($profilefield['editableby'], array('usergroup' => $user['usergroup'], 'additionalgroups' => $user['additionalgroups']))) - { - continue; - } - - // Does this field have a minimum post count? - if(!isset($this->data['profile_fields_editable']) && !empty($profilefield['postnum']) && $profilefield['postnum'] > $user['postnum']) - { - continue; - } - - $profilefield['type'] = htmlspecialchars_uni($profilefield['type']); - $profilefield['name'] = htmlspecialchars_uni($profilefield['name']); - $thing = explode("\n", $profilefield['type'], "2"); - $type = trim($thing[0]); - $field = "fid{$profilefield['fid']}"; - - if(!isset($profile_fields[$field])) - { - $profile_fields[$field] = ''; - } - - // If the profile field is required, but not filled in, present error. - if($type != "multiselect" && $type != "checkbox") - { - if(trim($profile_fields[$field]) == "" && $profilefield['required'] == 1 && !defined('IN_ADMINCP') && THIS_SCRIPT != "modcp.php") - { - $this->set_error('missing_required_profile_field', array($profilefield['name'])); - } - } - elseif(($type == "multiselect" || $type == "checkbox") && $profile_fields[$field] == "" && $profilefield['required'] == 1 && !defined('IN_ADMINCP') && THIS_SCRIPT != "modcp.php") - { - $this->set_error('missing_required_profile_field', array($profilefield['name'])); - } - - // Sort out multiselect/checkbox profile fields. - $options = ''; - if(($type == "multiselect" || $type == "checkbox") && is_array($profile_fields[$field])) - { - $expoptions = explode("\n", $thing[1]); - $expoptions = array_map('trim', $expoptions); - foreach($profile_fields[$field] as $value) - { - if(!in_array(htmlspecialchars_uni($value), $expoptions)) - { - $this->set_error('bad_profile_field_values', array($profilefield['name'])); - } - if($options) - { - $options .= "\n"; - } - $options .= $db->escape_string($value); - } - } - elseif($type == "select" || $type == "radio") - { - $expoptions = explode("\n", $thing[1]); - $expoptions = array_map('trim', $expoptions); - if(!in_array(htmlspecialchars_uni($profile_fields[$field]), $expoptions) && trim($profile_fields[$field]) != "") - { - $this->set_error('bad_profile_field_values', array($profilefield['name'])); - } - $options = $db->escape_string($profile_fields[$field]); - } - else - { - if($profilefield['maxlength'] > 0 && my_strlen($profile_fields[$field]) > $profilefield['maxlength']) - { - $this->set_error('max_limit_reached', array($profilefield['name'], $profilefield['maxlength'])); - } - - if(!empty($profilefield['regex']) && !preg_match("#".$profilefield['regex']."#i", $profile_fields[$field])) - { - $this->set_error('bad_profile_field_value', array($profilefield['name'])); - } - - $options = $db->escape_string($profile_fields[$field]); - } - $user['user_fields'][$field] = $options; - } - } - - return true; - } - - /** - * Verifies if an optionally entered referrer exists or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_referrer() - { - global $db, $mybb; - - $user = &$this->data; - - // Does the referrer exist or not? - if($mybb->settings['usereferrals'] == 1 && $user['referrer'] != '') - { - $referrer = get_user_by_username($user['referrer']); - - if(empty($referrer['uid'])) - { - $this->set_error('invalid_referrer', array($user['referrer'])); - return false; - } - - $user['referrer_uid'] = $referrer['uid']; - } - else - { - $user['referrer_uid'] = 0; - } - - return true; - } - - /** - * Verifies user options. - * - * @return boolean True when valid, false when invalid. - */ - function verify_options() - { - global $mybb; - - $options = &$this->data['options']; - - // Verify yes/no options. - $this->verify_yesno_option($options, 'allownotices', 1); - $this->verify_yesno_option($options, 'hideemail', 0); - $this->verify_yesno_option($options, 'receivepms', 1); - $this->verify_yesno_option($options, 'receivefrombuddy', 0); - $this->verify_yesno_option($options, 'pmnotice', 1); - $this->verify_yesno_option($options, 'pmnotify', 1); - $this->verify_yesno_option($options, 'invisible', 0); - $this->verify_yesno_option($options, 'showimages', 1); - $this->verify_yesno_option($options, 'showvideos', 1); - $this->verify_yesno_option($options, 'showsigs', 1); - $this->verify_yesno_option($options, 'showavatars', 1); - $this->verify_yesno_option($options, 'showquickreply', 1); - $this->verify_yesno_option($options, 'showredirect', 1); - $this->verify_yesno_option($options, 'showcodebuttons', 1); - $this->verify_yesno_option($options, 'sourceeditor', 0); - $this->verify_yesno_option($options, 'buddyrequestspm', 1); - $this->verify_yesno_option($options, 'buddyrequestsauto', 0); - - if($mybb->settings['postlayout'] == 'classic') - { - $this->verify_yesno_option($options, 'classicpostbit', 1); - } - else - { - $this->verify_yesno_option($options, 'classicpostbit', 0); - } - - if(array_key_exists('subscriptionmethod', $options)) - { - // Value out of range - $options['subscriptionmethod'] = (int)$options['subscriptionmethod']; - if($options['subscriptionmethod'] < 0 || $options['subscriptionmethod'] > 3) - { - $options['subscriptionmethod'] = 0; - } - } - - if(array_key_exists('dstcorrection', $options)) - { - // Value out of range - $options['dstcorrection'] = (int)$options['dstcorrection']; - if($options['dstcorrection'] < 0 || $options['dstcorrection'] > 2) - { - $options['dstcorrection'] = 0; - } - } - - if($options['dstcorrection'] == 1) - { - $options['dst'] = 1; - } - else if($options['dstcorrection'] == 0) - { - $options['dst'] = 0; - } - - if($this->method == "insert" || (isset($options['threadmode']) && $options['threadmode'] != "linear" && $options['threadmode'] != "threaded")) - { - if($mybb->settings['threadusenetstyle']) - { - $options['threadmode'] = 'threaded'; - } - else - { - $options['threadmode'] = 'linear'; - } - } - - // Verify the "threads per page" option. - if($this->method == "insert" || (array_key_exists('tpp', $options) && $mybb->settings['usertppoptions'])) - { - if(!isset($options['tpp'])) - { - $options['tpp'] = 0; - } - $explodedtpp = explode(",", $mybb->settings['usertppoptions']); - if(is_array($explodedtpp)) - { - @asort($explodedtpp); - $biggest = $explodedtpp[count($explodedtpp)-1]; - // Is the selected option greater than the allowed options? - if($options['tpp'] > $biggest) - { - $options['tpp'] = $biggest; - } - } - $options['tpp'] = (int)$options['tpp']; - } - // Verify the "posts per page" option. - if($this->method == "insert" || (array_key_exists('ppp', $options) && $mybb->settings['userpppoptions'])) - { - if(!isset($options['ppp'])) - { - $options['ppp'] = 0; - } - $explodedppp = explode(",", $mybb->settings['userpppoptions']); - if(is_array($explodedppp)) - { - @asort($explodedppp); - $biggest = $explodedppp[count($explodedppp)-1]; - // Is the selected option greater than the allowed options? - if($options['ppp'] > $biggest) - { - $options['ppp'] = $biggest; - } - } - $options['ppp'] = (int)$options['ppp']; - } - // Is our selected "days prune" option valid or not? - if($this->method == "insert" || array_key_exists('daysprune', $options)) - { - if(!isset($options['daysprune'])) - { - $options['daysprune'] = 0; - } - $options['daysprune'] = (int)$options['daysprune']; - if($options['daysprune'] < 0) - { - $options['daysprune'] = 0; - } - } - $this->data['options'] = $options; - } - - /** - * Verifies if a registration date is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_regdate() - { - $regdate = &$this->data['regdate']; - - $regdate = (int)$regdate; - // If the timestamp is below 0, set it to the current time. - if($regdate <= 0) - { - $regdate = TIME_NOW; - } - return true; - } - - /** - * Verifies if a last visit date is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_lastvisit() - { - $lastvisit = &$this->data['lastvisit']; - - $lastvisit = (int)$lastvisit; - // If the timestamp is below 0, set it to the current time. - if($lastvisit <= 0) - { - $lastvisit = TIME_NOW; - } - return true; - - } - - /** - * Verifies if a last active date is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_lastactive() - { - $lastactive = &$this->data['lastactive']; - - $lastactive = (int)$lastactive; - // If the timestamp is below 0, set it to the current time. - if($lastactive <= 0) - { - $lastactive = TIME_NOW; - } - return true; - - } - - /** - * Verifies if an away mode status is valid or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_away() - { - global $mybb; - - $user = &$this->data; - // If the board does not allow "away mode" or the user is marking as not away, set defaults. - if($mybb->settings['allowaway'] == 0 || !isset($user['away']['away']) || $user['away']['away'] != 1) - { - $user['away']['away'] = 0; - $user['away']['date'] = 0; - $user['away']['returndate'] = 0; - $user['away']['awayreason'] = ''; - return true; - } - else if($user['away']['returndate']) - { - list($returnday, $returnmonth, $returnyear) = explode('-', $user['away']['returndate']); - if(!$returnday || !$returnmonth || !$returnyear) - { - $this->set_error("missing_returndate"); - return false; - } - - // Validate the return date lengths - $user['away']['returndate'] = substr($returnday, 0, 2).'-'.substr($returnmonth, 0, 2).'-'.substr($returnyear, 0, 4); - } - return true; - } - - /** - * Verifies if a language is valid for this user or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_language() - { - global $lang; - - $language = &$this->data['language']; - - // An invalid language has been specified? - if($language != '' && !$lang->language_exists($language)) - { - $this->set_error("invalid_language"); - return false; - } - return true; - } - - /** - * Verifies if a style is valid for this user or not. - * - * @return boolean True when valid, false when invalid. - */ - function verify_style() - { - global $lang; - - $user = &$this->data; - - if($user['style']) - { - $theme = get_theme($user['style']); - - if(empty($theme) || !is_member($theme['allowedgroups'], $user) && $theme['allowedgroups'] != 'all') - { - $this->set_error('invalid_style'); - return false; - } - } - - return true; - } - - /** - * Verifies if this is coming from a spam bot or not - * - * @return boolean True when valid, false when invalid. - */ - function verify_checkfields() - { - $user = &$this->data; - - // An invalid language has been specified? - if($user['regcheck1'] !== "" || $user['regcheck2'] !== "true") - { - $this->set_error("invalid_checkfield"); - return false; - } - return true; - } - - /** - * Verifies if the user timezone is valid. - * If the timezone is invalid, the board default is used. - * - * @return boolean True when timezone was valid, false otherwise - */ - function verify_timezone() - { - $user = &$this->data; - - $timezones = get_supported_timezones(); - - if(!array_key_exists($user['timezone'], $timezones)) - { - $user['timezone'] = $mybb->settings['timezoneoffset']; - return false; - } - - return true; - } - - /** - * Validate all user assets. - * - * @return boolean True when valid, false when invalid. - */ - function validate_user() - { - global $mybb, $plugins; - - $user = &$this->data; - - // First, grab the old user details if this user exists - if(!empty($user['uid'])) - { - $old_user = get_user($user['uid']); - } - - if($this->method == "insert" || array_key_exists('username', $user)) - { - // If the username is the same - no need to verify - if(!isset($old_user['username']) || $user['username'] != $old_user['username']) - { - $this->verify_username(); - $this->verify_username_exists(); - } - else - { - unset($user['username']); - } - } - if($this->method == "insert" || array_key_exists('usertitle', $user)) - { - $this->verify_usertitle(); - } - if($this->method == "insert" || array_key_exists('password', $user)) - { - $this->verify_password(); - } - if($this->method == "insert" || array_key_exists('usergroup', $user)) - { - $this->verify_usergroup(); - } - if($this->method == "insert" || array_key_exists('email', $user)) - { - $this->verify_email(); - } - if($this->method == "insert" || array_key_exists('website', $user)) - { - $this->verify_website(); - } - if($this->method == "insert" || array_key_exists('icq', $user)) - { - $this->verify_icq(); - } - if($this->method == "insert" || (isset($user['birthday']) && is_array($user['birthday']))) - { - $this->verify_birthday(); - } - if($this->method == "insert" || array_key_exists('postnum', $user)) - { - $this->verify_postnum(); - } - if($this->method == "insert" || array_key_exists('threadnum', $user)) - { - $this->verify_threadnum(); - } - if($this->method == "insert" || array_key_exists('profile_fields', $user)) - { - $this->verify_profile_fields(); - } - if($this->method == "insert" || array_key_exists('referrer', $user)) - { - $this->verify_referrer(); - } - if($this->method == "insert" || array_key_exists('options', $user)) - { - $this->verify_options(); - } - if($this->method == "insert" || array_key_exists('regdate', $user)) - { - $this->verify_regdate(); - } - if($this->method == "insert" || array_key_exists('lastvisit', $user)) - { - $this->verify_lastvisit(); - } - if($this->method == "insert" || array_key_exists('lastactive', $user)) - { - $this->verify_lastactive(); - } - if($this->method == "insert" || array_key_exists('away', $user)) - { - $this->verify_away(); - } - if($this->method == "insert" || array_key_exists('language', $user)) - { - $this->verify_language(); - } - if($this->method == "insert" || array_key_exists('timezone', $user)) - { - $this->verify_timezone(); - } - if($this->method == "insert" && array_key_exists('regcheck1', $user) && array_key_exists('regcheck2', $user)) - { - $this->verify_checkfields(); - } - if(array_key_exists('birthdayprivacy', $user)) - { - $this->verify_birthday_privacy(); - } - if($this->method == "insert" || array_key_exists('style', $user)) - { - $this->verify_style(); - } - if($this->method == "insert" || array_key_exists('signature', $user)) - { - $this->verify_signature(); - } - - $plugins->run_hooks("datahandler_user_validate", $this); - - // We are done validating, return. - $this->set_validated(true); - if(count($this->get_errors()) > 0) - { - return false; - } - else - { - return true; - } - } - - /** - * Inserts a user into the database. - * - * @return array - */ - function insert_user() - { - global $db, $cache, $plugins; - - // Yes, validating is required. - if(!$this->get_validated()) - { - die("The user needs to be validated before inserting it into the DB."); - } - if(count($this->get_errors()) > 0) - { - die("The user is not valid."); - } - - $user = &$this->data; - - $array = array('postnum', 'threadnum', 'avatar', 'avatartype', 'additionalgroups', 'displaygroup', 'icq', 'aim', 'yahoo', 'skype', 'google', 'bday', 'signature', 'style', 'dateformat', 'timeformat', 'notepad'); - foreach($array as $value) - { - if(!isset($user[$value])) - { - $user[$value] = ''; - } - } - - $this->user_insert_data = array( - "username" => $db->escape_string($user['username']), - "password" => $user['password'], - "salt" => $user['salt'], - "loginkey" => $user['loginkey'], - "email" => $db->escape_string($user['email']), - "postnum" => (int)$user['postnum'], - "threadnum" => (int)$user['threadnum'], - "avatar" => $db->escape_string($user['avatar']), - "avatartype" => $db->escape_string($user['avatartype']), - "usergroup" => (int)$user['usergroup'], - "additionalgroups" => $db->escape_string($user['additionalgroups']), - "displaygroup" => (int)$user['displaygroup'], - "usertitle" => $db->escape_string(htmlspecialchars_uni($user['usertitle'])), - "regdate" => (int)$user['regdate'], - "lastactive" => (int)$user['lastactive'], - "lastvisit" => (int)$user['lastvisit'], - "website" => $db->escape_string($user['website']), - "icq" => (int)$user['icq'], - "aim" => $db->escape_string($user['aim']), - "yahoo" => $db->escape_string($user['yahoo']), - "skype" => $db->escape_string($user['skype']), - "google" => $db->escape_string($user['google']), - "birthday" => $user['bday'], - "signature" => $db->escape_string($user['signature']), - "allownotices" => (int)$user['options']['allownotices'], - "hideemail" => (int)$user['options']['hideemail'], - "subscriptionmethod" => (int)$user['options']['subscriptionmethod'], - "receivepms" => (int)$user['options']['receivepms'], - "receivefrombuddy" => (int)$user['options']['receivefrombuddy'], - "pmnotice" => (int)$user['options']['pmnotice'], - "pmnotify" => (int)$user['options']['pmnotify'], - "showimages" => (int)$user['options']['showimages'], - "showvideos" => (int)$user['options']['showvideos'], - "showsigs" => (int)$user['options']['showsigs'], - "showavatars" => (int)$user['options']['showavatars'], - "showquickreply" => (int)$user['options']['showquickreply'], - "showredirect" => (int)$user['options']['showredirect'], - "tpp" => (int)$user['options']['tpp'], - "ppp" => (int)$user['options']['ppp'], - "invisible" => (int)$user['options']['invisible'], - "style" => (int)$user['style'], - "timezone" => $db->escape_string($user['timezone']), - "dstcorrection" => (int)$user['options']['dstcorrection'], - "threadmode" => $user['options']['threadmode'], - "daysprune" => (int)$user['options']['daysprune'], - "dateformat" => $db->escape_string($user['dateformat']), - "timeformat" => $db->escape_string($user['timeformat']), - "regip" => $db->escape_binary($user['regip']), - "language" => $db->escape_string($user['language']), - "showcodebuttons" => (int)$user['options']['showcodebuttons'], - "sourceeditor" => (int)$user['options']['sourceeditor'], - "buddyrequestspm" => (int)$user['options']['buddyrequestspm'], - "buddyrequestsauto" => (int)$user['options']['buddyrequestsauto'], - "away" => (int)$user['away']['away'], - "awaydate" => (int)$user['away']['date'], - "returndate" => $user['away']['returndate'], - "awayreason" => $db->escape_string($user['away']['awayreason']), - "notepad" => $db->escape_string($user['notepad']), - "referrer" => (int)$user['referrer_uid'], - "referrals" => 0, - "buddylist" => '', - "ignorelist" => '', - "pmfolders" => '', - "notepad" => '', - "warningpoints" => 0, - "moderateposts" => 0, - "moderationtime" => 0, - "suspendposting" => 0, - "suspensiontime" => 0, - "coppauser" => (int)$user['coppa_user'], - "classicpostbit" => (int)$user['options']['classicpostbit'], - "usernotes" => '' - ); - - if($user['options']['dstcorrection'] == 1) - { - $this->user_insert_data['dst'] = 1; - } - else if($user['options']['dstcorrection'] == 0) - { - $this->user_insert_data['dst'] = 0; - } - - $plugins->run_hooks("datahandler_user_insert", $this); - - $this->uid = $db->insert_query("users", $this->user_insert_data); - - $user['user_fields']['ufid'] = $this->uid; - - $pfcache = $cache->read('profilefields'); - - if(is_array($pfcache)) - { - foreach($pfcache as $profile_field) - { - if(array_key_exists("fid{$profile_field['fid']}", $user['user_fields'])) - { - continue; - } - $user['user_fields']["fid{$profile_field['fid']}"] = ''; - } - } - - $db->insert_query("userfields", $user['user_fields'], false); - - if($this->user_insert_data['referrer'] != 0) - { - $db->write_query(" - UPDATE ".TABLE_PREFIX."users - SET referrals=referrals+1 - WHERE uid='{$this->user_insert_data['referrer']}' - "); - } - - // Update forum stats - update_stats(array('numusers' => '+1')); - - if((int)$user['usergroup'] == 5) - { - $cache->update_awaitingactivation(); - } - - $this->return_values = array( - "uid" => $this->uid, - "username" => $user['username'], - "loginkey" => $user['loginkey'], - "email" => $user['email'], - "password" => $user['password'], - "usergroup" => $user['usergroup'] - ); - - $plugins->run_hooks("datahandler_user_insert_end", $this); - - return $this->return_values; - } - - /** - * Updates a user in the database. - * - * @return bool - */ - function update_user() - { - global $db, $plugins, $cache; - - // Yes, validating is required. - if(!$this->get_validated()) - { - die("The user needs to be validated before inserting it into the DB."); - } - if(count($this->get_errors()) > 0) - { - die("The user is not valid."); - } - - $user = &$this->data; - $user['uid'] = (int)$user['uid']; - $this->uid = $user['uid']; - - // Set up the update data. - if(isset($user['username'])) - { - $this->user_update_data['username'] = $db->escape_string($user['username']); - } - if(isset($user['password'])) - { - $this->user_update_data['password'] = $user['password']; - } - if(isset($user['salt'])) - { - $this->user_update_data['salt'] = $user['salt']; - } - if(isset($user['loginkey'])) - { - $this->user_update_data['loginkey'] = $user['loginkey']; - } - if(isset($user['email'])) - { - $this->user_update_data['email'] = $user['email']; - } - if(isset($user['postnum'])) - { - $this->user_update_data['postnum'] = (int)$user['postnum']; - } - if(isset($user['threadnum'])) - { - $this->user_update_data['threadnum'] = (int)$user['threadnum']; - } - if(isset($user['avatar'])) - { - $this->user_update_data['avatar'] = $db->escape_string($user['avatar']); - $this->user_update_data['avatartype'] = $db->escape_string($user['avatartype']); - } - if(isset($user['usergroup'])) - { - $this->user_update_data['usergroup'] = (int)$user['usergroup']; - } - if(isset($user['additionalgroups'])) - { - $this->user_update_data['additionalgroups'] = $db->escape_string($user['additionalgroups']); - } - if(isset($user['displaygroup'])) - { - $this->user_update_data['displaygroup'] = (int)$user['displaygroup']; - } - if(isset($user['usertitle'])) - { - $this->user_update_data['usertitle'] = $db->escape_string($user['usertitle']); - } - if(isset($user['regdate'])) - { - $this->user_update_data['regdate'] = (int)$user['regdate']; - } - if(isset($user['lastactive'])) - { - $this->user_update_data['lastactive'] = (int)$user['lastactive']; - } - if(isset($user['lastvisit'])) - { - $this->user_update_data['lastvisit'] = (int)$user['lastvisit']; - } - if(isset($user['signature'])) - { - $this->user_update_data['signature'] = $db->escape_string($user['signature']); - } - if(isset($user['website'])) - { - $this->user_update_data['website'] = $db->escape_string($user['website']); - } - if(isset($user['icq'])) - { - $this->user_update_data['icq'] = (int)$user['icq']; - } - if(isset($user['aim'])) - { - $this->user_update_data['aim'] = $db->escape_string($user['aim']); - } - if(isset($user['yahoo'])) - { - $this->user_update_data['yahoo'] = $db->escape_string($user['yahoo']); - } - if(isset($user['skype'])) - { - $this->user_update_data['skype'] = $db->escape_string($user['skype']); - } - if(isset($user['google'])) - { - $this->user_update_data['google'] = $db->escape_string($user['google']); - } - if(isset($user['bday'])) - { - $this->user_update_data['birthday'] = $user['bday']; - } - if(isset($user['birthdayprivacy'])) - { - $this->user_update_data['birthdayprivacy'] = $db->escape_string($user['birthdayprivacy']); - } - if(isset($user['style'])) - { - $this->user_update_data['style'] = (int)$user['style']; - } - if(isset($user['timezone'])) - { - $this->user_update_data['timezone'] = $db->escape_string($user['timezone']); - } - if(isset($user['dateformat'])) - { - $this->user_update_data['dateformat'] = $db->escape_string($user['dateformat']); - } - if(isset($user['timeformat'])) - { - $this->user_update_data['timeformat'] = $db->escape_string($user['timeformat']); - } - if(isset($user['regip'])) - { - $this->user_update_data['regip'] = $db->escape_string($user['regip']); - } - if(isset($user['language'])) - { - $this->user_update_data['language'] = $db->escape_string($user['language']); - } - if(isset($user['away'])) - { - $this->user_update_data['away'] = (int)$user['away']['away']; - $this->user_update_data['awaydate'] = $db->escape_string($user['away']['date']); - $this->user_update_data['returndate'] = $db->escape_string($user['away']['returndate']); - $this->user_update_data['awayreason'] = $db->escape_string($user['away']['awayreason']); - } - if(isset($user['notepad'])) - { - $this->user_update_data['notepad'] = $db->escape_string($user['notepad']); - } - if(isset($user['usernotes'])) - { - $this->user_update_data['usernotes'] = $db->escape_string($user['usernotes']); - } - if(isset($user['options']) && is_array($user['options'])) - { - foreach($user['options'] as $option => $value) - { - $this->user_update_data[$option] = $value; - } - } - if(array_key_exists('coppa_user', $user)) - { - $this->user_update_data['coppauser'] = (int)$user['coppa_user']; - } - // First, grab the old user details for later use. - $old_user = get_user($user['uid']); - - // If old user has new pmnotice and new user has = yes, keep old value - if($old_user['pmnotice'] == "2" && $this->user_update_data['pmnotice'] == 1) - { - unset($this->user_update_data['pmnotice']); - } - - $plugins->run_hooks("datahandler_user_update", $this); - - if(count($this->user_update_data) < 1 && empty($user['user_fields'])) - { - return false; - } - - if(count($this->user_update_data) > 0) - { - // Actual updating happens here. - $db->update_query("users", $this->user_update_data, "uid='{$user['uid']}'"); - } - - $cache->update_moderators(); - if(isset($user['bday']) || isset($user['username'])) - { - $cache->update_birthdays(); - } - - if(isset($user['usergroup']) && (int)$user['usergroup'] == 5) - { - $cache->update_awaitingactivation(); - } - - // Maybe some userfields need to be updated? - if(isset($user['user_fields']) && is_array($user['user_fields'])) - { - $query = $db->simple_select("userfields", "*", "ufid='{$user['uid']}'"); - $fields = $db->fetch_array($query); - if(!$fields['ufid']) - { - $user_fields = array( - 'ufid' => $user['uid'] - ); - - $fields_array = $db->show_fields_from("userfields"); - foreach($fields_array as $field) - { - if($field['Field'] == 'ufid') - { - continue; - } - $user_fields[$field['Field']] = ''; - } - $db->insert_query("userfields", $user_fields); - } - $db->update_query("userfields", $user['user_fields'], "ufid='{$user['uid']}'", false); - } - - // Let's make sure the user's name gets changed everywhere in the db if it changed. - if(!empty($this->user_update_data['username']) && $this->user_update_data['username'] != $old_user['username']) - { - $username_update = array( - "username" => $this->user_update_data['username'] - ); - $lastposter_update = array( - "lastposter" => $this->user_update_data['username'] - ); - - $db->update_query("posts", $username_update, "uid='{$user['uid']}'"); - $db->update_query("threads", $username_update, "uid='{$user['uid']}'"); - $db->update_query("threads", $lastposter_update, "lastposteruid='{$user['uid']}'"); - $db->update_query("forums", $lastposter_update, "lastposteruid='{$user['uid']}'"); - - $stats = $cache->read("stats"); - if($stats['lastuid'] == $user['uid']) - { - // User was latest to register, update stats - update_stats(array("numusers" => "+0")); - } - } - - return true; - } - - /** - * Provides a method to completely delete a user. - * - * @param array $delete_uids Array of user information - * @param integer $prunecontent Whether if delete threads/posts or not - * @return array - */ - function delete_user($delete_uids, $prunecontent=0) - { - global $db, $plugins, $mybb, $cache; - - // Yes, validating is required. - if(count($this->get_errors()) > 0) - { - die('The user is not valid.'); - } - - $this->delete_uids = array_map('intval', (array)$delete_uids); - - foreach($this->delete_uids as $key => $uid) - { - if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid']) - { - // Remove super admins - unset($this->delete_uids[$key]); - } - } - - $plugins->run_hooks('datahandler_user_delete_start', $this); - - $this->delete_uids = implode(',', $this->delete_uids); - - if(empty($this->delete_uids)) - { - $this->deleted_users = 0; - $this->return_values = array( - "deleted_users" => $this->deleted_users - ); - - return $this->return_values; - } - - $this->delete_content(); - - // Delete the user - $query = $db->delete_query('users', "uid IN({$this->delete_uids})"); - $this->deleted_users = $db->affected_rows($query); - - // Are we removing the posts/threads of a user? - if((int)$prunecontent == 1) - { - $this->delete_posts(); - $db->delete_query('announcements', "uid IN({$this->delete_uids})"); - } - else - { - // We're just updating the UID - $db->update_query('pollvotes', array('uid' => 0), "uid IN({$this->delete_uids})"); - $db->update_query('posts', array('uid' => 0), "uid IN({$this->delete_uids})"); - $db->update_query('threads', array('uid' => 0), "uid IN({$this->delete_uids})"); - $db->update_query('attachments', array('uid' => 0), "uid IN({$this->delete_uids})"); - $db->update_query('announcements', array('uid' => 0), "uid IN({$this->delete_uids})"); - } - - $db->update_query('privatemessages', array('fromid' => 0), "fromid IN({$this->delete_uids})"); - $db->update_query('users', array('referrer' => 0), "referrer IN({$this->delete_uids})"); - - // Update thread ratings - $query = $db->query(" - SELECT r.*, t.numratings, t.totalratings - FROM ".TABLE_PREFIX."threadratings r - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=r.tid) - WHERE r.uid IN({$this->delete_uids}) - "); - while($rating = $db->fetch_array($query)) - { - $update_thread = array( - "numratings" => $rating['numratings'] - 1, - "totalratings" => $rating['totalratings'] - $rating['rating'] - ); - $db->update_query("threads", $update_thread, "tid='{$rating['tid']}'"); - } - - $db->delete_query('threadratings', "uid IN({$this->delete_uids})"); - - // Update forums & threads if user is the lastposter - $db->update_query('forums', array('lastposteruid' => 0), "lastposteruid IN({$this->delete_uids})"); - $db->update_query('threads', array('lastposteruid' => 0), "lastposteruid IN({$this->delete_uids})"); - - // Update forum stats - update_stats(array('numusers' => '-'.$this->deleted_users)); - - $this->return_values = array( - "deleted_users" => $this->deleted_users - ); - - $plugins->run_hooks("datahandler_user_delete_end", $this); - - // Update cache - $cache->update_banned(); - $cache->update_moderators(); - $cache->update_forumsdisplay(); - $cache->update_reportedcontent(); - $cache->update_awaitingactivation(); - $cache->update_birthdays(); - - return $this->return_values; - } - - /** - * Provides a method to delete users' content - * - * @param array|bool $delete_uids Array of user ids, false if they're already set (eg when using the delete_user function) - */ - function delete_content($delete_uids=false) - { - global $db, $plugins, $mybb; - - if($delete_uids != false) - { - $this->delete_uids = array_map('intval', (array)$delete_uids); - - foreach($this->delete_uids as $key => $uid) - { - if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid']) - { - // Remove super admins - unset($this->delete_uids[$key]); - } - } - - $this->delete_uids = implode(',', $this->delete_uids); - } - - $plugins->run_hooks('datahandler_user_delete_content', $this); - - if(empty($this->delete_uids)) - { - return; - } - - $db->delete_query('userfields', "ufid IN({$this->delete_uids})"); - $db->delete_query('privatemessages', "uid IN({$this->delete_uids})"); - $db->delete_query('events', "uid IN({$this->delete_uids})"); - $db->delete_query('moderators', "id IN({$this->delete_uids}) AND isgroup = 0"); - $db->delete_query('forumsubscriptions', "uid IN({$this->delete_uids})"); - $db->delete_query('threadsubscriptions', "uid IN({$this->delete_uids})"); - $db->delete_query('forumsread', "uid IN({$this->delete_uids})"); - $db->delete_query('threadsread', "uid IN({$this->delete_uids})"); - $db->delete_query('adminviews', "uid IN({$this->delete_uids})"); - $db->delete_query('adminoptions', "uid IN({$this->delete_uids})"); - $db->delete_query('adminsessions', "uid IN({$this->delete_uids})"); - $db->delete_query('sessions', "uid IN({$this->delete_uids})"); - $db->delete_query('banned', "uid IN({$this->delete_uids})"); - $db->delete_query('joinrequests', "uid IN({$this->delete_uids})"); - $db->delete_query('groupleaders', "uid IN({$this->delete_uids})"); - $db->delete_query('awaitingactivation', "uid IN({$this->delete_uids})"); - $db->delete_query('warnings', "uid IN({$this->delete_uids})"); - $db->delete_query('reputation', "uid IN({$this->delete_uids}) OR adduid IN({$this->delete_uids})"); - $db->delete_query('buddyrequests', "uid IN({$this->delete_uids}) OR touid IN({$this->delete_uids})"); - $db->delete_query('posts', "uid IN({$this->delete_uids}) AND visible = -2"); - $db->delete_query('threads', "uid IN({$this->delete_uids}) AND visible = -2"); - - // Delete reports made to the profile or reputation of the deleted users (i.e. made by them) - $db->delete_query('reportedcontent', "type='reputation' AND id3 IN({$this->delete_uids}) OR type='reputation' AND id2 IN({$this->delete_uids})"); - $db->delete_query('reportedcontent', "type='profile' AND id IN({$this->delete_uids})"); - - // Update the reports made by the deleted users by setting the uid to 0 - $db->update_query('reportedcontent', array('uid' => 0), "uid IN({$this->delete_uids})"); - - // Remove any of the user(s) uploaded avatars - require_once MYBB_ROOT.'inc/functions_upload.php'; - foreach(explode(',', $this->delete_uids) as $uid) - { - remove_avatars($uid); - } - } - - /** - * Provides a method to delete an users posts and threads - * - * @param array|bool $delete_uids Array of user ids, false if they're already set (eg when using the delete_user function) - */ - function delete_posts($delete_uids=false) - { - global $db, $plugins, $mybb; - - if($delete_uids != false) - { - $this->delete_uids = array_map('intval', (array)$delete_uids); - - foreach($this->delete_uids as $key => $uid) - { - if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid']) - { - // Remove super admins - unset($this->delete_uids[$key]); - } - } - - $this->delete_uids = implode(',', $this->delete_uids); - } - - require_once MYBB_ROOT.'inc/class_moderation.php'; - $moderation = new Moderation(); - - $plugins->run_hooks('datahandler_user_delete_posts', $this); - - if(empty($this->delete_uids)) - { - return; - } - - // Threads - $query = $db->simple_select('threads', 'tid', "uid IN({$this->delete_uids})"); - while($tid = $db->fetch_field($query, 'tid')) - { - $moderation->delete_thread($tid); - } - - // Posts - $query = $db->simple_select('posts', 'pid', "uid IN({$this->delete_uids})"); - while($pid = $db->fetch_field($query, 'pid')) - { - $moderation->delete_post($pid); - } - } - - /** - * Provides a method to clear an users profile - * - * @param array|bool $delete_uids Array of user ids, false if they're already set (eg when using the delete_user function) - * @param int $gid The new usergroup if the users should be moved (additional usergroups are always removed) - */ - function clear_profile($delete_uids=false, $gid=0) - { - global $db, $plugins, $mybb; - - // delete_uids isn't a nice name, but it's used as the functions above use the same - if($delete_uids != false) - { - $this->delete_uids = array_map('intval', (array)$delete_uids); - - foreach($this->delete_uids as $key => $uid) - { - if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid']) - { - // Remove super admins - unset($this->delete_uids[$key]); - } - } - - $this->delete_uids = implode(',', $this->delete_uids); - } - - $update = array( - "website" => "", - "birthday" => "", - "icq" => "", - "aim" => "", - "yahoo" => "", - "skype" => "", - "google" => "", - "usertitle" => "", - "away" => 0, - "awaydate" => 0, - "returndate" => "", - "awayreason" => "", - "additionalgroups" => "", - "displaygroup" => 0, - "signature" => "", - "avatar" => "", - 'avatardimensions' => '', - 'avatartype' => '' - ); - - if($gid > 0) - { - $update["usergroup"] = (int)$gid; - } - - $plugins->run_hooks('datahandler_user_clear_profile', $this); - - if(empty($this->delete_uids)) - { - return; - } - - $db->update_query("users", $update, "uid IN({$this->delete_uids})"); - $db->delete_query('userfields', "ufid IN({$this->delete_uids})"); - - // Remove any of the user(s) uploaded avatars - require_once MYBB_ROOT.'inc/functions_upload.php'; - foreach(explode(',', $this->delete_uids) as $uid) - { - remove_avatars($uid); - } - } - - public function verify_signature() - { - global $mybb, $parser; - - if(!isset($parser)) - { - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - } - - $parser_options = array( - 'allow_html' => $mybb->settings['sightml'], - 'filter_badwords' => 1, - 'allow_mycode' => $mybb->settings['sigmycode'], - 'allow_smilies' => $mybb->settings['sigsmilies'], - 'allow_imgcode' => $mybb->settings['sigimgcode'], - "filter_badwords" => 1 - ); - - $parsed_sig = $parser->parse_message($this->data['signature'], $parser_options); - - if((($mybb->settings['sigimgcode'] == 0 && $mybb->settings['sigsmilies'] != 1) && - substr_count($parsed_sig, " 0) || - (($mybb->settings['sigimgcode'] == 1 || $mybb->settings['sigsmilies'] == 1) && - substr_count($parsed_sig, " $mybb->settings['maxsigimages']) - ) - { - $imgsallowed = 0; - - if($mybb->settings['sigimgcode'] == 1) - { - $imgsallowed = $mybb->settings['maxsigimages']; - } - - $this->set_error('too_many_sig_images2', array($imgsallowed)); - } - - if($mybb->settings['sigcountmycode'] == 0) - { - $parsed_sig = $parser->text_parse_message($this->data['signature']); - } - else - { - $parsed_sig = $this->data['signature']; - } - - $parsed_sig = preg_replace("#\s#", "", $parsed_sig); - $sig_length = my_strlen($parsed_sig); - - if($sig_length > $mybb->settings['siglength']) - { - $this->set_error('sig_too_long', array($mybb->settings['siglength'])); - - if($sig_length - $mybb->settings['siglength'] > 1) - { - $this->set_error('sig_remove_chars_plural', array($sig_length-$mybb->settings['siglength'])); - } - else - { - $this->set_error('sig_remove_chars_singular'); - } - } - - if(count($this->get_errors()) > 0) - { - return false; - } - return true; - } -} diff --git a/html/forums/inc/datahandlers/warnings.php b/html/forums/inc/datahandlers/warnings.php deleted file mode 100644 index 97d9a85..0000000 --- a/html/forums/inc/datahandlers/warnings.php +++ /dev/null @@ -1,741 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/** - * Login handling class, provides common structure to handle login events. - * - */ -class WarningsHandler extends DataHandler -{ - /** - * The language file used in the data handler. - * - * @var string - */ - public $language_file = 'datahandler_warnings'; - - /** - * The prefix for the language variables used in the data handler. - * - * @var string - */ - public $language_prefix = 'warnings'; - - /** - * The stored data for the warning being written. - * - * @var array - */ - public $write_warning_data = array(); - - /** - * The stored data for the warning being retrieved. - * - * @var array - */ - private $read_warning_data = array(); - - /** - * Friendly redirect action after inserting a new warning. - * - * @var string - */ - public $friendly_action = ''; - - /** - * Validate a warning user assets. - * - * @return boolean True when valid, false when invalid. - */ - function validate_user() - { - global $mybb; - - $warning = &$this->data; - - $user = get_user($warning['uid']); - - if(!$user['uid']) - { - $this->set_error('error_invalid_user'); - return false; - } - - if($user['uid'] == $mybb->user['uid']) - { - $this->set_error('error_cannot_warn_self'); - return false; - } - - if($user['warningpoints'] >= $mybb->settings['maxwarningpoints']) - { - $this->set_error('error_user_reached_max_warning'); - return false; - } - - return true; - } - - /** - * Validate a warning post. - * - * @return boolean True when valid, false when invalid. - */ - function validate_post() - { - $warning = &$this->data; - - $post = get_post($warning['pid']); - - if(!$post['pid']) - { - $this->set_error('error_invalid_post'); - return false; - } - - return true; - } - - /** - * Validate a warning notes. - * - * @return boolean True when valid, false when invalid. - */ - function validate_notes() - { - $warning = &$this->data; - - if(!trim($warning['notes'])) - { - $this->set_error('error_no_note'); - return false; - } - - return true; - } - - /** - * Validate maximum warnings per day for current user. - * - * @return boolean True when valid, false when invalid. - */ - function validate_maximum() - { - global $mybb, $db, $lang; - - if($mybb->usergroup['maxwarningsday'] != 0) - { - $timecut = TIME_NOW-60*60*24; - $query = $db->simple_select("warnings", "COUNT(wid) AS given_today", "issuedby='{$mybb->user['uid']}' AND dateline>'$timecut'"); - $given_today = $db->fetch_field($query, "given_today"); - if($given_today >= $mybb->usergroup['maxwarningsday']) - { - $this->set_error('reached_max_warnings_day', array(my_number_format($mybb->usergroup['maxwarningsday']))); - return false; - } - } - - return true; - } - - /** - * Validate warnings type. - * - * @return boolean True when valid, false when invalid. - */ - function validate_type() - { - global $mybb, $db; - - $warning = &$this->data; - - // Issuing a custom warning - if($warning['type'] == 'custom') - { - if($mybb->settings['allowcustomwarnings'] == 0) - { - $this->set_error('error_cant_custom_warn'); - return false; - } - - if(!$warning['custom_reason']) - { - $this->set_error('error_no_custom_reason'); - return false; - } - - $warning['title'] = $warning['custom_reason']; - - if(!$warning['custom_points'] || $warning['custom_points'] > $mybb->settings['maxwarningpoints'] || $warning['custom_points'] < 0) - { - $this->set_error('error_invalid_custom_points', array(my_number_format($mybb->settings['maxwarningpoints']))); - return false; - } - - $warning['points'] = round($warning['custom_points']); - - // Build expiry date - if($warning['expires_period'] == "hours") - { - $warning['expires'] = $warning['expires']*3600 + TIME_NOW; - } - else if($warning['expires_period'] == "days") - { - $warning['expires'] = $warning['expires']*86400 + TIME_NOW; - } - else if($warning['expires_period'] == "weeks") - { - $warning['expires'] = $warning['expires']*604800 + TIME_NOW; - } - else if($warning['expires_period'] == "months") - { - $warning['expires'] = $warning['expires']*2592000 + TIME_NOW; - } - else if($warning['expires_period'] == "never") - { - $warning['expires'] = 0; - } - else - { - // unkown expires_period - $this->set_error('error_invalid_expires_period'); - return false; - } - } - // Using a predefined warning type - else - { - $query = $db->simple_select("warningtypes", "*", "tid='".(int)$warning['type']."'"); - $this->warning_type = $db->fetch_array($query); - - if(!$this->warning_type) - { - $this->set_error('error_invalid_type'); - return false; - } - - $warning['points'] = $this->warning_type['points']; - $warning['title'] = ''; - $warning['expires'] = 0; - - if($this->warning_type['expirationtime']) - { - $warning['expires'] = TIME_NOW+$this->warning_type['expirationtime']; - } - } - - return true; - } - - /** - * Validate a warning. - * - * @return boolean True when valid, false when invalid. - */ - function validate_warning() - { - global $plugins; - - $warning = &$this->data; - - // Verify all warning assets. - $this->validate_user(); - $this->validate_maximum(); - $this->validate_notes(); - - if(array_key_exists('pid', $warning)) - { - $this->validate_post(); - } - if(array_key_exists('type', $warning)) - { - $this->validate_type(); - } - - $plugins->run_hooks("datahandler_warnings_validate_warning", $this); - - // We are done validating, return. - $this->set_validated(true); - - if(count($this->get_errors()) > 0) - { - return false; - } - - return true; - } - - /** - * Gets a valid warning from the DB engine. - * - * @param int $wid - * @return array|bool array when valid, boolean false when invalid. - */ - function get($wid) - { - global $db; - - $wid = (int)$wid; - if($wid <= 0) - { - return false; - } - - $query = $db->simple_select("warnings", "*", "wid='".$wid."'"); - $this->read_warning_data = $db->fetch_array($query); - - if(!$this->read_warning_data['wid']) - { - return false; - } - - return $this->read_warning_data; - } - - /** - * Expire old warnings in the database. - * - * @return boolean True when finished. - */ - function expire_warnings() - { - global $db; - - $users = array(); - - $query = $db->query(" - SELECT w.wid, w.uid, w.points, u.warningpoints - FROM ".TABLE_PREFIX."warnings w - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=w.uid) - WHERE expires<".TIME_NOW." AND expires!=0 AND expired!=1 - "); - while($warning = $db->fetch_array($query)) - { - $updated_warning = array( - "expired" => 1 - ); - $db->update_query("warnings", $updated_warning, "wid='{$warning['wid']}'"); - - if(array_key_exists($warning['uid'], $users)) - { - $users[$warning['uid']] -= $warning['points']; - } - else - { - $users[$warning['uid']] = $warning['warningpoints']-$warning['points']; - } - } - - foreach($users as $uid => $warningpoints) - { - if($warningpoints < 0) - { - $warningpoints = 0; - } - - $updated_user = array( - "warningpoints" => (int)$warningpoints - ); - $db->update_query("users", $updated_user, "uid='".(int)$uid."'"); - } - - return true; - } - - /** - * Updates an user warning details. - * - * @return array Updated user details. - */ - function update_user($method='insert') - { - global $db, $mybb, $lang, $cache, $groupscache; - - if($mybb->settings['maxwarningpoints'] < 1) - { - $mybb->settings['maxwarningpoints'] = 10; - } - - if(!is_array($groupscache)) - { - $groupscache = $cache->read("usergroups"); - } - - $warning = &$this->data; - - $user = get_user($warning['uid']); - - if($method == 'insert') - { - // Build warning level & ensure it doesn't go over 100. - $current_level = round($user['warningpoints']/$mybb->settings['maxwarningpoints']*100); - $this->new_warning_level = round(($user['warningpoints']+$warning['points'])/$mybb->settings['maxwarningpoints']*100); - if($this->new_warning_level > 100) - { - $this->new_warning_level = 100; - } - - // Update user - $this->updated_user = array( - "warningpoints" => $user['warningpoints']+$warning['points'] - ); - - // Fetch warning level - $query = $db->simple_select("warninglevels", "*", "percentage<={$this->new_warning_level}", array("order_by" => "percentage", "order_dir" => "desc")); - $new_level = $db->fetch_array($query); - - if($new_level['lid']) - { - $expiration = 0; - $action = my_unserialize($new_level['action']); - - if($action['length'] > 0) - { - $expiration = TIME_NOW+$action['length']; - } - - switch($action['type']) - { - // Ban the user for a specified time - case 1: - // Fetch any previous bans for this user - $query = $db->simple_select("banned", "*", "uid='{$user['uid']}' AND gid='{$action['usergroup']}' AND lifted>".TIME_NOW); - $existing_ban = $db->fetch_array($query); - - // Only perform if no previous ban or new ban expires later than existing ban - if(($expiration > $existing_ban['lifted'] && $existing_ban['lifted'] != 0) || $expiration == 0 || !$existing_ban['uid']) - { - if(!$warning['title']) - { - $warning['title'] = $this->warning_type['title']; - } - - // Never lift the ban? - if($action['length'] <= 0) - { - $bantime = '---'; - } - else - { - $bantimes = fetch_ban_times(); - foreach($bantimes as $date => $string) - { - if($date == '---') - { - continue; - } - - $time = 0; - list($day, $month, $year) = explode('-', $date); - if($day > 0) - { - $time += 60*60*24*$day; - } - - if($month > 0) - { - $time += 60*60*24*30*$month; - } - - if($year > 0) - { - $time += 60*60*24*365*$year; - } - - if($time == $action['length']) - { - $bantime = $date; - break; - } - } - } - - $new_ban = array( - "uid" => $user['uid'], - "gid" => $action['usergroup'], - "oldgroup" => $user['usergroup'], - "oldadditionalgroups" => $user['additionalgroups'], - "olddisplaygroup" => $user['displaygroup'], - "admin" => $mybb->user['uid'], - "dateline" => TIME_NOW, - "bantime" => $db->escape_string($bantime), - "lifted" => $expiration, - "reason" => $db->escape_string($warning['title']) - ); - // Delete old ban for this user, taking details - if($existing_ban['uid']) - { - $db->delete_query("banned", "uid='{$user['uid']}' AND gid='{$action['usergroup']}'"); - // Override new ban details with old group info - $new_ban['oldgroup'] = $existing_ban['oldgroup']; - $new_ban['oldadditionalgroups'] = $existing_ban['oldadditionalgroups']; - $new_ban['olddisplaygroup'] = $existing_ban['olddisplaygroup']; - } - - $period = $lang->expiration_never; - $ban_length = fetch_friendly_expiration($action['length']); - - if($ban_length['time']) - { - $lang_str = "expiration_".$ban_length['period']; - $period = $lang->sprintf($lang->result_period, $ban_length['time'], $lang->$lang_str); - } - - $group_name = $groupscache[$action['usergroup']]['title']; - $this->friendly_action = $lang->sprintf($lang->redirect_warned_banned, $group_name, $period); - - $db->insert_query("banned", $new_ban); - $this->updated_user['usergroup'] = $action['usergroup']; - $this->updated_user['additionalgroups'] = ''; - $this->updated_user['displaygroup'] = 0; - } - break; - // Suspend posting privileges - case 2: - // Only perform if the expiration time is greater than the users current suspension period - if($expiration == 0 || $expiration > $user['suspensiontime']) - { - if(($user['suspensiontime'] != 0 && $user['suspendposting']) || !$user['suspendposting']) - { - $period = $lang->expiration_never; - $ban_length = fetch_friendly_expiration($action['length']); - - if($ban_length['time']) - { - $lang_str = "expiration_".$ban_length['period']; - $period = $lang->sprintf($lang->result_period, $ban_length['time'], $lang->$lang_str); - } - - $this->friendly_action = $lang->sprintf($lang->redirect_warned_suspended, $period); - - $this->updated_user['suspensiontime'] = $expiration; - $this->updated_user['suspendposting'] = 1; - } - } - break; - // Moderate new posts - case 3: - // Only perform if the expiration time is greater than the users current suspension period - if($expiration == 0 || $expiration > $user['moderationtime']) - { - if(($user['moderationtime'] != 0 && $user['moderateposts']) || !$user['suspendposting']) - { - $period = $lang->expiration_never; - $ban_length = fetch_friendly_expiration($action['length']); - - if($ban_length['time']) - { - $lang_str = "expiration_".$ban_length['period']; - $period = $lang->sprintf($lang->result_period, $ban_length['time'], $lang->$lang_str); - } - - $this->friendly_action = $lang->sprintf($lang->redirect_warned_moderate, $period); - - $this->updated_user['moderationtime'] = $expiration; - $this->updated_user['moderateposts'] = 1; - } - } - break; - } - } - } - else - { - // Warning is still active, lower users point count - if($warning['expired'] != 1) - { - $new_warning_points = $user['warningpoints']-$warning['points']; - if($new_warning_points < 0) - { - $new_warning_points = 0; - } - - $this->updated_user = array( - "warningpoints" => $new_warning_points - ); - - - // check if we need to revoke any consequences with this warning - $current_level = round($user['warningpoints']/$mybb->settings['maxwarningpoints']*100); - $this->new_warning_level = round($new_warning_points/$mybb->settings['maxwarningpoints']*100); - $query = $db->simple_select("warninglevels", "action", "percentage>{$this->new_warning_level} AND percentage<=$current_level"); - if($db->num_rows($query)) - { - // we have some warning levels we need to revoke - $max_expiration_times = $check_levels = array(); - find_warnlevels_to_check($query, $max_expiration_times, $check_levels); - - // now check warning levels already applied to this user to see if we need to lower any expiration times - $query = $db->simple_select("warninglevels", "action", "percentage<={$this->new_warning_level}"); - $lower_expiration_times = $lower_levels = array(); - find_warnlevels_to_check($query, $lower_expiration_times, $lower_levels); - - // now that we've got all the info, do necessary stuff - for($i = 1; $i <= 3; ++$i) - { - if($check_levels[$i]) - { - switch($i) - { - case 1: // Ban - // we'll have to resort to letting the admin/mod remove the ban manually, since there's an issue if stacked bans are in force... - continue; - case 2: // Revoke posting - $current_expiry_field = 'suspensiontime'; - $current_inforce_field = 'suspendposting'; - break; - case 3: - $current_expiry_field = 'moderationtime'; - $current_inforce_field = 'moderateposts'; - break; - } - - // if the thing isn't in force, don't bother with trying to update anything - if(!$user[$current_inforce_field]) - { - continue; - } - - if($lower_levels[$i]) - { - // lessen the expiration time if necessary - - if(!$lower_expiration_times[$i]) - { - // doesn't expire - enforce this - $this->updated_user[$current_expiry_field] = 0; - continue; - } - - if($max_expiration_times[$i]) - { - // if the old level did have an expiry time... - if($max_expiration_times[$i] <= $lower_expiration_times[$i]) - { - // if the lower expiration time is actually higher than the upper expiration time -> skip - continue; - } - // both new and old max expiry times aren't infinite, so we can take a difference - $expire_offset = ($lower_expiration_times[$i] - $max_expiration_times[$i]); - } - else - { - // the old level never expired, not much we can do but try to estimate a new expiry time... which will just happen to be starting from today... - $expire_offset = TIME_NOW + $lower_expiration_times[$i]; - // if the user's expiry time is already less than what we're going to set it to, skip - if($user[$current_expiry_field] <= $expire_offset) - { - continue; - } - } - - $this->updated_user[$current_expiry_field] = $user[$current_expiry_field] + $expire_offset; - // double-check if it's expired already - if($this->updated_user[$current_expiry_field] < TIME_NOW) - { - $this->updated_user[$current_expiry_field] = 0; - $this->updated_user[$current_inforce_field] = 0; - } - } - else - { - // there's no lower level for this type - remove the consequence entirely - $this->updated_user[$current_expiry_field] = 0; - $this->updated_user[$current_inforce_field] = 0; - } - } - } - } - } - } - - // Save updated details - $db->update_query("users", $this->updated_user, "uid='{$user['uid']}'"); - - $mybb->cache->update_moderators(); - - return $this->updated_user; - } - - /** - * Inserts a warning into the database - * - * @return array Warning database details. - */ - function insert_warning() - { - global $db, $mybb, $plugins; - - $warning = &$this->data; - - $this->write_warning_data = array( - "uid" => (int)$warning['uid'], - "tid" => (int)$warning['type'], - "pid" => (int)$warning['pid'], - "title" => $db->escape_string($warning['title']), - "points" => (int)$warning['points'], - "dateline" => TIME_NOW, - "issuedby" => $mybb->user['uid'], - "expires" => (int)$warning['expires'], - "expired" => 0, - "revokereason" => '', - "notes" => $db->escape_string($warning['notes']) - ); - - $this->write_warning_data['wid'] = $db->insert_query("warnings", $this->write_warning_data); - - $this->update_user(); - - $plugins->run_hooks("datahandler_warnings_insert_warning", $this); - - return $this->write_warning_data; - } - - /** - * Updates a warning in the database - * - * @return array Warning database details. - */ - function update_warning() - { - global $db, $mybb, $plugins; - - $warning = &$this->data; - - $warning['wid'] = (int)$warning['wid']; - if($warning['wid'] <= 0) - { - return false; - } - - $this->write_warning_data = array( - "expired" => 1, - "daterevoked" => TIME_NOW, - "revokedby" => $mybb->user['uid'], - "revokereason" => $db->escape_string($warning['reason']) - ); - - $plugins->run_hooks("datahandler_warnings_update_warning", $this); - - $db->update_query("warnings", $this->write_warning_data, "wid='{$warning['wid']}'"); - - $this->update_user('update'); - - return $this->write_warning_data; - } - -} - diff --git a/html/forums/inc/db_base.php b/html/forums/inc/db_base.php deleted file mode 100644 index 29d4122..0000000 --- a/html/forums/inc/db_base.php +++ /dev/null @@ -1,449 +0,0 @@ - write; 0 => read - * - * @var int - */ - - protected $last_query_type = 0; - - /** - * Connect to the database server. - * - * @param array $config Array of DBMS connection details. - * @return resource The DB connection resource. Returns false on fail or -1 on a db connect failure. - */ - function connect($config) - { - // Simple connection to one server - if(array_key_exists('hostname', $config)) - { - $connections['read'][] = $config; - } - // Connecting to more than one server - else - { - // Specified multiple servers, but no specific read/write servers - if(!array_key_exists('read', $config)) - { - foreach($config as $key => $settings) - { - if(is_int($key)) - { - $connections['read'][] = $settings; - } - } - } - // Specified both read & write servers - else - { - $connections = $config; - } - } - - $this->db_encoding = $config['encoding']; - - // Actually connect to the specified servers - foreach(array('read', 'write') as $type) - { - if(!isset($connections[$type]) || !is_array($connections[$type])) - { - break; - } - - if(array_key_exists('hostname', $connections[$type])) - { - $details = $connections[$type]; - unset($connections); - $connections[$type][] = $details; - } - - // Shuffle the connections - shuffle($connections[$type]); - - // Loop-de-loop - foreach($connections[$type] as $single_connection) - { - $connect_function = "mysql_connect"; - if(isset($single_connection['pconnect'])) - { - $connect_function = "mysql_pconnect"; - } - - $link = "{$type}_link"; - - get_execution_time(); - - $this->$link = @$connect_function($single_connection['hostname'], $single_connection['username'], $single_connection['password'], 1); - - $time_spent = get_execution_time(); - $this->query_time += $time_spent; - - // Successful connection? break down brother! - if($this->$link) - { - $this->connections[] = "[".strtoupper($type)."] {$single_connection['username']}@{$single_connection['hostname']} (Connected in ".format_time_duration($time_spent).")"; - break; - } - else - { - $this->connections[] = "[FAILED] [".strtoupper($type)."] {$single_connection['username']}@{$single_connection['hostname']}"; - } - } - } - - // No write server was specified (simple connection or just multiple servers) - mirror write link - if(!array_key_exists('write', $connections)) - { - $this->write_link = &$this->read_link; - } - - // Have no read connection? - if(!$this->read_link) - { - $this->error("[READ] Unable to connect to MySQL server"); - return false; - } - // No write? - else if(!$this->write_link) - { - $this->error("[WRITE] Unable to connect to MySQL server"); - return false; - } - - // Select databases - if(!$this->select_db($config['database'])) - { - return -1; - } - - $this->current_link = &$this->read_link; - return $this->read_link; - } - - /** - * Selects the database to use. - * - * @param string $database The database name. - * @return boolean True when successfully connected, false if not. - */ - function select_db($database) - { - $this->database = $database; - - $this->current_link = &$this->read_link; - $read_success = @mysql_select_db($database, $this->read_link) or $this->error("[READ] Unable to select database", $this->read_link); - if($this->write_link) - { - $this->current_link = &$this->write_link; - $write_success = @mysql_select_db($database, $this->write_link) or $this->error("[WRITE] Unable to select database", $this->write_link); - $success = ($read_success && $write_success ? true : false); - } - else - { - $success = $read_success; - } - - if($success && $this->db_encoding) - { - // A little magic to support PHP 5.2.0, 5.2.1 and 5.2.2 - if(version_compare(PHP_VERSION, '5.2.3', '>=')) { - @mysql_set_charset($this->db_encoding, $this->read_link); - } - else - { - $this->query("SET NAMES '{$this->db_encoding}'"); - } - - if($write_success && count($this->connections) > 1) - { - if(version_compare(PHP_VERSION, '5.2.3', '>=')) { - @mysql_set_charset($this->db_encoding, $this->write_link); - } - else - { - $this->write_query("SET NAMES '{$this->db_encoding}'"); - } - } - } - return $success; - } - - /** - * Query the database. - * - * @param string $string The query SQL. - * @param integer $hide_errors 1 if hide errors, 0 if not. - * @param integer $write_query 1 if executes on master database, 0 if not. - * @return resource The query data. - */ - function query($string, $hide_errors=0, $write_query=0) - { - global $mybb; - - get_execution_time(); - - // Only execute write queries on master database - if(($write_query || $this->last_query_type) && $this->write_link) - { - $this->current_link = &$this->write_link; - $query = @mysql_query($string, $this->write_link); - } - else - { - $this->current_link = &$this->read_link; - $query = @mysql_query($string, $this->read_link); - } - - if($this->error_number() && !$hide_errors) - { - $this->error($string); - exit; - } - - if($write_query) - { - $this->last_query_type = 1; - } - else - { - $this->last_query_type = 0; - } - - $query_time = get_execution_time(); - $this->query_time += $query_time; - $this->query_count++; - - if($mybb->debug_mode) - { - $this->explain_query($string, $query_time); - } - - return $query; - } - - /** - * Execute a write query on the master database - * - * @param string $query The query SQL. - * @param boolean|int $hide_errors 1 if hide errors, 0 if not. - * @return resource The query data. - */ - function write_query($query, $hide_errors=0) - { - return $this->query($query, $hide_errors, 1); - } - - /** - * Explain a query on the database. - * - * @param string $string The query SQL. - * @param string $qtime The time it took to perform the query. - */ - function explain_query($string, $qtime) - { - global $plugins; - - $debug_extra = ''; - if($plugins->current_hook) - { - $debug_extra = "
    (Plugin Hook: {$plugins->current_hook})
    "; - } - if(preg_match("#^\s*select#i", $string)) - { - $query = mysql_query("EXPLAIN $string", $this->current_link); - $this->explain .= "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n"; - - while($table = mysql_fetch_array($query)) - { - $this->explain .= - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n"; - } - $this->explain .= - "\n". - "\n". - "\n". - "
    {$debug_extra}
    #".$this->query_count." - Select Query
    ".htmlspecialchars_uni($string)."
    TableTypePossible KeysKeyKey LengthRefRowsExtra
    ".$table['table']."".$table['type']."".$table['possible_keys']."".$table['key']."".$table['key_len']."".$table['ref']."".$table['rows']."".$table['Extra']."
    Query Time: ".format_time_duration($qtime)."
    \n". - "
    \n"; - } - else - { - $this->explain .= "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "
    {$debug_extra}
    #".$this->query_count." - Write Query
    ".htmlspecialchars_uni($string)."
    Query Time: ".format_time_duration($qtime)."
    \n". - "
    \n"; - } - - $this->querylist[$this->query_count]['query'] = $string; - $this->querylist[$this->query_count]['time'] = $qtime; - } - - /** - * Return a result array for a query. - * - * @param resource $query The query ID. - * @param int $resulttype The type of array to return. Either MYSQL_NUM, MYSQL_BOTH or MYSQL_ASSOC - * @return array The array of results. - */ - function fetch_array($query, $resulttype=MYSQL_ASSOC) - { - switch($resulttype) - { - case MYSQL_NUM: - case MYSQL_BOTH: - break; - default: - $resulttype = MYSQL_ASSOC; - break; - } - - $array = mysql_fetch_array($query, $resulttype); - - return $array; - } - - /** - * Return a specific field from a query. - * - * @param resource $query The query ID. - * @param string $field The name of the field to return. - * @param int|bool $row The number of the row to fetch it from. - * @return mixed - */ - function fetch_field($query, $field, $row=false) - { - if($row === false) - { - $array = $this->fetch_array($query); - return $array[$field]; - } - else - { - return mysql_result($query, $row, $field); - } - } - - /** - * Moves internal row pointer to the next row - * - * @param resource $query The query ID. - * @param int $row The pointer to move the row to. - * @return bool - */ - function data_seek($query, $row) - { - return mysql_data_seek($query, $row); - } - - /** - * Return the number of rows resulting from a query. - * - * @param resource $query The query ID. - * @return int The number of rows in the result. - */ - function num_rows($query) - { - return mysql_num_rows($query); - } - - /** - * Return the last id number of inserted data. - * - * @return int The id number. - */ - function insert_id() - { - return mysql_insert_id($this->current_link); - } - - /** - * Close the connection with the DBMS. - * - */ - function close() - { - @mysql_close($this->read_link); - if($this->write_link) - { - @mysql_close($this->write_link); - } - } - - /** - * Return an error number. - * - * @return int The error number of the current error. - */ - function error_number() - { - if($this->current_link) - { - return @mysql_errno($this->current_link); - } - else - { - return @mysql_errno(); - } - } - - /** - * Return an error string. - * - * @return string The explanation for the current error. - */ - function error_string() - { - if($this->current_link) - { - return @mysql_error($this->current_link); - } - else - { - return @mysql_error(); - } - } - - /** - * Output a database error. - * - * @param string $string The string to present as an error. - * @return bool Returns false if error reporting is disabled, otherwise true - */ - function error($string="") - { - if($this->error_reporting) - { - if(class_exists("errorHandler")) - { - global $error_handler; - - if(!is_object($error_handler)) - { - require_once MYBB_ROOT."inc/class_error.php"; - $error_handler = new errorHandler(); - } - - $error = array( - "error_no" => $this->error_number(), - "error" => $this->error_string(), - "query" => $string - ); - $error_handler->error(MYBB_SQL, $error); - } - else - { - trigger_error("[SQL] [".$this->error_number()."] ".$this->error_string()."
    {$string}", E_USER_ERROR); - } - - return true; - } - else - { - return false; - } - } - - /** - * Returns the number of affected rows in a query. - * - * @return int The number of affected rows. - */ - function affected_rows() - { - return mysql_affected_rows($this->current_link); - } - - /** - * Return the number of fields. - * - * @param resource $query The query ID. - * @return int The number of fields. - */ - function num_fields($query) - { - return mysql_num_fields($query); - } - - /** - * Lists all tables in the database. - * - * @param string $database The database name. - * @param string $prefix Prefix of the table (optional) - * @return array The table list. - */ - function list_tables($database, $prefix='') - { - if($prefix) - { - if(version_compare($this->get_version(), '5.0.2', '>=')) - { - $query = $this->query("SHOW FULL TABLES FROM `$database` WHERE table_type = 'BASE TABLE' AND `Tables_in_$database` LIKE '".$this->escape_string($prefix)."%'"); - } - else - { - $query = $this->query("SHOW TABLES FROM `$database` LIKE '".$this->escape_string($prefix)."%'"); - } - } - else - { - if(version_compare($this->get_version(), '5.0.2', '>=')) - { - $query = $this->query("SHOW FULL TABLES FROM `$database` WHERE table_type = 'BASE TABLE'"); - } - else - { - $query = $this->query("SHOW TABLES FROM `$database`"); - } - } - - $tables = array(); - while(list($table) = mysql_fetch_array($query)) - { - $tables[] = $table; - } - - return $tables; - } - - /** - * Check if a table exists in a database. - * - * @param string $table The table name. - * @return boolean True when exists, false if not. - */ - function table_exists($table) - { - // Execute on master server to ensure if we've just created a table that we get the correct result - if(version_compare($this->get_version(), '5.0.2', '>=')) - { - $query = $this->query("SHOW FULL TABLES FROM `".$this->database."` WHERE table_type = 'BASE TABLE' AND `Tables_in_".$this->database."` = '{$this->table_prefix}$table'"); - } - else - { - $query = $this->query("SHOW TABLES LIKE '{$this->table_prefix}$table'"); - } - - $exists = $this->num_rows($query); - if($exists > 0) - { - return true; - } - else - { - return false; - } - } - - /** - * Check if a field exists in a database. - * - * @param string $field The field name. - * @param string $table The table name. - * @return boolean True when exists, false if not. - */ - function field_exists($field, $table) - { - $query = $this->write_query(" - SHOW COLUMNS - FROM {$this->table_prefix}$table - LIKE '$field' - "); - $exists = $this->num_rows($query); - if($exists > 0) - { - return true; - } - else - { - return false; - } - } - - /** - * Add a shutdown query. - * - * @param resource $query The query data. - * @param string $name An optional name for the query. - */ - function shutdown_query($query, $name="") - { - global $shutdown_queries; - if($name) - { - $shutdown_queries[$name] = $query; - } - else - { - $shutdown_queries[] = $query; - } - } - /** - * Performs a simple select query. - * - * @param string $table The table name to be queried. - * @param string $fields Comma delimetered list of fields to be selected. - * @param string $conditions SQL formatted list of conditions to be matched. - * @param array $options List of options: group by, order by, order direction, limit, limit start. - * @return resource The query data. - */ - function simple_select($table, $fields="*", $conditions="", $options=array()) - { - $query = "SELECT ".$fields." FROM {$this->table_prefix}{$table}"; - if($conditions != "") - { - $query .= " WHERE ".$conditions; - } - - if(isset($options['group_by'])) - { - $query .= " GROUP BY ".$options['group_by']; - } - - if(isset($options['order_by'])) - { - $query .= " ORDER BY ".$options['order_by']; - if(isset($options['order_dir'])) - { - $query .= " ".my_strtoupper($options['order_dir']); - } - } - - if(isset($options['limit_start']) && isset($options['limit'])) - { - $query .= " LIMIT ".$options['limit_start'].", ".$options['limit']; - } - elseif(isset($options['limit'])) - { - $query .= " LIMIT ".$options['limit']; - } - - return $this->query($query); - } - - /** - * Build an insert query from an array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of fields and their values. - * @return int The insert ID if available - */ - function insert_query($table, $array) - { - global $mybb; - - if(!is_array($array)) - { - return false; - } - - foreach($array as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $array[$field] = $value; - } - else - { - $array[$field] = $this->quote_val($value); - } - } - - $fields = "`".implode("`,`", array_keys($array))."`"; - $values = implode(",", $array); - $this->write_query(" - INSERT - INTO {$this->table_prefix}{$table} (".$fields.") - VALUES (".$values.") - "); - return $this->insert_id(); - } - - /** - * Build one query for multiple inserts from a multidimensional array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of inserts. - * @return void - */ - function insert_query_multiple($table, $array) - { - global $mybb; - - if(!is_array($array)) - { - return; - } - - // Field names - $fields = array_keys($array[0]); - $fields = "`".implode("`,`", $fields)."`"; - - $insert_rows = array(); - foreach($array as $values) - { - foreach($values as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $values[$field] = $value; - } - else - { - $values[$field] = $this->quote_val($value); - } - } - $insert_rows[] = "(".implode(",", $values).")"; - } - $insert_rows = implode(", ", $insert_rows); - - $this->write_query(" - INSERT - INTO {$this->table_prefix}{$table} ({$fields}) - VALUES {$insert_rows} - "); - } - - /** - * Build an update query from an array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of fields and their values. - * @param string $where An optional where clause for the query. - * @param string $limit An optional limit clause for the query. - * @param boolean $no_quote An option to quote incoming values of the array. - * @return resource The query data. - */ - function update_query($table, $array, $where="", $limit="", $no_quote=false) - { - global $mybb; - - if(!is_array($array)) - { - return false; - } - - $comma = ""; - $query = ""; - $quote = "'"; - - if($no_quote == true) - { - $quote = ""; - } - - foreach($array as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $query .= $comma."`".$field."`={$value}"; - } - else - { - $quoted_val = $this->quote_val($value, $quote); - - $query .= $comma."`".$field."`={$quoted_val}"; - } - $comma = ', '; - } - - if(!empty($where)) - { - $query .= " WHERE $where"; - } - - if(!empty($limit)) - { - $query .= " LIMIT $limit"; - } - - return $this->write_query(" - UPDATE {$this->table_prefix}$table - SET $query - "); - } - - /** - * @param int|string $value - * @param string $quote - * - * @return int|string - */ - private function quote_val($value, $quote="'") - { - if(is_int($value)) - { - $quoted = $value; - } - else - { - $quoted = $quote . $value . $quote; - } - - return $quoted; - } - - /** - * Build a delete query. - * - * @param string $table The table name to perform the query on. - * @param string $where An optional where clause for the query. - * @param string $limit An optional limit clause for the query. - * @return resource The query data. - */ - function delete_query($table, $where="", $limit="") - { - $query = ""; - if(!empty($where)) - { - $query .= " WHERE $where"; - } - - if(!empty($limit)) - { - $query .= " LIMIT $limit"; - } - - return $this->write_query(" - DELETE - FROM {$this->table_prefix}$table - $query - "); - } - - /** - * Escape a string according to the MySQL escape format. - * - * @param string $string The string to be escaped. - * @return string The escaped string. - */ - function escape_string($string) - { - if($this->db_encoding == 'utf8') - { - $string = validate_utf8_string($string, false); - } - elseif($this->db_encoding == 'utf8mb4') - { - $string = validate_utf8_string($string); - } - - if(function_exists("mysql_real_escape_string") && $this->read_link) - { - $string = mysql_real_escape_string($string, $this->read_link); - } - else - { - $string = addslashes($string); - } - return $string; - } - - /** - * Frees the resources of a MySQLi query. - * - * @param resource $query The query to destroy. - * @return boolean Returns true on success, false on faliure - */ - function free_result($query) - { - return mysql_free_result($query); - } - - /** - * Escape a string used within a like command. - * - * @param string $string The string to be escaped. - * @return string The escaped string. - */ - function escape_string_like($string) - { - return $this->escape_string(str_replace(array('%', '_') , array('\\%' , '\\_') , $string)); - } - - /** - * Gets the current version of MySQL. - * - * @return string Version of MySQL. - */ - function get_version() - { - if($this->version) - { - return $this->version; - } - - $query = $this->query("SELECT VERSION() as version"); - $ver = $this->fetch_array($query); - $version = $ver['version']; - - if($version) - { - $version = explode(".", $version, 3); - $this->version = (int)$version[0].".".(int)$version[1].".".(int)$version[2]; - } - return $this->version; - } - - /** - * Optimizes a specific table. - * - * @param string $table The name of the table to be optimized. - */ - function optimize_table($table) - { - $this->write_query("OPTIMIZE TABLE {$this->table_prefix}{$table}"); - } - - /** - * Analyzes a specific table. - * - * @param string $table The name of the table to be analyzed. - */ - function analyze_table($table) - { - $this->write_query("ANALYZE TABLE {$this->table_prefix}{$table}"); - } - - /** - * Show the "create table" command for a specific table. - * - * @param string $table The name of the table. - * @return string The MySQL command to create the specified table. - */ - function show_create_table($table) - { - $query = $this->write_query("SHOW CREATE TABLE {$this->table_prefix}{$table}"); - $structure = $this->fetch_array($query); - return $structure['Create Table']; - } - - /** - * Show the "show fields from" command for a specific table. - * - * @param string $table The name of the table. - * @return array Field info for that table - */ - function show_fields_from($table) - { - $query = $this->write_query("SHOW FIELDS FROM {$this->table_prefix}{$table}"); - $field_info = array(); - while($field = $this->fetch_array($query)) - { - $field_info[] = $field; - } - return $field_info; - } - - /** - * Returns whether or not the table contains a fulltext index. - * - * @param string $table The name of the table. - * @param string $index Optionally specify the name of the index. - * @return boolean True or false if the table has a fulltext index or not. - */ - function is_fulltext($table, $index="") - { - $structure = $this->show_create_table($table); - if($index != "") - { - if(preg_match("#FULLTEXT KEY (`?)$index(`?)#i", $structure)) - { - return true; - } - else - { - return false; - } - } - if(preg_match('#FULLTEXT KEY#i', $structure)) - { - return true; - } - return false; - } - - /** - * Returns whether or not this database engine supports fulltext indexing. - * - * @param string $table The table to be checked. - * @return boolean True or false if supported or not. - */ - - function supports_fulltext($table) - { - $version = $this->get_version(); - $query = $this->write_query("SHOW TABLE STATUS LIKE '{$this->table_prefix}$table'"); - $status = $this->fetch_array($query); - if($status['Engine']) - { - $table_type = my_strtoupper($status['Engine']); - } - else - { - $table_type = my_strtoupper($status['Type']); - } - if(version_compare($version, '3.23.23', '>=') && ($table_type == 'MYISAM' || $table_type == 'ARIA')) - { - return true; - } - elseif(version_compare($version, '5.6', '>=') && $table_type == 'INNODB') - { - return true; - } - return false; - } - - /** - * Checks to see if an index exists on a specified table - * - * @param string $table The name of the table. - * @param string $index The name of the index. - * @return bool Whether or not the index exists in that table - */ - function index_exists($table, $index) - { - $index_exists = false; - $query = $this->write_query("SHOW INDEX FROM {$this->table_prefix}{$table}"); - while($ukey = $this->fetch_array($query)) - { - if($ukey['Key_name'] == $index) - { - $index_exists = true; - break; - } - } - - if($index_exists) - { - return true; - } - - return false; - } - - /** - * Returns whether or not this database engine supports boolean fulltext matching. - * - * @param string $table The table to be checked. - * @return boolean True or false if supported or not. - */ - function supports_fulltext_boolean($table) - { - $version = $this->get_version(); - $supports_fulltext = $this->supports_fulltext($table); - if(version_compare($version, '4.0.1', '>=') && $supports_fulltext == true) - { - return true; - } - return false; - } - - /** - * Creates a fulltext index on the specified column in the specified table with optional index name. - * - * @param string $table The name of the table. - * @param string $column Name of the column to be indexed. - * @param string $name The index name, optional. - */ - function create_fulltext_index($table, $column, $name="") - { - $this->write_query(" - ALTER TABLE {$this->table_prefix}$table - ADD FULLTEXT $name ($column) - "); - } - - /** - * Drop an index with the specified name from the specified table - * - * @param string $table The name of the table. - * @param string $name The name of the index. - */ - function drop_index($table, $name) - { - $this->write_query(" - ALTER TABLE {$this->table_prefix}$table - DROP INDEX $name - "); - } - - /** - * Drop an table with the specified table - * - * @param string $table The table to drop - * @param boolean $hard hard drop - no checking - * @param boolean $table_prefix use table prefix - */ - function drop_table($table, $hard=false, $table_prefix=true) - { - if($table_prefix == false) - { - $table_prefix = ""; - } - else - { - $table_prefix = $this->table_prefix; - } - - if($hard == false) - { - $this->write_query('DROP TABLE IF EXISTS '.$table_prefix.$table); - } - else - { - $this->write_query('DROP TABLE '.$table_prefix.$table); - } - } - - /** - * Renames a table - * - * @param string $old_table The old table name - * @param string $new_table the new table name - * @param boolean $table_prefix use table prefix - * @return resource - */ - function rename_table($old_table, $new_table, $table_prefix=true) - { - if($table_prefix == false) - { - $table_prefix = ""; - } - else - { - $table_prefix = $this->table_prefix; - } - - return $this->write_query("RENAME TABLE {$table_prefix}{$old_table} TO {$table_prefix}{$new_table}"); - } - - /** - * Replace contents of table with values - * - * @param string $table The table - * @param array $replacements The replacements - * @return resource|bool - */ - function replace_query($table, $replacements=array()) - { - global $mybb; - - $values = ''; - $comma = ''; - foreach($replacements as $column => $value) - { - if(isset($mybb->binary_fields[$table][$column]) && $mybb->binary_fields[$table][$column]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $values .= $comma."`".$column."`=".$value; - } - else - { - $values .= $comma."`".$column."`=".$this->quote_val($value); - } - - $comma = ','; - } - - if(empty($replacements)) - { - return false; - } - - return $this->write_query("REPLACE INTO {$this->table_prefix}{$table} SET {$values}"); - } - - /** - * Drops a column - * - * @param string $table The table - * @param string $column The column name - * @return resource - */ - function drop_column($table, $column) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} DROP {$column}"); - } - - /** - * Adds a column - * - * @param string $table The table - * @param string $column The column name - * @param string $definition the new column definition - * @return resource - */ - function add_column($table, $column, $definition) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} ADD {$column} {$definition}"); - } - - /** - * Modifies a column - * - * @param string $table The table - * @param string $column The column name - * @param string $new_definition the new column definition - * @return resource - */ - function modify_column($table, $column, $new_definition) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} MODIFY {$column} {$new_definition}"); - } - - /** - * Renames a column - * - * @param string $table The table - * @param string $old_column The old column name - * @param string $new_column the new column name - * @param string $new_definition the new column definition - * @return resource - */ - function rename_column($table, $old_column, $new_column, $new_definition) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} CHANGE {$old_column} {$new_column} {$new_definition}"); - } - - /** - * Sets the table prefix used by the simple select, insert, update and delete functions - * - * @param string $prefix The new table prefix - */ - function set_table_prefix($prefix) - { - $this->table_prefix = $prefix; - } - - /** - * Fetched the total size of all mysql tables or a specific table - * - * @param string $table The table (optional) - * @return integer the total size of all mysql tables or a specific table - */ - function fetch_size($table='') - { - if($table != '') - { - $query = $this->query("SHOW TABLE STATUS LIKE '".$this->table_prefix.$table."'"); - } - else - { - $query = $this->query("SHOW TABLE STATUS"); - } - $total = 0; - while($table = $this->fetch_array($query)) - { - $total += $table['Data_length']+$table['Index_length']; - } - return $total; - } - - /** - * Fetch a list of database character sets this DBMS supports - * - * @return array|bool Array of supported character sets with array key being the name, array value being display name. False if unsupported - */ - function fetch_db_charsets() - { - if($this->write_link && version_compare($this->get_version(), "4.1", "<")) - { - return false; - } - return array( - 'big5' => 'Big5 Traditional Chinese', - 'dec8' => 'DEC West European', - 'cp850' => 'DOS West European', - 'hp8' => 'HP West European', - 'koi8r' => 'KOI8-R Relcom Russian', - 'latin1' => 'ISO 8859-1 Latin 1', - 'latin2' => 'ISO 8859-2 Central European', - 'swe7' => '7bit Swedish', - 'ascii' => 'US ASCII', - 'ujis' => 'EUC-JP Japanese', - 'sjis' => 'Shift-JIS Japanese', - 'hebrew' => 'ISO 8859-8 Hebrew', - 'tis620' => 'TIS620 Thai', - 'euckr' => 'EUC-KR Korean', - 'koi8u' => 'KOI8-U Ukrainian', - 'gb2312' => 'GB2312 Simplified Chinese', - 'greek' => 'ISO 8859-7 Greek', - 'cp1250' => 'Windows Central European', - 'gbk' => 'GBK Simplified Chinese', - 'latin5' => 'ISO 8859-9 Turkish', - 'armscii8' => 'ARMSCII-8 Armenian', - 'utf8' => 'UTF-8 Unicode', - 'utf8mb4' => '4-Byte UTF-8 Unicode (requires MySQL 5.5.3 or above)', - 'ucs2' => 'UCS-2 Unicode', - 'cp866' => 'DOS Russian', - 'keybcs2' => 'DOS Kamenicky Czech-Slovak', - 'macce' => 'Mac Central European', - 'macroman' => 'Mac West European', - 'cp852' => 'DOS Central European', - 'latin7' => 'ISO 8859-13 Baltic', - 'cp1251' => 'Windows Cyrillic', - 'cp1256' => 'Windows Arabic', - 'cp1257' => 'Windows Baltic', - 'geostd8' => 'GEOSTD8 Georgian', - 'cp932' => 'SJIS for Windows Japanese', - 'eucjpms' => 'UJIS for Windows Japanese', - ); - } - - /** - * Fetch a database collation for a particular database character set - * - * @param string $charset The database character set - * @return string|bool The matching database collation, false if unsupported - */ - function fetch_charset_collation($charset) - { - $collations = array( - 'big5' => 'big5_chinese_ci', - 'dec8' => 'dec8_swedish_ci', - 'cp850' => 'cp850_general_ci', - 'hp8' => 'hp8_english_ci', - 'koi8r' => 'koi8r_general_ci', - 'latin1' => 'latin1_swedish_ci', - 'latin2' => 'latin2_general_ci', - 'swe7' => 'swe7_swedish_ci', - 'ascii' => 'ascii_general_ci', - 'ujis' => 'ujis_japanese_ci', - 'sjis' => 'sjis_japanese_ci', - 'hebrew' => 'hebrew_general_ci', - 'tis620' => 'tis620_thai_ci', - 'euckr' => 'euckr_korean_ci', - 'koi8u' => 'koi8u_general_ci', - 'gb2312' => 'gb2312_chinese_ci', - 'greek' => 'greek_general_ci', - 'cp1250' => 'cp1250_general_ci', - 'gbk' => 'gbk_chinese_ci', - 'latin5' => 'latin5_turkish_ci', - 'armscii8' => 'armscii8_general_ci', - 'utf8' => 'utf8_general_ci', - 'utf8mb4' => 'utf8mb4_general_ci', - 'ucs2' => 'ucs2_general_ci', - 'cp866' => 'cp866_general_ci', - 'keybcs2' => 'keybcs2_general_ci', - 'macce' => 'macce_general_ci', - 'macroman' => 'macroman_general_ci', - 'cp852' => 'cp852_general_ci', - 'latin7' => 'latin7_general_ci', - 'cp1251' => 'cp1251_general_ci', - 'cp1256' => 'cp1256_general_ci', - 'cp1257' => 'cp1257_general_ci', - 'geostd8' => 'geostd8_general_ci', - 'cp932' => 'cp932_japanese_ci', - 'eucjpms' => 'eucjpms_japanese_ci', - ); - if($collations[$charset]) - { - return $collations[$charset]; - } - return false; - } - - /** - * Fetch a character set/collation string for use with CREATE TABLE statements. Uses current DB encoding - * - * @return string The built string, empty if unsupported - */ - function build_create_table_collation() - { - if(!$this->db_encoding) - { - return ''; - } - - $collation = $this->fetch_charset_collation($this->db_encoding); - if(!$collation) - { - return ''; - } - return " CHARACTER SET {$this->db_encoding} COLLATE {$collation}"; - } - - /** - * Time how long it takes for a particular piece of code to run. Place calls above & below the block of code. - * - * @deprecated - */ - function get_execution_time() - { - return get_execution_time(); - } - - /** - * Binary database fields require special attention. - * - * @param string $string Binary value - * @return string Encoded binary value - */ - function escape_binary($string) - { - return "X'".$this->escape_string(bin2hex($string))."'"; - } - - /** - * Unescape binary data. - * - * @param string $string Binary value - * @return string Encoded binary value - */ - function unescape_binary($string) - { - // Nothing to do - return $string; - } -} - diff --git a/html/forums/inc/db_mysqli.php b/html/forums/inc/db_mysqli.php deleted file mode 100644 index 845dbcb..0000000 --- a/html/forums/inc/db_mysqli.php +++ /dev/null @@ -1,1569 +0,0 @@ - write; 0 => read - * - * @var int - */ - protected $last_query_type = 0; - - /** - * Connect to the database server. - * - * @param array $config Array of DBMS connection details. - * @return mysqli The DB connection resource. Returns false on fail or -1 on a db connect failure. - */ - function connect($config) - { - // Simple connection to one server - if(array_key_exists('hostname', $config)) - { - $connections['read'][] = $config; - } - else - // Connecting to more than one server - { - // Specified multiple servers, but no specific read/write servers - if(!array_key_exists('read', $config)) - { - foreach($config as $key => $settings) - { - if(is_int($key)) - { - $connections['read'][] = $settings; - } - } - } - // Specified both read & write servers - else - { - $connections = $config; - } - } - - $this->db_encoding = $config['encoding']; - - // Actually connect to the specified servers - foreach(array('read', 'write') as $type) - { - if(!isset($connections[$type]) || !is_array($connections[$type])) - { - break; - } - - if(array_key_exists('hostname', $connections[$type])) - { - $details = $connections[$type]; - unset($connections); - $connections[$type][] = $details; - } - - // Shuffle the connections - shuffle($connections[$type]); - - // Loop-de-loop - foreach($connections[$type] as $single_connection) - { - $connect_function = "mysqli_connect"; - $persist = ""; - if(!empty($single_connection['pconnect']) && version_compare(PHP_VERSION, '5.3.0', '>=')) - { - $persist = 'p:'; - } - - $link = "{$type}_link"; - - get_execution_time(); - - // Specified a custom port for this connection? - $port = 0; - if(strstr($single_connection['hostname'],':')) - { - list($hostname, $port) = explode(":", $single_connection['hostname'], 2); - } - - if($port) - { - $this->$link = @$connect_function($persist.$hostname, $single_connection['username'], $single_connection['password'], "", $port); - } - else - { - $this->$link = @$connect_function($persist.$single_connection['hostname'], $single_connection['username'], $single_connection['password']); - } - - $time_spent = get_execution_time(); - $this->query_time += $time_spent; - - // Successful connection? break down brother! - if($this->$link) - { - $this->connections[] = "[".strtoupper($type)."] {$single_connection['username']}@{$single_connection['hostname']} (Connected in ".format_time_duration($time_spent).")"; - break; - } - else - { - $this->connections[] = "[FAILED] [".strtoupper($type)."] {$single_connection['username']}@{$single_connection['hostname']}"; - } - } - } - - // No write server was specified (simple connection or just multiple servers) - mirror write link - if(!array_key_exists('write', $connections)) - { - $this->write_link = &$this->read_link; - } - - // Have no read connection? - if(!$this->read_link) - { - $this->error("[READ] Unable to connect to MySQL server"); - return false; - } - // No write? - else if(!$this->write_link) - { - $this->error("[WRITE] Unable to connect to MySQL server"); - return false; - } - - // Select databases - if(!$this->select_db($config['database'])) - { - return -1; - } - - $this->current_link = &$this->read_link; - return $this->read_link; - } - - /** - * Selects the database to use. - * - * @param string $database The database name. - * @return boolean True when successfully connected, false if not. - */ - function select_db($database) - { - $this->database = $database; - - $master_success = @mysqli_select_db($this->read_link, $database) or $this->error("[READ] Unable to select database", $this->read_link); - if($this->write_link) - { - $slave_success = @mysqli_select_db($this->write_link, $database) or $this->error("[WRITE] Unable to select slave database", $this->write_link); - - $success = ($master_success && $slave_success ? true : false); - } - else - { - $success = $master_success; - } - - if($success && $this->db_encoding) - { - @mysqli_set_charset($this->read_link, $this->db_encoding); - - if($slave_success && count($this->connections) > 1) - { - @mysqli_set_charset($this->write_link, $this->db_encoding); - } - } - return $success; - } - - /** - * Query the database. - * - * @param string $string The query SQL. - * @param boolean|int $hide_errors 1 if hide errors, 0 if not. - * @param integer $write_query 1 if executes on master database, 0 if not. - * @return mysqli_result The query data. - */ - function query($string, $hide_errors=0, $write_query=0) - { - global $mybb; - - get_execution_time(); - - // Only execute write queries on master server - if(($write_query || $this->last_query_type) && $this->write_link) - { - $this->current_link = &$this->write_link; - $query = @mysqli_query($this->write_link, $string); - } - else - { - $this->current_link = &$this->read_link; - $query = @mysqli_query($this->read_link, $string); - } - - if($this->error_number() && !$hide_errors) - { - $this->error($string); - exit; - } - - if($write_query) - { - $this->last_query_type = 1; - } - else - { - $this->last_query_type = 0; - } - - $query_time = get_execution_time(); - $this->query_time += $query_time; - $this->query_count++; - - if($mybb->debug_mode) - { - $this->explain_query($string, $query_time); - } - return $query; - } - - /** - * Execute a write query on the master database - * - * @param string $query The query SQL. - * @param boolean|int $hide_errors 1 if hide errors, 0 if not. - * @return mysqli_result The query data. - */ - function write_query($query, $hide_errors=0) - { - return $this->query($query, $hide_errors, 1); - } - - /** - * Explain a query on the database. - * - * @param string $string The query SQL. - * @param string $qtime The time it took to perform the query. - */ - function explain_query($string, $qtime) - { - global $plugins; - - $debug_extra = ''; - if($plugins->current_hook) - { - $debug_extra = "
    (Plugin Hook: {$plugins->current_hook})
    "; - } - if(preg_match("#^\s*select#i", $string)) - { - $query = mysqli_query($this->current_link, "EXPLAIN $string"); - $this->explain .= "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n"; - - while($table = mysqli_fetch_assoc($query)) - { - $this->explain .= - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n"; - } - $this->explain .= - "\n". - "\n". - "\n". - "
    {$debug_extra}
    #".$this->query_count." - Select Query
    ".htmlspecialchars_uni($string)."
    TableTypePossible KeysKeyKey LengthRefRowsExtra
    ".$table['table']."".$table['type']."".$table['possible_keys']."".$table['key']."".$table['key_len']."".$table['ref']."".$table['rows']."".$table['Extra']."
    Query Time: ".format_time_duration($qtime)."
    \n". - "
    \n"; - } - else - { - $this->explain .= "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "
    {$debug_extra}
    #".$this->query_count." - Write Query
    ".htmlspecialchars_uni($string)."
    Query Time: ".format_time_duration($qtime)."
    \n". - "
    \n"; - } - - $this->querylist[$this->query_count]['query'] = $string; - $this->querylist[$this->query_count]['time'] = $qtime; - } - - /** - * Return a result array for a query. - * - * @param mysqli_result $query The query data. - * @param int $resulttype The type of array to return. Either MYSQLI_NUM, MYSQLI_BOTH or MYSQLI_ASSOC - * @return array The array of results. - */ - function fetch_array($query, $resulttype=MYSQLI_ASSOC) - { - switch($resulttype) - { - case MYSQLI_NUM: - case MYSQLI_BOTH: - break; - default: - $resulttype = MYSQLI_ASSOC; - break; - } - - $array = mysqli_fetch_array($query, $resulttype); - - return $array; - } - - /** - * Return a specific field from a query. - * - * @param mysqli_result $query The query ID. - * @param string $field The name of the field to return. - * @param int|bool $row The number of the row to fetch it from. - */ - function fetch_field($query, $field, $row=false) - { - if($row !== false) - { - $this->data_seek($query, $row); - } - $array = $this->fetch_array($query); - return $array[$field]; - } - - /** - * Moves internal row pointer to the next row - * - * @param mysqli_result $query The query ID. - * @param int $row The pointer to move the row to. - * @return bool - */ - function data_seek($query, $row) - { - return mysqli_data_seek($query, $row); - } - - /** - * Return the number of rows resulting from a query. - * - * @param mysqli_result $query The query data. - * @return int The number of rows in the result. - */ - function num_rows($query) - { - return mysqli_num_rows($query); - } - - /** - * Return the last id number of inserted data. - * - * @return int The id number. - */ - function insert_id() - { - $id = mysqli_insert_id($this->current_link); - return $id; - } - - /** - * Close the connection with the DBMS. - * - */ - function close() - { - @mysqli_close($this->read_link); - if($this->write_link) - { - @mysqli_close($this->write_link); - } - } - - /** - * Return an error number. - * - * @return int The error number of the current error. - */ - function error_number() - { - if($this->current_link) - { - return mysqli_errno($this->current_link); - } - else - { - return mysqli_connect_errno(); - } - } - - /** - * Return an error string. - * - * @return string The explanation for the current error. - */ - function error_string() - { - if($this->current_link) - { - return mysqli_error($this->current_link); - } - else - { - return mysqli_connect_error(); - } - } - - /** - * Output a database error. - * - * @param string $string The string to present as an error. - * @return bool Whether error reporting is enabled or not - */ - function error($string="") - { - if($this->error_reporting) - { - if(class_exists("errorHandler")) - { - global $error_handler; - - if(!is_object($error_handler)) - { - require_once MYBB_ROOT."inc/class_error.php"; - $error_handler = new errorHandler(); - } - - $error = array( - "error_no" => $this->error_number(), - "error" => $this->error_string(), - "query" => $string - ); - $error_handler->error(MYBB_SQL, $error); - } - else - { - trigger_error("[SQL] [".$this->error_number()."] ".$this->error_string()."
    {$string}", E_USER_ERROR); - } - - return true; - } - else - { - return false; - } - } - - /** - * Returns the number of affected rows in a query. - * - * @return int The number of affected rows. - */ - function affected_rows() - { - return mysqli_affected_rows($this->current_link); - } - - /** - * Return the number of fields. - * - * @param mysqli_result $query The query data. - * @return int The number of fields. - */ - function num_fields($query) - { - return mysqli_num_fields($query); - } - - /** - * Lists all tables in the database. - * - * @param string $database The database name. - * @param string $prefix Prefix of the table (optional) - * @return array The table list. - */ - function list_tables($database, $prefix='') - { - if($prefix) - { - if(version_compare($this->get_version(), '5.0.2', '>=')) - { - $query = $this->query("SHOW FULL TABLES FROM `$database` WHERE table_type = 'BASE TABLE' AND `Tables_in_$database` LIKE '".$this->escape_string($prefix)."%'"); - } - else - { - $query = $this->query("SHOW TABLES FROM `$database` LIKE '".$this->escape_string($prefix)."%'"); - } - } - else - { - if(version_compare($this->get_version(), '5.0.2', '>=')) - { - $query = $this->query("SHOW FULL TABLES FROM `$database` WHERE table_type = 'BASE TABLE'"); - } - else - { - $query = $this->query("SHOW TABLES FROM `$database`"); - } - } - - $tables = array(); - while(list($table) = mysqli_fetch_array($query)) - { - $tables[] = $table; - } - - return $tables; - } - - /** - * Check if a table exists in a database. - * - * @param string $table The table name. - * @return boolean True when exists, false if not. - */ - function table_exists($table) - { - // Execute on master server to ensure if we've just created a table that we get the correct result - if(version_compare($this->get_version(), '5.0.2', '>=')) - { - $query = $this->query("SHOW FULL TABLES FROM `".$this->database."` WHERE table_type = 'BASE TABLE' AND `Tables_in_".$this->database."` = '{$this->table_prefix}$table'"); - } - else - { - $query = $this->query("SHOW TABLES LIKE '{$this->table_prefix}$table'"); - } - - $exists = $this->num_rows($query); - if($exists > 0) - { - return true; - } - else - { - return false; - } - } - - /** - * Check if a field exists in a database. - * - * @param string $field The field name. - * @param string $table The table name. - * @return boolean True when exists, false if not. - */ - function field_exists($field, $table) - { - $query = $this->write_query(" - SHOW COLUMNS - FROM {$this->table_prefix}$table - LIKE '$field' - "); - $exists = $this->num_rows($query); - - if($exists > 0) - { - return true; - } - else - { - return false; - } - } - - /** - * Add a shutdown query. - * - * @param mysqli_result $query The query data. - * @param string $name An optional name for the query. - */ - function shutdown_query($query, $name="") - { - global $shutdown_queries; - if($name) - { - $shutdown_queries[$name] = $query; - } - else - { - $shutdown_queries[] = $query; - } - } - - /** - * Performs a simple select query. - * - * @param string $table The table name to be queried. - * @param string $fields Comma delimetered list of fields to be selected. - * @param string $conditions SQL formatted list of conditions to be matched. - * @param array $options List of options: group by, order by, order direction, limit, limit start. - * @return mysqli_result The query data. - */ - function simple_select($table, $fields="*", $conditions="", $options=array()) - { - $query = "SELECT ".$fields." FROM ".$this->table_prefix.$table; - - if($conditions != "") - { - $query .= " WHERE ".$conditions; - } - - if(isset($options['group_by'])) - { - $query .= " GROUP BY ".$options['group_by']; - } - - if(isset($options['order_by'])) - { - $query .= " ORDER BY ".$options['order_by']; - if(isset($options['order_dir'])) - { - $query .= " ".my_strtoupper($options['order_dir']); - } - } - - if(isset($options['limit_start']) && isset($options['limit'])) - { - $query .= " LIMIT ".$options['limit_start'].", ".$options['limit']; - } - else if(isset($options['limit'])) - { - $query .= " LIMIT ".$options['limit']; - } - - return $this->query($query); - } - - /** - * Build an insert query from an array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of fields and their values. - * @return int The insert ID if available - */ - function insert_query($table, $array) - { - global $mybb; - - if(!is_array($array)) - { - return false; - } - - foreach($array as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $array[$field] = $value; - } - else - { - $array[$field] = $this->quote_val($value); - } - } - - $fields = "`".implode("`,`", array_keys($array))."`"; - $values = implode(",", $array); - $this->write_query(" - INSERT - INTO {$this->table_prefix}{$table} (".$fields.") - VALUES (".$values.") - "); - return $this->insert_id(); - } - - /** - * Build one query for multiple inserts from a multidimensional array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of inserts. - * @return void - */ - function insert_query_multiple($table, $array) - { - global $mybb; - - if(!is_array($array)) - { - return; - } - // Field names - $fields = array_keys($array[0]); - $fields = "`".implode("`,`", $fields)."`"; - - $insert_rows = array(); - foreach($array as $values) - { - foreach($values as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $values[$field] = $value; - } - else - { - $values[$field] = $this->quote_val($value); - } - } - $insert_rows[] = "(".implode(",", $values).")"; - } - $insert_rows = implode(", ", $insert_rows); - - $this->write_query(" - INSERT - INTO {$this->table_prefix}{$table} ({$fields}) - VALUES {$insert_rows} - "); - } - - /** - * Build an update query from an array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of fields and their values. - * @param string $where An optional where clause for the query. - * @param string $limit An optional limit clause for the query. - * @param boolean $no_quote An option to quote incoming values of the array. - * @return mysqli_result The query data. - */ - function update_query($table, $array, $where="", $limit="", $no_quote=false) - { - global $mybb; - - if(!is_array($array)) - { - return false; - } - - $comma = ""; - $query = ""; - $quote = "'"; - - if($no_quote == true) - { - $quote = ""; - } - - foreach($array as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $query .= $comma."`".$field."`={$value}"; - } - else - { - $quoted_value = $this->quote_val($value, $quote); - - $query .= $comma."`".$field."`={$quoted_value}"; - } - $comma = ', '; - } - - if(!empty($where)) - { - $query .= " WHERE $where"; - } - - if(!empty($limit)) - { - $query .= " LIMIT $limit"; - } - - return $this->write_query(" - UPDATE {$this->table_prefix}$table - SET $query - "); - } - - /** - * @param int|string $value - * @param string $quote - * - * @return int|string - */ - private function quote_val($value, $quote="'") - { - if(is_int($value)) - { - $quoted = $value; - } - else - { - $quoted = $quote . $value . $quote; - } - - return $quoted; - } - - /** - * Build a delete query. - * - * @param string $table The table name to perform the query on. - * @param string $where An optional where clause for the query. - * @param string $limit An optional limit clause for the query. - * @return mysqli_result The query data. - */ - function delete_query($table, $where="", $limit="") - { - $query = ""; - if(!empty($where)) - { - $query .= " WHERE $where"; - } - if(!empty($limit)) - { - $query .= " LIMIT $limit"; - } - return $this->write_query("DELETE FROM {$this->table_prefix}$table $query"); - } - - /** - * Escape a string according to the MySQL escape format. - * - * @param string $string The string to be escaped. - * @return string The escaped string. - */ - function escape_string($string) - { - if($this->db_encoding == 'utf8') - { - $string = validate_utf8_string($string, false); - } - elseif($this->db_encoding == 'utf8mb4') - { - $string = validate_utf8_string($string); - } - - if(function_exists("mysqli_real_escape_string") && $this->read_link) - { - $string = mysqli_real_escape_string($this->read_link, $string); - } - else - { - $string = addslashes($string); - } - return $string; - } - - /** - * Frees the resources of a MySQLi query. - * - * @param mysqli_result $query The query to destroy. - * @return boolean Returns true - */ - function free_result($query) - { - mysqli_free_result($query); - return true; // Kept for compatibility reasons - } - - /** - * Escape a string used within a like command. - * - * @param string $string The string to be escaped. - * @return string The escaped string. - */ - function escape_string_like($string) - { - return $this->escape_string(str_replace(array('%', '_') , array('\\%' , '\\_') , $string)); - } - - /** - * Gets the current version of MySQL. - * - * @return string Version of MySQL. - */ - function get_version() - { - if($this->version) - { - return $this->version; - } - - $query = $this->query("SELECT VERSION() as version"); - $ver = $this->fetch_array($query); - $version = $ver['version']; - - if($version) - { - $version = explode(".", $version, 3); - $this->version = (int)$version[0].".".(int)$version[1].".".(int)$version[2]; - } - return $this->version; - } - - /** - * Optimizes a specific table. - * - * @param string $table The name of the table to be optimized. - */ - function optimize_table($table) - { - $this->write_query("OPTIMIZE TABLE ".$this->table_prefix.$table.""); - } - - /** - * Analyzes a specific table. - * - * @param string $table The name of the table to be analyzed. - */ - function analyze_table($table) - { - $this->write_query("ANALYZE TABLE ".$this->table_prefix.$table.""); - } - - /** - * Show the "create table" command for a specific table. - * - * @param string $table The name of the table. - * @return string The MySQL command to create the specified table. - */ - function show_create_table($table) - { - $query = $this->write_query("SHOW CREATE TABLE ".$this->table_prefix.$table.""); - $structure = $this->fetch_array($query); - - return $structure['Create Table']; - } - - /** - * Show the "show fields from" command for a specific table. - * - * @param string $table The name of the table. - * @return array Field info for that table - */ - function show_fields_from($table) - { - $query = $this->write_query("SHOW FIELDS FROM ".$this->table_prefix.$table.""); - $field_info = array(); - while($field = $this->fetch_array($query)) - { - $field_info[] = $field; - } - return $field_info; - } - - /** - * Returns whether or not the table contains a fulltext index. - * - * @param string $table The name of the table. - * @param string $index Optionally specify the name of the index. - * @return boolean True or false if the table has a fulltext index or not. - */ - function is_fulltext($table, $index="") - { - $structure = $this->show_create_table($table); - if($index != "") - { - if(preg_match("#FULLTEXT KEY (`?)$index(`?)#i", $structure)) - { - return true; - } - else - { - return false; - } - } - if(preg_match('#FULLTEXT KEY#i', $structure)) - { - return true; - } - return false; - } - - /** - * Returns whether or not this database engine supports fulltext indexing. - * - * @param string $table The table to be checked. - * @return boolean True or false if supported or not. - */ - - function supports_fulltext($table) - { - $version = $this->get_version(); - $query = $this->write_query("SHOW TABLE STATUS LIKE '{$this->table_prefix}$table'"); - $status = $this->fetch_array($query); - $table_type = my_strtoupper($status['Engine']); - if(version_compare($version, '3.23.23', '>=') && ($table_type == 'MYISAM' || $table_type == 'ARIA')) - { - return true; - } - elseif(version_compare($version, '5.6', '>=') && $table_type == 'INNODB') - { - return true; - } - return false; - } - - /** - * Returns whether or not this database engine supports boolean fulltext matching. - * - * @param string $table The table to be checked. - * @return boolean True or false if supported or not. - */ - function supports_fulltext_boolean($table) - { - $version = $this->get_version(); - $supports_fulltext = $this->supports_fulltext($table); - if(version_compare($version, '4.0.1', '>=') && $supports_fulltext == true) - { - return true; - } - return false; - } - - /** - * Checks to see if an index exists on a specified table - * - * @param string $table The name of the table. - * @param string $index The name of the index. - * @return bool Returns whether index exists - */ - function index_exists($table, $index) - { - $index_exists = false; - $query = $this->write_query("SHOW INDEX FROM {$this->table_prefix}{$table}"); - while($ukey = $this->fetch_array($query)) - { - if($ukey['Key_name'] == $index) - { - $index_exists = true; - break; - } - } - - if($index_exists) - { - return true; - } - - return false; - } - - /** - * Creates a fulltext index on the specified column in the specified table with optional index name. - * - * @param string $table The name of the table. - * @param string $column Name of the column to be indexed. - * @param string $name The index name, optional. - */ - function create_fulltext_index($table, $column, $name="") - { - $this->write_query("ALTER TABLE {$this->table_prefix}$table ADD FULLTEXT $name ($column)"); - } - - /** - * Drop an index with the specified name from the specified table - * - * @param string $table The name of the table. - * @param string $name The name of the index. - */ - function drop_index($table, $name) - { - $this->write_query("ALTER TABLE {$this->table_prefix}$table DROP INDEX $name"); - } - - /** - * Drop an table with the specified table - * - * @param string $table The table to drop - * @param boolean $hard hard drop - no checking - * @param boolean $table_prefix use table prefix - */ - function drop_table($table, $hard=false, $table_prefix=true) - { - if($table_prefix == false) - { - $table_prefix = ""; - } - else - { - $table_prefix = $this->table_prefix; - } - - if($hard == false) - { - $this->write_query('DROP TABLE IF EXISTS '.$table_prefix.$table); - } - else - { - $this->write_query('DROP TABLE '.$table_prefix.$table); - } - } - - /** - * Renames a table - * - * @param string $old_table The old table name - * @param string $new_table the new table name - * @param boolean $table_prefix use table prefix - * @return mysqli_result - */ - function rename_table($old_table, $new_table, $table_prefix=true) - { - if($table_prefix == false) - { - $table_prefix = ""; - } - else - { - $table_prefix = $this->table_prefix; - } - - return $this->write_query("RENAME TABLE {$table_prefix}{$old_table} TO {$table_prefix}{$new_table}"); - } - - /** - * Replace contents of table with values - * - * @param string $table The table - * @param array $replacements The replacements - * @return mysqli_result|bool - */ - function replace_query($table, $replacements=array()) - { - global $mybb; - - $values = ''; - $comma = ''; - foreach($replacements as $column => $value) - { - if(isset($mybb->binary_fields[$table][$column]) && $mybb->binary_fields[$table][$column]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $values .= $comma."`".$column."`=".$value; - } - else - { - $values .= $comma."`".$column."`=".$this->quote_val($value); - } - - $comma = ','; - } - - if(empty($replacements)) - { - return false; - } - - return $this->write_query("REPLACE INTO {$this->table_prefix}{$table} SET {$values}"); - } - - /** - * Drops a column - * - * @param string $table The table - * @param string $column The column name - * @return mysqli_result - */ - function drop_column($table, $column) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} DROP {$column}"); - } - - /** - * Adds a column - * - * @param string $table The table - * @param string $column The column name - * @param string $definition the new column definition - * @return mysqli_result - */ - function add_column($table, $column, $definition) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} ADD {$column} {$definition}"); - } - - /** - * Modifies a column - * - * @param string $table The table - * @param string $column The column name - * @param string $new_definition the new column definition - * @return mysqli_result - */ - function modify_column($table, $column, $new_definition) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} MODIFY {$column} {$new_definition}"); - } - - /** - * Renames a column - * - * @param string $table The table - * @param string $old_column The old column name - * @param string $new_column the new column name - * @param string $new_definition the new column definition - * @return mysqli_result - */ - function rename_column($table, $old_column, $new_column, $new_definition) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} CHANGE {$old_column} {$new_column} {$new_definition}"); - } - - /** - * Sets the table prefix used by the simple select, insert, update and delete functions - * - * @param string $prefix The new table prefix - */ - function set_table_prefix($prefix) - { - $this->table_prefix = $prefix; - } - - /** - * Fetched the total size of all mysql tables or a specific table - * - * @param string $table The table (optional) - * @return integer the total size of all mysql tables or a specific table - */ - function fetch_size($table='') - { - if($table != '') - { - $query = $this->query("SHOW TABLE STATUS LIKE '".$this->table_prefix.$table."'"); - } - else - { - $query = $this->query("SHOW TABLE STATUS"); - } - $total = 0; - while($table = $this->fetch_array($query)) - { - $total += $table['Data_length']+$table['Index_length']; - } - return $total; - } - - /** - * Fetch a list of database character sets this DBMS supports - * - * @return array|bool Array of supported character sets with array key being the name, array value being display name. False if unsupported - */ - function fetch_db_charsets() - { - if($this->write_link && version_compare($this->get_version(), "4.1", "<")) - { - return false; - } - return array( - 'big5' => 'Big5 Traditional Chinese', - 'dec8' => 'DEC West European', - 'cp850' => 'DOS West European', - 'hp8' => 'HP West European', - 'koi8r' => 'KOI8-R Relcom Russian', - 'latin1' => 'ISO 8859-1 Latin 1', - 'latin2' => 'ISO 8859-2 Central European', - 'swe7' => '7bit Swedish', - 'ascii' => 'US ASCII', - 'ujis' => 'EUC-JP Japanese', - 'sjis' => 'Shift-JIS Japanese', - 'hebrew' => 'ISO 8859-8 Hebrew', - 'tis620' => 'TIS620 Thai', - 'euckr' => 'EUC-KR Korean', - 'koi8u' => 'KOI8-U Ukrainian', - 'gb2312' => 'GB2312 Simplified Chinese', - 'greek' => 'ISO 8859-7 Greek', - 'cp1250' => 'Windows Central European', - 'gbk' => 'GBK Simplified Chinese', - 'latin5' => 'ISO 8859-9 Turkish', - 'armscii8' => 'ARMSCII-8 Armenian', - 'utf8' => 'UTF-8 Unicode', - 'utf8mb4' => '4-Byte UTF-8 Unicode (requires MySQL 5.5.3 or above)', - 'ucs2' => 'UCS-2 Unicode', - 'cp866' => 'DOS Russian', - 'keybcs2' => 'DOS Kamenicky Czech-Slovak', - 'macce' => 'Mac Central European', - 'macroman' => 'Mac West European', - 'cp852' => 'DOS Central European', - 'latin7' => 'ISO 8859-13 Baltic', - 'cp1251' => 'Windows Cyrillic', - 'cp1256' => 'Windows Arabic', - 'cp1257' => 'Windows Baltic', - 'geostd8' => 'GEOSTD8 Georgian', - 'cp932' => 'SJIS for Windows Japanese', - 'eucjpms' => 'UJIS for Windows Japanese', - ); - } - - /** - * Fetch a database collation for a particular database character set - * - * @param string $charset The database character set - * @return string|bool The matching database collation, false if unsupported - */ - function fetch_charset_collation($charset) - { - $collations = array( - 'big5' => 'big5_chinese_ci', - 'dec8' => 'dec8_swedish_ci', - 'cp850' => 'cp850_general_ci', - 'hp8' => 'hp8_english_ci', - 'koi8r' => 'koi8r_general_ci', - 'latin1' => 'latin1_swedish_ci', - 'latin2' => 'latin2_general_ci', - 'swe7' => 'swe7_swedish_ci', - 'ascii' => 'ascii_general_ci', - 'ujis' => 'ujis_japanese_ci', - 'sjis' => 'sjis_japanese_ci', - 'hebrew' => 'hebrew_general_ci', - 'tis620' => 'tis620_thai_ci', - 'euckr' => 'euckr_korean_ci', - 'koi8u' => 'koi8u_general_ci', - 'gb2312' => 'gb2312_chinese_ci', - 'greek' => 'greek_general_ci', - 'cp1250' => 'cp1250_general_ci', - 'gbk' => 'gbk_chinese_ci', - 'latin5' => 'latin5_turkish_ci', - 'armscii8' => 'armscii8_general_ci', - 'utf8' => 'utf8_general_ci', - 'utf8mb4' => 'utf8mb4_general_ci', - 'ucs2' => 'ucs2_general_ci', - 'cp866' => 'cp866_general_ci', - 'keybcs2' => 'keybcs2_general_ci', - 'macce' => 'macce_general_ci', - 'macroman' => 'macroman_general_ci', - 'cp852' => 'cp852_general_ci', - 'latin7' => 'latin7_general_ci', - 'cp1251' => 'cp1251_general_ci', - 'cp1256' => 'cp1256_general_ci', - 'cp1257' => 'cp1257_general_ci', - 'geostd8' => 'geostd8_general_ci', - 'cp932' => 'cp932_japanese_ci', - 'eucjpms' => 'eucjpms_japanese_ci', - ); - if($collations[$charset]) - { - return $collations[$charset]; - } - return false; - } - - /** - * Fetch a character set/collation string for use with CREATE TABLE statements. Uses current DB encoding - * - * @return string The built string, empty if unsupported - */ - function build_create_table_collation() - { - if(!$this->db_encoding) - { - return ''; - } - - $collation = $this->fetch_charset_collation($this->db_encoding); - if(!$collation) - { - return ''; - } - return " CHARACTER SET {$this->db_encoding} COLLATE {$collation}"; - } - - /** - * Time how long it takes for a particular piece of code to run. Place calls above & below the block of code. - * - * @deprecated - */ - function get_execution_time() - { - return get_execution_time(); - } - - /** - * Binary database fields require special attention. - * - * @param string $string Binary value - * @return string Encoded binary value - */ - function escape_binary($string) - { - return "X'".$this->escape_string(bin2hex($string))."'"; - } - - /** - * Unescape binary data. - * - * @param string $string Binary value - * @return string Encoded binary value - */ - function unescape_binary($string) - { - // Nothing to do - return $string; - } -} - diff --git a/html/forums/inc/db_pdo.php b/html/forums/inc/db_pdo.php deleted file mode 100644 index 52a129b..0000000 --- a/html/forums/inc/db_pdo.php +++ /dev/null @@ -1,234 +0,0 @@ -db = new PDO($dsn, $username, $password, $driver_options); - } - catch(PDOException $exception) - { - die('Connection failed: '.$exception->getMessage()); - } - - $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - } - - /** - * Query the database. - * - * @param string $string The query SQL. - * @return PDOStatement The query data. - */ - function query($string) - { - ++$this->queries; - - $query = $this->db->query($string, PDO::FETCH_BOTH); - $this->last_query = $query; - - $query->guid = $this->queries; - - return $query; - } - - /** - * Return a result array for a query. - * - * @param PDOStatement $query The query resource. - * @param int $resulttype One of PDO's constants: FETCH_ASSOC, FETCH_BOUND, FETCH_CLASS, FETCH_INTO, FETCH_LAZY, FETCH_NAMED, FETCH_NUM, FETCH_OBJ or FETCH_BOTH - * @return array The array of results. - */ - function fetch_array($query, $resulttype=PDO::FETCH_BOTH) - { - switch($resulttype) - { - case PDO::FETCH_ASSOC: - case PDO::FETCH_BOUND: - case PDO::FETCH_CLASS: - case PDO::FETCH_INTO: - case PDO::FETCH_LAZY: - case PDO::FETCH_NAMED: - case PDO::FETCH_NUM: - case PDO::FETCH_OBJ: - break; - default: - $resulttype = PDO::FETCH_BOTH; - break; - } - - if($this->seek_array[$query->guid]) - { - $array = $query->fetch($resulttype, $this->seek_array[$query->guid]['offset'], $this->seek_array[$query->guid]['row']); - } - else - { - $array = $query->fetch($resulttype); - } - - return $array; - } - - /** - * Moves internal row pointer to the next row - * - * @param PDOStatement $query The query resource. - * @param int $row The pointer to move the row to. - */ - function seek($query, $row) - { - $this->seek_array[$query->guid] = array('offset' => PDO::FETCH_ORI_ABS, 'row' => $row); - } - - /** - * Return the number of rows resulting from a query. - * - * @param PDOStatement $query The query resource. - * @return int The number of rows in the result. - */ - function num_rows($query) - { - if(stripos($query->queryString, 'SELECT') !== false) - { - $query = $this->db->query($query->queryString); - $result = $query->fetchAll(); - return count($result); - } - else - { - return $query->rowCount(); - } - } - - /** - * Return the last id number of inserted data. - * - * @param string $name The name of the insert id to check. (Optional) - * @return int The id number. - */ - function insert_id($name="") - { - return $this->db->lastInsertId($name); - } - - /** - * Return an error number. - * - * @param PDOStatement $query The query resource. - * @return int The error number of the current error. - */ - function error_number($query) - { - if(!method_exists($query, "errorCode")) - { - return 0; - } - - $errorcode = $query->errorCode(); - - return $errorcode; - } - - /** - * Return an error string. - * - * @param PDOStatement $query The query resource. - * @return array The error string of the current error. - */ - function error_string($query) - { - if(!method_exists($query, "errorInfo")) - { - return $this->db->errorInfo(); - } - return $query->errorInfo(); - } - - /** - * Returns the number of affected rows in a query. - * - * @param PDOStatement $query - * @return int The number of affected rows. - */ - function affected_rows($query) - { - return $query->rowCount(); - } - - /** - * Return the number of fields. - * - * @param PDOStatement $query The query resource. - * @return int The number of fields. - */ - function num_fields($query) - { - return $query->columnCount(); - } - - /** - * Escape a string according to the pdo escape format. - * - * @param string $string The string to be escaped. - * @return string The escaped string. - */ - function escape_string($string) - { - $string = $this->db->quote($string); - - // Remove ' from the begginging of the string and at the end of the string, because we already use it in insert_query - $string = substr($string, 1); - $string = substr($string, 0, -1); - - return $string; - } - - /** - * Return a selected attribute - * - * @param string $attribute The attribute to check. - * @return string The value of the attribute. - */ - function get_attribute($attribute) - { - $attribute = $this->db->getAttribute(constant("PDO::".$attribute."")); - - return $attribute; - } -} diff --git a/html/forums/inc/db_pgsql.php b/html/forums/inc/db_pgsql.php deleted file mode 100644 index 5bde4f9..0000000 --- a/html/forums/inc/db_pgsql.php +++ /dev/null @@ -1,1582 +0,0 @@ - $settings) - { - if(is_int($key)) $connections['read'][] = $settings; - } - } - // Specified both read & write servers - else - { - $connections = $config; - } - } - - $this->db_encoding = $config['encoding']; - - // Actually connect to the specified servers - foreach(array('read', 'write') as $type) - { - if(!isset($connections[$type]) || !is_array($connections[$type])) - { - break; - } - - if(array_key_exists('hostname', $connections[$type])) - { - $details = $connections[$type]; - unset($connections); - $connections[$type][] = $details; - } - - // Shuffle the connections - shuffle($connections[$type]); - - // Loop-de-loop - foreach($connections[$type] as $single_connection) - { - $connect_function = "pg_connect"; - if(isset($single_connection['pconnect'])) - { - $connect_function = "pg_pconnect"; - } - - $link = $type."_link"; - - get_execution_time(); - - $this->connect_string = "dbname={$single_connection['database']} user={$single_connection['username']}"; - - if(strpos($single_connection['hostname'], ':') !== false) - { - list($single_connection['hostname'], $single_connection['port']) = explode(':', $single_connection['hostname']); - } - - if($single_connection['port']) - { - $this->connect_string .= " port={$single_connection['port']}"; - } - - if($single_connection['hostname'] != "") - { - $this->connect_string .= " host={$single_connection['hostname']}"; - } - - if($single_connection['password']) - { - $this->connect_string .= " password={$single_connection['password']}"; - } - $this->$link = @$connect_function($this->connect_string); - - $time_spent = get_execution_time(); - $this->query_time += $time_spent; - - // Successful connection? break down brother! - if($this->$link) - { - $this->connections[] = "[".strtoupper($type)."] {$single_connection['username']}@{$single_connection['hostname']} (Connected in ".format_time_duration($time_spent).")"; - break; - } - else - { - $this->connections[] = "[FAILED] [".strtoupper($type)."] {$single_connection['username']}@{$single_connection['hostname']}"; - } - } - } - - // No write server was specified (simple connection or just multiple servers) - mirror write link - if(!array_key_exists('write', $connections)) - { - $this->write_link = &$this->read_link; - } - - // Have no read connection? - if(!$this->read_link) - { - $this->error("[READ] Unable to connect to PgSQL server"); - return false; - } - // No write? - else if(!$this->write_link) - { - $this->error("[WRITE] Unable to connect to PgSQL server"); - return false; - } - - $this->current_link = &$this->read_link; - return $this->read_link; - } - - /** - * Query the database. - * - * @param string $string The query SQL. - * @param boolean|int $hide_errors 1 if hide errors, 0 if not. - * @param integer $write_query 1 if executes on slave database, 0 if not. - * @return resource The query data. - */ - function query($string, $hide_errors=0, $write_query=0) - { - global $mybb; - - $string = preg_replace("#LIMIT (\s*)([0-9]+),(\s*)([0-9]+)$#im", "LIMIT $4 OFFSET $2", trim($string)); - - $this->last_query = $string; - - get_execution_time(); - - if(strtolower(substr(ltrim($string), 0, 5)) == 'alter') - { - $string = preg_replace("#\sAFTER\s([a-z_]+?)(;*?)$#i", "", $string); - if(strstr($string, 'CHANGE') !== false) - { - $string = str_replace(' CHANGE ', ' ALTER ', $string); - } - } - - if($write_query && $this->write_link) - { - while(pg_connection_busy($this->write_link)); - $this->current_link = &$this->write_link; - pg_send_query($this->current_link, $string); - $query = pg_get_result($this->current_link); - } - else - { - while(pg_connection_busy($this->read_link)); - $this->current_link = &$this->read_link; - pg_send_query($this->current_link, $string); - $query = pg_get_result($this->current_link); - } - - if((pg_result_error($query) && !$hide_errors)) - { - $this->error($string, $query); - exit; - } - - $query_time = get_execution_time(); - $this->query_time += $query_time; - $this->query_count++; - $this->last_result = $query; - - if($mybb->debug_mode) - { - $this->explain_query($string, $query_time); - } - return $query; - } - - /** - * Execute a write query on the slave database - * - * @param string $query The query SQL. - * @param boolean|int $hide_errors 1 if hide errors, 0 if not. - * @return resource The query data. - */ - function write_query($query, $hide_errors=0) - { - return $this->query($query, $hide_errors, 1); - } - - /** - * Explain a query on the database. - * - * @param string $string The query SQL. - * @param string $qtime The time it took to perform the query. - */ - function explain_query($string, $qtime) - { - if(preg_match("#^\s*select#i", $string)) - { - $query = pg_query($this->current_link, "EXPLAIN $string"); - $this->explain .= "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n"; - - while($table = pg_fetch_assoc($query)) - { - $this->explain .= - "\n". - "\n". - "\n"; - } - $this->explain .= - "\n". - "\n". - "\n". - "
    #".$this->query_count." - Select Query
    ".htmlspecialchars_uni($string)."
    Info
    ".$table['QUERY PLAN']."
    Query Time: ".format_time_duration($qtime)."
    \n". - "
    \n"; - } - else - { - $this->explain .= "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "
    #".$this->query_count." - Write Query
    ".htmlspecialchars_uni($string)."
    Query Time: ".format_time_duration($qtime)."
    \n". - "
    \n"; - } - - $this->querylist[$this->query_count]['query'] = $string; - $this->querylist[$this->query_count]['time'] = $qtime; - } - - /** - * Return a result array for a query. - * - * @param resource $query The query ID. - * @param int $resulttype The type of array to return. Either PGSQL_NUM, PGSQL_BOTH or PGSQL_ASSOC - * @return array The array of results. Note that all fields are returned as string: http://php.net/manual/en/function.pg-fetch-array.php - */ - function fetch_array($query, $resulttype=PGSQL_ASSOC) - { - switch($resulttype) - { - case PGSQL_NUM: - case PGSQL_BOTH: - break; - default: - $resulttype = PGSQL_ASSOC; - break; - } - - $array = pg_fetch_array($query, NULL, $resulttype); - - return $array; - } - - /** - * Return a specific field from a query. - * - * @param resource $query The query ID. - * @param string $field The name of the field to return. - * @param int|bool The number of the row to fetch it from. - * @return string|bool|null As per http://php.net/manual/en/function.pg-fetch-result.php - */ - function fetch_field($query, $field, $row=false) - { - if($row === false) - { - $array = $this->fetch_array($query); - return $array[$field]; - } - else - { - return pg_fetch_result($query, $row, $field); - } - } - - /** - * Moves internal row pointer to the next row - * - * @param resource $query The query ID. - * @param int $row The pointer to move the row to. - * @return bool - */ - function data_seek($query, $row) - { - return pg_result_seek($query, $row); - } - - /** - * Return the number of rows resulting from a query. - * - * @param resource $query The query ID. - * @return int The number of rows in the result. - */ - function num_rows($query) - { - return pg_num_rows($query); - } - - /** - * Return the last id number of inserted data. - * - * @return int The id number. - */ - function insert_id() - { - $this->last_query = str_replace(array("\r", "\t"), '', $this->last_query); - $this->last_query = str_replace("\n", ' ', $this->last_query); - preg_match('#INSERT INTO ([a-zA-Z0-9_\-]+)#i', $this->last_query, $matches); - - $table = $matches[1]; - - $query = $this->query("SELECT column_name FROM information_schema.constraint_column_usage WHERE table_name = '{$table}' and constraint_name = '{$table}_pkey' LIMIT 1"); - $field = $this->fetch_field($query, 'column_name'); - - // Do we not have a primary field? - if(!$field) - { - return 0; - } - - $id = $this->write_query("SELECT currval(pg_get_serial_sequence('{$table}', '{$field}')) AS last_value"); - return $this->fetch_field($id, 'last_value'); - } - - /** - * Close the connection with the DBMS. - * - */ - function close() - { - @pg_close($this->read_link); - if($this->write_link) - { - @pg_close($this->write_link); - } - } - - /** - * Return an error number. - * - * @param resource $query - * @return int The error number of the current error. - */ - function error_number($query=null) - { - if($query != null || !function_exists("pg_result_error_field")) - { - return 0; - } - - return pg_result_error_field($query, PGSQL_DIAG_SQLSTATE); - } - - /** - * Return an error string. - * - * @param resource $query - * @return string The explanation for the current error. - */ - function error_string($query=null) - { - if($query != null) - { - return pg_result_error($query); - } - - if($this->current_link) - { - return pg_last_error($this->current_link); - } - else - { - return pg_last_error(); - } - } - - /** - * Output a database error. - * - * @param string $string The string to present as an error. - * @param resource $query - */ - function error($string="", $query=null) - { - if($this->error_reporting) - { - if(class_exists("errorHandler")) - { - global $error_handler; - - if(!is_object($error_handler)) - { - require_once MYBB_ROOT."inc/class_error.php"; - $error_handler = new errorHandler(); - } - - $error = array( - "error_no" => $this->error_number($query), - "error" => $this->error_string($query), - "query" => $string - ); - $error_handler->error(MYBB_SQL, $error); - } - else - { - trigger_error("[SQL] [".$this->error_number()."] ".$this->error_string()."
    {$string}", E_USER_ERROR); - } - } - } - - /** - * Returns the number of affected rows in a query. - * - * @return int The number of affected rows. - */ - function affected_rows() - { - return pg_affected_rows($this->last_result); - } - - /** - * Return the number of fields. - * - * @param resource $query The query ID. - * @return int The number of fields. - */ - function num_fields($query) - { - return pg_num_fields($query); - } - - /** - * Lists all tables in the database. - * - * @param string $database The database name. - * @param string $prefix Prefix of the table (optional) - * @return array The table list. - */ - function list_tables($database, $prefix='') - { - if($prefix) - { - $query = $this->query("SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_name LIKE '".$this->escape_string($prefix)."%'"); - } - else - { - $query = $this->query("SELECT table_name FROM information_schema.tables WHERE table_schema='public'"); - } - - $tables = array(); - while($table = $this->fetch_array($query)) - { - $tables[] = $table['table_name']; - } - - return $tables; - } - - /** - * Check if a table exists in a database. - * - * @param string $table The table name. - * @return boolean True when exists, false if not. - */ - function table_exists($table) - { - // Execute on master server to ensure if we've just created a table that we get the correct result - $query = $this->write_query("SELECT COUNT(table_name) as table_names FROM information_schema.tables WHERE table_schema = 'public' AND table_name='{$this->table_prefix}{$table}'"); - - $exists = $this->fetch_field($query, 'table_names'); - - if($exists > 0) - { - return true; - } - else - { - return false; - } - } - - /** - * Check if a field exists in a database. - * - * @param string $field The field name. - * @param string $table The table name. - * @return boolean True when exists, false if not. - */ - function field_exists($field, $table) - { - $query = $this->write_query("SELECT COUNT(column_name) as column_names FROM information_schema.columns WHERE table_name='{$this->table_prefix}{$table}' AND column_name='{$field}'"); - - $exists = $this->fetch_field($query, "column_names"); - - if($exists > 0) - { - return true; - } - else - { - return false; - } - } - - /** - * Add a shutdown query. - * - * @param resource $query The query data. - * @param string $name An optional name for the query. - */ - function shutdown_query($query, $name="") - { - global $shutdown_queries; - if($name) - { - $shutdown_queries[$name] = $query; - } - else - { - $shutdown_queries[] = $query; - } - } - - /** - * Performs a simple select query. - * - * @param string $table The table name to be queried. - * @param string $fields Comma delimetered list of fields to be selected. - * @param string $conditions SQL formatted list of conditions to be matched. - * @param array $options List of options: group by, order by, order direction, limit, limit start. - * @return resource The query data. - */ - function simple_select($table, $fields="*", $conditions="", $options=array()) - { - $query = "SELECT ".$fields." FROM ".$this->table_prefix.$table; - if($conditions != "") - { - $query .= " WHERE ".$conditions; - } - - if(isset($options['group_by'])) - { - $query .= " GROUP BY ".$options['group_by']; - } - - if(isset($options['order_by'])) - { - $query .= " ORDER BY ".$options['order_by']; - if(isset($options['order_dir'])) - { - $query .= " ".my_strtoupper($options['order_dir']); - } - } - - if(isset($options['limit_start']) && isset($options['limit'])) - { - $query .= " LIMIT ".$options['limit_start'].", ".$options['limit']; - } - else if(isset($options['limit'])) - { - $query .= " LIMIT ".$options['limit']; - } - - return $this->query($query); - } - - /** - * Build an insert query from an array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of fields and their values. - * @param boolean $insert_id Whether or not to return an insert id. True by default - * @return int|bool The insert ID if available. False on failure and true if $insert_id is false - */ - function insert_query($table, $array, $insert_id=true) - { - global $mybb; - - if(!is_array($array)) - { - return false; - } - - foreach($array as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - $array[$field] = $value; - } - else - { - $array[$field] = $this->quote_val($value); - } - } - - $fields = implode(",", array_keys($array)); - $values = implode(",", $array); - $this->write_query(" - INSERT - INTO {$this->table_prefix}{$table} (".$fields.") - VALUES (".$values.") - "); - - if($insert_id != false) - { - return $this->insert_id(); - } - else - { - return true; - } - } - - /** - * Build one query for multiple inserts from a multidimensional array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of inserts. - * @return void - */ - function insert_query_multiple($table, $array) - { - global $mybb; - - if(!is_array($array)) - { - return; - } - // Field names - $fields = array_keys($array[0]); - $fields = implode(",", $fields); - - $insert_rows = array(); - foreach($array as $values) - { - foreach($values as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - $values[$field] = $value; - } - else - { - $values[$field] = $this->quote_val($value); - } - } - $insert_rows[] = "(".implode(",", $values).")"; - } - $insert_rows = implode(", ", $insert_rows); - - $this->write_query(" - INSERT - INTO {$this->table_prefix}{$table} ({$fields}) - VALUES {$insert_rows} - "); - } - - /** - * Build an update query from an array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of fields and their values. - * @param string $where An optional where clause for the query. - * @param string $limit An optional limit clause for the query. - * @param boolean $no_quote An option to quote incoming values of the array. - * @return resource The query data. - */ - function update_query($table, $array, $where="", $limit="", $no_quote=false) - { - global $mybb; - - if(!is_array($array)) - { - return false; - } - - $comma = ""; - $query = ""; - $quote = "'"; - - if($no_quote == true) - { - $quote = ""; - } - - foreach($array as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - $query .= $comma.$field."={$value}"; - } - else - { - $quoted_value = $this->quote_val($value, $quote); - - $query .= $comma.$field."={$quoted_value}"; - } - $comma = ', '; - } - if(!empty($where)) - { - $query .= " WHERE $where"; - } - return $this->write_query(" - UPDATE {$this->table_prefix}$table - SET $query - "); - } - - /** - * @param int|string $value - * @param string $quote - * - * @return int|string - */ - private function quote_val($value, $quote="'") - { - if(is_int($value)) - { - $quoted = $value; - } - else - { - $quoted = $quote . $value . $quote; - } - - return $quoted; - } - - /** - * Build a delete query. - * - * @param string $table The table name to perform the query on. - * @param string $where An optional where clause for the query. - * @param string $limit An optional limit clause for the query. - * @return resource The query data. - */ - function delete_query($table, $where="", $limit="") - { - $query = ""; - if(!empty($where)) - { - $query .= " WHERE $where"; - } - - return $this->write_query(" - DELETE - FROM {$this->table_prefix}$table - $query - "); - } - - /** - * Escape a string according to the pg escape format. - * - * @param string $string The string to be escaped. - * @return string The escaped string. - */ - function escape_string($string) - { - if(function_exists("pg_escape_string")) - { - $string = pg_escape_string($string); - } - else - { - $string = addslashes($string); - } - return $string; - } - - /** - * Frees the resources of a PgSQL query. - * - * @param resource $query The query to destroy. - * @return boolean Returns true on success, false on failure - */ - function free_result($query) - { - return pg_free_result($query); - } - - /** - * Escape a string used within a like command. - * - * @param string $string The string to be escaped. - * @return string The escaped string. - */ - function escape_string_like($string) - { - return $this->escape_string(str_replace(array('%', '_') , array('\\%' , '\\_') , $string)); - } - - /** - * Gets the current version of PgSQL. - * - * @return string Version of PgSQL. - */ - function get_version() - { - if($this->version) - { - return $this->version; - } - - $version = pg_version($this->current_link); - - $this->version = $version['server']; - - return $this->version; - } - - /** - * Optimizes a specific table. - * - * @param string $table The name of the table to be optimized. - */ - function optimize_table($table) - { - $this->write_query("VACUUM ".$this->table_prefix.$table.""); - } - - /** - * Analyzes a specific table. - * - * @param string $table The name of the table to be analyzed. - */ - function analyze_table($table) - { - $this->write_query("ANALYZE ".$this->table_prefix.$table.""); - } - - /** - * Show the "create table" command for a specific table. - * - * @param string $table The name of the table. - * @return string The pg command to create the specified table. - */ - function show_create_table($table) - { - $query = $this->write_query(" - SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull - FROM pg_class c - LEFT JOIN pg_attribute a ON (a.attrelid = c.oid) - LEFT JOIN pg_type t ON (a.atttypid = t.oid) - WHERE c.relname = '{$this->table_prefix}{$table}' AND a.attnum > 0 - ORDER BY a.attnum - "); - - $lines = array(); - $table_lines = "CREATE TABLE {$this->table_prefix}{$table} (\n"; - - while($row = $this->fetch_array($query)) - { - // Get the data from the table - $query2 = $this->write_query(" - SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault - FROM pg_attrdef d - LEFT JOIN pg_class c ON (c.oid = d.adrelid) - WHERE c.relname = '{$this->table_prefix}{$table}' AND d.adnum = '{$row['attnum']}' - "); - - if(!$query2) - { - unset($row['rowdefault']); - } - else - { - $row['rowdefault'] = $this->fetch_field($query2, 'rowdefault'); - } - - if($row['type'] == 'bpchar') - { - // Stored in the engine as bpchar, but in the CREATE TABLE statement it's char - $row['type'] = 'char'; - } - - $line = " {$row['field']} {$row['type']}"; - - if(strpos($row['type'], 'char') !== false) - { - if($row['lengthvar'] > 0) - { - $line .= '('.($row['lengthvar'] - 4).')'; - } - } - - if(strpos($row['type'], 'numeric') !== false) - { - $line .= '('.sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff)).')'; - } - - if(!empty($row['rowdefault'])) - { - $line .= " DEFAULT {$row['rowdefault']}"; - } - - if($row['notnull'] == 't') - { - $line .= ' NOT NULL'; - } - - $lines[] = $line; - } - - // Get the listing of primary keys. - $query = $this->write_query(" - SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key - FROM pg_class bc - LEFT JOIN pg_index i ON (bc.oid = i.indrelid) - LEFT JOIN pg_class ic ON (ic.oid = i.indexrelid) - LEFT JOIN pg_attribute ia ON (ia.attrelid = i.indexrelid) - LEFT JOIN pg_attribute ta ON (ta.attrelid = bc.oid AND ta.attrelid = i.indrelid AND ta.attnum = i.indkey[ia.attnum-1]) - WHERE bc.relname = '{$this->table_prefix}{$table}' - ORDER BY index_name, tab_name, column_name - "); - - $primary_key = array(); - $primary_key_name = ''; - - $unique_keys = array(); - - // We do this in two steps. It makes placing the comma easier - while($row = $this->fetch_array($query)) - { - if($row['primary_key'] == 't') - { - $primary_key[] = $row['column_name']; - $primary_key_name = $row['index_name']; - } - - if($row['unique_key'] == 't') - { - $unique_keys[$row['index_name']][] = $row['column_name']; - } - } - - if(!empty($primary_key)) - { - $lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (".implode(', ', $primary_key).")"; - } - - foreach($unique_keys as $key_name => $key_columns) - { - $lines[] = " CONSTRAINT $key_name UNIQUE (".implode(', ', $key_columns).")"; - } - - $table_lines .= implode(", \n", $lines); - $table_lines .= "\n)\n"; - - return $table_lines; - } - - /** - * Show the "show fields from" command for a specific table. - * - * @param string $table The name of the table. - * @return array Field info for that table - */ - function show_fields_from($table) - { - $query = $this->write_query("SELECT column_name FROM information_schema.constraint_column_usage WHERE table_name = '{$this->table_prefix}{$table}' and constraint_name = '{$this->table_prefix}{$table}_pkey' LIMIT 1"); - $primary_key = $this->fetch_field($query, 'column_name'); - - $query = $this->write_query(" - SELECT column_name as Field, data_type as Extra - FROM information_schema.columns - WHERE table_name = '{$this->table_prefix}{$table}' - "); - $field_info = array(); - while($field = $this->fetch_array($query)) - { - if($field['field'] == $primary_key) - { - $field['extra'] = 'auto_increment'; - } - - $field_info[] = array('Extra' => $field['extra'], 'Field' => $field['field']); - } - - return $field_info; - } - - /** - * Returns whether or not the table contains a fulltext index. - * - * @param string $table The name of the table. - * @param string $index Optionally specify the name of the index. - * @return boolean True or false if the table has a fulltext index or not. - */ - function is_fulltext($table, $index="") - { - return false; - } - - /** - * Returns whether or not this database engine supports fulltext indexing. - * - * @param string $table The table to be checked. - * @return boolean True or false if supported or not. - */ - - function supports_fulltext($table) - { - return false; - } - - /** - * Returns whether or not this database engine supports boolean fulltext matching. - * - * @param string $table The table to be checked. - * @return boolean True or false if supported or not. - */ - function supports_fulltext_boolean($table) - { - return false; - } - - /** - * Creates a fulltext index on the specified column in the specified table with optional index name. - * - * @param string $table The name of the table. - * @param string $column Name of the column to be indexed. - * @param string $name The index name, optional. - * @return bool - */ - function create_fulltext_index($table, $column, $name="") - { - return false; - } - - /** - * Drop an index with the specified name from the specified table - * - * @param string $table The name of the table. - * @param string $name The name of the index. - */ - function drop_index($table, $name) - { - $this->write_query(" - ALTER TABLE {$this->table_prefix}$table - DROP INDEX $name - "); - } - - /** - * Checks to see if an index exists on a specified table - * - * @param string $table The name of the table. - * @param string $index The name of the index. - * @return bool Returns whether index exists - */ - function index_exists($table, $index) - { - $err = $this->error_reporting; - $this->error_reporting = 0; - - $query = $this->write_query("SELECT * FROM pg_indexes WHERE tablename='".$this->escape_string($this->table_prefix.$table)."'"); - - $exists = $this->fetch_field($query, $index); - $this->error_reporting = $err; - - if($exists) - { - return true; - } - else - { - return false; - } - } - - /** - * Drop an table with the specified table - * - * @param string $table The name of the table. - * @param boolean $hard hard drop - no checking - * @param boolean $table_prefix use table prefix - */ - function drop_table($table, $hard=false, $table_prefix=true) - { - if($table_prefix == false) - { - $table_prefix = ""; - } - else - { - $table_prefix = $this->table_prefix; - } - - if($hard == false) - { - if($this->table_exists($table)) - { - $this->write_query('DROP TABLE '.$table_prefix.$table); - } - } - else - { - $this->write_query('DROP TABLE '.$table_prefix.$table); - } - - $query = $this->query("SELECT column_name FROM information_schema.constraint_column_usage WHERE table_name = '{$table}' and constraint_name = '{$table}_pkey' LIMIT 1"); - $field = $this->fetch_field($query, 'column_name'); - - // Do we not have a primary field? - if($field) - { - $this->write_query('DROP SEQUENCE {$table}_{$field}_id_seq'); - } - } - - /** - * Renames a table - * - * @param string $old_table The old table name - * @param string $new_table the new table name - * @param boolean $table_prefix use table prefix - * @return resource - */ - function rename_table($old_table, $new_table, $table_prefix=true) - { - if($table_prefix == false) - { - $table_prefix = ""; - } - else - { - $table_prefix = $this->table_prefix; - } - - return $this->write_query("ALTER TABLE {$table_prefix}{$old_table} RENAME TO {$table_prefix}{$new_table}"); - } - - /** - * Replace contents of table with values - * - * @param string $table The table - * @param array $replacements The replacements - * @param string|array $default_field The default field(s) - * @param boolean $insert_id Whether or not to return an insert id. True by default - * @return int|resource|bool Returns either the insert id (if a new row is inserted and $insert_id is true), a boolean (if $insert_id is wrong) or the query resource (if a row is updated) - */ - function replace_query($table, $replacements=array(), $default_field="", $insert_id=true) - { - global $mybb; - - if($default_field == "") - { - $query = $this->write_query("SELECT column_name FROM information_schema.constraint_column_usage WHERE table_name = '{$this->table_prefix}{$table}' and constraint_name = '{$this->table_prefix}{$table}_pkey' LIMIT 1"); - $main_field = $this->fetch_field($query, 'column_name'); - } - else - { - $main_field = $default_field; - } - - $update = false; - $search_bit = array(); - - if(!is_array($main_field)) - { - $main_field = array($main_field); - } - - foreach($main_field as $field) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - $search_bit[] = "{$field} = ".$replacements[$field]; - } - else - { - $search_bit[] = "{$field} = ".$this->quote_val($replacements[$field]); - } - } - $search_bit = implode(" AND ", $search_bit); - $query = $this->write_query("SELECT COUNT(".$main_field[0].") as count FROM {$this->table_prefix}{$table} WHERE {$search_bit} LIMIT 1"); - if($this->fetch_field($query, "count") == 1) - { - $update = true; - } - - if($update === true) - { - return $this->update_query($table, $replacements, $search_bit); - } - else - { - return $this->insert_query($table, $replacements, $insert_id); - } - } - - /** - * @param string $table - * @param string $append - * - * @return string - */ - function build_fields_string($table, $append="") - { - $fields = $this->show_fields_from($table); - $comma = $fieldstring = ''; - - foreach($fields as $key => $field) - { - $fieldstring .= $comma.$append.$field['Field']; - $comma = ','; - } - - return $fieldstring; - } - - /** - * Drops a column - * - * @param string $table The table - * @param string $column The column name - * @return resource - */ - function drop_column($table, $column) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} DROP {$column}"); - } - - /** - * Adds a column - * - * @param string $table The table - * @param string $column The column name - * @param string $definition the new column definition - * @return resource - */ - function add_column($table, $column, $definition) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} ADD {$column} {$definition}"); - } - - /** - * Modifies a column - * - * @param string $table The table - * @param string $column The column name - * @param string $new_definition the new column definition - * @param boolean $new_not_null Whether to drop or set a column - * @param boolean $new_default_value The new default value (if one is to be set) - * @return bool Returns true if all queries are executed successfully or false if one of them failed - */ - function modify_column($table, $column, $new_definition, $new_not_null=false, $new_default_value=false) - { - $result1 = $result2 = $result3 = true; - - if($new_definition !== false) - { - $result1 = $this->write_query("ALTER TABLE {$this->table_prefix}{$table} ALTER COLUMN {$column} TYPE {$new_definition}"); - } - - if($new_not_null !== false) - { - $set_drop = "DROP"; - - if(strtolower($new_not_null) == "set") - { - $set_drop = "SET"; - } - - $result2 = $this->write_query("ALTER TABLE {$this->table_prefix}{$table} ALTER COLUMN {$column} {$set_drop} NOT NULL"); - } - - if($new_default_value !== false) - { - $result3 = $this->write_query("ALTER TABLE {$this->table_prefix}{$table} ALTER COLUMN {$column} SET DEFAULT {$new_default_value}"); - } - else - { - $result3 = $this->write_query("ALTER TABLE {$this->table_prefix}{$table} ALTER COLUMN {$column} DROP DEFAULT"); - } - - return $result1 && $result2 && $result3; - } - - /** - * Renames a column - * - * @param string $table The table - * @param string $old_column The old column name - * @param string $new_column the new column name - * @param string $new_definition the new column definition - * @param boolean $new_not_null Whether to drop or set a column - * @param boolean $new_default_value The new default value (if one is to be set) - * @return bool Returns true if all queries are executed successfully - */ - function rename_column($table, $old_column, $new_column, $new_definition, $new_not_null=false, $new_default_value=false) - { - $result1 = $this->write_query("ALTER TABLE {$this->table_prefix}{$table} RENAME COLUMN {$old_column} TO {$new_column}"); - $result2 = $this->modify_column($table, $new_column, $new_definition, $new_not_null, $new_default_value); - return ($result1 && $result2); - } - - /** - * Sets the table prefix used by the simple select, insert, update and delete functions - * - * @param string $prefix The new table prefix - */ - function set_table_prefix($prefix) - { - $this->table_prefix = $prefix; - } - - /** - * Fetched the total size of all mysql tables or a specific table - * - * @param string $table The table (optional) - * @return integer the total size of all mysql tables or a specific table - */ - function fetch_size($table='') - { - if($table != '') - { - $query = $this->query("SELECT reltuples, relpages FROM pg_class WHERE relname = '".$this->table_prefix.$table."'"); - } - else - { - $query = $this->query("SELECT reltuples, relpages FROM pg_class"); - } - $total = 0; - while($table = $this->fetch_array($query)) - { - $total += $table['relpages']+$table['reltuples']; - } - return $total; - } - - /** - * Fetch a list of database character sets this DBMS supports - * - * @return array|bool Array of supported character sets with array key being the name, array value being display name. False if unsupported - */ - function fetch_db_charsets() - { - return false; - } - - /** - * Fetch a database collation for a particular database character set - * - * @param string $charset The database character set - * @return string|bool The matching database collation, false if unsupported - */ - function fetch_charset_collation($charset) - { - return false; - } - - /** - * Fetch a character set/collation string for use with CREATE TABLE statements. Uses current DB encoding - * - * @return string The built string, empty if unsupported - */ - function build_create_table_collation() - { - return ''; - } - - /** - * Time how long it takes for a particular piece of code to run. Place calls above & below the block of code. - * - * @deprecated - */ - function get_execution_time() - { - return get_execution_time(); - } - - /** - * Binary database fields require special attention. - * - * @param string $string Binary value - * @return string Encoded binary value - */ - function escape_binary($string) - { - return "'".pg_escape_bytea($string)."'"; - } - - /** - * Unescape binary data. - * - * @param string $string Binary value - * @return string Encoded binary value - */ - function unescape_binary($string) - { - // hex format - if(substr($string, 0, 2) == '\x') - { - return pack('H*', substr($string, 2)); - } - // escape format - else - { - return pg_unescape_bytea($string); - } - } -} - diff --git a/html/forums/inc/db_sqlite.php b/html/forums/inc/db_sqlite.php deleted file mode 100644 index 052b8c9..0000000 --- a/html/forums/inc/db_sqlite.php +++ /dev/null @@ -1,1534 +0,0 @@ -db = new dbpdoEngine("sqlite:{$config['database']}"); - - $query_time = get_execution_time(); - - $this->query_time += $query_time; - - $this->connections[] = "[WRITE] {$config['database']} (Connected in ".format_time_duration($query_time).")"; - - if($this->db) - { - $this->query('PRAGMA short_column_names = 1'); - return true; - } - else - { - return false; - } - } - - /** - * Query the database. - * - * @param string $string The query SQL. - * @param boolean|int $hide_errors 1 if hide errors, 0 if not. - * @param integer $write_query 1 if executes on master database, 0 if not. - * @return PDOStatement The query data. - */ - function query($string, $hide_errors=0, $write_query=0) - { - global $mybb; - - get_execution_time(); - - if(strtolower(substr(ltrim($string), 0, 5)) == 'alter') - { - $string = preg_replace("#\sAFTER\s([a-z_]+?)(;*?)$#i", "", $string); - - $queryparts = preg_split("/[\s]+/", $string, 4, PREG_SPLIT_NO_EMPTY); - $tablename = $queryparts[2]; - $alterdefs = $queryparts[3]; - if(strtolower($queryparts[1]) != 'table' || $queryparts[2] == '') - { - $this->error_msg = "near \"{$queryparts[0]}\": syntax error"; - } - else - { - // SQLITE 3 supports ADD and RENAME TO alter statements - if(strtolower(substr(ltrim($alterdefs), 0, 3)) == 'add' || strtolower(substr(ltrim($alterdefs), 0, 9)) == "rename to") - { - $query = $this->db->query($string); - $query->closeCursor(); - } - else - { - $query = $this->alter_table_parse($tablename, $alterdefs, $string); - } - } - } - else - { - try - { - $query = $this->db->query($string); - } - catch(PDOException $exception) - { - $error = array( - "message" => $exception->getMessage(), - "code" => $exception->getCode() - ); - - $this->error($error['message'], $error['code']); - } - } - - $this->query_objects[] = $query; - - if($this->error_number($query) > 0 && !$hide_errors) - { - $this->error($string, $query); - exit; - } - - $query_time = get_execution_time(); - $this->query_time += $query_time; - $this->query_count++; - - if($mybb->debug_mode) - { - $this->explain_query($string, $query_time); - } - - if(strtolower(substr(ltrim($string), 0, 6)) == "create") - { - $query->closeCursor(); - return null; - } - - return $query; - } - - /** - * Explain a query on the database. - * - * @param string $string The query SQL. - * @param string $qtime The time it took to perform the query. - */ - function explain_query($string, $qtime) - { - if(preg_match("#^\s*select#i", $string)) - { - $this->explain .= "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "
    #".$this->query_count." - Select Query
    ".htmlspecialchars_uni($string)."
    Query Time: ".format_time_duration($qtime)."
    \n". - "
    \n"; - } - else - { - $this->explain .= "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "\n". - "
    #".$this->query_count." - Write Query
    ".htmlspecialchars_uni($string)."
    Query Time: ".format_time_duration($qtime)."
    \n". - "
    \n"; - } - - $this->querylist[$this->query_count]['query'] = $string; - $this->querylist[$this->query_count]['time'] = $qtime; - } - - /** - * Execute a write query on the database - * - * @param string $query The query SQL. - * @param boolean|int $hide_errors 1 if hide errors, 0 if not. - * @return PDOStatement The query data. - */ - function write_query($query, $hide_errors=0) - { - return $this->query($query, $hide_errors); - } - - /** - * Return a result array for a query. - * - * @param PDOStatement $query The result data. - * @param int $resulttype One of PDO's constants: FETCH_ASSOC, FETCH_BOUND, FETCH_CLASS, FETCH_INTO, FETCH_LAZY, FETCH_NAMED, FETCH_NUM, FETCH_OBJ or FETCH_BOTH - * @return array The array of results. - */ - function fetch_array($query, $resulttype=PDO::FETCH_BOTH) - { - $array = $this->db->fetch_array($query, $resulttype); - return $array; - } - - /** - * Return a specific field from a query. - * - * @param PDOStatement $query The query ID. - * @param string $field The name of the field to return. - * @param int|bool $row The number of the row to fetch it from. - * @return mixed - */ - function fetch_field($query, $field, $row=false) - { - if($row !== false) - { - $this->data_seek($query, $row); - } - $array = $this->fetch_array($query); - return $array[$field]; - } - - /** - * Moves internal row pointer to the next row - * - * @param PDOStatement $query The query ID. - * @param int $row The pointer to move the row to. - */ - function data_seek($query, $row) - { - $this->db->seek($query, $row); - } - - /** - * Closes cursors of registered queries. - * - */ - function close_cursors() - { - $result = true; - - foreach($this->query_objects as $query) - { - if(!$query->closeCursor()) - { - $result = false; - } - } - - return $result; - } - - /** - * Return the number of rows resulting from a query. - * - * @param PDOStatement $query The query data. - * @return int The number of rows in the result. - */ - function num_rows($query) - { - return $this->db->num_rows($query); - } - - /** - * Return the last id number of inserted data. - * - * @param string $name - * @return int The id number. - */ - function insert_id($name="") - { - return $this->db->insert_id($name); - } - - /** - * Close the connection with the DBMS. - * - */ - function close() - { - return; - } - - /** - * Return an error number. - * - * @param PDOStatement $query - * @return int The error number of the current error. - */ - function error_number($query=null) - { - if($query == null) - { - $query = $this->db->last_query; - } - - $this->error_number = $this->db->error_number($query); - - return $this->error_number; - } - - /** - * Return an error string. - * - * @param PDOStatement $query - * @return string The explanation for the current error. - */ - function error_string($query=null) - { - if($this->error_number != "") - { - if($query == null) - { - $query = $this->db->last_query; - } - - $error_string = $this->db->error_string($query); - $this->error_number = ""; - - return $error_string; - } - - return ''; - } - - /** - * Output a database error. - * - * @param string $string The string to present as an error. - * @param PDOStatement $query - * @param string $error - * @param int $error_no - */ - function error($string="", $query=null, $error="", $error_no=0) - { - if($this->error_reporting) - { - if($query == null) - { - $query = $this->db->last_query; - } - - if($error_no == 0) - { - $error_no = $this->error_number($query); - } - - if($error == "") - { - $error = $this->error_string($query); - } - - if(class_exists("errorHandler")) - { - global $error_handler; - - if(!is_object($error_handler)) - { - require_once MYBB_ROOT."inc/class_error.php"; - $error_handler = new errorHandler(); - } - - $error = array( - "error_no" => $error_no, - "error" => $error, - "query" => $string - ); - $error_handler->error(MYBB_SQL, $error); - } - else - { - trigger_error("[SQL] [{$error_no}] {$error}
    {$string}", E_USER_ERROR); - } - } - } - - /** - * Returns the number of affected rows in a query. - * - * @param PDOStatement $query - * @return int The number of affected rows. - */ - function affected_rows($query=null) - { - if($query == null) - { - $query = $this->db->last_query; - } - - return $this->db->affected_rows($query); - } - - /** - * Return the number of fields. - * - * @param PDOStatement $query The query data. - * @return int The number of fields. - */ - function num_fields($query) - { - if(!$query) - { - $query = $this->db->last_query; - } - - return $this->db->num_fields($query); - } - - /** - * Lists all tables in the database. - * - * @param string $database The database name. - * @param string $prefix Prefix of the table (optional) - * @return array The table list. - */ - function list_tables($database, $prefix='') - { - if($prefix) - { - $query = $this->query("SELECT tbl_name FROM sqlite_master WHERE type = 'table' AND tbl_name LIKE '".$this->escape_string($prefix)."%'"); - } - else - { - $query = $this->query("SELECT tbl_name FROM sqlite_master WHERE type = 'table'"); - } - - $tables = array(); - while($table = $this->fetch_array($query)) - { - $tables[] = $table['tbl_name']; - } - $query->closeCursor(); - return $tables; - } - - /** - * Check if a table exists in a database. - * - * @param string $table The table name. - * @return boolean True when exists, false if not. - */ - function table_exists($table) - { - $query = $this->query("SELECT COUNT(name) as count FROM sqlite_master WHERE type='table' AND name='{$this->table_prefix}{$table}'"); - $exists = $this->fetch_field($query, "count"); - $query->closeCursor(); - - if($exists > 0) - { - return true; - } - else - { - return false; - } - } - - /** - * Check if a field exists in a database. - * - * @param string $field The field name. - * @param string $table The table name. - * @return boolean True when exists, false if not. - */ - function field_exists($field, $table) - { - $query = $this->query("PRAGMA table_info('{$this->table_prefix}{$table}')"); - - $exists = 0; - - while($row = $this->fetch_array($query)) - { - if($row['name'] == $field) - { - ++$exists; - } - } - - $query->closeCursor(); - - if($exists > 0) - { - return true; - } - else - { - return false; - } - } - - /** - * Add a shutdown query. - * - * @param PDOStatement $query The query data. - * @param string $name An optional name for the query. - */ - function shutdown_query($query, $name="") - { - global $shutdown_queries; - if($name) - { - $shutdown_queries[$name] = $query; - } - else - { - $shutdown_queries[] = $query; - } - } - - /** - * Performs a simple select query. - * - * @param string $table The table name to be queried. - * @param string $fields Comma delimetered list of fields to be selected. - * @param string $conditions SQL formatted list of conditions to be matched. - * @param array $options List of options: group by, order by, order direction, limit, limit start. - * @return PDOStatement The query data. - */ - function simple_select($table, $fields="*", $conditions="", $options=array()) - { - $query = "SELECT ".$fields." FROM ".$this->table_prefix.$table; - - if($conditions != "") - { - $query .= " WHERE ".$conditions; - } - - if(isset($options['group_by'])) - { - $query .= " GROUP BY ".$options['group_by']; - } - - if(isset($options['order_by'])) - { - $query .= " ORDER BY ".$options['order_by']; - - if(isset($options['order_dir'])) - { - $query .= " ".strtoupper($options['order_dir']); - } - } - - if(isset($options['limit_start']) && isset($options['limit'])) - { - $query .= " LIMIT ".$options['limit_start'].", ".$options['limit']; - } - else if(isset($options['limit'])) - { - $query .= " LIMIT ".$options['limit']; - } - - return $this->query($query); - } - - /** - * Build an insert query from an array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of fields and their values. - * @return int|bool The insert ID if available or false if an error is found - */ - function insert_query($table, $array) - { - global $mybb; - - if(!is_array($array)) - { - return false; - } - - foreach($array as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $array[$field] = $value; - } - else - { - $array[$field] = $this->quote_val($value); - } - } - - $fields = implode(",", array_keys($array)); - $values = implode(",", $array); - $query = $this->write_query(" - INSERT - INTO {$this->table_prefix}{$table} (".$fields.") - VALUES (".$values.") - "); - $query->closeCursor(); - return $this->insert_id(); - } - - /** - * Build one query for multiple inserts from a multidimensional array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of inserts. - * @return void - */ - function insert_query_multiple($table, $array) - { - global $mybb; - - if(!is_array($array)) - { - return; - } - // Field names - $fields = array_keys($array[0]); - $fields = implode(",", $fields); - - $insert_rows = array(); - foreach($array as $values) - { - foreach($values as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $values[$field] = $value; - } - else - { - $values[$field] = $this->quote_val($value); - } - } - $insert_rows[] = "(".implode(",", $values).")"; - } - $insert_rows = implode(", ", $insert_rows); - - $query = $this->write_query(" - INSERT - INTO {$this->table_prefix}{$table} ({$fields}) - VALUES {$insert_rows} - "); - $query->closeCursor(); - } - - /** - * Build an update query from an array. - * - * @param string $table The table name to perform the query on. - * @param array $array An array of fields and their values. - * @param string $where An optional where clause for the query. - * @param string $limit An optional limit clause for the query. - * @param boolean $no_quote An option to quote incoming values of the array. - * @return PDOStatement The query data. - */ - function update_query($table, $array, $where="", $limit="", $no_quote=false) - { - global $mybb; - - if(!is_array($array)) - { - return false; - } - - $comma = ""; - $query = ""; - $quote = "'"; - - if($no_quote == true) - { - $quote = ""; - } - - foreach($array as $field => $value) - { - if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $query .= $comma.$field."=".$value; - } - else - { - $quoted_value = $this->quote_val($value, $quote); - - $query .= $comma.$field."={$quoted_value}"; - } - $comma = ', '; - } - - if(!empty($where)) - { - $query .= " WHERE $where"; - } - - $query = $this->query("UPDATE {$this->table_prefix}$table SET $query"); - $query->closeCursor(); - return $query; - } - - /** - * @param int|string $value - * @param string $quote - * - * @return int|string - */ - private function quote_val($value, $quote="'") - { - if(is_int($value)) - { - $quoted = $value; - } - else - { - $quoted = $quote . $value . $quote; - } - - return $quoted; - } - - /** - * Build a delete query. - * - * @param string $table The table name to perform the query on. - * @param string $where An optional where clause for the query. - * @param string $limit An optional limit clause for the query. - * @return PDOStatement The query data. - */ - function delete_query($table, $where="", $limit="") - { - $query = ""; - if(!empty($where)) - { - $query .= " WHERE $where"; - } - - $query = $this->query("DELETE FROM {$this->table_prefix}$table $query"); - $query->closeCursor(); - return $query; - } - - /** - * Escape a string - * - * @param string $string The string to be escaped. - * @return string The escaped string. - */ - function escape_string($string) - { - $string = $this->db->escape_string($string); - return $string; - } - - /** - * Serves no purposes except compatibility - * - * @param PDOStatement $query - * @return boolean Returns true on success, false on failure - */ - function free_result($query) - { - return true; - } - - /** - * Escape a string used within a like command. - * - * @param string $string The string to be escaped. - * @return string The escaped string. - */ - function escape_string_like($string) - { - return $this->escape_string(str_replace(array('%', '_') , array('\\%' , '\\_') , $string)); - } - - /** - * Gets the current version of SQLLite. - * - * @return string Version of MySQL. - */ - function get_version() - { - if($this->version) - { - return $this->version; - } - $this->version = $this->db->get_attribute("ATTR_SERVER_VERSION"); - - return $this->version; - } - - /** - * Optimizes a specific table. - * - * @param string $table The name of the table to be optimized. - */ - function optimize_table($table) - { - $query = $this->query("VACUUM ".$this->table_prefix.$table.""); - $query->closeCursor(); - } - - /** - * Analyzes a specific table. - * - * @param string $table The name of the table to be analyzed. - */ - function analyze_table($table) - { - $query = $this->query("ANALYZE ".$this->table_prefix.$table.""); - $query->closeCursor(); - } - - /** - * Show the "create table" command for a specific table. - * - * @param string $table The name of the table. - * @return string The SQLite command to create the specified table. - */ - function show_create_table($table) - { - $old_tbl_prefix = $this->table_prefix; - $this->set_table_prefix(""); - $query = $this->simple_select("sqlite_master", "sql", "type = 'table' AND name = '{$old_tbl_prefix}{$table}' ORDER BY type DESC, name"); - $this->set_table_prefix($old_tbl_prefix); - - $result = $this->fetch_field($query, 'sql'); - - $query->closeCursor(); - - return $result; - } - - /** - * Show the "show fields from" command for a specific table. - * - * @param string $table The name of the table. - * @return array Field info for that table - */ - function show_fields_from($table) - { - $old_tbl_prefix = $this->table_prefix; - $this->set_table_prefix(""); - $query = $this->simple_select("sqlite_master", "sql", "type = 'table' AND name = '{$old_tbl_prefix}{$table}'"); - $this->set_table_prefix($old_tbl_prefix); - $table = trim(preg_replace('#CREATE\s+TABLE\s+"?'.$this->table_prefix.$table.'"?#i', '', $this->fetch_field($query, "sql"))); - $query->closeCursor(); - - preg_match('#\((.*)\)#s', $table, $matches); - - $field_info = array(); - $table_cols = explode(',', trim($matches[1])); - foreach($table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - $column_name = preg_replace('/"?([^"]+)"?/', '\1', $entities[0]); - - $field_info[] = array('Extra' => $entities[1], 'Field' => $column_name); - } - - return $field_info; - } - - /** - * Returns whether or not the table contains a fulltext index. - * - * @param string $table The name of the table. - * @param string $index Optionally specify the name of the index. - * @return boolean True or false if the table has a fulltext index or not. - */ - function is_fulltext($table, $index="") - { - return false; - } - - /** - * Returns whether or not this database engine supports fulltext indexing. - * - * @param string $table The table to be checked. - * @return boolean True or false if supported or not. - */ - - function supports_fulltext($table) - { - return false; - } - - /** - * Returns whether or not this database engine supports boolean fulltext matching. - * - * @param string $table The table to be checked. - * @return boolean True or false if supported or not. - */ - function supports_fulltext_boolean($table) - { - return false; - } - - /** - * Creates a fulltext index on the specified column in the specified table with optional index name. - * - * @param string $table The name of the table. - * @param string $column Name of the column to be indexed. - * @param string $name The index name, optional. - * @return bool - */ - function create_fulltext_index($table, $column, $name="") - { - return false; - } - - /** - * Drop an index with the specified name from the specified table - * - * @param string $table The name of the table. - * @param string $name The name of the index. - */ - function drop_index($table, $name) - { - $query = $this->query("ALTER TABLE {$this->table_prefix}$table DROP INDEX $name"); - $query->closeCursor(); - } - - /** - * Checks to see if an index exists on a specified table - * - * @param string $table The name of the table. - * @param string $index The name of the index. - * @return bool Returns whether index exists - */ - function index_exists($table, $index) - { - return false; - } - - /** - * Drop an table with the specified table - * - * @param string $table The name of the table. - * @param boolean $hard hard drop - no checking - * @param boolean $table_prefix use table prefix - */ - function drop_table($table, $hard=false, $table_prefix=true) - { - if($table_prefix == false) - { - $table_prefix = ""; - } - else - { - $table_prefix = $this->table_prefix; - } - - if($hard == false) - { - if($this->table_exists($table)) - { - $query = $this->query('DROP TABLE '.$table_prefix.$table); - } - } - else - { - $query = $this->query('DROP TABLE '.$table_prefix.$table); - } - - if(isset($query)) - { - $query->closeCursor(); - } - } - - /** - * Renames a table - * - * @param string $old_table The old table name - * @param string $new_table the new table name - * @param boolean $table_prefix use table prefix - * @return PDOStatement - */ - function rename_table($old_table, $new_table, $table_prefix=true) - { - if($table_prefix == false) - { - $table_prefix = ""; - } - else - { - $table_prefix = $this->table_prefix; - } - - $query = $this->write_query("ALTER TABLE {$table_prefix}{$old_table} RENAME TO {$table_prefix}{$new_table}"); - $query->closeCursor(); - return $query; - } - - /** - * Replace contents of table with values - * - * @param string $table The table - * @param array $replacements The replacements - * @param mixed $default_field The default field(s) - * @return int|PDOStatement|bool Returns either the insert id (if a new row is inserted), the query resource (if a row is updated) or false on failure - */ - function replace_query($table, $replacements=array(), $default_field="") - { - global $mybb; - - $columns = ''; - $values = ''; - $comma = ''; - foreach($replacements as $column => $value) - { - $columns .= $comma.$column; - if(isset($mybb->binary_fields[$table][$column]) && $mybb->binary_fields[$table][$column]) - { - if($value[0] != 'X') // Not escaped? - { - $value = $this->escape_binary($value); - } - - $values .= $comma.$value; - } - else - { - $values .= $comma.$this->quote_val($value); - } - - $comma = ','; - } - - if(empty($columns) || empty($values)) - { - return false; - } - - if($default_field == "") - { - $query = $this->query("REPLACE INTO {$this->table_prefix}{$table} ({$columns}) VALUES({$values})"); - $query->closeCursor(); - return $query; - } - else - { - $update = false; - if(is_array($default_field) && !empty($default_field)) - { - $search_bit = array(); - foreach($default_field as $field) - { - $search_bit[] = "{$field} = '".$replacements[$field]."'"; - } - - $search_bit = implode(" AND ", $search_bit); - $query = $this->write_query("SELECT COUNT(".$default_field[0].") as count FROM {$this->table_prefix}{$table} WHERE {$search_bit} LIMIT 1"); - if($this->fetch_field($query, "count") == 1) - { - $update = true; - } - } - else - { - $query = $this->write_query("SELECT {$default_field} FROM {$this->table_prefix}{$table}"); - $search_bit = "{$default_field}='".$replacements[$default_field]."'"; - - while($column = $this->fetch_array($query)) - { - if($column[$default_field] == $replacements[$default_field]) - { - $update = true; - break; - } - } - } - - if($update === true) - { - return $this->update_query($table, $replacements, $search_bit); - } - else - { - return $this->insert_query($table, $replacements); - } - } - } - - /** - * Sets the table prefix used by the simple select, insert, update and delete functions - * - * @param string $prefix The new table prefix - */ - function set_table_prefix($prefix) - { - $this->table_prefix = $prefix; - } - - /** - * Fetched the total size of all mysql tables or a specific table - * - * @param string $table The table (optional) (ignored) - * @return integer the total size of all mysql tables or a specific table - */ - function fetch_size($table='') - { - global $config, $lang; - - $total = @filesize($config['database']['database']); - if(!$total || $table != '') - { - $total = $lang->na; - } - return $total; - } - - /** - * Perform an "Alter Table" query in SQLite < 3.2.0 - Code taken from http://code.jenseng.com/db/ - * - * @param string $table The table (optional) - * @param string $alterdefs - * @param string $fullquery - * @return bool True on success, false on failure - */ - function alter_table_parse($table, $alterdefs, $fullquery="") - { - if(!$fullquery) - { - $fullquery = " ... {$alterdefs}"; - } - - if(!defined("TIME_NOW")) - { - define("TIME_NOW", time()); - } - - if($alterdefs != '') - { - $result = $this->query("SELECT sql,name,type FROM sqlite_master WHERE tbl_name = '{$table}' ORDER BY type DESC"); - if($this->num_rows($result) > 0) - { - $row = $this->fetch_array($result); // Table sql - $result->closeCursor(); - $tmpname = 't'.TIME_NOW; - $origsql = trim(preg_replace("/[\s]+/", " ", str_replace(",", ", ", preg_replace("/[\(]/","( ", $row['sql'], 1)))); - $createtemptableSQL = 'CREATE TEMPORARY '.substr(trim(preg_replace("'".$table."'", $tmpname, $origsql, 1)), 6); - $defs = preg_split("/[,]+/", $alterdefs, -1, PREG_SPLIT_NO_EMPTY); - $prevword = $table; - $oldcols = preg_split("/[,]+/", substr(trim($createtemptableSQL), strpos(trim($createtemptableSQL), '(')+1), -1, PREG_SPLIT_NO_EMPTY); - $newcols = array(); - - for($i = 0; $i < sizeof($oldcols); $i++) - { - $colparts = preg_split("/[\s]+/", $oldcols[$i], -1, PREG_SPLIT_NO_EMPTY); - $oldcols[$i] = $colparts[0]; - $newcols[$colparts[0]] = $colparts[0]; - } - - $newcolumns = ''; - $oldcolumns = ''; - reset($newcols); - - foreach($newcols as $key => $val) - { - $newcolumns .= ($newcolumns ? ', ' : '').$val; - $oldcolumns .= ($oldcolumns ? ', ' : '').$key; - } - - $copytotempsql = 'INSERT INTO '.$tmpname.'('.$newcolumns.') SELECT '.$oldcolumns.' FROM '.$table; - $dropoldsql = 'DROP TABLE '.$table; - $createtesttableSQL = $createtemptableSQL; - - foreach($defs as $def) - { - $defparts = preg_split("/[\s]+/", $def, -1, PREG_SPLIT_NO_EMPTY); - $action = strtolower($defparts[0]); - - switch($action) - { - case 'change': - if(sizeof($defparts) <= 3) - { - $this->error($alterdefs, 'near "'.$defparts[0].($defparts[1] ? ' '.$defparts[1] : '').($defparts[2] ? ' '.$defparts[2] : '').'": syntax error', E_USER_WARNING); - return false; - } - - if($severpos = strpos($createtesttableSQL, ' '.$defparts[1].' ')) - { - if($newcols[$defparts[1]] != $defparts[1]) - { - $this->error($alterdefs, 'unknown column "'.$defparts[1].'" in "'.$table.'"'); - return false; - } - - $newcols[$defparts[1]] = $defparts[2]; - $nextcommapos = strpos($createtesttableSQL, ',', $severpos); - $insertval = ''; - - for($i = 2; $i < sizeof($defparts); $i++) - { - $insertval .= ' '.$defparts[$i]; - } - - if($nextcommapos) - { - $createtesttableSQL = substr($createtesttableSQL, 0, $severpos).$insertval.substr($createtesttableSQL, $nextcommapos); - } - else - { - $createtesttableSQL = substr($createtesttableSQL, 0, $severpos-(strpos($createtesttableSQL, ',') ? 0 : 1)).$insertval.')'; - } - } - else - { - $this->error($fullquery, 'unknown column "'.$defparts[1].'" in "'.$table.'"', E_USER_WARNING); - return false; - } - break; - case 'drop': - if(sizeof($defparts) < 2) - { - $this->error($fullquery, 'near "'.$defparts[0].($defparts[1] ? ' '.$defparts[1] : '').'": syntax error'); - return false; - } - - if($severpos = strpos($createtesttableSQL, ' '.$defparts[1].' ')) - { - $nextcommapos = strpos($createtesttableSQL, ',', $severpos); - - if($nextcommapos) - { - $createtesttableSQL = substr($createtesttableSQL, 0, $severpos).substr($createtesttableSQL, $nextcommapos + 1); - } - else - { - $createtesttableSQL = substr($createtesttableSQL, 0, $severpos-(strpos($createtesttableSQL, ',') ? 0 : 1) - 1).')'; - } - - unset($newcols[$defparts[1]]); - } - else - { - $this->error($fullquery, 'unknown column "'.$defparts[1].'" in "'.$table.'"'); - return false; - } - break; - default: - $this->error($fullquery, 'near "'.$prevword.'": syntax error'); - return false; - } - - $prevword = $defparts[sizeof($defparts)-1]; - } - - // This block of code generates a test table simply to verify that the columns specifed are valid in an sql statement - // This ensures that no reserved words are used as columns, for example - $this->query($createtesttableSQL); - - $droptempsql = 'DROP TABLE '.$tmpname; - $query = $this->query($droptempsql, 0); - if($query === false) - { - return false; - } - $query->closeCursor(); - // End block - - - $createnewtableSQL = 'CREATE '.substr(trim(preg_replace("'{$tmpname}'", $table, $createtesttableSQL, 1)), 17); - $newcolumns = ''; - $oldcolumns = ''; - reset($newcols); - - foreach($newcols as $key => $val) - { - $newcolumns .= ($newcolumns ? ', ' : '').$val; - $oldcolumns .= ($oldcolumns ? ', ' : '').$key; - } - - $copytonewsql = 'INSERT INTO '.$table.'('.$newcolumns.') SELECT '.$oldcolumns.' FROM '.$tmpname; - - - $this->query($createtemptableSQL); // Create temp table - $query = $this->query($copytotempsql); // Copy to table - $query->closeCursor(); - $query = $this->query($dropoldsql); // Drop old table - $query->closeCursor(); - - $this->query($createnewtableSQL); // Recreate original table - $query = $this->query($copytonewsql); // Copy back to original table - $query->closeCursor(); - $query = $this->query($droptempsql); // Drop temp table - $query->closeCursor(); - } - else - { - $this->error($fullquery, 'no such table: '.$table); - return false; - } - } - return true; - } - - /** - * Drops a column - * - * @param string $table The table - * @param string $column The column name - * @return PDOStatement - */ - function drop_column($table, $column) - { - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} DROP {$column}"); - } - - /** - * Adds a column - * - * @param string $table The table - * @param string $column The column name - * @param string $definition the new column definition - * @return PDOStatement - */ - function add_column($table, $column, $definition) - { - $query = $this->write_query("ALTER TABLE {$this->table_prefix}{$table} ADD {$column} {$definition}"); - $query->closeCursor(); - return $query; - } - - /** - * Modifies a column - * - * @param string $table The table - * @param string $column The column name - * @param string $new_definition the new column definition - */ - function modify_column($table, $column, $new_definition) - { - // We use a rename query as both need to duplicate the table etc... - $this->rename_column($table, $column, $column, $new_definition); - } - - /** - * Renames a column - * - * @param string $table The table - * @param string $old_column The old column name - * @param string $new_column the new column name - * @param string $new_definition the new column definition - * @return PDOStatement - */ - function rename_column($table, $old_column, $new_column, $new_definition) - { - // This will trigger the "alter_table_parse" function which will copy the table and rename the column - return $this->write_query("ALTER TABLE {$this->table_prefix}{$table} CHANGE {$old_column} {$new_column} {$new_definition}"); - } - - /** - * Fetch a list of database character sets this DBMS supports - * - * @return array|bool Array of supported character sets with array key being the name, array value being display name. False if unsupported - */ - function fetch_db_charsets() - { - return false; - } - - /** - * Fetch a database collation for a particular database character set - * - * @param string $charset The database character set - * @return string|bool The matching database collation, false if unsupported - */ - function fetch_charset_collation($charset) - { - return false; - } - - /** - * Fetch a character set/collation string for use with CREATE TABLE statements. Uses current DB encoding - * - * @return string The built string, empty if unsupported - */ - function build_create_table_collation() - { - return ''; - } - - /** - * Time how long it takes for a particular piece of code to run. Place calls above & below the block of code. - * - * @deprecated - */ - function get_execution_time() - { - return get_execution_time(); - } - - /** - * Binary database fields require special attention. - * - * @param string $string Binary value - * @return string Encoded binary value - */ - function escape_binary($string) - { - return "X'".$this->escape_string(bin2hex($string))."'"; - } - - /** - * Unescape binary data. - * - * @param string $string Binary value - * @return string Encoded binary value - */ - function unescape_binary($string) - { - // Nothing to do - return $string; - } -} - diff --git a/html/forums/inc/functions.php b/html/forums/inc/functions.php deleted file mode 100644 index 6305b67..0000000 --- a/html/forums/inc/functions.php +++ /dev/null @@ -1,8676 +0,0 @@ -stop()); - $contents = $plugins->run_hooks("pre_output_page", $contents); - - if($mybb->usergroup['cancp'] == 1 || $mybb->dev_mode == 1) - { - if($mybb->settings['extraadmininfo'] != 0) - { - $phptime = $maintimer->totaltime - $db->query_time; - $query_time = $db->query_time; - - if($maintimer->totaltime > 0) - { - $percentphp = number_format((($phptime/$maintimer->totaltime) * 100), 2); - $percentsql = number_format((($query_time/$maintimer->totaltime) * 100), 2); - } - else - { - // if we've got a super fast script... all we can do is assume something - $percentphp = 0; - $percentsql = 0; - } - - $serverload = get_server_load(); - - if(my_strpos(getenv("REQUEST_URI"), "?")) - { - $debuglink = htmlspecialchars_uni(getenv("REQUEST_URI")) . "&debug=1"; - } - else - { - $debuglink = htmlspecialchars_uni(getenv("REQUEST_URI")) . "?debug=1"; - } - - $memory_usage = get_memory_usage(); - - if($memory_usage) - { - $memory_usage = $lang->sprintf($lang->debug_memory_usage, get_friendly_size($memory_usage)); - } - else - { - $memory_usage = ''; - } - // MySQLi is still MySQL, so present it that way to the user - $database_server = $db->short_title; - - if($database_server == 'MySQLi') - { - $database_server = 'MySQL'; - } - $generated_in = $lang->sprintf($lang->debug_generated_in, $totaltime); - $debug_weight = $lang->sprintf($lang->debug_weight, $percentphp, $percentsql, $database_server); - $sql_queries = $lang->sprintf($lang->debug_sql_queries, $db->query_count); - $server_load = $lang->sprintf($lang->debug_server_load, $serverload); - - eval("\$debugstuff = \"".$templates->get("debug_summary")."\";"); - $contents = str_replace("", $debugstuff, $contents); - } - - if($mybb->debug_mode == true) - { - debug_page(); - } - } - - $contents = str_replace("", "", $contents); - - if($mybb->settings['gzipoutput'] == 1) - { - $contents = gzip_encode($contents, $mybb->settings['gziplevel']); - } - - @header("Content-type: text/html; charset={$lang->settings['charset']}"); - - echo $contents; - - $plugins->run_hooks("post_output_page"); -} - -/** - * Adds a function or class to the list of code to run on shutdown. - * - * @param string|array $name The name of the function. - * @param mixed $arguments Either an array of arguments for the function or one argument - * @return boolean True if function exists, otherwise false. - */ -function add_shutdown($name, $arguments=array()) -{ - global $shutdown_functions; - - if(!is_array($shutdown_functions)) - { - $shutdown_functions = array(); - } - - if(!is_array($arguments)) - { - $arguments = array($arguments); - } - - if(is_array($name) && method_exists($name[0], $name[1])) - { - $shutdown_functions[] = array('function' => $name, 'arguments' => $arguments); - return true; - } - else if(!is_array($name) && function_exists($name)) - { - $shutdown_functions[] = array('function' => $name, 'arguments' => $arguments); - return true; - } - - return false; -} - -/** - * Runs the shutdown items after the page has been sent to the browser. - * - */ -function run_shutdown() -{ - global $config, $db, $cache, $plugins, $error_handler, $shutdown_functions, $shutdown_queries, $done_shutdown, $mybb; - - if($done_shutdown == true || !$config || (isset($error_handler) && $error_handler->has_errors)) - { - return; - } - - if(empty($shutdown_queries) && empty($shutdown_functions)) - { - // Nothing to do - return; - } - - // Missing the core? Build - if(!is_object($mybb)) - { - require_once MYBB_ROOT."inc/class_core.php"; - $mybb = new MyBB; - - // Load the settings - require MYBB_ROOT."inc/settings.php"; - $mybb->settings = &$settings; - } - - // If our DB has been deconstructed already (bad PHP 5.2.0), reconstruct - if(!is_object($db)) - { - if(!isset($config) || empty($config['database']['type'])) - { - require MYBB_ROOT."inc/config.php"; - } - - if(isset($config)) - { - // Load DB interface - require_once MYBB_ROOT."inc/db_base.php"; - - require_once MYBB_ROOT."inc/db_".$config['database']['type'].".php"; - switch($config['database']['type']) - { - case "sqlite": - $db = new DB_SQLite; - break; - case "pgsql": - $db = new DB_PgSQL; - break; - case "mysqli": - $db = new DB_MySQLi; - break; - default: - $db = new DB_MySQL; - } - - $db->connect($config['database']); - if(!defined("TABLE_PREFIX")) - { - define("TABLE_PREFIX", $config['database']['table_prefix']); - } - $db->set_table_prefix(TABLE_PREFIX); - } - } - - // Cache object deconstructed? reconstruct - if(!is_object($cache)) - { - require_once MYBB_ROOT."inc/class_datacache.php"; - $cache = new datacache; - $cache->cache(); - } - - // And finally.. plugins - if(!is_object($plugins) && !defined("NO_PLUGINS") && !($mybb->settings['no_plugins'] == 1)) - { - require_once MYBB_ROOT."inc/class_plugins.php"; - $plugins = new pluginSystem; - $plugins->load(); - } - - // We have some shutdown queries needing to be run - if(is_array($shutdown_queries)) - { - // Loop through and run them all - foreach($shutdown_queries as $query) - { - $db->query($query); - } - } - - // Run any shutdown functions if we have them - if(is_array($shutdown_functions)) - { - foreach($shutdown_functions as $function) - { - call_user_func_array($function['function'], $function['arguments']); - } - } - - $done_shutdown = true; -} - -/** - * Sends a specified amount of messages from the mail queue - * - * @param int $count The number of messages to send (Defaults to 10) - */ -function send_mail_queue($count=10) -{ - global $db, $cache, $plugins; - - $plugins->run_hooks("send_mail_queue_start"); - - // Check to see if the mail queue has messages needing to be sent - $mailcache = $cache->read("mailqueue"); - if($mailcache['queue_size'] > 0 && ($mailcache['locked'] == 0 || $mailcache['locked'] < TIME_NOW-300)) - { - // Lock the queue so no other messages can be sent whilst these are (for popular boards) - $cache->update_mailqueue(0, TIME_NOW); - - // Fetch emails for this page view - and send them - $query = $db->simple_select("mailqueue", "*", "", array("order_by" => "mid", "order_dir" => "asc", "limit_start" => 0, "limit" => $count)); - - while($email = $db->fetch_array($query)) - { - // Delete the message from the queue - $db->delete_query("mailqueue", "mid='{$email['mid']}'"); - - if($db->affected_rows() == 1) - { - my_mail($email['mailto'], $email['subject'], $email['message'], $email['mailfrom'], "", $email['headers'], true); - } - } - // Update the mailqueue cache and remove the lock - $cache->update_mailqueue(TIME_NOW, 0); - } - - $plugins->run_hooks("send_mail_queue_end"); -} - -/** - * Parses the contents of a page before outputting it. - * - * @param string $contents The contents of the page. - * @return string The parsed page. - */ -function parse_page($contents) -{ - global $lang, $theme, $mybb, $htmldoctype, $archive_url, $error_handler; - - $contents = str_replace('', build_breadcrumb(), $contents); - $contents = str_replace('', $archive_url, $contents); - - if($htmldoctype) - { - $contents = $htmldoctype.$contents; - } - else - { - $contents = "\n".$contents; - } - - $contents = str_replace("settings['rtl'] == 1) - { - $contents = str_replace("settings['htmllang']) - { - $contents = str_replace("settings['htmllang']."\" lang=\"".$lang->settings['htmllang']."\"", $contents); - } - - if($error_handler->warnings) - { - $contents = str_replace("", "\n".$error_handler->show_warnings(), $contents); - } - - return $contents; -} - -/** - * Turn a unix timestamp in to a "friendly" date/time format for the user. - * - * @param string $format A date format according to PHP's date structure. - * @param int $stamp The unix timestamp the date should be generated for. - * @param int|string $offset The offset in hours that should be applied to times. (timezones) Or an empty string to determine that automatically - * @param int $ty Whether or not to use today/yesterday formatting. - * @param boolean $adodb Whether or not to use the adodb time class for < 1970 or > 2038 times - * @return string The formatted timestamp. - */ -function my_date($format, $stamp=0, $offset="", $ty=1, $adodb=false) -{ - global $mybb, $lang, $mybbadmin, $plugins; - - // If the stamp isn't set, use TIME_NOW - if(empty($stamp)) - { - $stamp = TIME_NOW; - } - - if(!$offset && $offset != '0') - { - if(isset($mybb->user['uid']) && $mybb->user['uid'] != 0 && array_key_exists("timezone", $mybb->user)) - { - $offset = (float)$mybb->user['timezone']; - $dstcorrection = $mybb->user['dst']; - } - elseif(defined("IN_ADMINCP")) - { - $offset = (float)$mybbadmin['timezone']; - $dstcorrection = $mybbadmin['dst']; - } - else - { - $offset = (float)$mybb->settings['timezoneoffset']; - $dstcorrection = $mybb->settings['dstcorrection']; - } - - // If DST correction is enabled, add an additional hour to the timezone. - if($dstcorrection == 1) - { - ++$offset; - if(my_substr($offset, 0, 1) != "-") - { - $offset = "+".$offset; - } - } - } - - if($offset == "-") - { - $offset = 0; - } - - // Using ADOdb? - if($adodb == true && !function_exists('adodb_date')) - { - $adodb = false; - } - - $todaysdate = $yesterdaysdate = ''; - if($ty && ($format == $mybb->settings['dateformat'] || $format == 'relative')) - { - $_stamp = TIME_NOW; - if($adodb == true) - { - $date = adodb_date($mybb->settings['dateformat'], $stamp + ($offset * 3600)); - $todaysdate = adodb_date($mybb->settings['dateformat'], $_stamp + ($offset * 3600)); - $yesterdaysdate = adodb_date($mybb->settings['dateformat'], ($_stamp - 86400) + ($offset * 3600)); - } - else - { - $date = gmdate($mybb->settings['dateformat'], $stamp + ($offset * 3600)); - $todaysdate = gmdate($mybb->settings['dateformat'], $_stamp + ($offset * 3600)); - $yesterdaysdate = gmdate($mybb->settings['dateformat'], ($_stamp - 86400) + ($offset * 3600)); - } - } - - if($format == 'relative') - { - // Relative formats both date and time - $real_date = $real_time = ''; - if($adodb == true) - { - $real_date = adodb_date($mybb->settings['dateformat'], $stamp + ($offset * 3600)); - $real_time = $mybb->settings['datetimesep']; - $real_time .= adodb_date($mybb->settings['timeformat'], $stamp + ($offset * 3600)); - } - else - { - $real_date = gmdate($mybb->settings['dateformat'], $stamp + ($offset * 3600)); - $real_time = $mybb->settings['datetimesep']; - $real_time .= gmdate($mybb->settings['timeformat'], $stamp + ($offset * 3600)); - } - - if($ty != 2 && abs(TIME_NOW - $stamp) < 3600) - { - $diff = TIME_NOW - $stamp; - $relative = array('prefix' => '', 'minute' => 0, 'plural' => $lang->rel_minutes_plural, 'suffix' => $lang->rel_ago); - - if($diff < 0) - { - $diff = abs($diff); - $relative['suffix'] = ''; - $relative['prefix'] = $lang->rel_in; - } - - $relative['minute'] = floor($diff / 60); - - if($relative['minute'] <= 1) - { - $relative['minute'] = 1; - $relative['plural'] = $lang->rel_minutes_single; - } - - if($diff <= 60) - { - // Less than a minute - $relative['prefix'] = $lang->rel_less_than; - } - - $date = $lang->sprintf($lang->rel_time, $relative['prefix'], $relative['minute'], $relative['plural'], $relative['suffix'], $real_date, $real_time); - } - elseif($ty != 2 && abs(TIME_NOW - $stamp) < 43200) - { - $diff = TIME_NOW - $stamp; - $relative = array('prefix' => '', 'hour' => 0, 'plural' => $lang->rel_hours_plural, 'suffix' => $lang->rel_ago); - - if($diff < 0) - { - $diff = abs($diff); - $relative['suffix'] = ''; - $relative['prefix'] = $lang->rel_in; - } - - $relative['hour'] = floor($diff / 3600); - - if($relative['hour'] <= 1) - { - $relative['hour'] = 1; - $relative['plural'] = $lang->rel_hours_single; - } - - $date = $lang->sprintf($lang->rel_time, $relative['prefix'], $relative['hour'], $relative['plural'], $relative['suffix'], $real_date, $real_time); - } - else - { - if($ty) - { - if($todaysdate == $date) - { - $date = $lang->sprintf($lang->today, $real_date); - } - else if($yesterdaysdate == $date) - { - $date = $lang->sprintf($lang->yesterday, $real_date); - } - } - - $date .= $mybb->settings['datetimesep']; - if($adodb == true) - { - $date .= adodb_date($mybb->settings['timeformat'], $stamp + ($offset * 3600)); - } - else - { - $date .= gmdate($mybb->settings['timeformat'], $stamp + ($offset * 3600)); - } - } - } - else - { - if($ty && $format == $mybb->settings['dateformat']) - { - if($todaysdate == $date) - { - $date = $lang->sprintf($lang->today, $real_date); - } - else if($yesterdaysdate == $date) - { - $date = $lang->sprintf($lang->yesterday, $real_date); - } - } - else - { - if($adodb == true) - { - $date = adodb_date($format, $stamp + ($offset * 3600)); - } - else - { - $date = gmdate($format, $stamp + ($offset * 3600)); - } - } - } - - if(is_object($plugins)) - { - $date = $plugins->run_hooks("my_date", $date); - } - - return $date; -} - -/** - * Sends an email using PHP's mail function, formatting it appropriately. - * - * @param string $to Address the email should be addressed to. - * @param string $subject The subject of the email being sent. - * @param string $message The message being sent. - * @param string $from The from address of the email, if blank, the board name will be used. - * @param string $charset The chracter set being used to send this email. - * @param string $headers - * @param boolean $keep_alive Do we wish to keep the connection to the mail server alive to send more than one message (SMTP only) - * @param string $format The format of the email to be sent (text or html). text is default - * @param string $message_text The text message of the email if being sent in html format, for email clients that don't support html - * @param string $return_email The email address to return to. Defaults to admin return email address. - * @return bool - */ -function my_mail($to, $subject, $message, $from="", $charset="", $headers="", $keep_alive=false, $format="text", $message_text="", $return_email="") -{ - global $mybb; - static $mail; - - // Does our object not exist? Create it - if(!is_object($mail)) - { - require_once MYBB_ROOT."inc/class_mailhandler.php"; - - if($mybb->settings['mail_handler'] == 'smtp') - { - require_once MYBB_ROOT."inc/mailhandlers/smtp.php"; - $mail = new SmtpMail(); - } - else - { - require_once MYBB_ROOT."inc/mailhandlers/php.php"; - $mail = new PhpMail(); - } - } - - // Using SMTP based mail - if($mybb->settings['mail_handler'] == 'smtp') - { - if($keep_alive == true) - { - $mail->keep_alive = true; - } - } - - // Using PHP based mail() - else - { - if($mybb->settings['mail_parameters'] != '') - { - $mail->additional_parameters = $mybb->settings['mail_parameters']; - } - } - - // Build and send - $mail->build_message($to, $subject, $message, $from, $charset, $headers, $format, $message_text, $return_email); - return $mail->send(); -} - -/** - * Generates a unique code for POST requests to prevent XSS/CSRF attacks - * - * @return string The generated code - */ -function generate_post_check() -{ - global $mybb, $session; - if($mybb->user['uid']) - { - return md5($mybb->user['loginkey'].$mybb->user['salt'].$mybb->user['regdate']); - } - // Guests get a special string - else - { - return md5($session->useragent.$mybb->config['database']['username'].$mybb->settings['internal']['encryption_key']); - } -} - -/** - * Verifies a POST check code is valid, if not shows an error (silently returns false on silent parameter) - * - * @param string $code The incoming POST check code - * @param boolean $silent Silent mode or not (silent mode will not show the error to the user but returns false) - * @return bool - */ -function verify_post_check($code, $silent=false) -{ - global $lang; - if(generate_post_check() !== $code) - { - if($silent == true) - { - return false; - } - else - { - if(defined("IN_ADMINCP")) - { - return false; - } - else - { - error($lang->invalid_post_code); - } - } - } - else - { - return true; - } -} - -/** - * Return a parent list for the specified forum. - * - * @param int $fid The forum id to get the parent list for. - * @return string The comma-separated parent list. - */ -function get_parent_list($fid) -{ - global $forum_cache; - static $forumarraycache; - - if($forumarraycache[$fid]) - { - return $forumarraycache[$fid]['parentlist']; - } - elseif($forum_cache[$fid]) - { - return $forum_cache[$fid]['parentlist']; - } - else - { - cache_forums(); - return $forum_cache[$fid]['parentlist']; - } -} - -/** - * Build a parent list of a specific forum, suitable for querying - * - * @param int $fid The forum ID - * @param string $column The column name to add to the query - * @param string $joiner The joiner for each forum for querying (OR | AND | etc) - * @param string $parentlist The parent list of the forum - if you have it - * @return string The query string generated - */ -function build_parent_list($fid, $column="fid", $joiner="OR", $parentlist="") -{ - if(!$parentlist) - { - $parentlist = get_parent_list($fid); - } - - $parentsexploded = explode(",", $parentlist); - $builtlist = "("; - $sep = ''; - - foreach($parentsexploded as $key => $val) - { - $builtlist .= "$sep$column='$val'"; - $sep = " $joiner "; - } - - $builtlist .= ")"; - - return $builtlist; -} - -/** - * Load the forum cache in to memory - * - * @param boolean $force True to force a reload of the cache - * @return array The forum cache - */ -function cache_forums($force=false) -{ - global $forum_cache, $cache; - - if($force == true) - { - $forum_cache = $cache->read("forums", 1); - return $forum_cache; - } - - if(!$forum_cache) - { - $forum_cache = $cache->read("forums"); - if(!$forum_cache) - { - $cache->update_forums(); - $forum_cache = $cache->read("forums", 1); - } - } - return $forum_cache; -} - -/** - * Generate an array of all child and descendant forums for a specific forum. - * - * @param int $fid The forum ID - * @return Array of descendants - */ -function get_child_list($fid) -{ - static $forums_by_parent; - - $forums = array(); - if(!is_array($forums_by_parent)) - { - $forum_cache = cache_forums(); - foreach($forum_cache as $forum) - { - if($forum['active'] != 0) - { - $forums_by_parent[$forum['pid']][$forum['fid']] = $forum; - } - } - } - if(!is_array($forums_by_parent[$fid])) - { - return $forums; - } - - foreach($forums_by_parent[$fid] as $forum) - { - $forums[] = $forum['fid']; - $children = get_child_list($forum['fid']); - if(is_array($children)) - { - $forums = array_merge($forums, $children); - } - } - return $forums; -} - -/** - * Produce a friendly error message page - * - * @param string $error The error message to be shown - * @param string $title The title of the message shown in the title of the page and the error table - */ -function error($error="", $title="") -{ - global $header, $footer, $theme, $headerinclude, $db, $templates, $lang, $mybb, $plugins; - - $error = $plugins->run_hooks("error", $error); - if(!$error) - { - $error = $lang->unknown_error; - } - - // AJAX error message? - if($mybb->get_input('ajax', MyBB::INPUT_INT)) - { - // Send our headers. - @header("Content-type: application/json; charset={$lang->settings['charset']}"); - echo json_encode(array("errors" => array($error))); - exit; - } - - if(!$title) - { - $title = $mybb->settings['bbname']; - } - - $timenow = my_date('relative', TIME_NOW); - reset_breadcrumb(); - add_breadcrumb($lang->error); - - eval("\$errorpage = \"".$templates->get("error")."\";"); - output_page($errorpage); - - exit; -} - -/** - * Produce an error message for displaying inline on a page - * - * @param array $errors Array of errors to be shown - * @param string $title The title of the error message - * @param array $json_data JSON data to be encoded (we may want to send more data; e.g. newreply.php uses this for CAPTCHA) - * @return string The inline error HTML - */ -function inline_error($errors, $title="", $json_data=array()) -{ - global $theme, $mybb, $db, $lang, $templates; - - if(!$title) - { - $title = $lang->please_correct_errors; - } - - if(!is_array($errors)) - { - $errors = array($errors); - } - - // AJAX error message? - if($mybb->get_input('ajax', MyBB::INPUT_INT)) - { - // Send our headers. - @header("Content-type: application/json; charset={$lang->settings['charset']}"); - - if(empty($json_data)) - { - echo json_encode(array("errors" => $errors)); - } - else - { - echo json_encode(array_merge(array("errors" => $errors), $json_data)); - } - exit; - } - - $errorlist = ''; - - foreach($errors as $error) - { - $errorlist .= "
  • ".$error."
  • \n"; - } - - eval("\$errors = \"".$templates->get("error_inline")."\";"); - - return $errors; -} - -/** - * Presents the user with a "no permission" page - */ -function error_no_permission() -{ - global $mybb, $theme, $templates, $db, $lang, $plugins, $session; - - $time = TIME_NOW; - $plugins->run_hooks("no_permission"); - - $noperm_array = array ( - "nopermission" => '1', - "location1" => 0, - "location2" => 0 - ); - - $db->update_query("sessions", $noperm_array, "sid='{$session->sid}'"); - - if($mybb->get_input('ajax', MyBB::INPUT_INT)) - { - // Send our headers. - header("Content-type: application/json; charset={$lang->settings['charset']}"); - echo json_encode(array("errors" => array($lang->error_nopermission_user_ajax))); - exit; - } - - if($mybb->user['uid']) - { - $lang->error_nopermission_user_username = $lang->sprintf($lang->error_nopermission_user_username, htmlspecialchars_uni($mybb->user['username'])); - eval("\$errorpage = \"".$templates->get("error_nopermission_loggedin")."\";"); - } - else - { - // Redirect to where the user came from - $redirect_url = $_SERVER['PHP_SELF']; - if($_SERVER['QUERY_STRING']) - { - $redirect_url .= '?'.$_SERVER['QUERY_STRING']; - } - - $redirect_url = htmlspecialchars_uni($redirect_url); - - switch($mybb->settings['username_method']) - { - case 0: - $lang_username = $lang->username; - break; - case 1: - $lang_username = $lang->username1; - break; - case 2: - $lang_username = $lang->username2; - break; - default: - $lang_username = $lang->username; - break; - } - eval("\$errorpage = \"".$templates->get("error_nopermission")."\";"); - } - - error($errorpage); -} - -/** - * Redirect the user to a given URL with a given message - * - * @param string $url The URL to redirect the user to - * @param string $message The redirection message to be shown - * @param string $title The title of the redirection page - * @param boolean $force_redirect Force the redirect page regardless of settings - */ -function redirect($url, $message="", $title="", $force_redirect=false) -{ - global $header, $footer, $mybb, $theme, $headerinclude, $templates, $lang, $plugins; - - $redirect_args = array('url' => &$url, 'message' => &$message, 'title' => &$title); - - $plugins->run_hooks("redirect", $redirect_args); - - if($mybb->get_input('ajax', MyBB::INPUT_INT)) - { - // Send our headers. - //@header("Content-type: text/html; charset={$lang->settings['charset']}"); - $data = "\n"; - //exit; - - @header("Content-type: application/json; charset={$lang->settings['charset']}"); - echo json_encode(array("data" => $data)); - exit; - } - - if(!$message) - { - $message = $lang->redirect; - } - - $time = TIME_NOW; - $timenow = my_date('relative', $time); - - if(!$title) - { - $title = $mybb->settings['bbname']; - } - - // Show redirects only if both ACP and UCP settings are enabled, or ACP is enabled, and user is a guest, or they are forced. - if($force_redirect == true || ($mybb->settings['redirects'] == 1 && ($mybb->user['showredirect'] == 1 || !$mybb->user['uid']))) - { - $url = str_replace("&", "&", $url); - $url = htmlspecialchars_uni($url); - - eval("\$redirectpage = \"".$templates->get("redirect")."\";"); - output_page($redirectpage); - } - else - { - $url = htmlspecialchars_decode($url); - $url = str_replace(array("\n","\r",";"), "", $url); - - run_shutdown(); - - if(!my_validate_url($url, true, true)) - { - header("Location: {$mybb->settings['bburl']}/{$url}"); - } - else - { - header("Location: {$url}"); - } - } - - exit; -} - -/** - * Generate a listing of page - pagination - * - * @param int $count The number of items - * @param int $perpage The number of items to be shown per page - * @param int $page The current page number - * @param string $url The URL to have page numbers tacked on to (If {page} is specified, the value will be replaced with the page #) - * @param boolean $breadcrumb Whether or not the multipage is being shown in the navigation breadcrumb - * @return string The generated pagination - */ -function multipage($count, $perpage, $page, $url, $breadcrumb=false) -{ - global $theme, $templates, $lang, $mybb; - - if($count <= $perpage) - { - return ''; - } - - $url = str_replace("&", "&", $url); - $url = htmlspecialchars_uni($url); - - $pages = ceil($count / $perpage); - - $prevpage = ''; - if($page > 1) - { - $prev = $page-1; - $page_url = fetch_page_url($url, $prev); - eval("\$prevpage = \"".$templates->get("multipage_prevpage")."\";"); - } - - // Maximum number of "page bits" to show - if(!$mybb->settings['maxmultipagelinks']) - { - $mybb->settings['maxmultipagelinks'] = 5; - } - - $from = $page-floor($mybb->settings['maxmultipagelinks']/2); - $to = $page+floor($mybb->settings['maxmultipagelinks']/2); - - if($from <= 0) - { - $from = 1; - $to = $from+$mybb->settings['maxmultipagelinks']-1; - } - - if($to > $pages) - { - $to = $pages; - $from = $pages-$mybb->settings['maxmultipagelinks']+1; - if($from <= 0) - { - $from = 1; - } - } - - if($to == 0) - { - $to = $pages; - } - - $start = ''; - if($from > 1) - { - if($from-1 == 1) - { - $lang->multipage_link_start = ''; - } - - $page_url = fetch_page_url($url, 1); - eval("\$start = \"".$templates->get("multipage_start")."\";"); - } - - $mppage = ''; - for($i = $from; $i <= $to; ++$i) - { - $page_url = fetch_page_url($url, $i); - if($page == $i) - { - if($breadcrumb == true) - { - eval("\$mppage .= \"".$templates->get("multipage_page_link_current")."\";"); - } - else - { - eval("\$mppage .= \"".$templates->get("multipage_page_current")."\";"); - } - } - else - { - eval("\$mppage .= \"".$templates->get("multipage_page")."\";"); - } - } - - $end = ''; - if($to < $pages) - { - if($to+1 == $pages) - { - $lang->multipage_link_end = ''; - } - - $page_url = fetch_page_url($url, $pages); - eval("\$end = \"".$templates->get("multipage_end")."\";"); - } - - $nextpage = ''; - if($page < $pages) - { - $next = $page+1; - $page_url = fetch_page_url($url, $next); - eval("\$nextpage = \"".$templates->get("multipage_nextpage")."\";"); - } - - $jumptopage = ''; - if($pages > ($mybb->settings['maxmultipagelinks']+1) && $mybb->settings['jumptopagemultipage'] == 1) - { - // When the second parameter is set to 1, fetch_page_url thinks it's the first page and removes it from the URL as it's unnecessary - $jump_url = fetch_page_url($url, 1); - eval("\$jumptopage = \"".$templates->get("multipage_jump_page")."\";"); - } - - $lang->multipage_pages = $lang->sprintf($lang->multipage_pages, $pages); - - if($breadcrumb == true) - { - eval("\$multipage = \"".$templates->get("multipage_breadcrumb")."\";"); - } - else - { - eval("\$multipage = \"".$templates->get("multipage")."\";"); - } - - return $multipage; -} - -/** - * Generate a page URL for use by the multipage function - * - * @param string $url The URL being passed - * @param int $page The page number - * @return string - */ -function fetch_page_url($url, $page) -{ - if($page <= 1) - { - $find = array( - "-page-{page}", - "&page={page}", - "{page}" - ); - - // Remove "Page 1" to the defacto URL - $url = str_replace($find, array("", "", $page), $url); - return $url; - } - else if(strpos($url, "{page}") === false) - { - // If no page identifier is specified we tack it on to the end of the URL - if(strpos($url, "?") === false) - { - $url .= "?"; - } - else - { - $url .= "&"; - } - - $url .= "page=$page"; - } - else - { - $url = str_replace("{page}", $page, $url); - } - - return $url; -} - -/** - * Fetch the permissions for a specific user - * - * @param int $uid The user ID - * @return array Array of user permissions for the specified user - */ -function user_permissions($uid=0) -{ - global $mybb, $cache, $groupscache, $user_cache; - - // If no user id is specified, assume it is the current user - if($uid == 0) - { - $uid = $mybb->user['uid']; - } - - // User id does not match current user, fetch permissions - if($uid != $mybb->user['uid']) - { - // We've already cached permissions for this user, return them. - if($user_cache[$uid]['permissions']) - { - return $user_cache[$uid]['permissions']; - } - - // This user was not already cached, fetch their user information. - if(!$user_cache[$uid]) - { - $user_cache[$uid] = get_user($uid); - } - - // Collect group permissions. - $gid = $user_cache[$uid]['usergroup'].",".$user_cache[$uid]['additionalgroups']; - $groupperms = usergroup_permissions($gid); - - // Store group permissions in user cache. - $user_cache[$uid]['permissions'] = $groupperms; - return $groupperms; - } - // This user is the current user, return their permissions - else - { - return $mybb->usergroup; - } -} - -/** - * Fetch the usergroup permissions for a specific group or series of groups combined - * - * @param int|string $gid A list of groups (Can be a single integer, or a list of groups separated by a comma) - * @return array Array of permissions generated for the groups, containing also a list of comma-separated checked groups under 'all_usergroups' index - */ -function usergroup_permissions($gid=0) -{ - global $cache, $groupscache, $grouppermignore, $groupzerogreater; - - if(!is_array($groupscache)) - { - $groupscache = $cache->read("usergroups"); - } - - $groups = explode(",", $gid); - - if(count($groups) == 1) - { - $groupscache[$gid]['all_usergroups'] = $gid; - return $groupscache[$gid]; - } - - $usergroup = array(); - $usergroup['all_usergroups'] = $gid; - - foreach($groups as $gid) - { - if(trim($gid) == "" || empty($groupscache[$gid])) - { - continue; - } - - foreach($groupscache[$gid] as $perm => $access) - { - if(!in_array($perm, $grouppermignore)) - { - if(isset($usergroup[$perm])) - { - $permbit = $usergroup[$perm]; - } - else - { - $permbit = ""; - } - - // 0 represents unlimited for numerical group permissions (i.e. private message limit) so take that into account. - if(in_array($perm, $groupzerogreater) && ($access == 0 || $permbit === 0)) - { - $usergroup[$perm] = 0; - continue; - } - - if($access > $permbit || ($access == "yes" && $permbit == "no") || !$permbit) // Keep yes/no for compatibility? - { - $usergroup[$perm] = $access; - } - } - } - } - - return $usergroup; -} - -/** - * Fetch the display group properties for a specific display group - * - * @param int $gid The group ID to fetch the display properties for - * @return array Array of display properties for the group - */ -function usergroup_displaygroup($gid) -{ - global $cache, $groupscache, $displaygroupfields; - - if(!is_array($groupscache)) - { - $groupscache = $cache->read("usergroups"); - } - - $displaygroup = array(); - $group = $groupscache[$gid]; - - foreach($displaygroupfields as $field) - { - $displaygroup[$field] = $group[$field]; - } - - return $displaygroup; -} - -/** - * Build the forum permissions for a specific forum, user or group - * - * @param int $fid The forum ID to build permissions for (0 builds for all forums) - * @param int $uid The user to build the permissions for (0 will select the uid automatically) - * @param int $gid The group of the user to build permissions for (0 will fetch it) - * @return array Forum permissions for the specific forum or forums - */ -function forum_permissions($fid=0, $uid=0, $gid=0) -{ - global $db, $cache, $groupscache, $forum_cache, $fpermcache, $mybb, $cached_forum_permissions_permissions, $cached_forum_permissions; - - if($uid == 0) - { - $uid = $mybb->user['uid']; - } - - if(!$gid || $gid == 0) // If no group, we need to fetch it - { - if($uid != 0 && $uid != $mybb->user['uid']) - { - $user = get_user($uid); - - $gid = $user['usergroup'].",".$user['additionalgroups']; - $groupperms = usergroup_permissions($gid); - } - else - { - $gid = $mybb->user['usergroup']; - - if(isset($mybb->user['additionalgroups'])) - { - $gid .= ",".$mybb->user['additionalgroups']; - } - - $groupperms = $mybb->usergroup; - } - } - - if(!is_array($forum_cache)) - { - $forum_cache = cache_forums(); - - if(!$forum_cache) - { - return false; - } - } - - if(!is_array($fpermcache)) - { - $fpermcache = $cache->read("forumpermissions"); - } - - if($fid) // Fetch the permissions for a single forum - { - if(empty($cached_forum_permissions_permissions[$gid][$fid])) - { - $cached_forum_permissions_permissions[$gid][$fid] = fetch_forum_permissions($fid, $gid, $groupperms); - } - return $cached_forum_permissions_permissions[$gid][$fid]; - } - else - { - if(empty($cached_forum_permissions[$gid])) - { - foreach($forum_cache as $forum) - { - $cached_forum_permissions[$gid][$forum['fid']] = fetch_forum_permissions($forum['fid'], $gid, $groupperms); - } - } - return $cached_forum_permissions[$gid]; - } -} - -/** - * Fetches the permissions for a specific forum/group applying the inheritance scheme. - * Called by forum_permissions() - * - * @param int $fid The forum ID - * @param string $gid A comma separated list of usergroups - * @param array $groupperms Group permissions - * @return array Permissions for this forum -*/ -function fetch_forum_permissions($fid, $gid, $groupperms) -{ - global $groupscache, $forum_cache, $fpermcache, $mybb, $fpermfields; - - $groups = explode(",", $gid); - - if(empty($fpermcache[$fid])) // This forum has no custom or inherited permissions so lets just return the group permissions - { - return $groupperms; - } - - $current_permissions = array(); - $only_view_own_threads = 1; - $only_reply_own_threads = 1; - - foreach($groups as $gid) - { - if(!empty($groupscache[$gid])) - { - $level_permissions = $fpermcache[$fid][$gid]; - - // If our permissions arn't inherited we need to figure them out - if(empty($fpermcache[$fid][$gid])) - { - $parents = explode(',', $forum_cache[$fid]['parentlist']); - rsort($parents); - if(!empty($parents)) - { - foreach($parents as $parent_id) - { - if(!empty($fpermcache[$parent_id][$gid])) - { - $level_permissions = $fpermcache[$parent_id][$gid]; - break; - } - } - } - } - - // If we STILL don't have forum permissions we use the usergroup itself - if(empty($level_permissions)) - { - $level_permissions = $groupscache[$gid]; - } - - foreach($level_permissions as $permission => $access) - { - if(empty($current_permissions[$permission]) || $access >= $current_permissions[$permission] || ($access == "yes" && $current_permissions[$permission] == "no")) - { - $current_permissions[$permission] = $access; - } - } - - if($level_permissions["canview"] && empty($level_permissions["canonlyviewownthreads"])) - { - $only_view_own_threads = 0; - } - - if($level_permissions["canpostreplys"] && empty($level_permissions["canonlyreplyownthreads"])) - { - $only_reply_own_threads = 0; - } - } - } - - // Figure out if we can view more than our own threads - if($only_view_own_threads == 0) - { - $current_permissions["canonlyviewownthreads"] = 0; - } - - // Figure out if we can reply more than our own threads - if($only_reply_own_threads == 0) - { - $current_permissions["canonlyreplyownthreads"] = 0; - } - - if(count($current_permissions) == 0) - { - $current_permissions = $groupperms; - } - return $current_permissions; -} - -/** - * Check the password given on a certain forum for validity - * - * @param int $fid The forum ID - * @param int $pid The Parent ID - * @param bool $return - * @return bool - */ -function check_forum_password($fid, $pid=0, $return=false) -{ - global $mybb, $header, $footer, $headerinclude, $theme, $templates, $lang, $forum_cache; - - $showform = true; - - if(!is_array($forum_cache)) - { - $forum_cache = cache_forums(); - if(!$forum_cache) - { - return false; - } - } - - // Loop through each of parent forums to ensure we have a password for them too - if(isset($forum_cache[$fid]['parentlist'])) - { - $parents = explode(',', $forum_cache[$fid]['parentlist']); - rsort($parents); - } - if(!empty($parents)) - { - foreach($parents as $parent_id) - { - if($parent_id == $fid || $parent_id == $pid) - { - continue; - } - - if($forum_cache[$parent_id]['password'] != "") - { - check_forum_password($parent_id, $fid); - } - } - } - - if(!empty($forum_cache[$fid]['password'])) - { - $password = $forum_cache[$fid]['password']; - if(isset($mybb->input['pwverify']) && $pid == 0) - { - if($password === $mybb->get_input('pwverify')) - { - my_setcookie("forumpass[$fid]", md5($mybb->user['uid'].$mybb->get_input('pwverify')), null, true); - $showform = false; - } - else - { - eval("\$pwnote = \"".$templates->get("forumdisplay_password_wrongpass")."\";"); - $showform = true; - } - } - else - { - if(!$mybb->cookies['forumpass'][$fid] || ($mybb->cookies['forumpass'][$fid] && md5($mybb->user['uid'].$password) !== $mybb->cookies['forumpass'][$fid])) - { - $showform = true; - } - else - { - $showform = false; - } - } - } - else - { - $showform = false; - } - - if($return) - { - return $showform; - } - - if($showform) - { - if($pid) - { - header("Location: ".$mybb->settings['bburl']."/".get_forum_link($fid)); - } - else - { - $_SERVER['REQUEST_URI'] = htmlspecialchars_uni($_SERVER['REQUEST_URI']); - eval("\$pwform = \"".$templates->get("forumdisplay_password")."\";"); - output_page($pwform); - } - exit; - } -} - -/** - * Return the permissions for a moderator in a specific forum - * - * @param int $fid The forum ID - * @param int $uid The user ID to fetch permissions for (0 assumes current logged in user) - * @param string $parentslist The parent list for the forum (if blank, will be fetched) - * @return array Array of moderator permissions for the specific forum - */ -function get_moderator_permissions($fid, $uid=0, $parentslist="") -{ - global $mybb, $cache, $db; - static $modpermscache; - - if($uid < 1) - { - $uid = $mybb->user['uid']; - } - - if($uid == 0) - { - return false; - } - - if(isset($modpermscache[$fid][$uid])) - { - return $modpermscache[$fid][$uid]; - } - - if(!$parentslist) - { - $parentslist = explode(',', get_parent_list($fid)); - } - - // Get user groups - $perms = array(); - $user = get_user($uid); - - $groups = array($user['usergroup']); - - if(!empty($user['additionalgroups'])) - { - $extra_groups = explode(",", $user['additionalgroups']); - - foreach($extra_groups as $extra_group) - { - $groups[] = $extra_group; - } - } - - $mod_cache = $cache->read("moderators"); - - foreach($mod_cache as $forumid => $forum) - { - if(!is_array($forum) || !in_array($forumid, $parentslist)) - { - // No perms or we're not after this forum - continue; - } - - // User settings override usergroup settings - if(is_array($forum['users'][$uid])) - { - $perm = $forum['users'][$uid]; - foreach($perm as $action => $value) - { - if(strpos($action, "can") === false) - { - continue; - } - - // Figure out the user permissions - if($value == 0) - { - // The user doesn't have permission to set this action - $perms[$action] = 0; - } - else - { - $perms[$action] = max($perm[$action], $perms[$action]); - } - } - } - - foreach($groups as $group) - { - if(!is_array($forum['usergroups'][$group])) - { - // There are no permissions set for this group - continue; - } - - $perm = $forum['usergroups'][$group]; - foreach($perm as $action => $value) - { - if(strpos($action, "can") === false) - { - continue; - } - - $perms[$action] = max($perm[$action], $perms[$action]); - } - } - } - - $modpermscache[$fid][$uid] = $perms; - - return $perms; -} - -/** - * Checks if a moderator has permissions to perform an action in a specific forum - * - * @param int $fid The forum ID (0 assumes global) - * @param string $action The action tyring to be performed. (blank assumes any action at all) - * @param int $uid The user ID (0 assumes current user) - * @return bool Returns true if the user has permission, false if they do not - */ -function is_moderator($fid=0, $action="", $uid=0) -{ - global $mybb, $cache; - - if($uid == 0) - { - $uid = $mybb->user['uid']; - } - - if($uid == 0) - { - return false; - } - - $user_perms = user_permissions($uid); - if($user_perms['issupermod'] == 1) - { - if($fid) - { - $forumpermissions = forum_permissions($fid); - if($forumpermissions['canview'] && $forumpermissions['canviewthreads'] && !$forumpermissions['canonlyviewownthreads']) - { - return true; - } - return false; - } - return true; - } - else - { - if(!$fid) - { - $modcache = $cache->read('moderators'); - if(!empty($modcache)) - { - foreach($modcache as $modusers) - { - if(isset($modusers['users'][$uid]) && $modusers['users'][$uid]['mid'] && (!$action || !empty($modusers['users'][$uid][$action]))) - { - return true; - } - - $groups = explode(',', $user_perms['all_usergroups']); - - foreach($groups as $group) - { - if(trim($group) != '' && isset($modusers['usergroups'][$group]) && (!$action || !empty($modusers['usergroups'][$group][$action]))) - { - return true; - } - } - } - } - return false; - } - else - { - $modperms = get_moderator_permissions($fid, $uid); - - if(!$action && $modperms) - { - return true; - } - else - { - if(isset($modperms[$action]) && $modperms[$action] == 1) - { - return true; - } - else - { - return false; - } - } - } - } -} - -/** - * Generate a list of the posticons. - * - * @return string The template of posticons. - */ -function get_post_icons() -{ - global $mybb, $cache, $icon, $theme, $templates, $lang; - - if(isset($mybb->input['icon'])) - { - $icon = $mybb->get_input('icon'); - } - - $iconlist = ''; - $no_icons_checked = " checked=\"checked\""; - // read post icons from cache, and sort them accordingly - $posticons_cache = $cache->read("posticons"); - $posticons = array(); - foreach($posticons_cache as $posticon) - { - $posticons[$posticon['name']] = $posticon; - } - krsort($posticons); - - foreach($posticons as $dbicon) - { - $dbicon['path'] = str_replace("{theme}", $theme['imgdir'], $dbicon['path']); - $dbicon['path'] = htmlspecialchars_uni($mybb->get_asset_url($dbicon['path'])); - $dbicon['name'] = htmlspecialchars_uni($dbicon['name']); - - if($icon == $dbicon['iid']) - { - $checked = " checked=\"checked\""; - $no_icons_checked = ''; - } - else - { - $checked = ''; - } - - eval("\$iconlist .= \"".$templates->get("posticons_icon")."\";"); - } - - if(!empty($iconlist)) - { - eval("\$posticons = \"".$templates->get("posticons")."\";"); - } - else - { - $posticons = ''; - } - - return $posticons; -} - -/** - * MyBB setcookie() wrapper. - * - * @param string $name The cookie identifier. - * @param string $value The cookie value. - * @param int|string $expires The timestamp of the expiry date. - * @param boolean $httponly True if setting a HttpOnly cookie (supported by the majority of web browsers) - */ -function my_setcookie($name, $value="", $expires="", $httponly=false) -{ - global $mybb; - - if(!$mybb->settings['cookiepath']) - { - $mybb->settings['cookiepath'] = "/"; - } - - if($expires == -1) - { - $expires = 0; - } - elseif($expires == "" || $expires == null) - { - $expires = TIME_NOW + (60*60*24*365); // Make the cookie expire in a years time - } - else - { - $expires = TIME_NOW + (int)$expires; - } - - $mybb->settings['cookiepath'] = str_replace(array("\n","\r"), "", $mybb->settings['cookiepath']); - $mybb->settings['cookiedomain'] = str_replace(array("\n","\r"), "", $mybb->settings['cookiedomain']); - $mybb->settings['cookieprefix'] = str_replace(array("\n","\r", " "), "", $mybb->settings['cookieprefix']); - - // Versions of PHP prior to 5.2 do not support HttpOnly cookies and IE is buggy when specifying a blank domain so set the cookie manually - $cookie = "Set-Cookie: {$mybb->settings['cookieprefix']}{$name}=".urlencode($value); - - if($expires > 0) - { - $cookie .= "; expires=".@gmdate('D, d-M-Y H:i:s \\G\\M\\T', $expires); - } - - if(!empty($mybb->settings['cookiepath'])) - { - $cookie .= "; path={$mybb->settings['cookiepath']}"; - } - - if(!empty($mybb->settings['cookiedomain'])) - { - $cookie .= "; domain={$mybb->settings['cookiedomain']}"; - } - - if($httponly == true) - { - $cookie .= "; HttpOnly"; - } - - if($mybb->settings['cookiesecureflag']) - { - $cookie .= "; Secure"; - } - - $mybb->cookies[$name] = $value; - - header($cookie, false); -} - -/** - * Unset a cookie set by MyBB. - * - * @param string $name The cookie identifier. - */ -function my_unsetcookie($name) -{ - global $mybb; - - $expires = -3600; - my_setcookie($name, "", $expires); - - unset($mybb->cookies[$name]); -} - -/** - * Get the contents from a serialised cookie array. - * - * @param string $name The cookie identifier. - * @param int $id The cookie content id. - * @return array|boolean The cookie id's content array or false when non-existent. - */ -function my_get_array_cookie($name, $id) -{ - global $mybb; - - if(!isset($mybb->cookies['mybb'][$name])) - { - return false; - } - - $cookie = my_unserialize($mybb->cookies['mybb'][$name]); - - if(is_array($cookie) && isset($cookie[$id])) - { - return $cookie[$id]; - } - else - { - return 0; - } -} - -/** - * Set a serialised cookie array. - * - * @param string $name The cookie identifier. - * @param int $id The cookie content id. - * @param string $value The value to set the cookie to. - * @param int|string $expires The timestamp of the expiry date. - */ -function my_set_array_cookie($name, $id, $value, $expires="") -{ - global $mybb; - - $cookie = $mybb->cookies['mybb']; - if(isset($cookie[$name])) - { - $newcookie = my_unserialize($cookie[$name]); - } - else - { - $newcookie = array(); - } - - $newcookie[$id] = $value; - $newcookie = my_serialize($newcookie); - my_setcookie("mybb[$name]", addslashes($newcookie), $expires); - - // Make sure our current viarables are up-to-date as well - $mybb->cookies['mybb'][$name] = $newcookie; -} - -/* - * Arbitrary limits for _safe_unserialize() - */ -define('MAX_SERIALIZED_INPUT_LENGTH', 10240); -define('MAX_SERIALIZED_ARRAY_LENGTH', 256); -define('MAX_SERIALIZED_ARRAY_DEPTH', 5); - -/** - * Credits go to https://github.com/piwik - * Safe unserialize() replacement - * - accepts a strict subset of PHP's native my_serialized representation - * - does not unserialize objects - * - * @param string $str - * @return mixed - * @throw Exception if $str is malformed or contains unsupported types (e.g., resources, objects) - */ -function _safe_unserialize($str) -{ - if(strlen($str) > MAX_SERIALIZED_INPUT_LENGTH) - { - // input exceeds MAX_SERIALIZED_INPUT_LENGTH - return false; - } - - if(empty($str) || !is_string($str)) - { - return false; - } - - $stack = array(); - $expected = array(); - - /* - * states: - * 0 - initial state, expecting a single value or array - * 1 - terminal state - * 2 - in array, expecting end of array or a key - * 3 - in array, expecting value or another array - */ - $state = 0; - while($state != 1) - { - $type = isset($str[0]) ? $str[0] : ''; - - if($type == '}') - { - $str = substr($str, 1); - } - else if($type == 'N' && $str[1] == ';') - { - $value = null; - $str = substr($str, 2); - } - else if($type == 'b' && preg_match('/^b:([01]);/', $str, $matches)) - { - $value = $matches[1] == '1' ? true : false; - $str = substr($str, 4); - } - else if($type == 'i' && preg_match('/^i:(-?[0-9]+);(.*)/s', $str, $matches)) - { - $value = (int)$matches[1]; - $str = $matches[2]; - } - else if($type == 'd' && preg_match('/^d:(-?[0-9]+\.?[0-9]*(E[+-][0-9]+)?);(.*)/s', $str, $matches)) - { - $value = (float)$matches[1]; - $str = $matches[3]; - } - else if($type == 's' && preg_match('/^s:([0-9]+):"(.*)/s', $str, $matches) && substr($matches[2], (int)$matches[1], 2) == '";') - { - $value = substr($matches[2], 0, (int)$matches[1]); - $str = substr($matches[2], (int)$matches[1] + 2); - } - else if($type == 'a' && preg_match('/^a:([0-9]+):{(.*)/s', $str, $matches) && $matches[1] < MAX_SERIALIZED_ARRAY_LENGTH) - { - $expectedLength = (int)$matches[1]; - $str = $matches[2]; - } - else - { - // object or unknown/malformed type - return false; - } - - switch($state) - { - case 3: // in array, expecting value or another array - if($type == 'a') - { - if(count($stack) >= MAX_SERIALIZED_ARRAY_DEPTH) - { - // array nesting exceeds MAX_SERIALIZED_ARRAY_DEPTH - return false; - } - - $stack[] = &$list; - $list[$key] = array(); - $list = &$list[$key]; - $expected[] = $expectedLength; - $state = 2; - break; - } - if($type != '}') - { - $list[$key] = $value; - $state = 2; - break; - } - - // missing array value - return false; - - case 2: // in array, expecting end of array or a key - if($type == '}') - { - if(count($list) < end($expected)) - { - // array size less than expected - return false; - } - - unset($list); - $list = &$stack[count($stack)-1]; - array_pop($stack); - - // go to terminal state if we're at the end of the root array - array_pop($expected); - if(count($expected) == 0) { - $state = 1; - } - break; - } - if($type == 'i' || $type == 's') - { - if(count($list) >= MAX_SERIALIZED_ARRAY_LENGTH) - { - // array size exceeds MAX_SERIALIZED_ARRAY_LENGTH - return false; - } - if(count($list) >= end($expected)) - { - // array size exceeds expected length - return false; - } - - $key = $value; - $state = 3; - break; - } - - // illegal array index type - return false; - - case 0: // expecting array or value - if($type == 'a') - { - if(count($stack) >= MAX_SERIALIZED_ARRAY_DEPTH) - { - // array nesting exceeds MAX_SERIALIZED_ARRAY_DEPTH - return false; - } - - $data = array(); - $list = &$data; - $expected[] = $expectedLength; - $state = 2; - break; - } - if($type != '}') - { - $data = $value; - $state = 1; - break; - } - - // not in array - return false; - } - } - - if(!empty($str)) - { - // trailing data in input - return false; - } - return $data; -} - -/** - * Credits go to https://github.com/piwik - * Wrapper for _safe_unserialize() that handles exceptions and multibyte encoding issue - * - * @param string $str - * @return mixed - */ -function my_unserialize($str) -{ - // Ensure we use the byte count for strings even when strlen() is overloaded by mb_strlen() - if(function_exists('mb_internal_encoding') && (((int)ini_get('mbstring.func_overload')) & 2)) - { - $mbIntEnc = mb_internal_encoding(); - mb_internal_encoding('ASCII'); - } - - $out = _safe_unserialize($str); - - if(isset($mbIntEnc)) - { - mb_internal_encoding($mbIntEnc); - } - - return $out; -} - -/** - * Credits go to https://github.com/piwik - * Safe serialize() replacement - * - output a strict subset of PHP's native serialized representation - * - does not my_serialize objects - * - * @param mixed $value - * @return string - * @throw Exception if $value is malformed or contains unsupported types (e.g., resources, objects) - */ -function _safe_serialize( $value ) -{ - if(is_null($value)) - { - return 'N;'; - } - - if(is_bool($value)) - { - return 'b:'.(int)$value.';'; - } - - if(is_int($value)) - { - return 'i:'.$value.';'; - } - - if(is_float($value)) - { - return 'd:'.str_replace(',', '.', $value).';'; - } - - if(is_string($value)) - { - return 's:'.strlen($value).':"'.$value.'";'; - } - - if(is_array($value)) - { - $out = ''; - foreach($value as $k => $v) - { - $out .= _safe_serialize($k) . _safe_serialize($v); - } - - return 'a:'.count($value).':{'.$out.'}'; - } - - // safe_serialize cannot my_serialize resources or objects - return false; -} - -/** - * Credits go to https://github.com/piwik - * Wrapper for _safe_serialize() that handles exceptions and multibyte encoding issue - * - * @param mixed $value - * @return string -*/ -function my_serialize($value) -{ - // ensure we use the byte count for strings even when strlen() is overloaded by mb_strlen() - if(function_exists('mb_internal_encoding') && (((int)ini_get('mbstring.func_overload')) & 2)) - { - $mbIntEnc = mb_internal_encoding(); - mb_internal_encoding('ASCII'); - } - - $out = _safe_serialize($value); - if(isset($mbIntEnc)) - { - mb_internal_encoding($mbIntEnc); - } - - return $out; -} - -/** - * Returns the serverload of the system. - * - * @return int The serverload of the system. - */ -function get_server_load() -{ - global $mybb, $lang; - - $serverload = array(); - - // DIRECTORY_SEPARATOR checks if running windows - if(DIRECTORY_SEPARATOR != '\\') - { - if(function_exists("sys_getloadavg")) - { - // sys_getloadavg() will return an array with [0] being load within the last minute. - $serverload = sys_getloadavg(); - $serverload[0] = round($serverload[0], 4); - } - else if(@file_exists("/proc/loadavg") && $load = @file_get_contents("/proc/loadavg")) - { - $serverload = explode(" ", $load); - $serverload[0] = round($serverload[0], 4); - } - if(!is_numeric($serverload[0])) - { - if($mybb->safemode) - { - return $lang->unknown; - } - - // Suhosin likes to throw a warning if exec is disabled then die - weird - if($func_blacklist = @ini_get('suhosin.executor.func.blacklist')) - { - if(strpos(",".$func_blacklist.",", 'exec') !== false) - { - return $lang->unknown; - } - } - // PHP disabled functions? - if($func_blacklist = @ini_get('disable_functions')) - { - if(strpos(",".$func_blacklist.",", 'exec') !== false) - { - return $lang->unknown; - } - } - - $load = @exec("uptime"); - $load = explode("load average: ", $load); - $serverload = explode(",", $load[1]); - if(!is_array($serverload)) - { - return $lang->unknown; - } - } - } - else - { - return $lang->unknown; - } - - $returnload = trim($serverload[0]); - - return $returnload; -} - -/** - * Returns the amount of memory allocated to the script. - * - * @return int The amount of memory allocated to the script. - */ -function get_memory_usage() -{ - if(function_exists('memory_get_peak_usage')) - { - return memory_get_peak_usage(true); - } - elseif(function_exists('memory_get_usage')) - { - return memory_get_usage(true); - } - return false; -} - -/** - * Updates the forum statistics with specific values (or addition/subtraction of the previous value) - * - * @param array $changes Array of items being updated (numthreads,numposts,numusers,numunapprovedthreads,numunapprovedposts,numdeletedposts,numdeletedthreads) - * @param boolean $force Force stats update? - */ -function update_stats($changes=array(), $force=false) -{ - global $cache, $db; - static $stats_changes; - - if(empty($stats_changes)) - { - // Update stats after all changes are done - add_shutdown('update_stats', array(array(), true)); - } - - if(empty($stats_changes) || $stats_changes['inserted']) - { - $stats_changes = array( - 'numthreads' => '+0', - 'numposts' => '+0', - 'numusers' => '+0', - 'numunapprovedthreads' => '+0', - 'numunapprovedposts' => '+0', - 'numdeletedposts' => '+0', - 'numdeletedthreads' => '+0', - 'inserted' => false // Reset after changes are inserted into cache - ); - $stats = $stats_changes; - } - - if($force) // Force writing to cache? - { - if(!empty($changes)) - { - // Calculate before writing to cache - update_stats($changes); - } - $stats = $cache->read("stats"); - $changes = $stats_changes; - } - else - { - $stats = $stats_changes; - } - - $new_stats = array(); - $counters = array('numthreads', 'numunapprovedthreads', 'numposts', 'numunapprovedposts', 'numusers', 'numdeletedposts', 'numdeletedthreads'); - foreach($counters as $counter) - { - if(array_key_exists($counter, $changes)) - { - if(substr($changes[$counter], 0, 2) == "+-") - { - $changes[$counter] = substr($changes[$counter], 1); - } - // Adding or subtracting from previous value? - if(substr($changes[$counter], 0, 1) == "+" || substr($changes[$counter], 0, 1) == "-") - { - if((int)$changes[$counter] != 0) - { - $new_stats[$counter] = $stats[$counter] + $changes[$counter]; - if(!$force && (substr($stats[$counter], 0, 1) == "+" || substr($stats[$counter], 0, 1) == "-")) - { - // We had relative values? Then it is still relative - if($new_stats[$counter] >= 0) - { - $new_stats[$counter] = "+{$new_stats[$counter]}"; - } - } - // Less than 0? That's bad - elseif($new_stats[$counter] < 0) - { - $new_stats[$counter] = 0; - } - } - } - else - { - $new_stats[$counter] = $changes[$counter]; - // Less than 0? That's bad - if($new_stats[$counter] < 0) - { - $new_stats[$counter] = 0; - } - } - } - } - - if(!$force) - { - $stats_changes = array_merge($stats, $new_stats); // Overwrite changed values - return; - } - - // Fetch latest user if the user count is changing - if(array_key_exists('numusers', $changes)) - { - $query = $db->simple_select("users", "uid, username", "", array('order_by' => 'regdate', 'order_dir' => 'DESC', 'limit' => 1)); - $lastmember = $db->fetch_array($query); - $new_stats['lastuid'] = $lastmember['uid']; - $new_stats['lastusername'] = $lastmember['username'] = htmlspecialchars_uni($lastmember['username']); - } - - if(!empty($new_stats)) - { - if(is_array($stats)) - { - $stats = array_merge($stats, $new_stats); // Overwrite changed values - } - else - { - $stats = $new_stats; - } - } - - // Update stats row for today in the database - $todays_stats = array( - "dateline" => mktime(0, 0, 0, date("m"), date("j"), date("Y")), - "numusers" => (int)$stats['numusers'], - "numthreads" => (int)$stats['numthreads'], - "numposts" => (int)$stats['numposts'] - ); - $db->replace_query("stats", $todays_stats, "dateline"); - - $cache->update("stats", $stats, "dateline"); - $stats_changes['inserted'] = true; -} - -/** - * Updates the forum counters with a specific value (or addition/subtraction of the previous value) - * - * @param int $fid The forum ID - * @param array $changes Array of items being updated (threads, posts, unapprovedthreads, unapprovedposts, deletedposts, deletedthreads) and their value (ex, 1, +1, -1) - */ -function update_forum_counters($fid, $changes=array()) -{ - global $db; - - $update_query = array(); - - $counters = array('threads', 'unapprovedthreads', 'posts', 'unapprovedposts', 'deletedposts', 'deletedthreads'); - - // Fetch above counters for this forum - $query = $db->simple_select("forums", implode(",", $counters), "fid='{$fid}'"); - $forum = $db->fetch_array($query); - - foreach($counters as $counter) - { - if(array_key_exists($counter, $changes)) - { - if(substr($changes[$counter], 0, 2) == "+-") - { - $changes[$counter] = substr($changes[$counter], 1); - } - // Adding or subtracting from previous value? - if(substr($changes[$counter], 0, 1) == "+" || substr($changes[$counter], 0, 1) == "-") - { - if((int)$changes[$counter] != 0) - { - $update_query[$counter] = $forum[$counter] + $changes[$counter]; - } - } - else - { - $update_query[$counter] = $changes[$counter]; - } - - // Less than 0? That's bad - if(isset($update_query[$counter]) && $update_query[$counter] < 0) - { - $update_query[$counter] = 0; - } - } - } - - // Only update if we're actually doing something - if(count($update_query) > 0) - { - $db->update_query("forums", $update_query, "fid='".(int)$fid."'"); - } - - // Guess we should update the statistics too? - $new_stats = array(); - if(array_key_exists('threads', $update_query)) - { - $threads_diff = $update_query['threads'] - $forum['threads']; - if($threads_diff > -1) - { - $new_stats['numthreads'] = "+{$threads_diff}"; - } - else - { - $new_stats['numthreads'] = "{$threads_diff}"; - } - } - - if(array_key_exists('unapprovedthreads', $update_query)) - { - $unapprovedthreads_diff = $update_query['unapprovedthreads'] - $forum['unapprovedthreads']; - if($unapprovedthreads_diff > -1) - { - $new_stats['numunapprovedthreads'] = "+{$unapprovedthreads_diff}"; - } - else - { - $new_stats['numunapprovedthreads'] = "{$unapprovedthreads_diff}"; - } - } - - if(array_key_exists('posts', $update_query)) - { - $posts_diff = $update_query['posts'] - $forum['posts']; - if($posts_diff > -1) - { - $new_stats['numposts'] = "+{$posts_diff}"; - } - else - { - $new_stats['numposts'] = "{$posts_diff}"; - } - } - - if(array_key_exists('unapprovedposts', $update_query)) - { - $unapprovedposts_diff = $update_query['unapprovedposts'] - $forum['unapprovedposts']; - if($unapprovedposts_diff > -1) - { - $new_stats['numunapprovedposts'] = "+{$unapprovedposts_diff}"; - } - else - { - $new_stats['numunapprovedposts'] = "{$unapprovedposts_diff}"; - } - } - - if(array_key_exists('deletedposts', $update_query)) - { - $deletedposts_diff = $update_query['deletedposts'] - $forum['deletedposts']; - if($deletedposts_diff > -1) - { - $new_stats['numdeletedposts'] = "+{$deletedposts_diff}"; - } - else - { - $new_stats['numdeletedposts'] = "{$deletedposts_diff}"; - } - } - - if(array_key_exists('deletedthreads', $update_query)) - { - $deletedthreads_diff = $update_query['deletedthreads'] - $forum['deletedthreads']; - if($deletedthreads_diff > -1) - { - $new_stats['numdeletedthreads'] = "+{$deletedthreads_diff}"; - } - else - { - $new_stats['numdeletedthreads'] = "{$deletedthreads_diff}"; - } - } - - if(!empty($new_stats)) - { - update_stats($new_stats); - } -} - -/** - * Update the last post information for a specific forum - * - * @param int $fid The forum ID - */ -function update_forum_lastpost($fid) -{ - global $db; - - // Fetch the last post for this forum - $query = $db->query(" - SELECT tid, lastpost, lastposter, lastposteruid, subject - FROM ".TABLE_PREFIX."threads - WHERE fid='{$fid}' AND visible='1' AND closed NOT LIKE 'moved|%' - ORDER BY lastpost DESC - LIMIT 0, 1 - "); - $lastpost = $db->fetch_array($query); - - $updated_forum = array( - "lastpost" => (int)$lastpost['lastpost'], - "lastposter" => $db->escape_string($lastpost['lastposter']), - "lastposteruid" => (int)$lastpost['lastposteruid'], - "lastposttid" => (int)$lastpost['tid'], - "lastpostsubject" => $db->escape_string($lastpost['subject']) - ); - - $db->update_query("forums", $updated_forum, "fid='{$fid}'"); -} - -/** - * Updates the thread counters with a specific value (or addition/subtraction of the previous value) - * - * @param int $tid The thread ID - * @param array $changes Array of items being updated (replies, unapprovedposts, deletedposts, attachmentcount) and their value (ex, 1, +1, -1) - */ -function update_thread_counters($tid, $changes=array()) -{ - global $db; - - $update_query = array(); - $tid = (int)$tid; - - $counters = array('replies', 'unapprovedposts', 'attachmentcount', 'deletedposts', 'attachmentcount'); - - // Fetch above counters for this thread - $query = $db->simple_select("threads", implode(",", $counters), "tid='{$tid}'"); - $thread = $db->fetch_array($query); - - foreach($counters as $counter) - { - if(array_key_exists($counter, $changes)) - { - if(substr($changes[$counter], 0, 2) == "+-") - { - $changes[$counter] = substr($changes[$counter], 1); - } - // Adding or subtracting from previous value? - if(substr($changes[$counter], 0, 1) == "+" || substr($changes[$counter], 0, 1) == "-") - { - if((int)$changes[$counter] != 0) - { - $update_query[$counter] = $thread[$counter] + $changes[$counter]; - } - } - else - { - $update_query[$counter] = $changes[$counter]; - } - - // Less than 0? That's bad - if(isset($update_query[$counter]) && $update_query[$counter] < 0) - { - $update_query[$counter] = 0; - } - } - } - - $db->free_result($query); - - // Only update if we're actually doing something - if(count($update_query) > 0) - { - $db->update_query("threads", $update_query, "tid='{$tid}'"); - } -} - -/** - * Update the first post and lastpost data for a specific thread - * - * @param int $tid The thread ID - */ -function update_thread_data($tid) -{ - global $db; - - $thread = get_thread($tid); - - // If this is a moved thread marker, don't update it - we need it to stay as it is - if(strpos($thread['closed'], 'moved|') !== false) - { - return; - } - - $query = $db->query(" - SELECT u.uid, u.username, p.username AS postusername, p.dateline - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.tid='$tid' AND p.visible='1' - ORDER BY p.dateline DESC - LIMIT 1" - ); - $lastpost = $db->fetch_array($query); - - $db->free_result($query); - - $query = $db->query(" - SELECT u.uid, u.username, p.pid, p.username AS postusername, p.dateline - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.tid='$tid' - ORDER BY p.dateline ASC - LIMIT 1 - "); - $firstpost = $db->fetch_array($query); - - $db->free_result($query); - - if(empty($firstpost['username'])) - { - $firstpost['username'] = $firstpost['postusername']; - } - - if(empty($lastpost['username'])) - { - $lastpost['username'] = $lastpost['postusername']; - } - - if(empty($lastpost['dateline'])) - { - $lastpost['username'] = $firstpost['username']; - $lastpost['uid'] = $firstpost['uid']; - $lastpost['dateline'] = $firstpost['dateline']; - } - - $lastpost['username'] = $db->escape_string($lastpost['username']); - $firstpost['username'] = $db->escape_string($firstpost['username']); - - $update_array = array( - 'firstpost' => (int)$firstpost['pid'], - 'username' => $firstpost['username'], - 'uid' => (int)$firstpost['uid'], - 'dateline' => (int)$firstpost['dateline'], - 'lastpost' => (int)$lastpost['dateline'], - 'lastposter' => $lastpost['username'], - 'lastposteruid' => (int)$lastpost['uid'], - ); - $db->update_query("threads", $update_array, "tid='{$tid}'"); -} - -/** - * Updates the user counters with a specific value (or addition/subtraction of the previous value) - * - * @param int $uid The user ID - * @param array $changes Array of items being updated (postnum, threadnum) and their value (ex, 1, +1, -1) - */ -function update_user_counters($uid, $changes=array()) -{ - global $db; - - $update_query = array(); - - $counters = array('postnum', 'threadnum'); - $uid = (int)$uid; - - // Fetch above counters for this user - $query = $db->simple_select("users", implode(",", $counters), "uid='{$uid}'"); - $user = $db->fetch_array($query); - - foreach($counters as $counter) - { - if(array_key_exists($counter, $changes)) - { - if(substr($changes[$counter], 0, 2) == "+-") - { - $changes[$counter] = substr($changes[$counter], 1); - } - // Adding or subtracting from previous value? - if(substr($changes[$counter], 0, 1) == "+" || substr($changes[$counter], 0, 1) == "-") - { - if((int)$changes[$counter] != 0) - { - $update_query[$counter] = $user[$counter] + $changes[$counter]; - } - } - else - { - $update_query[$counter] = $changes[$counter]; - } - - // Less than 0? That's bad - if(isset($update_query[$counter]) && $update_query[$counter] < 0) - { - $update_query[$counter] = 0; - } - } - } - - $db->free_result($query); - - // Only update if we're actually doing something - if(count($update_query) > 0) - { - $db->update_query("users", $update_query, "uid='{$uid}'"); - } -} - -/** - * Deletes a thread from the database - * - * @param int $tid The thread ID - * @return bool - */ -function delete_thread($tid) -{ - global $moderation; - - if(!is_object($moderation)) - { - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation; - } - - return $moderation->delete_thread($tid); -} - -/** - * Deletes a post from the database - * - * @param int $pid The thread ID - * @return bool - */ -function delete_post($pid) -{ - global $moderation; - - if(!is_object($moderation)) - { - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation; - } - - return $moderation->delete_post($pid); -} - -/** - * Builds a forum jump menu - * - * @param int $pid The parent forum to start with - * @param int $selitem The selected item ID - * @param int $addselect If we need to add select boxes to this cal or not - * @param string $depth The current depth of forums we're at - * @param int $showextras Whether or not to show extra items such as User CP, Forum home - * @param boolean $showall Ignore the showinjump setting and show all forums (for moderation pages) - * @param mixed $permissions deprecated - * @param string $name The name of the forum jump - * @return string Forum jump items - */ -function build_forum_jump($pid=0, $selitem=0, $addselect=1, $depth="", $showextras=1, $showall=false, $permissions="", $name="fid") -{ - global $forum_cache, $jumpfcache, $permissioncache, $mybb, $forumjump, $forumjumpbits, $gobutton, $theme, $templates, $lang; - - $pid = (int)$pid; - - if(!is_array($jumpfcache)) - { - if(!is_array($forum_cache)) - { - cache_forums(); - } - - foreach($forum_cache as $fid => $forum) - { - if($forum['active'] != 0) - { - $jumpfcache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; - } - } - } - - if(!is_array($permissioncache)) - { - $permissioncache = forum_permissions(); - } - - if(isset($jumpfcache[$pid]) && is_array($jumpfcache[$pid])) - { - foreach($jumpfcache[$pid] as $main) - { - foreach($main as $forum) - { - $perms = $permissioncache[$forum['fid']]; - - if($forum['fid'] != "0" && ($perms['canview'] != 0 || $mybb->settings['hideprivateforums'] == 0) && $forum['linkto'] == '' && ($forum['showinjump'] != 0 || $showall == true)) - { - $optionselected = ""; - - if($selitem == $forum['fid']) - { - $optionselected = 'selected="selected"'; - } - - $forum['name'] = htmlspecialchars_uni(strip_tags($forum['name'])); - - eval("\$forumjumpbits .= \"".$templates->get("forumjump_bit")."\";"); - - if($forum_cache[$forum['fid']]) - { - $newdepth = $depth."--"; - $forumjumpbits .= build_forum_jump($forum['fid'], $selitem, 0, $newdepth, $showextras, $showall); - } - } - } - } - } - - if($addselect) - { - if($showextras == 0) - { - $template = "special"; - } - else - { - $template = "advanced"; - - if(strpos(FORUM_URL, '.html') !== false) - { - $forum_link = "'".str_replace('{fid}', "'+option+'", FORUM_URL)."'"; - } - else - { - $forum_link = "'".str_replace('{fid}', "'+option", FORUM_URL); - } - } - - eval("\$forumjump = \"".$templates->get("forumjump_".$template)."\";"); - } - - return $forumjump; -} - -/** - * Returns the extension of a file. - * - * @param string $file The filename. - * @return string The extension of the file. - */ -function get_extension($file) -{ - return my_strtolower(my_substr(strrchr($file, "."), 1)); -} - -/** - * Generates a random string. - * - * @param int $length The length of the string to generate. - * @param bool $complex Whether to return complex string. Defaults to false - * @return string The random string. - */ -function random_str($length=8, $complex=false) -{ - $set = array_merge(range(0, 9), range('A', 'Z'), range('a', 'z')); - $str = array(); - - // Complex strings have always at least 3 characters, even if $length < 3 - if($complex == true) - { - // At least one number - $str[] = $set[my_rand(0, 9)]; - - // At least one big letter - $str[] = $set[my_rand(10, 35)]; - - // At least one small letter - $str[] = $set[my_rand(36, 61)]; - - $length -= 3; - } - - for($i = 0; $i < $length; ++$i) - { - $str[] = $set[my_rand(0, 61)]; - } - - // Make sure they're in random order and convert them to a string - shuffle($str); - - return implode($str); -} - -/** - * Formats a username based on their display group - * - * @param string $username The username - * @param int $usergroup The usergroup for the user - * @param int $displaygroup The display group for the user - * @return string The formatted username - */ -function format_name($username, $usergroup, $displaygroup=0) -{ - global $groupscache, $cache; - - if(!is_array($groupscache)) - { - $groupscache = $cache->read("usergroups"); - } - - if($displaygroup != 0) - { - $usergroup = $displaygroup; - } - - $ugroup = $groupscache[$usergroup]; - $format = $ugroup['namestyle']; - $userin = substr_count($format, "{username}"); - - if($userin == 0) - { - $format = "{username}"; - } - - $format = stripslashes($format); - - return str_replace("{username}", $username, $format); -} - -/** - * Formats an avatar to a certain dimension - * - * @param string $avatar The avatar file name - * @param string $dimensions Dimensions of the avatar, width x height (e.g. 44|44) - * @param string $max_dimensions The maximum dimensions of the formatted avatar - * @return array Information for the formatted avatar - */ -function format_avatar($avatar, $dimensions = '', $max_dimensions = '') -{ - global $mybb, $theme; - static $avatars; - - if(!isset($avatars)) - { - $avatars = array(); - } - - if(my_strpos($avatar, '://') !== false && !$mybb->settings['allowremoteavatars']) - { - // Remote avatar, but remote avatars are disallowed. - $avatar = null; - } - - if(!$avatar) - { - // Default avatar - if(defined('IN_ADMINCP')) - { - $theme['imgdir'] = '../images'; - } - - $avatar = str_replace('{theme}', $theme['imgdir'], $mybb->settings['useravatar']); - $dimensions = $mybb->settings['useravatardims']; - } - - if(!$max_dimensions) - { - $max_dimensions = $mybb->settings['maxavatardims']; - } - - // An empty key wouldn't work so we need to add a fall back - $key = $dimensions; - if(empty($key)) - { - $key = 'default'; - } - $key2 = $max_dimensions; - if(empty($key2)) - { - $key2 = 'default'; - } - - if(isset($avatars[$avatar][$key][$key2])) - { - return $avatars[$avatar][$key][$key2]; - } - - $avatar_width_height = ''; - - if($dimensions) - { - $dimensions = explode("|", $dimensions); - - if($dimensions[0] && $dimensions[1]) - { - list($max_width, $max_height) = explode('x', $max_dimensions); - - if(!empty($max_dimensions) && ($dimensions[0] > $max_width || $dimensions[1] > $max_height)) - { - require_once MYBB_ROOT."inc/functions_image.php"; - $scaled_dimensions = scale_image($dimensions[0], $dimensions[1], $max_width, $max_height); - $avatar_width_height = "width=\"{$scaled_dimensions['width']}\" height=\"{$scaled_dimensions['height']}\""; - } - else - { - $avatar_width_height = "width=\"{$dimensions[0]}\" height=\"{$dimensions[1]}\""; - } - } - } - - $avatars[$avatar][$key][$key2] = array( - 'image' => htmlspecialchars_uni($mybb->get_asset_url($avatar)), - 'width_height' => $avatar_width_height - ); - - return $avatars[$avatar][$key][$key2]; -} - -/** - * Build the javascript based MyCode inserter. - * - * @param string $bind The ID of the textarea to bind to. Defaults to "message". - * @param bool $smilies Whether to include smilies. Defaults to true. - * - * @return string The MyCode inserter - */ -function build_mycode_inserter($bind="message", $smilies = true) -{ - global $db, $mybb, $theme, $templates, $lang, $plugins, $smiliecache, $cache; - - if($mybb->settings['bbcodeinserter'] != 0) - { - $editor_lang_strings = array( - "editor_bold" => "Bold", - "editor_italic" => "Italic", - "editor_underline" => "Underline", - "editor_strikethrough" => "Strikethrough", - "editor_subscript" => "Subscript", - "editor_superscript" => "Superscript", - "editor_alignleft" => "Align left", - "editor_center" => "Center", - "editor_alignright" => "Align right", - "editor_justify" => "Justify", - "editor_fontname" => "Font Name", - "editor_fontsize" => "Font Size", - "editor_fontcolor" => "Font Color", - "editor_removeformatting" => "Remove Formatting", - "editor_cut" => "Cut", - "editor_cutnosupport" => "Your browser does not allow the cut command. Please use the keyboard shortcut Ctrl/Cmd-X", - "editor_copy" => "Copy", - "editor_copynosupport" => "Your browser does not allow the copy command. Please use the keyboard shortcut Ctrl/Cmd-C", - "editor_paste" => "Paste", - "editor_pastenosupport" => "Your browser does not allow the paste command. Please use the keyboard shortcut Ctrl/Cmd-V", - "editor_pasteentertext" => "Paste your text inside the following box:", - "editor_pastetext" => "PasteText", - "editor_numlist" => "Numbered list", - "editor_bullist" => "Bullet list", - "editor_undo" => "Undo", - "editor_redo" => "Redo", - "editor_rows" => "Rows:", - "editor_cols" => "Cols:", - "editor_inserttable" => "Insert a table", - "editor_inserthr" => "Insert a horizontal rule", - "editor_code" => "Code", - "editor_width" => "Width (optional):", - "editor_height" => "Height (optional):", - "editor_insertimg" => "Insert an image", - "editor_email" => "E-mail:", - "editor_insertemail" => "Insert an email", - "editor_url" => "URL:", - "editor_insertlink" => "Insert a link", - "editor_unlink" => "Unlink", - "editor_more" => "More", - "editor_insertemoticon" => "Insert an emoticon", - "editor_videourl" => "Video URL:", - "editor_videotype" => "Video Type:", - "editor_insert" => "Insert", - "editor_insertyoutubevideo" => "Insert a YouTube video", - "editor_currentdate" => "Insert current date", - "editor_currenttime" => "Insert current time", - "editor_print" => "Print", - "editor_viewsource" => "View source", - "editor_description" => "Description (optional):", - "editor_enterimgurl" => "Enter the image URL:", - "editor_enteremail" => "Enter the e-mail address:", - "editor_enterdisplayedtext" => "Enter the displayed text:", - "editor_enterurl" => "Enter URL:", - "editor_enteryoutubeurl" => "Enter the YouTube video URL or ID:", - "editor_insertquote" => "Insert a Quote", - "editor_invalidyoutube" => "Invalid YouTube video", - "editor_dailymotion" => "Dailymotion", - "editor_metacafe" => "MetaCafe", - "editor_veoh" => "Veoh", - "editor_vimeo" => "Vimeo", - "editor_youtube" => "Youtube", - "editor_facebook" => "Facebook", - "editor_liveleak" => "LiveLeak", - "editor_insertvideo" => "Insert a video", - "editor_php" => "PHP", - "editor_maximize" => "Maximize" - ); - $editor_language = "(function ($) {\n$.sceditor.locale[\"mybblang\"] = {\n"; - - $editor_lang_strings = $plugins->run_hooks("mycode_add_codebuttons", $editor_lang_strings); - - $editor_languages_count = count($editor_lang_strings); - $i = 0; - foreach($editor_lang_strings as $lang_string => $key) - { - $i++; - $js_lang_string = str_replace("\"", "\\\"", $key); - $string = str_replace("\"", "\\\"", $lang->$lang_string); - $editor_language .= "\t\"{$js_lang_string}\": \"{$string}\""; - - if($i < $editor_languages_count) - { - $editor_language .= ","; - } - - $editor_language .= "\n"; - } - - $editor_language .= "}})(jQuery);"; - - if(defined("IN_ADMINCP")) - { - global $page; - $codeinsert = $page->build_codebuttons_editor($bind, $editor_language, $smilies); - } - else - { - // Smilies - $emoticon = ""; - $emoticons_enabled = "false"; - if($smilies) - { - if(!$smiliecache) - { - if(!isset($smilie_cache) || !is_array($smilie_cache)) - { - $smilie_cache = $cache->read("smilies"); - } - foreach($smilie_cache as $smilie) - { - $smilie['image'] = str_replace("{theme}", $theme['imgdir'], $smilie['image']); - $smiliecache[$smilie['sid']] = $smilie; - } - } - - if($mybb->settings['smilieinserter'] && $mybb->settings['smilieinsertercols'] && $mybb->settings['smilieinsertertot'] && !empty($smiliecache)) - { - $emoticon = ",emoticon"; - } - $emoticons_enabled = "true"; - - unset($smilie); - - if(is_array($smiliecache)) - { - reset($smiliecache); - - $dropdownsmilies = $moresmilies = $hiddensmilies = ""; - $i = 0; - - foreach($smiliecache as $smilie) - { - $finds = explode("\n", $smilie['find']); - $finds_count = count($finds); - - // Only show the first text to replace in the box - $smilie['find'] = $finds[0]; - - $find = str_replace(array('\\', '"'), array('\\\\', '\"'), htmlspecialchars_uni($smilie['find'])); - $image = htmlspecialchars_uni($mybb->get_asset_url($smilie['image'])); - $image = str_replace(array('\\', '"'), array('\\\\', '\"'), $image); - - if(!$mybb->settings['smilieinserter'] || !$mybb->settings['smilieinsertercols'] || !$mybb->settings['smilieinsertertot'] || !$smilie['showclickable']) - { - $hiddensmilies .= '"'.$find.'": "'.$image.'",'; - } - elseif($i < $mybb->settings['smilieinsertertot']) - { - $dropdownsmilies .= '"'.$find.'": "'.$image.'",'; - ++$i; - } - else - { - $moresmilies .= '"'.$find.'": "'.$image.'",'; - } - - for($j = 1; $j < $finds_count; ++$j) - { - $find = str_replace(array('\\', '"'), array('\\\\', '\"'), htmlspecialchars_uni($finds[$j])); - $hiddensmilies .= '"'.$find.'": "'.$image.'",'; - } - } - } - } - - $basic1 = $basic2 = $align = $font = $size = $color = $removeformat = $email = $link = $list = $code = $sourcemode = ""; - - if($mybb->settings['allowbasicmycode'] == 1) - { - $basic1 = "bold,italic,underline,strike|"; - $basic2 = "horizontalrule,"; - } - - if($mybb->settings['allowalignmycode'] == 1) - { - $align = "left,center,right,justify|"; - } - - if($mybb->settings['allowfontmycode'] == 1) - { - $font = "font,"; - } - - if($mybb->settings['allowsizemycode'] == 1) - { - $size = "size,"; - } - - if($mybb->settings['allowcolormycode'] == 1) - { - $color = "color,"; - } - - if($mybb->settings['allowfontmycode'] == 1 || $mybb->settings['allowsizemycode'] == 1 || $mybb->settings['allowcolormycode'] == 1) - { - $removeformat = "removeformat|"; - } - - if($mybb->settings['allowemailmycode'] == 1) - { - $email = "email,"; - } - - if($mybb->settings['allowlinkmycode'] == 1) - { - $link = "link,unlink"; - } - - if($mybb->settings['allowlistmycode'] == 1) - { - $list = "bulletlist,orderedlist|"; - } - - if($mybb->settings['allowcodemycode'] == 1) - { - $code = "code,php,"; - } - - if($mybb->user['sourceeditor'] == 1) - { - $sourcemode = "MyBBEditor.sourceMode(true);"; - } - - eval("\$codeinsert = \"".$templates->get("codebuttons")."\";"); - } - } - - return $codeinsert; -} - -/** - * Build the javascript clickable smilie inserter - * - * @return string The clickable smilies list - */ -function build_clickable_smilies() -{ - global $cache, $smiliecache, $theme, $templates, $lang, $mybb, $smiliecount; - - if($mybb->settings['smilieinserter'] != 0 && $mybb->settings['smilieinsertercols'] && $mybb->settings['smilieinsertertot']) - { - if(!$smiliecount) - { - $smilie_cache = $cache->read("smilies"); - $smiliecount = count($smilie_cache); - } - - if(!$smiliecache) - { - if(!is_array($smilie_cache)) - { - $smilie_cache = $cache->read("smilies"); - } - foreach($smilie_cache as $smilie) - { - $smilie['image'] = str_replace("{theme}", $theme['imgdir'], $smilie['image']); - $smiliecache[$smilie['sid']] = $smilie; - } - } - - unset($smilie); - - if(is_array($smiliecache)) - { - reset($smiliecache); - - $getmore = ''; - if($mybb->settings['smilieinsertertot'] >= $smiliecount) - { - $mybb->settings['smilieinsertertot'] = $smiliecount; - } - else if($mybb->settings['smilieinsertertot'] < $smiliecount) - { - $smiliecount = $mybb->settings['smilieinsertertot']; - eval("\$getmore = \"".$templates->get("smilieinsert_getmore")."\";"); - } - - $smilies = ''; - $counter = 0; - $i = 0; - - $extra_class = ''; - foreach($smiliecache as $smilie) - { - if($i < $mybb->settings['smilieinsertertot'] && $smilie['showclickable'] != 0) - { - $smilie['image'] = str_replace("{theme}", $theme['imgdir'], $smilie['image']); - $smilie['image'] = htmlspecialchars_uni($mybb->get_asset_url($smilie['image'])); - $smilie['name'] = htmlspecialchars_uni($smilie['name']); - - // Only show the first text to replace in the box - $temp = explode("\n", $smilie['find']); // assign to temporary variable for php 5.3 compatibility - $smilie['find'] = $temp[0]; - - $find = str_replace(array('\\', "'"), array('\\\\', "\'"), htmlspecialchars_uni($smilie['find'])); - - $onclick = " onclick=\"MyBBEditor.insertText(' $find ');\""; - $extra_class = ' smilie_pointer'; - eval('$smilie = "'.$templates->get('smilie', 1, 0).'";'); - eval("\$smilie_icons .= \"".$templates->get("smilieinsert_smilie")."\";"); - ++$i; - ++$counter; - - if($counter == $mybb->settings['smilieinsertercols']) - { - $counter = 0; - eval("\$smilies .= \"".$templates->get("smilieinsert_row")."\";"); - $smilie_icons = ''; - } - } - } - - if($counter != 0) - { - $colspan = $mybb->settings['smilieinsertercols'] - $counter; - eval("\$smilies .= \"".$templates->get("smilieinsert_row_empty")."\";"); - } - - eval("\$clickablesmilies = \"".$templates->get("smilieinsert")."\";"); - } - else - { - $clickablesmilies = ""; - } - } - else - { - $clickablesmilies = ""; - } - - return $clickablesmilies; -} - -/** - * Builds thread prefixes and returns a selected prefix (or all) - * - * @param int $pid The prefix ID (0 to return all) - * @return array The thread prefix's values (or all thread prefixes) - */ -function build_prefixes($pid=0) -{ - global $cache; - static $prefixes_cache; - - if(is_array($prefixes_cache)) - { - if($pid > 0 && is_array($prefixes_cache[$pid])) - { - return $prefixes_cache[$pid]; - } - - return $prefixes_cache; - } - - $prefix_cache = $cache->read("threadprefixes"); - - if(!is_array($prefix_cache)) - { - // No cache - $prefix_cache = $cache->read("threadprefixes", true); - - if(!is_array($prefix_cache)) - { - return array(); - } - } - - $prefixes_cache = array(); - foreach($prefix_cache as $prefix) - { - $prefixes_cache[$prefix['pid']] = $prefix; - } - - if($pid != 0 && is_array($prefixes_cache[$pid])) - { - return $prefixes_cache[$pid]; - } - else if(!empty($prefixes_cache)) - { - return $prefixes_cache; - } - - return false; -} - -/** - * Build the thread prefix selection menu for the current user - * - * @param int|string $fid The forum ID (integer ID or string all) - * @param int|string $selected_pid The selected prefix ID (integer ID or string any) - * @param int $multiple Allow multiple prefix selection - * @param int $previous_pid The previously selected prefix ID - * @return string The thread prefix selection menu - */ -function build_prefix_select($fid, $selected_pid=0, $multiple=0, $previous_pid=0) -{ - global $cache, $db, $lang, $mybb, $templates; - - if($fid != 'all') - { - $fid = (int)$fid; - } - - $prefix_cache = build_prefixes(0); - if(empty($prefix_cache)) - { - // We've got no prefixes to show - return ''; - } - - // Go through each of our prefixes and decide which ones we can use - $prefixes = array(); - foreach($prefix_cache as $prefix) - { - if($fid != "all" && $prefix['forums'] != "-1") - { - // Decide whether this prefix can be used in our forum - $forums = explode(",", $prefix['forums']); - - if(!in_array($fid, $forums) && $prefix['pid'] != $previous_pid) - { - // This prefix is not in our forum list - continue; - } - } - - if(is_member($prefix['groups']) || $prefix['pid'] == $previous_pid) - { - // The current user can use this prefix - $prefixes[$prefix['pid']] = $prefix; - } - } - - if(empty($prefixes)) - { - return ''; - } - - $prefixselect = $prefixselect_prefix = ''; - - if($multiple == 1) - { - $any_selected = ""; - if($selected_pid == 'any') - { - $any_selected = " selected=\"selected\""; - } - } - - $default_selected = ""; - if(((int)$selected_pid == 0) && $selected_pid != 'any') - { - $default_selected = " selected=\"selected\""; - } - - foreach($prefixes as $prefix) - { - $selected = ""; - if($prefix['pid'] == $selected_pid) - { - $selected = " selected=\"selected\""; - } - - $prefix['prefix'] = htmlspecialchars_uni($prefix['prefix']); - eval("\$prefixselect_prefix .= \"".$templates->get("post_prefixselect_prefix")."\";"); - } - - if($multiple != 0) - { - eval("\$prefixselect = \"".$templates->get("post_prefixselect_multiple")."\";"); - } - else - { - eval("\$prefixselect = \"".$templates->get("post_prefixselect_single")."\";"); - } - - return $prefixselect; -} - -/** - * Build the thread prefix selection menu for a forum without group permission checks - * - * @param int $fid The forum ID (integer ID) - * @param int $selected_pid The selected prefix ID (integer ID) - * @return string The thread prefix selection menu - */ -function build_forum_prefix_select($fid, $selected_pid=0) -{ - global $cache, $db, $lang, $mybb, $templates; - - $fid = (int)$fid; - - $prefix_cache = build_prefixes(0); - if(empty($prefix_cache)) - { - // We've got no prefixes to show - return ''; - } - - // Go through each of our prefixes and decide which ones we can use - $prefixes = array(); - foreach($prefix_cache as $prefix) - { - if($prefix['forums'] != "-1") - { - // Decide whether this prefix can be used in our forum - $forums = explode(",", $prefix['forums']); - - if(in_array($fid, $forums)) - { - // This forum can use this prefix! - $prefixes[$prefix['pid']] = $prefix; - } - } - else - { - // This prefix is for anybody to use... - $prefixes[$prefix['pid']] = $prefix; - } - } - - if(empty($prefixes)) - { - return ''; - } - - $default_selected = array(); - $selected_pid = (int)$selected_pid; - - if($selected_pid == 0) - { - $default_selected['all'] = ' selected="selected"'; - } - else if($selected_pid == -1) - { - $default_selected['none'] = ' selected="selected"'; - } - else if($selected_pid == -2) - { - $default_selected['any'] = ' selected="selected"'; - } - - foreach($prefixes as $prefix) - { - $selected = ''; - if($prefix['pid'] == $selected_pid) - { - $selected = ' selected="selected"'; - } - - $prefix['prefix'] = htmlspecialchars_uni($prefix['prefix']); - eval('$prefixselect_prefix .= "'.$templates->get("forumdisplay_threadlist_prefixes_prefix").'";'); - } - - eval('$prefixselect = "'.$templates->get("forumdisplay_threadlist_prefixes").'";'); - return $prefixselect; -} - -/** - * Gzip encodes text to a specified level - * - * @param string $contents The string to encode - * @param int $level The level (1-9) to encode at - * @return string The encoded string - */ -function gzip_encode($contents, $level=1) -{ - if(function_exists("gzcompress") && function_exists("crc32") && !headers_sent() && !(ini_get('output_buffering') && my_strpos(' '.ini_get('output_handler'), 'ob_gzhandler'))) - { - $httpaccept_encoding = ''; - - if(isset($_SERVER['HTTP_ACCEPT_ENCODING'])) - { - $httpaccept_encoding = $_SERVER['HTTP_ACCEPT_ENCODING']; - } - - if(my_strpos(" ".$httpaccept_encoding, "x-gzip")) - { - $encoding = "x-gzip"; - } - - if(my_strpos(" ".$httpaccept_encoding, "gzip")) - { - $encoding = "gzip"; - } - - if(isset($encoding)) - { - header("Content-Encoding: $encoding"); - - if(function_exists("gzencode")) - { - $contents = gzencode($contents, $level); - } - else - { - $size = strlen($contents); - $crc = crc32($contents); - $gzdata = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff"; - $gzdata .= my_substr(gzcompress($contents, $level), 2, -4); - $gzdata .= pack("V", $crc); - $gzdata .= pack("V", $size); - $contents = $gzdata; - } - } - } - - return $contents; -} - -/** - * Log the actions of a moderator. - * - * @param array $data The data of the moderator's action. - * @param string $action The message to enter for the action the moderator performed. - */ -function log_moderator_action($data, $action="") -{ - global $mybb, $db, $session; - - $fid = 0; - if(isset($data['fid'])) - { - $fid = (int)$data['fid']; - unset($data['fid']); - } - - $tid = 0; - if(isset($data['tid'])) - { - $tid = (int)$data['tid']; - unset($data['tid']); - } - - $pid = 0; - if(isset($data['pid'])) - { - $pid = (int)$data['pid']; - unset($data['pid']); - } - - // Any remaining extra data - we my_serialize and insert in to its own column - if(is_array($data)) - { - $data = my_serialize($data); - } - - $sql_array = array( - "uid" => (int)$mybb->user['uid'], - "dateline" => TIME_NOW, - "fid" => (int)$fid, - "tid" => $tid, - "pid" => $pid, - "action" => $db->escape_string($action), - "data" => $db->escape_string($data), - "ipaddress" => $db->escape_binary($session->packedip) - ); - $db->insert_query("moderatorlog", $sql_array); -} - -/** - * Get the formatted reputation for a user. - * - * @param int $reputation The reputation value - * @param int $uid The user ID (if not specified, the generated reputation will not be a link) - * @return string The formatted repuation - */ -function get_reputation($reputation, $uid=0) -{ - global $theme, $templates; - - $display_reputation = $reputation_class = ''; - if($reputation < 0) - { - $reputation_class = "reputation_negative"; - } - elseif($reputation > 0) - { - $reputation_class = "reputation_positive"; - } - else - { - $reputation_class = "reputation_neutral"; - } - - $reputation = my_number_format($reputation); - - if($uid != 0) - { - eval("\$display_reputation = \"".$templates->get("postbit_reputation_formatted_link")."\";"); - } - else - { - eval("\$display_reputation = \"".$templates->get("postbit_reputation_formatted")."\";"); - } - - return $display_reputation; -} - -/** - * Fetch a color coded version of a warning level (based on it's percentage) - * - * @param int $level The warning level (percentage of 100) - * @return string Formatted warning level - */ -function get_colored_warning_level($level) -{ - global $templates; - - $warning_class = ''; - if($level >= 80) - { - $warning_class = "high_warning"; - } - else if($level >= 50) - { - $warning_class = "moderate_warning"; - } - else if($level >= 25) - { - $warning_class = "low_warning"; - } - else - { - $warning_class = "normal_warning"; - } - - eval("\$level = \"".$templates->get("postbit_warninglevel_formatted")."\";"); - return $level; -} - -/** - * Fetch the IP address of the current user. - * - * @return string The IP address. - */ -function get_ip() -{ - global $mybb, $plugins; - - $ip = strtolower($_SERVER['REMOTE_ADDR']); - - if($mybb->settings['ip_forwarded_check']) - { - $addresses = array(); - - if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) - { - $addresses = explode(',', strtolower($_SERVER['HTTP_X_FORWARDED_FOR'])); - } - elseif(isset($_SERVER['HTTP_X_REAL_IP'])) - { - $addresses = explode(',', strtolower($_SERVER['HTTP_X_REAL_IP'])); - } - - if(is_array($addresses)) - { - foreach($addresses as $val) - { - $val = trim($val); - // Validate IP address and exclude private addresses - if(my_inet_ntop(my_inet_pton($val)) == $val && !preg_match("#^(10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.|fe80:|fe[c-f][0-f]:|f[c-d][0-f]{2}:)#", $val)) - { - $ip = $val; - break; - } - } - } - } - - if(!$ip) - { - if(isset($_SERVER['HTTP_CLIENT_IP'])) - { - $ip = strtolower($_SERVER['HTTP_CLIENT_IP']); - } - } - - if($plugins) - { - $ip_array = array("ip" => &$ip); // Used for backwards compatibility on this hook with the updated run_hooks() function. - $plugins->run_hooks("get_ip", $ip_array); - } - - return $ip; -} - -/** - * Fetch the friendly size (GB, MB, KB, B) for a specified file size. - * - * @param int $size The size in bytes - * @return string The friendly file size - */ -function get_friendly_size($size) -{ - global $lang; - - if(!is_numeric($size)) - { - return $lang->na; - } - - // Yottabyte (1024 Zettabytes) - if($size >= 1208925819614629174706176) - { - $size = my_number_format(round(($size / 1208925819614629174706176), 2))." ".$lang->size_yb; - } - // Zetabyte (1024 Exabytes) - elseif($size >= 1180591620717411303424) - { - $size = my_number_format(round(($size / 1180591620717411303424), 2))." ".$lang->size_zb; - } - // Exabyte (1024 Petabytes) - elseif($size >= 1152921504606846976) - { - $size = my_number_format(round(($size / 1152921504606846976), 2))." ".$lang->size_eb; - } - // Petabyte (1024 Terabytes) - elseif($size >= 1125899906842624) - { - $size = my_number_format(round(($size / 1125899906842624), 2))." ".$lang->size_pb; - } - // Terabyte (1024 Gigabytes) - elseif($size >= 1099511627776) - { - $size = my_number_format(round(($size / 1099511627776), 2))." ".$lang->size_tb; - } - // Gigabyte (1024 Megabytes) - elseif($size >= 1073741824) - { - $size = my_number_format(round(($size / 1073741824), 2))." ".$lang->size_gb; - } - // Megabyte (1024 Kilobytes) - elseif($size >= 1048576) - { - $size = my_number_format(round(($size / 1048576), 2))." ".$lang->size_mb; - } - // Kilobyte (1024 bytes) - elseif($size >= 1024) - { - $size = my_number_format(round(($size / 1024), 2))." ".$lang->size_kb; - } - elseif($size == 0) - { - $size = "0 ".$lang->size_bytes; - } - else - { - $size = my_number_format($size)." ".$lang->size_bytes; - } - - return $size; -} - -/** - * Format a decimal number in to microseconds, milliseconds, or seconds. - * - * @param int $time The time in microseconds - * @return string The friendly time duration - */ -function format_time_duration($time) -{ - global $lang; - - if(!is_numeric($time)) - { - return $lang->na; - } - - if(round(1000000 * $time, 2) < 1000) - { - $time = number_format(round(1000000 * $time, 2))." μs"; - } - elseif(round(1000000 * $time, 2) >= 1000 && round(1000000 * $time, 2) < 1000000) - { - $time = number_format(round((1000 * $time), 2))." ms"; - } - else - { - $time = round($time, 3)." seconds"; - } - - return $time; -} - -/** - * Get the attachment icon for a specific file extension - * - * @param string $ext The file extension - * @return string The attachment icon - */ -function get_attachment_icon($ext) -{ - global $cache, $attachtypes, $theme, $templates, $lang, $mybb; - - if(!$attachtypes) - { - $attachtypes = $cache->read("attachtypes"); - } - - $ext = my_strtolower($ext); - - if($attachtypes[$ext]['icon']) - { - static $attach_icons_schemes = array(); - if(!isset($attach_icons_schemes[$ext])) - { - $attach_icons_schemes[$ext] = parse_url($attachtypes[$ext]['icon']); - if(!empty($attach_icons_schemes[$ext]['scheme'])) - { - $attach_icons_schemes[$ext] = $attachtypes[$ext]['icon']; - } - elseif(defined("IN_ADMINCP")) - { - $attach_icons_schemes[$ext] = str_replace("{theme}", "", $attachtypes[$ext]['icon']); - if(my_substr($attach_icons_schemes[$ext], 0, 1) != "/") - { - $attach_icons_schemes[$ext] = "../".$attach_icons_schemes[$ext]; - } - } - elseif(defined("IN_PORTAL")) - { - global $change_dir; - $attach_icons_schemes[$ext] = $change_dir."/".str_replace("{theme}", $theme['imgdir'], $attachtypes[$ext]['icon']); - $attach_icons_schemes[$ext] = $mybb->get_asset_url($attach_icons_schemes[$ext]); - } - else - { - $attach_icons_schemes[$ext] = str_replace("{theme}", $theme['imgdir'], $attachtypes[$ext]['icon']); - $attach_icons_schemes[$ext] = $mybb->get_asset_url($attach_icons_schemes[$ext]); - } - } - - $icon = $attach_icons_schemes[$ext]; - - $name = htmlspecialchars_uni($attachtypes[$ext]['name']); - } - else - { - if(defined("IN_ADMINCP")) - { - $theme['imgdir'] = "../images"; - } - else if(defined("IN_PORTAL")) - { - global $change_dir; - $theme['imgdir'] = "{$change_dir}/images"; - } - - $icon = "{$theme['imgdir']}/attachtypes/unknown.png"; - - $name = $lang->unknown; - } - - $icon = htmlspecialchars_uni($icon); - eval("\$attachment_icon = \"".$templates->get("attachment_icon")."\";"); - return $attachment_icon; -} - -/** - * Get a list of the unviewable forums for the current user - * - * @param boolean $only_readable_threads Set to true to only fetch those forums for which users can actually read a thread in. - * @return string Comma separated values list of the forum IDs which the user cannot view - */ -function get_unviewable_forums($only_readable_threads=false) -{ - global $forum_cache, $permissioncache, $mybb; - - if(!is_array($forum_cache)) - { - cache_forums(); - } - - if(!is_array($permissioncache)) - { - $permissioncache = forum_permissions(); - } - - $password_forums = $unviewable = array(); - foreach($forum_cache as $fid => $forum) - { - if($permissioncache[$forum['fid']]) - { - $perms = $permissioncache[$forum['fid']]; - } - else - { - $perms = $mybb->usergroup; - } - - $pwverified = 1; - - if($forum['password'] != "") - { - if($mybb->cookies['forumpass'][$forum['fid']] !== md5($mybb->user['uid'].$forum['password'])) - { - $pwverified = 0; - } - - $password_forums[$forum['fid']] = $forum['password']; - } - else - { - // Check parents for passwords - $parents = explode(",", $forum['parentlist']); - foreach($parents as $parent) - { - if(isset($password_forums[$parent]) && $mybb->cookies['forumpass'][$parent] !== md5($mybb->user['uid'].$password_forums[$parent])) - { - $pwverified = 0; - } - } - } - - if($perms['canview'] == 0 || $pwverified == 0 || ($only_readable_threads == true && $perms['canviewthreads'] == 0)) - { - $unviewable[] = $forum['fid']; - } - } - - $unviewableforums = implode(',', $unviewable); - - return $unviewableforums; -} - -/** - * Fixes mktime for dates earlier than 1970 - * - * @param string $format The date format to use - * @param int $year The year of the date - * @return string The correct date format - */ -function fix_mktime($format, $year) -{ - // Our little work around for the date < 1970 thing. - // -2 idea provided by Matt Light (http://www.mephex.com) - $format = str_replace("Y", $year, $format); - $format = str_replace("y", my_substr($year, -2), $format); - - return $format; -} - -/** - * Build the breadcrumb navigation trail from the specified items - * - * @return string The formatted breadcrumb navigation trail - */ -function build_breadcrumb() -{ - global $nav, $navbits, $templates, $theme, $lang, $mybb; - - eval("\$navsep = \"".$templates->get("nav_sep")."\";"); - - $i = 0; - $activesep = ''; - - if(is_array($navbits)) - { - reset($navbits); - foreach($navbits as $key => $navbit) - { - if(isset($navbits[$key+1])) - { - if(isset($navbits[$key+2])) - { - $sep = $navsep; - } - else - { - $sep = ""; - } - - $multipage = null; - $multipage_dropdown = null; - if(!empty($navbit['multipage'])) - { - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - $multipage = multipage($navbit['multipage']['num_threads'], $mybb->settings['threadsperpage'], $navbit['multipage']['current_page'], $navbit['multipage']['url'], true); - if($multipage) - { - ++$i; - eval("\$multipage_dropdown = \"".$templates->get("nav_dropdown")."\";"); - $sep = $multipage_dropdown.$sep; - } - } - - // Replace page 1 URLs - $navbit['url'] = str_replace("-page-1.html", ".html", $navbit['url']); - $navbit['url'] = preg_replace("/&page=1$/", "", $navbit['url']); - - eval("\$nav .= \"".$templates->get("nav_bit")."\";"); - } - } - } - - $activesep = ''; - $navsize = count($navbits); - $navbit = $navbits[$navsize-1]; - - if($nav) - { - eval("\$activesep = \"".$templates->get("nav_sep_active")."\";"); - } - - eval("\$activebit = \"".$templates->get("nav_bit_active")."\";"); - eval("\$donenav = \"".$templates->get("nav")."\";"); - - return $donenav; -} - -/** - * Add a breadcrumb menu item to the list. - * - * @param string $name The name of the item to add - * @param string $url The URL of the item to add - */ -function add_breadcrumb($name, $url="") -{ - global $navbits; - - $navsize = count($navbits); - $navbits[$navsize]['name'] = $name; - $navbits[$navsize]['url'] = $url; -} - -/** - * Build the forum breadcrumb nagiation (the navigation to a specific forum including all parent forums) - * - * @param int $fid The forum ID to build the navigation for - * @param array $multipage The multipage drop down array of information - * @return int Returns 1 in every case. Kept for compatibility - */ -function build_forum_breadcrumb($fid, $multipage=array()) -{ - global $pforumcache, $currentitem, $forum_cache, $navbits, $lang, $base_url, $archiveurl; - - if(!$pforumcache) - { - if(!is_array($forum_cache)) - { - cache_forums(); - } - - foreach($forum_cache as $key => $val) - { - $pforumcache[$val['fid']][$val['pid']] = $val; - } - } - - if(is_array($pforumcache[$fid])) - { - foreach($pforumcache[$fid] as $key => $forumnav) - { - if($fid == $forumnav['fid']) - { - if(!empty($pforumcache[$forumnav['pid']])) - { - build_forum_breadcrumb($forumnav['pid']); - } - - $navsize = count($navbits); - // Convert & to & - $navbits[$navsize]['name'] = preg_replace("#&(?!\#[0-9]+;)#si", "&", $forumnav['name']); - - if(defined("IN_ARCHIVE")) - { - // Set up link to forum in breadcrumb. - if($pforumcache[$fid][$forumnav['pid']]['type'] == 'f' || $pforumcache[$fid][$forumnav['pid']]['type'] == 'c') - { - $navbits[$navsize]['url'] = "{$base_url}forum-".$forumnav['fid'].".html"; - } - else - { - $navbits[$navsize]['url'] = $archiveurl."/index.php"; - } - } - elseif(!empty($multipage)) - { - $navbits[$navsize]['url'] = get_forum_link($forumnav['fid'], $multipage['current_page']); - - $navbits[$navsize]['multipage'] = $multipage; - $navbits[$navsize]['multipage']['url'] = str_replace('{fid}', $forumnav['fid'], FORUM_URL_PAGED); - } - else - { - $navbits[$navsize]['url'] = get_forum_link($forumnav['fid']); - } - } - } - } - - return 1; -} - -/** - * Resets the breadcrumb navigation to the first item, and clears the rest - */ -function reset_breadcrumb() -{ - global $navbits; - - $newnav[0]['name'] = $navbits[0]['name']; - $newnav[0]['url'] = $navbits[0]['url']; - if(!empty($navbits[0]['options'])) - { - $newnav[0]['options'] = $navbits[0]['options']; - } - - unset($GLOBALS['navbits']); - $GLOBALS['navbits'] = $newnav; -} - -/** - * Builds a URL to an archive mode page - * - * @param string $type The type of page (thread|announcement|forum) - * @param int $id The ID of the item - * @return string The URL - */ -function build_archive_link($type="", $id=0) -{ - global $mybb; - - // If the server OS is not Windows and not Apache or the PHP is running as a CGI or we have defined ARCHIVE_QUERY_STRINGS, use query strings - DIRECTORY_SEPARATOR checks if running windows - //if((DIRECTORY_SEPARATOR == '\\' && is_numeric(stripos($_SERVER['SERVER_SOFTWARE'], "apache")) == false) || is_numeric(stripos(SAPI_NAME, "cgi")) !== false || defined("ARCHIVE_QUERY_STRINGS")) - if($mybb->settings['seourls_archive'] == 1) - { - $base_url = $mybb->settings['bburl']."/archive/index.php/"; - } - else - { - $base_url = $mybb->settings['bburl']."/archive/index.php?"; - } - - switch($type) - { - case "thread": - $url = "{$base_url}thread-{$id}.html"; - break; - case "announcement": - $url = "{$base_url}announcement-{$id}.html"; - break; - case "forum": - $url = "{$base_url}forum-{$id}.html"; - break; - default: - $url = $mybb->settings['bburl']."/archive/index.php"; - } - - return $url; -} - -/** - * Prints a debug information page - */ -function debug_page() -{ - global $db, $debug, $templates, $templatelist, $mybb, $maintimer, $globaltime, $ptimer, $parsetime, $lang, $cache; - - $totaltime = format_time_duration($maintimer->totaltime); - $phptime = $maintimer->totaltime - $db->query_time; - $query_time = $db->query_time; - $globaltime = format_time_duration($globaltime); - - $percentphp = number_format((($phptime/$maintimer->totaltime)*100), 2); - $percentsql = number_format((($query_time/$maintimer->totaltime)*100), 2); - - $phptime = format_time_duration($maintimer->totaltime - $db->query_time); - $query_time = format_time_duration($db->query_time); - - $call_time = format_time_duration($cache->call_time); - - $phpversion = PHP_VERSION; - - $serverload = get_server_load(); - - if($mybb->settings['gzipoutput'] != 0) - { - $gzipen = "Enabled"; - } - else - { - $gzipen = "Disabled"; - } - - echo "\n"; - echo ""; - echo ""; - echo ""; - echo ""; - echo "MyBB Debug Information"; - echo ""; - echo ""; - echo "

    MyBB Debug Information

    \n"; - echo "

    Page Generation

    \n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - - $memory_usage = get_memory_usage(); - if(!$memory_usage) - { - $memory_usage = $lang->unknown; - } - else - { - $memory_usage = get_friendly_size($memory_usage)." ({$memory_usage} bytes)"; - } - $memory_limit = @ini_get("memory_limit"); - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - - echo "
    Page Generation Statistics
    Page Generation Time:$totaltimeNo. DB Queries:$db->query_count
    PHP Processing Time:$phptime ($percentphp%)DB Processing Time:$query_time ($percentsql%)
    Extensions Used:{$mybb->config['database']['type']}, xmlGlobal.php Processing Time:$globaltime
    PHP Version:$phpversionServer Load:$serverload
    GZip Encoding Status:$gzipenNo. Templates Used:".count($templates->cache)." (".(int)count(explode(",", $templatelist))." Cached / ".(int)count($templates->uncached_templates)." Manually Loaded)
    Memory Usage:{$memory_usage}Memory Limit:{$memory_limit}
    \n"; - - echo "

    Database Connections (".count($db->connections)." Total)

    \n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "
    ".implode("
    ", $db->connections)."
    \n"; - echo "
    \n"; - - echo "

    Database Queries (".$db->query_count." Total)

    \n"; - echo $db->explain; - - if($cache->call_count > 0) - { - echo "

    Cache Calls (".$cache->call_count." Total, ".$call_time.")

    \n"; - echo $cache->cache_debug; - } - - echo "

    Template Statistics

    \n"; - - if(count($templates->cache) > 0) - { - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "
    Templates Used (Loaded for this Page) - ".count($templates->cache)." Total
    ".implode(", ", array_keys($templates->cache))."
    \n"; - echo "
    \n"; - } - - if(count($templates->uncached_templates) > 0) - { - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "
    Templates Requiring Additional Calls (Not Cached at Startup) - ".count($templates->uncached_templates)." Total
    ".implode(", ", $templates->uncached_templates)."
    \n"; - echo "
    \n"; - } - echo ""; - echo ""; - exit; -} - -/** - * Outputs the correct page headers. - */ -function send_page_headers() -{ - global $mybb; - - if($mybb->settings['nocacheheaders'] == 1) - { - header("Expires: Sat, 1 Jan 2000 01:00:00 GMT"); - header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); - header("Cache-Control: no-cache, must-revalidate"); - header("Pragma: no-cache"); - } -} - -/** - * Mark specific reported posts of a certain type as dealt with - * - * @param array|int $id An array or int of the ID numbers you're marking as dealt with - * @param string $type The type of item the above IDs are for - post, posts, thread, threads, forum, all - */ -function mark_reports($id, $type="post") -{ - global $db, $cache, $plugins; - - switch($type) - { - case "posts": - if(is_array($id)) - { - $rids = implode($id, "','"); - $rids = "'0','$rids'"; - $db->update_query("reportedcontent", array('reportstatus' => 1), "id IN($rids) AND reportstatus='0' AND (type = 'post' OR type = '')"); - } - break; - case "post": - $db->update_query("reportedcontent", array('reportstatus' => 1), "id='$id' AND reportstatus='0' AND (type = 'post' OR type = '')"); - break; - case "threads": - if(is_array($id)) - { - $rids = implode($id, "','"); - $rids = "'0','$rids'"; - $db->update_query("reportedcontent", array('reportstatus' => 1), "id2 IN($rids) AND reportstatus='0' AND (type = 'post' OR type = '')"); - } - break; - case "thread": - $db->update_query("reportedcontent", array('reportstatus' => 1), "id2='$id' AND reportstatus='0' AND (type = 'post' OR type = '')"); - break; - case "forum": - $db->update_query("reportedcontent", array('reportstatus' => 1), "id3='$id' AND reportstatus='0' AND (type = 'post' OR type = '')"); - break; - case "all": - $db->update_query("reportedcontent", array('reportstatus' => 1), "reportstatus='0' AND (type = 'post' OR type = '')"); - break; - } - - $arguments = array('id' => $id, 'type' => $type); - $plugins->run_hooks("mark_reports", $arguments); - $cache->update_reportedcontent(); -} - -/** - * Fetch a friendly x days, y months etc date stamp from a timestamp - * - * @param int $stamp The timestamp - * @param array $options Array of options - * @return string The friendly formatted timestamp - */ -function nice_time($stamp, $options=array()) -{ - global $lang; - - $ysecs = 365*24*60*60; - $mosecs = 31*24*60*60; - $wsecs = 7*24*60*60; - $dsecs = 24*60*60; - $hsecs = 60*60; - $msecs = 60; - - if(isset($options['short'])) - { - $lang_year = $lang->year_short; - $lang_years = $lang->years_short; - $lang_month = $lang->month_short; - $lang_months = $lang->months_short; - $lang_week = $lang->week_short; - $lang_weeks = $lang->weeks_short; - $lang_day = $lang->day_short; - $lang_days = $lang->days_short; - $lang_hour = $lang->hour_short; - $lang_hours = $lang->hours_short; - $lang_minute = $lang->minute_short; - $lang_minutes = $lang->minutes_short; - $lang_second = $lang->second_short; - $lang_seconds = $lang->seconds_short; - } - else - { - $lang_year = " ".$lang->year; - $lang_years = " ".$lang->years; - $lang_month = " ".$lang->month; - $lang_months = " ".$lang->months; - $lang_week = " ".$lang->week; - $lang_weeks = " ".$lang->weeks; - $lang_day = " ".$lang->day; - $lang_days = " ".$lang->days; - $lang_hour = " ".$lang->hour; - $lang_hours = " ".$lang->hours; - $lang_minute = " ".$lang->minute; - $lang_minutes = " ".$lang->minutes; - $lang_second = " ".$lang->second; - $lang_seconds = " ".$lang->seconds; - } - - $years = floor($stamp/$ysecs); - $stamp %= $ysecs; - $months = floor($stamp/$mosecs); - $stamp %= $mosecs; - $weeks = floor($stamp/$wsecs); - $stamp %= $wsecs; - $days = floor($stamp/$dsecs); - $stamp %= $dsecs; - $hours = floor($stamp/$hsecs); - $stamp %= $hsecs; - $minutes = floor($stamp/$msecs); - $stamp %= $msecs; - $seconds = $stamp; - - if($years == 1) - { - $nicetime['years'] = "1".$lang_year; - } - else if($years > 1) - { - $nicetime['years'] = $years.$lang_years; - } - - if($months == 1) - { - $nicetime['months'] = "1".$lang_month; - } - else if($months > 1) - { - $nicetime['months'] = $months.$lang_months; - } - - if($weeks == 1) - { - $nicetime['weeks'] = "1".$lang_week; - } - else if($weeks > 1) - { - $nicetime['weeks'] = $weeks.$lang_weeks; - } - - if($days == 1) - { - $nicetime['days'] = "1".$lang_day; - } - else if($days > 1) - { - $nicetime['days'] = $days.$lang_days; - } - - if(!isset($options['hours']) || $options['hours'] !== false) - { - if($hours == 1) - { - $nicetime['hours'] = "1".$lang_hour; - } - else if($hours > 1) - { - $nicetime['hours'] = $hours.$lang_hours; - } - } - - if(!isset($options['minutes']) || $options['minutes'] !== false) - { - if($minutes == 1) - { - $nicetime['minutes'] = "1".$lang_minute; - } - else if($minutes > 1) - { - $nicetime['minutes'] = $minutes.$lang_minutes; - } - } - - if(!isset($options['seconds']) || $options['seconds'] !== false) - { - if($seconds == 1) - { - $nicetime['seconds'] = "1".$lang_second; - } - else if($seconds > 1) - { - $nicetime['seconds'] = $seconds.$lang_seconds; - } - } - - if(is_array($nicetime)) - { - return implode(", ", $nicetime); - } -} - -/** - * Select an alternating row colour based on the previous call to this function - * - * @param int $reset 1 to reset the row to trow1. - * @return string trow1 or trow2 depending on the previous call - */ -function alt_trow($reset=0) -{ - global $alttrow; - - if($alttrow == "trow1" && !$reset) - { - $trow = "trow2"; - } - else - { - $trow = "trow1"; - } - - $alttrow = $trow; - - return $trow; -} - -/** - * Add a user to a specific additional user group. - * - * @param int $uid The user ID - * @param int $joingroup The user group ID to join - * @return bool - */ -function join_usergroup($uid, $joingroup) -{ - global $db, $mybb; - - if($uid == $mybb->user['uid']) - { - $user = $mybb->user; - } - else - { - $query = $db->simple_select("users", "additionalgroups, usergroup", "uid='".(int)$uid."'"); - $user = $db->fetch_array($query); - } - - // Build the new list of additional groups for this user and make sure they're in the right format - $usergroups = ""; - $usergroups = $user['additionalgroups'].",".$joingroup; - $groupslist = ""; - $groups = explode(",", $usergroups); - - if(is_array($groups)) - { - $comma = ''; - foreach($groups as $gid) - { - if(trim($gid) != "" && $gid != $user['usergroup'] && !isset($donegroup[$gid])) - { - $groupslist .= $comma.$gid; - $comma = ","; - $donegroup[$gid] = 1; - } - } - } - - // What's the point in updating if they're the same? - if($groupslist != $user['additionalgroups']) - { - $db->update_query("users", array('additionalgroups' => $groupslist), "uid='".(int)$uid."'"); - return true; - } - else - { - return false; - } -} - -/** - * Remove a user from a specific additional user group - * - * @param int $uid The user ID - * @param int $leavegroup The user group ID - */ -function leave_usergroup($uid, $leavegroup) -{ - global $db, $mybb, $cache; - - $user = get_user($uid); - - $groupslist = $comma = ''; - $usergroups = $user['additionalgroups'].","; - $donegroup = array(); - - $groups = explode(",", $user['additionalgroups']); - - if(is_array($groups)) - { - foreach($groups as $gid) - { - if(trim($gid) != "" && $leavegroup != $gid && empty($donegroup[$gid])) - { - $groupslist .= $comma.$gid; - $comma = ","; - $donegroup[$gid] = 1; - } - } - } - - $dispupdate = ""; - if($leavegroup == $user['displaygroup']) - { - $dispupdate = ", displaygroup=usergroup"; - } - - $db->write_query(" - UPDATE ".TABLE_PREFIX."users - SET additionalgroups='$groupslist' $dispupdate - WHERE uid='".(int)$uid."' - "); - - $cache->update_moderators(); -} - -/** - * Get the current location taking in to account different web serves and systems - * - * @param boolean $fields True to return as "hidden" fields - * @param array $ignore Array of fields to ignore if first argument is true - * @param boolean $quick True to skip all inputs and return only the file path part of the URL - * @return string The current URL being accessed - */ -function get_current_location($fields=false, $ignore=array(), $quick=false) -{ - if(defined("MYBB_LOCATION")) - { - return MYBB_LOCATION; - } - - if(!empty($_SERVER['SCRIPT_NAME'])) - { - $location = htmlspecialchars_uni($_SERVER['SCRIPT_NAME']); - } - elseif(!empty($_SERVER['PHP_SELF'])) - { - $location = htmlspecialchars_uni($_SERVER['PHP_SELF']); - } - elseif(!empty($_ENV['PHP_SELF'])) - { - $location = htmlspecialchars_uni($_ENV['PHP_SELF']); - } - elseif(!empty($_SERVER['PATH_INFO'])) - { - $location = htmlspecialchars_uni($_SERVER['PATH_INFO']); - } - else - { - $location = htmlspecialchars_uni($_ENV['PATH_INFO']); - } - - if($quick) - { - return $location; - } - - if($fields == true) - { - global $mybb; - - if(!is_array($ignore)) - { - $ignore = array($ignore); - } - - $form_html = ''; - if(!empty($mybb->input)) - { - foreach($mybb->input as $name => $value) - { - if(in_array($name, $ignore) || is_array($name) || is_array($value)) - { - continue; - } - - $form_html .= "\n"; - } - } - - return array('location' => $location, 'form_html' => $form_html, 'form_method' => $mybb->request_method); - } - else - { - if(isset($_SERVER['QUERY_STRING'])) - { - $location .= "?".htmlspecialchars_uni($_SERVER['QUERY_STRING']); - } - else if(isset($_ENV['QUERY_STRING'])) - { - $location .= "?".htmlspecialchars_uni($_ENV['QUERY_STRING']); - } - - if((isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == "POST") || (isset($_ENV['REQUEST_METHOD']) && $_ENV['REQUEST_METHOD'] == "POST")) - { - $post_array = array('action', 'fid', 'pid', 'tid', 'uid', 'eid'); - - foreach($post_array as $var) - { - if(isset($_POST[$var])) - { - $addloc[] = urlencode($var).'='.urlencode($_POST[$var]); - } - } - - if(isset($addloc) && is_array($addloc)) - { - if(strpos($location, "?") === false) - { - $location .= "?"; - } - else - { - $location .= "&"; - } - $location .= implode("&", $addloc); - } - } - - return $location; - } -} - -/** - * Build a theme selection menu - * - * @param string $name The name of the menu - * @param int $selected The ID of the selected theme - * @param int $tid The ID of the parent theme to select from - * @param string $depth The current selection depth - * @param boolean $usergroup_override Whether or not to override usergroup permissions (true to override) - * @param boolean $footer Whether or not theme select is in the footer (true if it is) - * @param boolean $count_override Whether or not to override output based on theme count (true to override) - * @return string The theme selection list - */ -function build_theme_select($name, $selected=-1, $tid=0, $depth="", $usergroup_override=false, $footer=false, $count_override=false) -{ - global $db, $themeselect, $tcache, $lang, $mybb, $limit, $templates, $num_themes, $themeselect_option; - - if($tid == 0) - { - $tid = 1; - $num_themes = 0; - $themeselect_option = ''; - - if(!isset($lang->use_default)) - { - $lang->use_default = $lang->lang_select_default; - } - } - - if(!is_array($tcache)) - { - $query = $db->simple_select('themes', 'tid, name, pid, allowedgroups', "pid!='0'"); - - while($theme = $db->fetch_array($query)) - { - $tcache[$theme['pid']][$theme['tid']] = $theme; - } - } - - if(is_array($tcache[$tid])) - { - foreach($tcache[$tid] as $theme) - { - $sel = ""; - // Show theme if allowed, or if override is on - if(is_member($theme['allowedgroups']) || $theme['allowedgroups'] == "all" || $usergroup_override == true) - { - if($theme['tid'] == $selected) - { - $sel = " selected=\"selected\""; - } - - if($theme['pid'] != 0) - { - $theme['name'] = htmlspecialchars_uni($theme['name']); - eval("\$themeselect_option .= \"".$templates->get("usercp_themeselector_option")."\";"); - ++$num_themes; - $depthit = $depth."--"; - } - - if(array_key_exists($theme['tid'], $tcache)) - { - build_theme_select($name, $selected, $theme['tid'], $depthit, $usergroup_override, $footer, $count_override); - } - } - } - } - - if($tid == 1 && ($num_themes > 1 || $count_override == true)) - { - if($footer == true) - { - eval("\$themeselect = \"".$templates->get("footer_themeselector")."\";"); - } - else - { - eval("\$themeselect = \"".$templates->get("usercp_themeselector")."\";"); - } - - return $themeselect; - } - else - { - return false; - } -} - -/** - * Get the theme data of a theme id. - * - * @param int $tid The theme id of the theme. - * @return boolean|array False if no valid theme, Array with the theme data otherwise - */ -function get_theme($tid) -{ - global $tcache, $db; - - if(!is_array($tcache)) - { - $query = $db->simple_select('themes', 'tid, name, pid, allowedgroups', "pid!='0'"); - - while($theme = $db->fetch_array($query)) - { - $tcache[$theme['pid']][$theme['tid']] = $theme; - } - } - - $s_theme = false; - - foreach($tcache as $themes) - { - foreach($themes as $theme) - { - if($tid == $theme['tid']) - { - $s_theme = $theme; - break 2; - } - } - } - - return $s_theme; -} - -/** - * Custom function for htmlspecialchars which takes in to account unicode - * - * @param string $message The string to format - * @return string The string with htmlspecialchars applied - */ -function htmlspecialchars_uni($message) -{ - $message = preg_replace("#&(?!\#[0-9]+;)#si", "&", $message); // Fix & but allow unicode - $message = str_replace("<", "<", $message); - $message = str_replace(">", ">", $message); - $message = str_replace("\"", """, $message); - return $message; -} - -/** - * Custom function for formatting numbers. - * - * @param int $number The number to format. - * @return int The formatted number. - */ -function my_number_format($number) -{ - global $mybb; - - if($number == "-") - { - return $number; - } - - if(is_int($number)) - { - return number_format($number, 0, $mybb->settings['decpoint'], $mybb->settings['thousandssep']); - } - else - { - $parts = explode('.', $number); - - if(isset($parts[1])) - { - $decimals = my_strlen($parts[1]); - } - else - { - $decimals = 0; - } - - return number_format((double)$number, $decimals, $mybb->settings['decpoint'], $mybb->settings['thousandssep']); - } -} - -/** - * Converts a string of text to or from UTF-8. - * - * @param string $str The string of text to convert - * @param boolean $to Whether or not the string is being converted to or from UTF-8 (true if converting to) - * @return string The converted string - */ -function convert_through_utf8($str, $to=true) -{ - global $lang; - static $charset; - static $use_mb; - static $use_iconv; - - if(!isset($charset)) - { - $charset = my_strtolower($lang->settings['charset']); - } - - if($charset == "utf-8") - { - return $str; - } - - if(!isset($use_iconv)) - { - $use_iconv = function_exists("iconv"); - } - - if(!isset($use_mb)) - { - $use_mb = function_exists("mb_convert_encoding"); - } - - if($use_iconv || $use_mb) - { - if($to) - { - $from_charset = $lang->settings['charset']; - $to_charset = "UTF-8"; - } - else - { - $from_charset = "UTF-8"; - $to_charset = $lang->settings['charset']; - } - if($use_iconv) - { - return iconv($from_charset, $to_charset."//IGNORE", $str); - } - else - { - return @mb_convert_encoding($str, $to_charset, $from_charset); - } - } - elseif($charset == "iso-8859-1" && function_exists("utf8_encode")) - { - if($to) - { - return utf8_encode($str); - } - else - { - return utf8_decode($str); - } - } - else - { - return $str; - } -} - -/** - * DEPRECATED! Please use other alternatives. - * - * @deprecated - * @param string $message - * - * @return string - */ -function my_wordwrap($message) -{ - return $message; -} - -/** - * Workaround for date limitation in PHP to establish the day of a birthday (Provided by meme) - * - * @param int $month The month of the birthday - * @param int $day The day of the birthday - * @param int $year The year of the bithday - * @return int The numeric day of the week for the birthday - */ -function get_weekday($month, $day, $year) -{ - $h = 4; - - for($i = 1969; $i >= $year; $i--) - { - $j = get_bdays($i); - - for($k = 11; $k >= 0; $k--) - { - $l = ($k + 1); - - for($m = $j[$k]; $m >= 1; $m--) - { - $h--; - - if($i == $year && $l == $month && $m == $day) - { - return $h; - } - - if($h == 0) - { - $h = 7; - } - } - } - } -} - -/** - * Workaround for date limitation in PHP to establish the day of a birthday (Provided by meme) - * - * @param int $in The year. - * @return array The number of days in each month of that year - */ -function get_bdays($in) -{ - return array( - 31, - ($in % 4 == 0 && ($in % 100 > 0 || $in % 400 == 0) ? 29 : 28), - 31, - 30, - 31, - 30, - 31, - 31, - 30, - 31, - 30, - 31 - ); -} - -/** - * DEPRECATED! Please use mktime()! - * Formats a birthday appropriately - * - * @deprecated - * @param string $display The PHP date format string - * @param int $bm The month of the birthday - * @param int $bd The day of the birthday - * @param int $by The year of the birthday - * @param int $wd The weekday of the birthday - * @return string The formatted birthday - */ -function format_bdays($display, $bm, $bd, $by, $wd) -{ - global $lang; - - $bdays = array( - $lang->sunday, - $lang->monday, - $lang->tuesday, - $lang->wednesday, - $lang->thursday, - $lang->friday, - $lang->saturday - ); - - $bmonth = array( - $lang->month_1, - $lang->month_2, - $lang->month_3, - $lang->month_4, - $lang->month_5, - $lang->month_6, - $lang->month_7, - $lang->month_8, - $lang->month_9, - $lang->month_10, - $lang->month_11, - $lang->month_12 - ); - - - // This needs to be in this specific order - $find = array( - 'm', - 'n', - 'd', - 'D', - 'y', - 'Y', - 'j', - 'S', - 'F', - 'l', - 'M', - ); - - $html = array( - 'm', - 'n', - 'c', - 'D', - 'y', - 'Y', - 'j', - 'S', - 'F', - 'l', - 'M', - ); - - $bdays = str_replace($find, $html, $bdays); - $bmonth = str_replace($find, $html, $bmonth); - - $replace = array( - sprintf('%02s', $bm), - $bm, - sprintf('%02s', $bd), - ($wd == 2 ? my_substr($bdays[$wd], 0, 4) : ($wd == 4 ? my_substr($bdays[$wd], 0, 5) : my_substr($bdays[$wd], 0, 3))), - my_substr($by, 2), - $by, - ($bd[0] == 0 ? my_substr($bd, 1) : $bd), - ($bd == 1 || $bd == 21 || $bd == 31 ? 'st' : ($bd == 2 || $bd == 22 ? 'nd' : ($bd == 3 || $bd == 23 ? 'rd' : 'th'))), - $bmonth[$bm-1], - $wd, - ($bm == 9 ? my_substr($bmonth[$bm-1], 0, 4) : my_substr($bmonth[$bm-1], 0, 3)), - ); - - // Do we have the full month in our output? - // If so there's no need for the short month - if(strpos($display, 'F') !== false) - { - array_pop($find); - array_pop($replace); - } - - return str_replace($find, $replace, $display); -} - -/** - * Returns the age of a user with specified birthday. - * - * @param string $birthday The birthday of a user. - * @return int The age of a user with that birthday. - */ -function get_age($birthday) -{ - $bday = explode("-", $birthday); - if(!$bday[2]) - { - return; - } - - list($day, $month, $year) = explode("-", my_date("j-n-Y", TIME_NOW, 0, 0)); - - $age = $year-$bday[2]; - - if(($month == $bday[1] && $day < $bday[0]) || $month < $bday[1]) - { - --$age; - } - return $age; -} - -/** - * Updates the first posts in a thread. - * - * @param int $tid The thread id for which to update the first post id. - */ -function update_first_post($tid) -{ - global $db; - - $query = $db->query(" - SELECT u.uid, u.username, p.pid, p.username AS postusername, p.dateline - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.tid='$tid' - ORDER BY p.dateline ASC - LIMIT 1 - "); - $firstpost = $db->fetch_array($query); - - if(empty($firstpost['username'])) - { - $firstpost['username'] = $firstpost['postusername']; - } - $firstpost['username'] = $db->escape_string($firstpost['username']); - - $update_array = array( - 'firstpost' => (int)$firstpost['pid'], - 'username' => $firstpost['username'], - 'uid' => (int)$firstpost['uid'], - 'dateline' => (int)$firstpost['dateline'] - ); - $db->update_query("threads", $update_array, "tid='{$tid}'"); -} - -/** - * Updates the last posts in a thread. - * - * @param int $tid The thread id for which to update the last post id. - */ -function update_last_post($tid) -{ - global $db; - - $query = $db->query(" - SELECT u.uid, u.username, p.username AS postusername, p.dateline - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.tid='$tid' AND p.visible='1' - ORDER BY p.dateline DESC - LIMIT 1" - ); - $lastpost = $db->fetch_array($query); - - if(empty($lastpost['username'])) - { - $lastpost['username'] = $lastpost['postusername']; - } - - if(empty($lastpost['dateline'])) - { - $query = $db->query(" - SELECT u.uid, u.username, p.pid, p.username AS postusername, p.dateline - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.tid='$tid' - ORDER BY p.dateline ASC - LIMIT 1 - "); - $firstpost = $db->fetch_array($query); - - $lastpost['username'] = $firstpost['username']; - $lastpost['uid'] = $firstpost['uid']; - $lastpost['dateline'] = $firstpost['dateline']; - } - - $lastpost['username'] = $db->escape_string($lastpost['username']); - - $update_array = array( - 'lastpost' => (int)$lastpost['dateline'], - 'lastposter' => $lastpost['username'], - 'lastposteruid' => (int)$lastpost['uid'] - ); - $db->update_query("threads", $update_array, "tid='{$tid}'"); -} - -/** - * Checks for the length of a string, mb strings accounted for - * - * @param string $string The string to check the length of. - * @return int The length of the string. - */ -function my_strlen($string) -{ - global $lang; - - $string = preg_replace("#&\#([0-9]+);#", "-", $string); - - if(strtolower($lang->settings['charset']) == "utf-8") - { - // Get rid of any excess RTL and LTR override for they are the workings of the devil - $string = str_replace(dec_to_utf8(8238), "", $string); - $string = str_replace(dec_to_utf8(8237), "", $string); - - // Remove dodgy whitespaces - $string = str_replace(chr(0xCA), "", $string); - } - $string = trim($string); - - if(function_exists("mb_strlen")) - { - $string_length = mb_strlen($string); - } - else - { - $string_length = strlen($string); - } - - return $string_length; -} - -/** - * Cuts a string at a specified point, mb strings accounted for - * - * @param string $string The string to cut. - * @param int $start Where to cut - * @param int $length (optional) How much to cut - * @param bool $handle_entities (optional) Properly handle HTML entities? - * @return string The cut part of the string. - */ -function my_substr($string, $start, $length=null, $handle_entities = false) -{ - if($handle_entities) - { - $string = unhtmlentities($string); - } - if(function_exists("mb_substr")) - { - if($length != null) - { - $cut_string = mb_substr($string, $start, $length); - } - else - { - $cut_string = mb_substr($string, $start); - } - } - else - { - if($length != null) - { - $cut_string = substr($string, $start, $length); - } - else - { - $cut_string = substr($string, $start); - } - } - - if($handle_entities) - { - $cut_string = htmlspecialchars_uni($cut_string); - } - return $cut_string; -} - -/** - * Lowers the case of a string, mb strings accounted for - * - * @param string $string The string to lower. - * @return string The lowered string. - */ -function my_strtolower($string) -{ - if(function_exists("mb_strtolower")) - { - $string = mb_strtolower($string); - } - else - { - $string = strtolower($string); - } - - return $string; -} - -/** - * Finds a needle in a haystack and returns it position, mb strings accounted for - * - * @param string $haystack String to look in (haystack) - * @param string $needle What to look for (needle) - * @param int $offset (optional) How much to offset - * @return int|bool false on needle not found, integer position if found - */ -function my_strpos($haystack, $needle, $offset=0) -{ - if($needle == '') - { - return false; - } - - if(function_exists("mb_strpos")) - { - $position = mb_strpos($haystack, $needle, $offset); - } - else - { - $position = strpos($haystack, $needle, $offset); - } - - return $position; -} - -/** - * Ups the case of a string, mb strings accounted for - * - * @param string $string The string to up. - * @return string The uped string. - */ -function my_strtoupper($string) -{ - if(function_exists("mb_strtoupper")) - { - $string = mb_strtoupper($string); - } - else - { - $string = strtoupper($string); - } - - return $string; -} - -/** - * Returns any html entities to their original character - * - * @param string $string The string to un-htmlentitize. - * @return string The un-htmlentitied' string. - */ -function unhtmlentities($string) -{ - // Replace numeric entities - $string = preg_replace_callback('~&#x([0-9a-f]+);~i', create_function('$matches', 'return unichr(hexdec($matches[1]));'), $string); - $string = preg_replace_callback('~&#([0-9]+);~', create_function('$matches', 'return unichr($matches[1]);'), $string); - - // Replace literal entities - $trans_tbl = get_html_translation_table(HTML_ENTITIES); - $trans_tbl = array_flip($trans_tbl); - - return strtr($string, $trans_tbl); -} - -/** - * Returns any ascii to it's character (utf-8 safe). - * - * @param int $c The ascii to characterize. - * @return string|bool The characterized ascii. False on failure - */ -function unichr($c) -{ - if($c <= 0x7F) - { - return chr($c); - } - else if($c <= 0x7FF) - { - return chr(0xC0 | $c >> 6) . chr(0x80 | $c & 0x3F); - } - else if($c <= 0xFFFF) - { - return chr(0xE0 | $c >> 12) . chr(0x80 | $c >> 6 & 0x3F) - . chr(0x80 | $c & 0x3F); - } - else if($c <= 0x10FFFF) - { - return chr(0xF0 | $c >> 18) . chr(0x80 | $c >> 12 & 0x3F) - . chr(0x80 | $c >> 6 & 0x3F) - . chr(0x80 | $c & 0x3F); - } - else - { - return false; - } -} - -/** - * Get the event poster. - * - * @param array $event The event data array. - * @return string The link to the event poster. - */ -function get_event_poster($event) -{ - $event['username'] = htmlspecialchars_uni($event['username']); - $event['username'] = format_name($event['username'], $event['usergroup'], $event['displaygroup']); - $event_poster = build_profile_link($event['username'], $event['author']); - return $event_poster; -} - -/** - * Get the event date. - * - * @param array $event The event data array. - * @return string The event date. - */ -function get_event_date($event) -{ - global $mybb; - - $event_date = explode("-", $event['date']); - $event_date = gmmktime(0, 0, 0, $event_date[1], $event_date[0], $event_date[2]); - $event_date = my_date($mybb->settings['dateformat'], $event_date); - - return $event_date; -} - -/** - * Get the profile link. - * - * @param int $uid The user id of the profile. - * @return string The url to the profile. - */ -function get_profile_link($uid=0) -{ - $link = str_replace("{uid}", $uid, PROFILE_URL); - return htmlspecialchars_uni($link); -} - -/** - * Get the announcement link. - * - * @param int $aid The announement id of the announcement. - * @return string The url to the announcement. - */ -function get_announcement_link($aid=0) -{ - $link = str_replace("{aid}", $aid, ANNOUNCEMENT_URL); - return htmlspecialchars_uni($link); -} - -/** - * Build the profile link. - * - * @param string $username The Username of the profile. - * @param int $uid The user id of the profile. - * @param string $target The target frame - * @param string $onclick Any onclick javascript. - * @return string The complete profile link. - */ -function build_profile_link($username="", $uid=0, $target="", $onclick="") -{ - global $mybb, $lang; - - if(!$username && $uid == 0) - { - // Return Guest phrase for no UID, no guest nickname - return $lang->guest; - } - elseif($uid == 0) - { - // Return the guest's nickname if user is a guest but has a nickname - return $username; - } - else - { - // Build the profile link for the registered user - if(!empty($target)) - { - $target = " target=\"{$target}\""; - } - - if(!empty($onclick)) - { - $onclick = " onclick=\"{$onclick}\""; - } - - return "settings['bburl']}/".get_profile_link($uid)."\"{$target}{$onclick}>{$username}"; - } -} - -/** - * Build the forum link. - * - * @param int $fid The forum id of the forum. - * @param int $page (Optional) The page number of the forum. - * @return string The url to the forum. - */ -function get_forum_link($fid, $page=0) -{ - if($page > 0) - { - $link = str_replace("{fid}", $fid, FORUM_URL_PAGED); - $link = str_replace("{page}", $page, $link); - return htmlspecialchars_uni($link); - } - else - { - $link = str_replace("{fid}", $fid, FORUM_URL); - return htmlspecialchars_uni($link); - } -} - -/** - * Build the thread link. - * - * @param int $tid The thread id of the thread. - * @param int $page (Optional) The page number of the thread. - * @param string $action (Optional) The action we're performing (ex, lastpost, newpost, etc) - * @return string The url to the thread. - */ -function get_thread_link($tid, $page=0, $action='') -{ - if($page > 1) - { - if($action) - { - $link = THREAD_URL_ACTION; - $link = str_replace("{action}", $action, $link); - } - else - { - $link = THREAD_URL_PAGED; - } - $link = str_replace("{tid}", $tid, $link); - $link = str_replace("{page}", $page, $link); - return htmlspecialchars_uni($link); - } - else - { - if($action) - { - $link = THREAD_URL_ACTION; - $link = str_replace("{action}", $action, $link); - } - else - { - $link = THREAD_URL; - } - $link = str_replace("{tid}", $tid, $link); - return htmlspecialchars_uni($link); - } -} - -/** - * Build the post link. - * - * @param int $pid The post ID of the post - * @param int $tid The thread id of the post. - * @return string The url to the post. - */ -function get_post_link($pid, $tid=0) -{ - if($tid > 0) - { - $link = str_replace("{tid}", $tid, THREAD_URL_POST); - $link = str_replace("{pid}", $pid, $link); - return htmlspecialchars_uni($link); - } - else - { - $link = str_replace("{pid}", $pid, POST_URL); - return htmlspecialchars_uni($link); - } -} - -/** - * Build the event link. - * - * @param int $eid The event ID of the event - * @return string The URL of the event - */ -function get_event_link($eid) -{ - $link = str_replace("{eid}", $eid, EVENT_URL); - return htmlspecialchars_uni($link); -} - -/** - * Build the link to a specified date on the calendar - * - * @param int $calendar The ID of the calendar - * @param int $year The year - * @param int $month The month - * @param int $day The day (optional) - * @return string The URL of the calendar - */ -function get_calendar_link($calendar, $year=0, $month=0, $day=0) -{ - if($day > 0) - { - $link = str_replace("{month}", $month, CALENDAR_URL_DAY); - $link = str_replace("{year}", $year, $link); - $link = str_replace("{day}", $day, $link); - $link = str_replace("{calendar}", $calendar, $link); - return htmlspecialchars_uni($link); - } - else if($month > 0) - { - $link = str_replace("{month}", $month, CALENDAR_URL_MONTH); - $link = str_replace("{year}", $year, $link); - $link = str_replace("{calendar}", $calendar, $link); - return htmlspecialchars_uni($link); - } - /* Not implemented - else if($year > 0) - { - }*/ - else - { - $link = str_replace("{calendar}", $calendar, CALENDAR_URL); - return htmlspecialchars_uni($link); - } -} - -/** - * Build the link to a specified week on the calendar - * - * @param int $calendar The ID of the calendar - * @param int $week The week - * @return string The URL of the calendar - */ -function get_calendar_week_link($calendar, $week) -{ - if($week < 0) - { - $week = str_replace('-', "n", $week); - } - $link = str_replace("{week}", $week, CALENDAR_URL_WEEK); - $link = str_replace("{calendar}", $calendar, $link); - return htmlspecialchars_uni($link); -} - -/** - * Get the user data of an user id. - * - * @param int $uid The user id of the user. - * @return array The users data - */ -function get_user($uid) -{ - global $mybb, $db; - static $user_cache; - - $uid = (int)$uid; - - if(!empty($mybb->user) && $uid == $mybb->user['uid']) - { - return $mybb->user; - } - elseif(isset($user_cache[$uid])) - { - return $user_cache[$uid]; - } - elseif($uid > 0) - { - $query = $db->simple_select("users", "*", "uid = '{$uid}'"); - $user_cache[$uid] = $db->fetch_array($query); - - return $user_cache[$uid]; - } - return array(); -} - -/** - * Get the user data of an user username. - * - * @param string $username The user username of the user. - * @param array $options - * @return array The users data - */ -function get_user_by_username($username, $options=array()) -{ - global $mybb, $db; - - $username = $db->escape_string(my_strtolower($username)); - - if(!isset($options['username_method'])) - { - $options['username_method'] = 0; - } - - switch($db->type) - { - case 'mysql': - case 'mysqli': - $field = 'username'; - $efield = 'email'; - break; - default: - $field = 'LOWER(username)'; - $efield = 'LOWER(email)'; - break; - } - - switch($options['username_method']) - { - case 1: - $sqlwhere = "{$efield}='{$username}'"; - break; - case 2: - $sqlwhere = "{$field}='{$username}' OR {$efield}='{$username}'"; - break; - default: - $sqlwhere = "{$field}='{$username}'"; - break; - } - - $fields = array('uid'); - if(isset($options['fields'])) - { - $fields = array_merge((array)$options['fields'], $fields); - } - - $query = $db->simple_select('users', implode(',', array_unique($fields)), $sqlwhere, array('limit' => 1)); - - if(isset($options['exists'])) - { - return (bool)$db->num_rows($query); - } - - return $db->fetch_array($query); -} - -/** - * Get the forum of a specific forum id. - * - * @param int $fid The forum id of the forum. - * @param int $active_override (Optional) If set to 1, will override the active forum status - * @return array|bool The database row of a forum. False on failure - */ -function get_forum($fid, $active_override=0) -{ - global $cache; - static $forum_cache; - - if(!isset($forum_cache) || is_array($forum_cache)) - { - $forum_cache = $cache->read("forums"); - } - - if(empty($forum_cache[$fid])) - { - return false; - } - - if($active_override != 1) - { - $parents = explode(",", $forum_cache[$fid]['parentlist']); - if(is_array($parents)) - { - foreach($parents as $parent) - { - if($forum_cache[$parent]['active'] == 0) - { - return false; - } - } - } - } - - return $forum_cache[$fid]; -} - -/** - * Get the thread of a thread id. - * - * @param int $tid The thread id of the thread. - * @param boolean $recache Whether or not to recache the thread. - * @return array|bool The database row of the thread. False on failure - */ -function get_thread($tid, $recache = false) -{ - global $db; - static $thread_cache; - - $tid = (int)$tid; - - if(isset($thread_cache[$tid]) && !$recache) - { - return $thread_cache[$tid]; - } - else - { - $query = $db->simple_select("threads", "*", "tid = '{$tid}'"); - $thread = $db->fetch_array($query); - - if($thread) - { - $thread_cache[$tid] = $thread; - return $thread; - } - else - { - $thread_cache[$tid] = false; - return false; - } - } -} - -/** - * Get the post of a post id. - * - * @param int $pid The post id of the post. - * @return array|bool The database row of the post. False on failure - */ -function get_post($pid) -{ - global $db; - static $post_cache; - - $pid = (int)$pid; - - if(isset($post_cache[$pid])) - { - return $post_cache[$pid]; - } - else - { - $query = $db->simple_select("posts", "*", "pid = '{$pid}'"); - $post = $db->fetch_array($query); - - if($post) - { - $post_cache[$pid] = $post; - return $post; - } - else - { - $post_cache[$pid] = false; - return false; - } - } -} - -/** - * Get inactivate forums. - * - * @return string The comma separated values of the inactivate forum. - */ -function get_inactive_forums() -{ - global $forum_cache, $cache; - - if(!$forum_cache) - { - cache_forums(); - } - - $inactive = array(); - - foreach($forum_cache as $fid => $forum) - { - if($forum['active'] == 0) - { - $inactive[] = $fid; - foreach($forum_cache as $fid1 => $forum1) - { - if(my_strpos(",".$forum1['parentlist'].",", ",".$fid.",") !== false && !in_array($fid1, $inactive)) - { - $inactive[] = $fid1; - } - } - } - } - - $inactiveforums = implode(",", $inactive); - - return $inactiveforums; -} - -/** - * Checks to make sure a user has not tried to login more times than permitted - * - * @param bool $fatal (Optional) Stop execution if it finds an error with the login. Default is True - * @return bool|int Number of logins when success, false if failed. - */ -function login_attempt_check($fatal = true) -{ - global $mybb, $lang, $session, $db; - - if($mybb->settings['failedlogincount'] == 0) - { - return 1; - } - // Note: Number of logins is defaulted to 1, because using 0 seems to clear cookie data. Not really a problem as long as we account for 1 being default. - - // Use cookie if possible, otherwise use session - // Find better solution to prevent clearing cookies - $loginattempts = 0; - $failedlogin = 0; - - if(!empty($mybb->cookies['loginattempts'])) - { - $loginattempts = $mybb->cookies['loginattempts']; - } - - if(!empty($mybb->cookies['failedlogin'])) - { - $failedlogin = $mybb->cookies['failedlogin']; - } - - // Work out if the user has had more than the allowed number of login attempts - if($loginattempts > $mybb->settings['failedlogincount']) - { - // If so, then we need to work out if they can try to login again - // Some maths to work out how long they have left and display it to them - $now = TIME_NOW; - - if(empty($mybb->cookies['failedlogin'])) - { - $failedtime = $now; - } - else - { - $failedtime = $mybb->cookies['failedlogin']; - } - - $secondsleft = $mybb->settings['failedlogintime'] * 60 + $failedtime - $now; - $hoursleft = floor($secondsleft / 3600); - $minsleft = floor(($secondsleft / 60) % 60); - $secsleft = floor($secondsleft % 60); - - // This value will be empty the first time the user doesn't login in, set it - if(empty($failedlogin)) - { - my_setcookie('failedlogin', $now); - if($fatal) - { - error($lang->sprintf($lang->failed_login_wait, $hoursleft, $minsleft, $secsleft)); - } - - return false; - } - - // Work out if the user has waited long enough before letting them login again - if($mybb->cookies['failedlogin'] < ($now - $mybb->settings['failedlogintime'] * 60)) - { - my_setcookie('loginattempts', 1); - my_unsetcookie('failedlogin'); - if($mybb->user['uid'] != 0) - { - $update_array = array( - 'loginattempts' => 1 - ); - $db->update_query("users", $update_array, "uid = '{$mybb->user['uid']}'"); - } - return 1; - } - // Not waited long enough - else if($mybb->cookies['failedlogin'] > ($now - $mybb->settings['failedlogintime'] * 60)) - { - if($fatal) - { - error($lang->sprintf($lang->failed_login_wait, $hoursleft, $minsleft, $secsleft)); - } - - return false; - } - } - - // User can attempt another login - return $loginattempts; -} - -/** - * Validates the format of an email address. - * - * @param string $email The string to check. - * @return boolean True when valid, false when invalid. - */ -function validate_email_format($email) -{ - if(strpos($email, ' ') !== false) - { - return false; - } - // Valid local characters for email addresses: http://www.remote.org/jochen/mail/info/chars.html - return preg_match("/^[a-zA-Z0-9&*+\-_.{}~^\?=\/]+@[a-zA-Z0-9-]+\.([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]{2,}$/si", $email); -} - -/** - * Checks to see if the email is already in use by another - * - * @param string $email The email to check. - * @param int $uid User ID of the user (updating only) - * @return boolean True when in use, false when not. - */ -function email_already_in_use($email, $uid=0) -{ - global $db; - - $uid_string = ""; - if($uid) - { - $uid_string = " AND uid != '".(int)$uid."'"; - } - $query = $db->simple_select("users", "COUNT(email) as emails", "email = '".$db->escape_string($email)."'{$uid_string}"); - - if($db->fetch_field($query, "emails") > 0) - { - return true; - } - - return false; -} - -/** - * Rebuilds settings.php - * - */ -function rebuild_settings() -{ - global $db, $mybb; - - if(!file_exists(MYBB_ROOT."inc/settings.php")) - { - $mode = "x"; - } - else - { - $mode = "w"; - } - - $options = array( - "order_by" => "title", - "order_dir" => "ASC" - ); - $query = $db->simple_select("settings", "value, name", "", $options); - - $settings = null; - while($setting = $db->fetch_array($query)) - { - $mybb->settings[$setting['name']] = $setting['value']; - $setting['value'] = addcslashes($setting['value'], '\\"$'); - $settings .= "\$settings['{$setting['name']}'] = \"{$setting['value']}\";\n"; - } - - $settings = "<"."?php\n/*********************************\ \n DO NOT EDIT THIS FILE, PLEASE USE\n THE SETTINGS EDITOR\n\*********************************/\n\n$settings\n"; - $file = @fopen(MYBB_ROOT."inc/settings.php", $mode); - @fwrite($file, $settings); - @fclose($file); - - $GLOBALS['settings'] = &$mybb->settings; -} - -/** - * Build a PREG compatible array of search highlight terms to replace in posts. - * - * @param string $terms Incoming terms to highlight - * @return array PREG compatible array of terms - */ -function build_highlight_array($terms) -{ - global $mybb; - - if($mybb->settings['minsearchword'] < 1) - { - $mybb->settings['minsearchword'] = 3; - } - - if(is_array($terms)) - { - $terms = implode(' ', $terms); - } - - // Strip out any characters that shouldn't be included - $bad_characters = array( - "(", - ")", - "+", - "-", - "~" - ); - $terms = str_replace($bad_characters, '', $terms); - - // Check if this is a "series of words" - should be treated as an EXACT match - if(my_strpos($terms, "\"") !== false) - { - $inquote = false; - $terms = explode("\"", $terms); - $words = array(); - foreach($terms as $phrase) - { - $phrase = htmlspecialchars_uni($phrase); - if($phrase != "") - { - if($inquote) - { - $words[] = trim($phrase); - } - else - { - $split_words = preg_split("#\s{1,}#", $phrase, -1); - if(!is_array($split_words)) - { - continue; - } - foreach($split_words as $word) - { - if(!$word || strlen($word) < $mybb->settings['minsearchword']) - { - continue; - } - $words[] = trim($word); - } - } - } - $inquote = !$inquote; - } - } - // Otherwise just a simple search query with no phrases - else - { - $terms = htmlspecialchars_uni($terms); - $split_words = preg_split("#\s{1,}#", $terms, -1); - if(is_array($split_words)) - { - foreach($split_words as $word) - { - if(!$word || strlen($word) < $mybb->settings['minsearchword']) - { - continue; - } - $words[] = trim($word); - } - } - } - - if(!is_array($words)) - { - return false; - } - - // Sort the word array by length. Largest terms go first and work their way down to the smallest term. - // This resolves problems like "test tes" where "tes" will be highlighted first, then "test" can't be highlighted because of the changed html - usort($words, create_function('$a,$b', 'return strlen($b) - strlen($a);')); - - // Loop through our words to build the PREG compatible strings - foreach($words as $word) - { - $word = trim($word); - - $word = my_strtolower($word); - - // Special boolean operators should be stripped - if($word == "" || $word == "or" || $word == "not" || $word == "and") - { - continue; - } - - // Now make PREG compatible - $find = "#(?!<.*?)(".preg_quote($word, "#").")(?![^<>]*?>)#ui"; - $replacement = "$1"; - $highlight_cache[$find] = $replacement; - } - - return $highlight_cache; -} - -/** - * Converts a decimal reference of a character to its UTF-8 equivalent - * (Code by Anne van Kesteren, http://annevankesteren.nl/2005/05/character-references) - * - * @param int $src Decimal value of a character reference - * @return string|bool - */ -function dec_to_utf8($src) -{ - $dest = ''; - - if($src < 0) - { - return false; - } - elseif($src <= 0x007f) - { - $dest .= chr($src); - } - elseif($src <= 0x07ff) - { - $dest .= chr(0xc0 | ($src >> 6)); - $dest .= chr(0x80 | ($src & 0x003f)); - } - elseif($src <= 0xffff) - { - $dest .= chr(0xe0 | ($src >> 12)); - $dest .= chr(0x80 | (($src >> 6) & 0x003f)); - $dest .= chr(0x80 | ($src & 0x003f)); - } - elseif($src <= 0x10ffff) - { - $dest .= chr(0xf0 | ($src >> 18)); - $dest .= chr(0x80 | (($src >> 12) & 0x3f)); - $dest .= chr(0x80 | (($src >> 6) & 0x3f)); - $dest .= chr(0x80 | ($src & 0x3f)); - } - else - { - // Out of range - return false; - } - - return $dest; -} - -/** - * Checks if a username has been disallowed for registration/use. - * - * @param string $username The username - * @param boolean $update_lastuse True if the 'last used' dateline should be updated if a match is found. - * @return boolean True if banned, false if not banned - */ -function is_banned_username($username, $update_lastuse=false) -{ - global $db; - $query = $db->simple_select('banfilters', 'filter, fid', "type='2'"); - while($banned_username = $db->fetch_array($query)) - { - // Make regular expression * match - $banned_username['filter'] = str_replace('\*', '(.*)', preg_quote($banned_username['filter'], '#')); - if(preg_match("#(^|\b){$banned_username['filter']}($|\b)#i", $username)) - { - // Updating last use - if($update_lastuse == true) - { - $db->update_query("banfilters", array("lastuse" => TIME_NOW), "fid='{$banned_username['fid']}'"); - } - return true; - } - } - // Still here - good username - return false; -} - -/** - * Check if a specific email address has been banned. - * - * @param string $email The email address. - * @param boolean $update_lastuse True if the 'last used' dateline should be updated if a match is found. - * @return boolean True if banned, false if not banned - */ -function is_banned_email($email, $update_lastuse=false) -{ - global $cache, $db; - - $banned_cache = $cache->read("bannedemails"); - - if($banned_cache === false) - { - // Failed to read cache, see if we can rebuild it - $cache->update_bannedemails(); - $banned_cache = $cache->read("bannedemails"); - } - - if(is_array($banned_cache) && !empty($banned_cache)) - { - foreach($banned_cache as $banned_email) - { - // Make regular expression * match - $banned_email['filter'] = str_replace('\*', '(.*)', preg_quote($banned_email['filter'], '#')); - - if(preg_match("#{$banned_email['filter']}#i", $email)) - { - // Updating last use - if($update_lastuse == true) - { - $db->update_query("banfilters", array("lastuse" => TIME_NOW), "fid='{$banned_email['fid']}'"); - } - return true; - } - } - } - - // Still here - good email - return false; -} - -/** - * Checks if a specific IP address has been banned. - * - * @param string $ip_address The IP address. - * @param boolean $update_lastuse True if the 'last used' dateline should be updated if a match is found. - * @return boolean True if banned, false if not banned. - */ -function is_banned_ip($ip_address, $update_lastuse=false) -{ - global $db, $cache; - - $banned_ips = $cache->read("bannedips"); - if(!is_array($banned_ips)) - { - return false; - } - - $ip_address = my_inet_pton($ip_address); - foreach($banned_ips as $banned_ip) - { - if(!$banned_ip['filter']) - { - continue; - } - - $banned = false; - - $ip_range = fetch_ip_range($banned_ip['filter']); - if(is_array($ip_range)) - { - if(strcmp($ip_range[0], $ip_address) <= 0 && strcmp($ip_range[1], $ip_address) >= 0) - { - $banned = true; - } - } - elseif($ip_address == $ip_range) - { - $banned = true; - } - if($banned) - { - // Updating last use - if($update_lastuse == true) - { - $db->update_query("banfilters", array("lastuse" => TIME_NOW), "fid='{$banned_ip['fid']}'"); - } - return true; - } - } - - // Still here - good ip - return false; -} - -/** - * Returns an array of supported timezones - * - * @return string[] Key is timezone offset, Value the language description - */ -function get_supported_timezones() -{ - global $lang; - $timezones = array( - "-12" => $lang->timezone_gmt_minus_1200, - "-11" => $lang->timezone_gmt_minus_1100, - "-10" => $lang->timezone_gmt_minus_1000, - "-9.5" => $lang->timezone_gmt_minus_950, - "-9" => $lang->timezone_gmt_minus_900, - "-8" => $lang->timezone_gmt_minus_800, - "-7" => $lang->timezone_gmt_minus_700, - "-6" => $lang->timezone_gmt_minus_600, - "-5" => $lang->timezone_gmt_minus_500, - "-4.5" => $lang->timezone_gmt_minus_450, - "-4" => $lang->timezone_gmt_minus_400, - "-3.5" => $lang->timezone_gmt_minus_350, - "-3" => $lang->timezone_gmt_minus_300, - "-2" => $lang->timezone_gmt_minus_200, - "-1" => $lang->timezone_gmt_minus_100, - "0" => $lang->timezone_gmt, - "1" => $lang->timezone_gmt_100, - "2" => $lang->timezone_gmt_200, - "3" => $lang->timezone_gmt_300, - "3.5" => $lang->timezone_gmt_350, - "4" => $lang->timezone_gmt_400, - "4.5" => $lang->timezone_gmt_450, - "5" => $lang->timezone_gmt_500, - "5.5" => $lang->timezone_gmt_550, - "5.75" => $lang->timezone_gmt_575, - "6" => $lang->timezone_gmt_600, - "6.5" => $lang->timezone_gmt_650, - "7" => $lang->timezone_gmt_700, - "8" => $lang->timezone_gmt_800, - "8.5" => $lang->timezone_gmt_850, - "8.75" => $lang->timezone_gmt_875, - "9" => $lang->timezone_gmt_900, - "9.5" => $lang->timezone_gmt_950, - "10" => $lang->timezone_gmt_1000, - "10.5" => $lang->timezone_gmt_1050, - "11" => $lang->timezone_gmt_1100, - "11.5" => $lang->timezone_gmt_1150, - "12" => $lang->timezone_gmt_1200, - "12.75" => $lang->timezone_gmt_1275, - "13" => $lang->timezone_gmt_1300, - "14" => $lang->timezone_gmt_1400 - ); - return $timezones; -} - -/** - * Build a time zone selection list. - * - * @param string $name The name of the select - * @param int $selected The selected time zone (defaults to GMT) - * @param boolean $short True to generate a "short" list with just timezone and current time - * @return string - */ -function build_timezone_select($name, $selected=0, $short=false) -{ - global $mybb, $lang, $templates; - - $timezones = get_supported_timezones(); - - $selected = str_replace("+", "", $selected); - foreach($timezones as $timezone => $label) - { - $selected_add = ""; - if($selected == $timezone) - { - $selected_add = " selected=\"selected\""; - } - if($short == true) - { - $label = ''; - if($timezone != 0) - { - $label = $timezone; - if($timezone > 0) - { - $label = "+{$label}"; - } - if(strpos($timezone, ".") !== false) - { - $label = str_replace(".", ":", $label); - $label = str_replace(":5", ":30", $label); - $label = str_replace(":75", ":45", $label); - } - else - { - $label .= ":00"; - } - } - $time_in_zone = my_date($mybb->settings['timeformat'], TIME_NOW, $timezone); - $label = $lang->sprintf($lang->timezone_gmt_short, $label." ", $time_in_zone); - } - - eval("\$timezone_option .= \"".$templates->get("usercp_options_timezone_option")."\";"); - } - - eval("\$select = \"".$templates->get("usercp_options_timezone")."\";"); - return $select; -} - -/** - * Fetch the contents of a remote file. - * - * @param string $url The URL of the remote file - * @param array $post_data The array of post data - * @param int $max_redirects Number of maximum redirects - * @return string|bool The remote file contents. False on failure - */ -function fetch_remote_file($url, $post_data=array(), $max_redirects=20) -{ - global $mybb, $config; - - if(!my_validate_url($url, true)) - { - return false; - } - - $url_components = @parse_url($url); - - if(!isset($url_components['scheme'])) - { - $url_components['scheme'] = 'https'; - } - if(!isset($url_components['port'])) - { - $url_components['port'] = $url_components['scheme'] == 'https' ? 443 : 80; - } - - if( - !$url_components || - empty($url_components['host']) || - (!empty($url_components['scheme']) && !in_array($url_components['scheme'], array('http', 'https'))) || - (!in_array($url_components['port'], array(80, 8080, 443))) || - (!empty($config['disallowed_remote_hosts']) && in_array($url_components['host'], $config['disallowed_remote_hosts'])) - ) - { - return false; - } - - $addresses = get_ip_by_hostname($url_components['host']); - $destination_address = $addresses[0]; - - if(!empty($config['disallowed_remote_addresses'])) - { - foreach($config['disallowed_remote_addresses'] as $disallowed_address) - { - $ip_range = fetch_ip_range($disallowed_address); - - $packed_address = my_inet_pton($destination_address); - - if(is_array($ip_range)) - { - if(strcmp($ip_range[0], $packed_address) <= 0 && strcmp($ip_range[1], $packed_address) >= 0) - { - return false; - } - } - elseif($destination_address == $disallowed_address) - { - return false; - } - } - } - - $post_body = ''; - if(!empty($post_data)) - { - foreach($post_data as $key => $val) - { - $post_body .= '&'.urlencode($key).'='.urlencode($val); - } - $post_body = ltrim($post_body, '&'); - } - - if(function_exists("curl_init")) - { - $fetch_header = $max_redirects > 0; - - $ch = curl_init(); - - $curlopt = array( - CURLOPT_URL => $url, - CURLOPT_HEADER => $fetch_header, - CURLOPT_TIMEOUT => 10, - CURLOPT_RETURNTRANSFER => 1, - CURLOPT_FOLLOWLOCATION => 0, - ); - - if($ca_bundle_path = get_ca_bundle_path()) - { - $curlopt[CURLOPT_SSL_VERIFYPEER] = 1; - $curlopt[CURLOPT_CAINFO] = $ca_bundle_path; - } - else - { - $curlopt[CURLOPT_SSL_VERIFYPEER] = 0; - } - - $curl_version_info = curl_version(); - $curl_version = $curl_version_info['version']; - - if(version_compare(PHP_VERSION, '7.0.7', '>=') && version_compare($curl_version, '7.49', '>=')) - { - // CURLOPT_CONNECT_TO - $curlopt[10243] = array( - $url_components['host'].':'.$url_components['port'].':'.$destination_address - ); - } - elseif(version_compare(PHP_VERSION, '5.5', '>=') && version_compare($curl_version, '7.21.3', '>=')) - { - // CURLOPT_RESOLVE - $curlopt[10203] = array( - $url_components['host'].':'.$url_components['port'].':'.$destination_address - ); - } - - if(!empty($post_body)) - { - $curlopt[CURLOPT_POST] = 1; - $curlopt[CURLOPT_POSTFIELDS] = $post_body; - } - - curl_setopt_array($ch, $curlopt); - - $response = curl_exec($ch); - - if($fetch_header) - { - $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); - $header = substr($response, 0, $header_size); - $body = substr($response, $header_size); - - if(in_array(curl_getinfo($ch, CURLINFO_HTTP_CODE), array(301, 302))) - { - preg_match('/Location:(.*?)(?:\n|$)/', $header, $matches); - - if($matches) - { - $data = fetch_remote_file(trim(array_pop($matches)), $post_data, --$max_redirects); - } - } - else - { - $data = $body; - } - } - else - { - $data = $response; - } - - curl_close($ch); - return $data; - } - else if(function_exists("fsockopen")) - { - if(!isset($url_components['path'])) - { - $url_components['path'] = "/"; - } - if(isset($url_components['query'])) - { - $url_components['path'] .= "?{$url_components['query']}"; - } - - $scheme = ''; - - if($url_components['scheme'] == 'https') - { - $scheme = 'ssl://'; - if($url_components['port'] == 80) - { - $url_components['port'] = 443; - } - } - - if(function_exists('stream_context_create')) - { - if($url_components['scheme'] == 'https' && $ca_bundle_path = get_ca_bundle_path()) - { - $context = stream_context_create(array( - 'ssl' => array( - 'verify_peer' => true, - 'verify_peer_name' => true, - 'peer_name' => $url_components['host'], - 'cafile' => $ca_bundle_path, - ), - )); - } - else - { - $context = stream_context_create(array( - 'ssl' => array( - 'verify_peer' => false, - 'verify_peer_name' => false, - ), - )); - } - - $fp = @stream_socket_client($scheme.$destination_address.':'.(int)$url_components['port'], $error_no, $error, 10, STREAM_CLIENT_CONNECT, $context); - } - else - { - $fp = @fsockopen($scheme.$url_components['host'], (int)$url_components['port'], $error_no, $error, 10); - } - - @stream_set_timeout($fp, 10); - if(!$fp) - { - return false; - } - $headers = array(); - if(!empty($post_body)) - { - $headers[] = "POST {$url_components['path']} HTTP/1.0"; - $headers[] = "Content-Length: ".strlen($post_body); - $headers[] = "Content-Type: application/x-www-form-urlencoded"; - } - else - { - $headers[] = "GET {$url_components['path']} HTTP/1.0"; - } - - $headers[] = "Host: {$url_components['host']}"; - $headers[] = "Connection: Close"; - $headers[] = ''; - - if(!empty($post_body)) - { - $headers[] = $post_body; - } - else - { - // If we have no post body, we need to add an empty element to make sure we've got \r\n\r\n before the (non-existent) body starts - $headers[] = ''; - } - - $headers = implode("\r\n", $headers); - if(!@fwrite($fp, $headers)) - { - return false; - } - - $data = null; - - while(!feof($fp)) - { - $data .= fgets($fp, 12800); - } - fclose($fp); - - $data = explode("\r\n\r\n", $data, 2); - - $header = $data[0]; - $status_line = current(explode("\n\n", $header, 1)); - $body = $data[1]; - - if($max_redirects > 0 && (strstr($status_line, ' 301 ') || strstr($status_line, ' 302 '))) - { - preg_match('/Location:(.*?)(?:\n|$)/', $header, $matches); - - if($matches) - { - $data = fetch_remote_file(trim(array_pop($matches)), $post_data, --$max_redirects); - } - } - else - { - $data = $body; - } - - return $data; - } - else - { - return false; - } -} - -/** - * Resolves a hostname into a set of IP addresses. - * - * @param string $hostname The hostname to be resolved - * @return array|bool The resulting IP addresses. False on failure - */ -function get_ip_by_hostname($hostname) -{ - $addresses = @gethostbynamel($hostname); - - if(!$addresses) - { - $result_set = @dns_get_record($hostname, DNS_A | DNS_AAAA); - - if($result_set) - { - $addresses = array_column($result_set, 'ip'); - } - else - { - return false; - } - } - - return $addresses; -} - -/** - * Returns the location of the CA bundle defined in the PHP configuration. - * - * @return string|bool The location of the CA bundle, false if not set - */ -function get_ca_bundle_path() -{ - if($path = ini_get('openssl.cafile')) - { - return $path; - } - if($path = ini_get('curl.cainfo')) - { - return $path; - } - - return false; -} - -/** - * Checks if a particular user is a super administrator. - * - * @param int $uid The user ID to check against the list of super admins - * @return boolean True if a super admin, false if not - */ -function is_super_admin($uid) -{ - static $super_admins; - - if(!isset($super_admins)) - { - global $mybb; - $super_admins = str_replace(" ", "", $mybb->config['super_admins']); - } - - if(my_strpos(",{$super_admins},", ",{$uid},") === false) - { - return false; - } - else - { - return true; - } -} - -/** - * Checks if a user is a member of a particular group - * Originates from frostschutz's PluginLibrary - * github.com/frostschutz - * - * @param array|int|string A selection of groups (as array or comma seperated) to check or -1 for any group - * @param bool|array|int False assumes the current user. Otherwise an user array or an id can be passed - * @return array Array of groups specified in the first param to which the user belongs - */ -function is_member($groups, $user = false) -{ - global $mybb; - - if(empty($groups)) - { - return array(); - } - - if($user == false) - { - $user = $mybb->user; - } - else if(!is_array($user)) - { - // Assume it's a UID - $user = get_user($user); - } - - $memberships = array_map('intval', explode(',', $user['additionalgroups'])); - $memberships[] = $user['usergroup']; - - if(!is_array($groups)) - { - if((int)$groups == -1) - { - return $memberships; - } - else - { - if(is_string($groups)) - { - $groups = explode(',', $groups); - } - else - { - $groups = (array)$groups; - } - } - } - - $groups = array_filter(array_map('intval', $groups)); - - return array_intersect($groups, $memberships); -} - -/** - * Split a string based on the specified delimeter, ignoring said delimeter in escaped strings. - * Ex: the "quick brown fox" jumped, could return 1 => the, 2 => quick brown fox, 3 => jumped - * - * @param string $delimeter The delimeter to split by - * @param string $string The string to split - * @param string $escape The escape character or string if we have one. - * @return array Array of split string - */ -function escaped_explode($delimeter, $string, $escape="") -{ - $strings = array(); - $original = $string; - $in_escape = false; - if($escape) - { - if(is_array($escape)) - { - function escaped_explode_escape($string) - { - return preg_quote($string, "#"); - } - $escape_preg = "(".implode("|", array_map("escaped_explode_escape", $escape)).")"; - } - else - { - $escape_preg = preg_quote($escape, "#"); - } - $quoted_strings = preg_split("#(? "1 {$lang->day}", - "2-0-0" => "2 {$lang->days}", - "3-0-0" => "3 {$lang->days}", - "4-0-0" => "4 {$lang->days}", - "5-0-0" => "5 {$lang->days}", - "6-0-0" => "6 {$lang->days}", - "7-0-0" => "1 {$lang->week}", - "14-0-0" => "2 {$lang->weeks}", - "21-0-0" => "3 {$lang->weeks}", - "0-1-0" => "1 {$lang->month}", - "0-2-0" => "2 {$lang->months}", - "0-3-0" => "3 {$lang->months}", - "0-4-0" => "4 {$lang->months}", - "0-5-0" => "5 {$lang->months}", - "0-6-0" => "6 {$lang->months}", - "0-0-1" => "1 {$lang->year}", - "0-0-2" => "2 {$lang->years}" - ); - - $ban_times = $plugins->run_hooks("functions_fetch_ban_times", $ban_times); - - $ban_times['---'] = $lang->permanent; - return $ban_times; -} - -/** - * Format a ban length in to a UNIX timestamp. - * - * @param string $date The ban length string - * @param int $stamp The optional UNIX timestamp, if 0, current time is used. - * @return int The UNIX timestamp when the ban will be lifted - */ -function ban_date2timestamp($date, $stamp=0) -{ - if($stamp == 0) - { - $stamp = TIME_NOW; - } - $d = explode('-', $date); - $nowdate = date("H-j-n-Y", $stamp); - $n = explode('-', $nowdate); - $n[1] += $d[0]; - $n[2] += $d[1]; - $n[3] += $d[2]; - return mktime(date("G", $stamp), date("i", $stamp), 0, $n[2], $n[1], $n[3]); -} - -/** - * Expire old warnings in the database. - * - * @return bool - */ -function expire_warnings() -{ - global $warningshandler; - - if(!is_object($warningshandler)) - { - require_once MYBB_ROOT.'inc/datahandlers/warnings.php'; - $warningshandler = new WarningsHandler('update'); - } - - return $warningshandler->expire_warnings(); -} - -/** - * Custom chmod function to fix problems with hosts who's server configurations screw up umasks - * - * @param string $file The file to chmod - * @param string $mode The mode to chmod(i.e. 0666) - * @return bool - */ -function my_chmod($file, $mode) -{ - // Passing $mode as an octal number causes strlen and substr to return incorrect values. Instead pass as a string - if(substr($mode, 0, 1) != '0' || strlen($mode) !== 4) - { - return false; - } - $old_umask = umask(0); - - // We convert the octal string to a decimal number because passing a octal string doesn't work with chmod - // and type casting subsequently removes the prepended 0 which is needed for octal numbers - $result = chmod($file, octdec($mode)); - umask($old_umask); - return $result; -} - -/** - * Custom rmdir function to loop through an entire directory and delete all files/folders within - * - * @param string $path The path to the directory - * @param array $ignore Any files you wish to ignore (optional) - * @return bool - */ -function my_rmdir_recursive($path, $ignore=array()) -{ - global $orig_dir; - - if(!isset($orig_dir)) - { - $orig_dir = $path; - } - - if(@is_dir($path) && !@is_link($path)) - { - if($dh = @opendir($path)) - { - while(($file = @readdir($dh)) !== false) - { - if($file == '.' || $file == '..' || $file == '.svn' || in_array($path.'/'.$file, $ignore) || !my_rmdir_recursive($path.'/'.$file)) - { - continue; - } - } - @closedir($dh); - } - - // Are we done? Don't delete the main folder too and return true - if($path == $orig_dir) - { - return true; - } - - return @rmdir($path); - } - - return @unlink($path); -} - -/** - * Counts the number of subforums in a array([pid][disporder][fid]) starting from the pid - * - * @param array $array The array of forums - * @return integer The number of sub forums - */ -function subforums_count($array) -{ - $count = 0; - foreach($array as $array2) - { - $count += count($array2); - } - - return $count; -} - -/** - * DEPRECATED! Please use IPv6 compatible my_inet_pton! - * Fix for PHP's ip2long to guarantee a 32-bit signed integer value is produced (this is aimed - * at 64-bit versions of PHP) - * - * @deprecated - * @param string $ip The IP to convert - * @return integer IP in 32-bit signed format - */ -function my_ip2long($ip) -{ - $ip_long = ip2long($ip); - - if(!$ip_long) - { - $ip_long = sprintf("%u", ip2long($ip)); - - if(!$ip_long) - { - return 0; - } - } - - if($ip_long >= 2147483648) // Won't occur on 32-bit PHP - { - $ip_long -= 4294967296; - } - - return $ip_long; -} - -/** - * DEPRECATED! Please use IPv6 compatible my_inet_ntop! - * As above, fix for PHP's long2ip on 64-bit versions - * - * @deprecated - * @param integer $long The IP to convert (will accept 64-bit IPs as well) - * @return string IP in IPv4 format - */ -function my_long2ip($long) -{ - // On 64-bit machines is_int will return true. On 32-bit it will return false - if($long < 0 && is_int(2147483648)) - { - // We have a 64-bit system - $long += 4294967296; - } - return long2ip($long); -} - -/** - * Converts a human readable IP address to its packed in_addr representation - * - * @param string $ip The IP to convert - * @return string IP in 32bit or 128bit binary format - */ -function my_inet_pton($ip) -{ - if(function_exists('inet_pton')) - { - return @inet_pton($ip); - } - else - { - /** - * Replace inet_pton() - * - * @category PHP - * @package PHP_Compat - * @license LGPL - http://www.gnu.org/licenses/lgpl.html - * @copyright 2004-2007 Aidan Lister , Arpad Ray - * @link http://php.net/inet_pton - * @author Arpad Ray - * @version $Revision: 269597 $ - */ - $r = ip2long($ip); - if($r !== false && $r != -1) - { - return pack('N', $r); - } - - $delim_count = substr_count($ip, ':'); - if($delim_count < 1 || $delim_count > 7) - { - return false; - } - - $r = explode(':', $ip); - $rcount = count($r); - if(($doub = array_search('', $r, 1)) !== false) - { - $length = (!$doub || $doub == $rcount - 1 ? 2 : 1); - array_splice($r, $doub, $length, array_fill(0, 8 + $length - $rcount, 0)); - } - - $r = array_map('hexdec', $r); - array_unshift($r, 'n*'); - $r = call_user_func_array('pack', $r); - - return $r; - } -} - -/** - * Converts a packed internet address to a human readable representation - * - * @param string $ip IP in 32bit or 128bit binary format - * @return string IP in human readable format - */ -function my_inet_ntop($ip) -{ - if(function_exists('inet_ntop')) - { - return @inet_ntop($ip); - } - else - { - /** - * Replace inet_ntop() - * - * @category PHP - * @package PHP_Compat - * @license LGPL - http://www.gnu.org/licenses/lgpl.html - * @copyright 2004-2007 Aidan Lister , Arpad Ray - * @link http://php.net/inet_ntop - * @author Arpad Ray - * @version $Revision: 269597 $ - */ - switch(strlen($ip)) - { - case 4: - list(,$r) = unpack('N', $ip); - return long2ip($r); - case 16: - $r = substr(chunk_split(bin2hex($ip), 4, ':'), 0, -1); - $r = preg_replace( - array('/(?::?\b0+\b:?){2,}/', '/\b0+([^0])/e'), - array('::', '(int)"$1"?"$1":"0$1"'), - $r); - return $r; - } - return false; - } -} - -/** - * Fetch an binary formatted range for searching IPv4 and IPv6 IP addresses. - * - * @param string $ipaddress The IP address to convert to a range - * @return string|array|bool If a full IP address is provided, the in_addr representation, otherwise an array of the upper & lower extremities of the IP. False on failure - */ -function fetch_ip_range($ipaddress) -{ - // Wildcard - if(strpos($ipaddress, '*') !== false) - { - if(strpos($ipaddress, ':') !== false) - { - // IPv6 - $upper = str_replace('*', 'ffff', $ipaddress); - $lower = str_replace('*', '0', $ipaddress); - } - else - { - // IPv4 - $ip_bits = count(explode('.', $ipaddress)); - if($ip_bits < 4) - { - // Support for 127.0.* - $replacement = str_repeat('.*', 4-$ip_bits); - $ipaddress = substr_replace($ipaddress, $replacement, strrpos($ipaddress, '*')+1, 0); - } - $upper = str_replace('*', '255', $ipaddress); - $lower = str_replace('*', '0', $ipaddress); - } - $upper = my_inet_pton($upper); - $lower = my_inet_pton($lower); - if($upper === false || $lower === false) - { - return false; - } - return array($lower, $upper); - } - // CIDR notation - elseif(strpos($ipaddress, '/') !== false) - { - $ipaddress = explode('/', $ipaddress); - $ip_address = $ipaddress[0]; - $ip_range = (int)$ipaddress[1]; - - if(empty($ip_address) || empty($ip_range)) - { - // Invalid input - return false; - } - else - { - $ip_address = my_inet_pton($ip_address); - - if(!$ip_address) - { - // Invalid IP address - return false; - } - } - - /** - * Taken from: https://github.com/NewEraCracker/php_work/blob/master/ipRangeCalculate.php - * Author: NewEraCracker - * License: Public Domain - */ - - // Pack IP, Set some vars - $ip_pack = $ip_address; - $ip_pack_size = strlen($ip_pack); - $ip_bits_size = $ip_pack_size*8; - - // IP bits (lots of 0's and 1's) - $ip_bits = ''; - for($i = 0; $i < $ip_pack_size; $i = $i+1) - { - $bit = decbin(ord($ip_pack[$i])); - $bit = str_pad($bit, 8, '0', STR_PAD_LEFT); - $ip_bits .= $bit; - } - - // Significative bits (from the ip range) - $ip_bits = substr($ip_bits, 0, $ip_range); - - // Some calculations - $ip_lower_bits = str_pad($ip_bits, $ip_bits_size, '0', STR_PAD_RIGHT); - $ip_higher_bits = str_pad($ip_bits, $ip_bits_size, '1', STR_PAD_RIGHT); - - // Lower IP - $ip_lower_pack = ''; - for($i=0; $i < $ip_bits_size; $i=$i+8) - { - $chr = substr($ip_lower_bits, $i, 8); - $chr = chr(bindec($chr)); - $ip_lower_pack .= $chr; - } - - // Higher IP - $ip_higher_pack = ''; - for($i=0; $i < $ip_bits_size; $i=$i+8) - { - $chr = substr($ip_higher_bits, $i, 8); - $chr = chr( bindec($chr) ); - $ip_higher_pack .= $chr; - } - - return array($ip_lower_pack, $ip_higher_pack); - } - // Just on IP address - else - { - return my_inet_pton($ipaddress); - } -} - -/** - * Time how long it takes for a particular piece of code to run. Place calls above & below the block of code. - * - * @return float The time taken - */ -function get_execution_time() -{ - static $time_start; - - $time = microtime(true); - - - // Just starting timer, init and return - if(!$time_start) - { - $time_start = $time; - return; - } - // Timer has run, return execution time - else - { - $total = $time-$time_start; - if($total < 0) $total = 0; - $time_start = 0; - return $total; - } -} - -/** - * Processes a checksum list on MyBB files and returns a result set - * - * @param string $path The base path - * @param int $count The count of files - * @return array The bad files - */ -function verify_files($path=MYBB_ROOT, $count=0) -{ - global $mybb, $checksums, $bad_verify_files; - - // We don't need to check these types of files - $ignore = array(".", "..", ".svn", "config.php", "settings.php", "Thumb.db", "config.default.php", "lock", "htaccess.txt", "htaccess-nginx.txt", "logo.gif", "logo.png"); - $ignore_ext = array("attach"); - - if(substr($path, -1, 1) == "/") - { - $path = substr($path, 0, -1); - } - - if(!is_array($bad_verify_files)) - { - $bad_verify_files = array(); - } - - // Make sure that we're in a directory and it's not a symbolic link - if(@is_dir($path) && !@is_link($path)) - { - if($dh = @opendir($path)) - { - // Loop through all the files/directories in this directory - while(($file = @readdir($dh)) !== false) - { - if(in_array($file, $ignore) || in_array(get_extension($file), $ignore_ext)) - { - continue; - } - - // Recurse through the directory tree - if(is_dir($path."/".$file)) - { - verify_files($path."/".$file, ($count+1)); - continue; - } - - // We only need the last part of the path (from the MyBB directory to the file. i.e. inc/functions.php) - $file_path = ".".str_replace(substr(MYBB_ROOT, 0, -1), "", $path)."/".$file; - - // Does this file even exist in our official list? Perhaps it's a plugin - if(array_key_exists($file_path, $checksums)) - { - $filename = $path."/".$file; - $handle = fopen($filename, "rb"); - $contents = ''; - while(!feof($handle)) - { - $contents .= fread($handle, 8192); - } - fclose($handle); - - $md5 = md5($contents); - - // Does it match any of our hashes (unix/windows new lines taken into consideration with the hashes) - if(!in_array($md5, $checksums[$file_path])) - { - $bad_verify_files[] = array("status" => "changed", "path" => $file_path); - } - } - unset($checksums[$file_path]); - } - @closedir($dh); - } - } - - if($count == 0) - { - if(!empty($checksums)) - { - foreach($checksums as $file_path => $hashes) - { - if(in_array(basename($file_path), $ignore)) - { - continue; - } - $bad_verify_files[] = array("status" => "missing", "path" => $file_path); - } - } - } - - // uh oh - if($count == 0) - { - return $bad_verify_files; - } -} - -/** - * Returns a signed value equal to an integer - * - * @param int $int The integer - * @return string The signed equivalent - */ -function signed($int) -{ - if($int < 0) - { - return "$int"; - } - else - { - return "+$int"; - } -} - -/** - * Returns a securely generated seed - * - * @return string A secure binary seed - */ -function secure_binary_seed_rng($bytes) -{ - $output = null; - - if(version_compare(PHP_VERSION, '7.0', '>=')) - { - try - { - $output = random_bytes($bytes); - } catch (Exception $e) { - } - } - - if(strlen($output) < $bytes) - { - if(@is_readable('/dev/urandom') && ($handle = @fopen('/dev/urandom', 'rb'))) - { - $output = @fread($handle, $bytes); - @fclose($handle); - } - } - else - { - return $output; - } - - if(strlen($output) < $bytes) - { - if(function_exists('mcrypt_create_iv')) - { - if (DIRECTORY_SEPARATOR == '/') - { - $source = MCRYPT_DEV_URANDOM; - } - else - { - $source = MCRYPT_RAND; - } - - $output = @mcrypt_create_iv($bytes, $source); - } - } - else - { - return $output; - } - - if(strlen($output) < $bytes) - { - if(function_exists('openssl_random_pseudo_bytes')) - { - // PHP <5.3.4 had a bug which makes that function unusable on Windows - if ((DIRECTORY_SEPARATOR == '/') || version_compare(PHP_VERSION, '5.3.4', '>=')) - { - $output = openssl_random_pseudo_bytes($bytes, $crypto_strong); - if ($crypto_strong == false) - { - $output = null; - } - } - } - } - else - { - return $output; - } - - if(strlen($output) < $bytes) - { - if(class_exists('COM')) - { - try - { - $CAPI_Util = new COM('CAPICOM.Utilities.1'); - if(is_callable(array($CAPI_Util, 'GetRandom'))) - { - $output = $CAPI_Util->GetRandom($bytes, 0); - } - } catch (Exception $e) { - } - } - } - else - { - return $output; - } - - if(strlen($output) < $bytes) - { - // Close to what PHP basically uses internally to seed, but not quite. - $unique_state = microtime().@getmypid(); - - $rounds = ceil($bytes / 16); - - for($i = 0; $i < $rounds; $i++) - { - $unique_state = md5(microtime().$unique_state); - $output .= md5($unique_state); - } - - $output = substr($output, 0, ($bytes * 2)); - - $output = pack('H*', $output); - - return $output; - } - else - { - return $output; - } -} - -/** - * Returns a securely generated seed integer - * - * @return int An integer equivalent of a secure hexadecimal seed - */ -function secure_seed_rng() -{ - $bytes = PHP_INT_SIZE; - - do - { - - $output = secure_binary_seed_rng($bytes); - - // convert binary data to a decimal number - if ($bytes == 4) - { - $elements = unpack('i', $output); - $output = abs($elements[1]); - } - else - { - $elements = unpack('N2', $output); - $output = abs($elements[1] << 32 | $elements[2]); - } - - } while($output > PHP_INT_MAX); - - return $output; -} - -/** - * Generates a cryptographically secure random number. - * - * @param int $min Optional lowest value to be returned (default: 0) - * @param int $max Optional highest value to be returned (default: PHP_INT_MAX) - */ -function my_rand($min=0, $max=PHP_INT_MAX) -{ - // backward compatibility - if($min === null || $max === null || $max < $min) - { - $min = 0; - $max = PHP_INT_MAX; - } - - if(version_compare(PHP_VERSION, '7.0', '>=')) - { - try - { - $result = random_int($min, $max); - } catch (Exception $e) { - } - - if(isset($result)) - { - return $result; - } - } - - $seed = secure_seed_rng(); - - $distance = $max - $min; - return $min + floor($distance * ($seed / PHP_INT_MAX) ); -} - -/** - * More robust version of PHP's trim() function. It includes a list of UTF-8 blank characters - * from http://kb.mozillazine.org/Network.IDN.blacklist_chars - * - * @param string $string The string to trim from - * @param string $charlist Optional. The stripped characters can also be specified using the charlist parameter - * @return string The trimmed string - */ -function trim_blank_chrs($string, $charlist="") -{ - $hex_chrs = array( - 0x09 => 1, // \x{0009} - 0x0A => 1, // \x{000A} - 0x0B => 1, // \x{000B} - 0x0D => 1, // \x{000D} - 0x20 => 1, // \x{0020} - 0xC2 => array(0x81 => 1, 0x8D => 1, 0x90 => 1, 0x9D => 1, 0xA0 => 1, 0xAD => 1), // \x{0081}, \x{008D}, \x{0090}, \x{009D}, \x{00A0}, \x{00AD} - 0xCC => array(0xB7 => 1, 0xB8 => 1), // \x{0337}, \x{0338} - 0xE1 => array(0x85 => array(0x9F => 1, 0xA0 => 1), 0x9A => array(0x80 => 1), 0xA0 => array(0x8E => 1)), // \x{115F}, \x{1160}, \x{1680}, \x{180E} - 0xE2 => array(0x80 => array(0x80 => 1, 0x81 => 1, 0x82 => 1, 0x83 => 1, 0x84 => 1, 0x85 => 1, 0x86 => 1, 0x87 => 1, 0x88 => 1, 0x89 => 1, 0x8A => 1, 0x8B => 1, 0x8C => 1, 0x8D => 1, 0x8E => 1, 0x8F => 1, // \x{2000} - \x{200F} - 0xA8 => 1, 0xA9 => 1, 0xAA => 1, 0xAB => 1, 0xAC => 1, 0xAD => 1, 0xAE => 1, 0xAF => 1), // \x{2028} - \x{202F} - 0x81 => array(0x9F => 1)), // \x{205F} - 0xE3 => array(0x80 => array(0x80 => 1), // \x{3000} - 0x85 => array(0xA4 => 1)), // \x{3164} - 0xEF => array(0xBB => array(0xBF => 1), // \x{FEFF} - 0xBE => array(0xA0 => 1), // \x{FFA0} - 0xBF => array(0xB9 => 1, 0xBA => 1, 0xBB => 1)), // \x{FFF9} - \x{FFFB} - ); - - $hex_chrs_rev = array( - 0x09 => 1, // \x{0009} - 0x0A => 1, // \x{000A} - 0x0B => 1, // \x{000B} - 0x0D => 1, // \x{000D} - 0x20 => 1, // \x{0020} - 0x81 => array(0xC2 => 1, 0x80 => array(0xE2 => 1)), // \x{0081}, \x{2001} - 0x8D => array(0xC2 => 1, 0x80 => array(0xE2 => 1)), // \x{008D}, \x{200D} - 0x90 => array(0xC2 => 1), // \x{0090} - 0x9D => array(0xC2 => 1), // \x{009D} - 0xA0 => array(0xC2 => 1, 0x85 => array(0xE1 => 1), 0x81 => array(0xE2 => 1), 0xBE => array(0xEF => 1)), // \x{00A0}, \x{1160}, \x{2060}, \x{FFA0} - 0xAD => array(0xC2 => 1, 0x80 => array(0xE2 => 1)), // \x{00AD}, \x{202D} - 0xB8 => array(0xCC => 1), // \x{0338} - 0xB7 => array(0xCC => 1), // \x{0337} - 0x9F => array(0x85 => array(0xE1 => 1), 0x81 => array(0xE2 => 1)), // \x{115F}, \x{205F} - 0x80 => array(0x9A => array(0xE1 => 1), 0x80 => array(0xE2 => 1, 0xE3 => 1)), // \x{1680}, \x{2000}, \x{3000} - 0x8E => array(0xA0 => array(0xE1 => 1), 0x80 => array(0xE2 => 1)), // \x{180E}, \x{200E} - 0x82 => array(0x80 => array(0xE2 => 1)), // \x{2002} - 0x83 => array(0x80 => array(0xE2 => 1)), // \x{2003} - 0x84 => array(0x80 => array(0xE2 => 1)), // \x{2004} - 0x85 => array(0x80 => array(0xE2 => 1)), // \x{2005} - 0x86 => array(0x80 => array(0xE2 => 1)), // \x{2006} - 0x87 => array(0x80 => array(0xE2 => 1)), // \x{2007} - 0x88 => array(0x80 => array(0xE2 => 1)), // \x{2008} - 0x89 => array(0x80 => array(0xE2 => 1)), // \x{2009} - 0x8A => array(0x80 => array(0xE2 => 1)), // \x{200A} - 0x8B => array(0x80 => array(0xE2 => 1)), // \x{200B} - 0x8C => array(0x80 => array(0xE2 => 1)), // \x{200C} - 0x8F => array(0x80 => array(0xE2 => 1)), // \x{200F} - 0xA8 => array(0x80 => array(0xE2 => 1)), // \x{2028} - 0xA9 => array(0x80 => array(0xE2 => 1)), // \x{2029} - 0xAA => array(0x80 => array(0xE2 => 1)), // \x{202A} - 0xAB => array(0x80 => array(0xE2 => 1)), // \x{202B} - 0xAC => array(0x80 => array(0xE2 => 1)), // \x{202C} - 0xAE => array(0x80 => array(0xE2 => 1)), // \x{202E} - 0xAF => array(0x80 => array(0xE2 => 1)), // \x{202F} - 0xA4 => array(0x85 => array(0xE3 => 1)), // \x{3164} - 0xBF => array(0xBB => array(0xEF => 1)), // \x{FEFF} - 0xB9 => array(0xBF => array(0xEF => 1)), // \x{FFF9} - 0xBA => array(0xBF => array(0xEF => 1)), // \x{FFFA} - 0xBB => array(0xBF => array(0xEF => 1)), // \x{FFFB} - ); - - // Start from the beginning and work our way in - do - { - // Check to see if we have matched a first character in our utf-8 array - $offset = match_sequence($string, $hex_chrs); - if(!$offset) - { - // If not, then we must have a "good" character and we don't need to do anymore processing - break; - } - $string = substr($string, $offset); - } - while(++$i); - - // Start from the end and work our way in - $string = strrev($string); - do - { - // Check to see if we have matched a first character in our utf-8 array - $offset = match_sequence($string, $hex_chrs_rev); - if(!$offset) - { - // If not, then we must have a "good" character and we don't need to do anymore processing - break; - } - $string = substr($string, $offset); - } - while(++$i); - $string = strrev($string); - - if($charlist) - { - $string = trim($string, $charlist); - } - else - { - $string = trim($string); - } - - return $string; -} - -/** - * Match a sequence - * - * @param string $string The string to match from - * @param array $array The array to match from - * @param int $i Number in the string - * @param int $n Number of matches - * @return int The number matched - */ -function match_sequence($string, $array, $i=0, $n=0) -{ - if($string === "") - { - return 0; - } - - $ord = ord($string[$i]); - if(array_key_exists($ord, $array)) - { - $level = $array[$ord]; - ++$n; - if(is_array($level)) - { - ++$i; - return match_sequence($string, $level, $i, $n); - } - return $n; - } - - return 0; -} - -/** - * Obtain the version of GD installed. - * - * @return float Version of GD - */ -function gd_version() -{ - static $gd_version; - - if($gd_version) - { - return $gd_version; - } - if(!extension_loaded('gd')) - { - return; - } - - if(function_exists("gd_info")) - { - $gd_info = gd_info(); - preg_match('/\d/', $gd_info['GD Version'], $gd); - $gd_version = $gd[0]; - } - else - { - ob_start(); - phpinfo(8); - $info = ob_get_contents(); - ob_end_clean(); - $info = stristr($info, 'gd version'); - preg_match('/\d/', $info, $gd); - $gd_version = $gd[0]; - } - - return $gd_version; -} - -/* - * Validates an UTF-8 string. - * - * @param string $input The string to be checked - * @param boolean $allow_mb4 Allow 4 byte UTF-8 characters? - * @param boolean $return Return the cleaned string? - * @return string|boolean Cleaned string or boolean - */ -function validate_utf8_string($input, $allow_mb4=true, $return=true) -{ - // Valid UTF-8 sequence? - if(!preg_match('##u', $input)) - { - $string = ''; - $len = strlen($input); - for($i = 0; $i < $len; $i++) - { - $c = ord($input[$i]); - if($c > 128) - { - if($c > 247 || $c <= 191) - { - if($return) - { - $string .= '?'; - continue; - } - else - { - return false; - } - } - elseif($c > 239) - { - $bytes = 4; - } - elseif($c > 223) - { - $bytes = 3; - } - elseif($c > 191) - { - $bytes = 2; - } - if(($i + $bytes) > $len) - { - if($return) - { - $string .= '?'; - break; - } - else - { - return false; - } - } - $valid = true; - $multibytes = $input[$i]; - while($bytes > 1) - { - $i++; - $b = ord($input[$i]); - if($b < 128 || $b > 191) - { - if($return) - { - $valid = false; - $string .= '?'; - break; - } - else - { - return false; - } - } - else - { - $multibytes .= $input[$i]; - } - $bytes--; - } - if($valid) - { - $string .= $multibytes; - } - } - else - { - $string .= $input[$i]; - } - } - $input = $string; - } - if($return) - { - if($allow_mb4) - { - return $input; - } - else - { - return preg_replace("#[^\\x00-\\x7F][\\x80-\\xBF]{3,}#", '?', $input); - } - } - else - { - if($allow_mb4) - { - return true; - } - else - { - return !preg_match("#[^\\x00-\\x7F][\\x80-\\xBF]{3,}#", $input); - } - } -} - -/** - * Send a Private Message to a user. - * - * @param array $pm Array containing: 'subject', 'message', 'touid' and 'receivepms' (the latter should reflect the value found in the users table: receivepms and receivefrombuddy) - * @param int $fromid Sender UID (0 if you want to use $mybb->user['uid'] or -1 to use MyBB Engine) - * @param bool $admin_override Whether or not do override user defined options for receiving PMs - * @return bool True if PM sent - */ -function send_pm($pm, $fromid = 0, $admin_override=false) -{ - global $lang, $mybb, $db, $session; - - if($mybb->settings['enablepms'] == 0) - { - return false; - } - - if(!is_array($pm)) - { - return false; - } - - if(isset($pm['language'])) - { - if($pm['language'] != $mybb->user['language'] && $lang->language_exists($pm['language'])) - { - // Load user language - $lang->set_language($pm['language']); - $lang->load($pm['language_file']); - - $revert = true; - } - - foreach(array('subject', 'message') as $key) - { - if(is_array($pm[$key])) - { - $lang_string = $lang->{$pm[$key][0]}; - $num_args = count($pm[$key]); - - for($i = 1; $i < $num_args; $i++) - { - $lang_string = str_replace('{'.$i.'}', $pm[$key][$i], $lang_string); - } - } - else - { - $lang_string = $lang->{$pm[$key]}; - } - - $pm[$key] = $lang_string; - } - - if(isset($revert)) - { - // Revert language - $lang->set_language($mybb->user['language']); - $lang->load($pm['language_file']); - } - } - - if(!$pm['subject'] ||!$pm['message'] || !$pm['touid'] || (!$pm['receivepms'] && !$admin_override)) - { - return false; - } - - require_once MYBB_ROOT."inc/datahandlers/pm.php"; - - $pmhandler = new PMDataHandler(); - - $subject = $pm['subject']; - $message = $pm['message']; - $toid = $pm['touid']; - - // Our recipients - if(is_array($toid)) - { - $recipients_to = $toid; - } - else - { - $recipients_to = array($toid); - } - - $recipients_bcc = array(); - - // Determine user ID - if((int)$fromid == 0) - { - $fromid = (int)$mybb->user['uid']; - } - elseif((int)$fromid < 0) - { - $fromid = 0; - } - - // Build our final PM array - $pm = array( - "subject" => $subject, - "message" => $message, - "icon" => -1, - "fromid" => $fromid, - "toid" => $recipients_to, - "bccid" => $recipients_bcc, - "do" => '', - "pmid" => '' - ); - - if(isset($session)) - { - $pm['ipaddress'] = $session->packedip; - } - - $pm['options'] = array( - "signature" => 0, - "disablesmilies" => 0, - "savecopy" => 0, - "readreceipt" => 0 - ); - - $pm['saveasdraft'] = 0; - - // Admin override - $pmhandler->admin_override = (int)$admin_override; - - $pmhandler->set_data($pm); - - if($pmhandler->validate_pm()) - { - $pmhandler->insert_pm(); - return true; - } - - return false; -} - -/** - * Log a user spam block from StopForumSpam (or other spam service providers...) - * - * @param string $username The username that the user was using. - * @param string $email The email address the user was using. - * @param string $ip_address The IP addres of the user. - * @param array $data An array of extra data to go with the block (eg: confidence rating). - * @return bool Whether the action was logged successfully. - */ -function log_spam_block($username = '', $email = '', $ip_address = '', $data = array()) -{ - global $db, $session; - - if(!is_array($data)) - { - $data = array($data); - } - - if(!$ip_address) - { - $ip_address = get_ip(); - } - - $ip_address = my_inet_pton($ip_address); - - $insert_array = array( - 'username' => $db->escape_string($username), - 'email' => $db->escape_string($email), - 'ipaddress' => $db->escape_binary($ip_address), - 'dateline' => (int)TIME_NOW, - 'data' => $db->escape_string(@my_serialize($data)), - ); - - return (bool)$db->insert_query('spamlog', $insert_array); -} - -/** - * Copy a file to the CDN. - * - * @param string $file_path The path to the file to upload to the CDN. - * - * @param string $uploaded_path The path the file was uploaded to, reference parameter for when this may be needed. - * - * @return bool Whether the file was copied successfully. - */ -function copy_file_to_cdn($file_path = '', &$uploaded_path = null) -{ - global $mybb, $plugins; - - $success = false; - - $file_path = (string)$file_path; - - $real_file_path = realpath($file_path); - - $file_dir_path = dirname($real_file_path); - $file_dir_path = str_replace(MYBB_ROOT, '', $file_dir_path); - $file_dir_path = ltrim($file_dir_path, './\\'); - - $file_name = basename($real_file_path); - - if(file_exists($file_path)) - { - if($mybb->settings['usecdn'] && !empty($mybb->settings['cdnpath'])) - { - $cdn_path = rtrim($mybb->settings['cdnpath'], '/\\'); - - if(substr($file_dir_path, 0, my_strlen(MYBB_ROOT)) == MYBB_ROOT) - { - $file_dir_path = str_replace(MYBB_ROOT, '', $file_dir_path); - } - - $cdn_upload_path = $cdn_path . DIRECTORY_SEPARATOR . $file_dir_path; - - if(!($dir_exists = is_dir($cdn_upload_path))) - { - $dir_exists = @mkdir($cdn_upload_path, 0777, true); - } - - if($dir_exists) - { - if(($cdn_upload_path = realpath($cdn_upload_path)) !== false) - { - $success = @copy($file_path, $cdn_upload_path.DIRECTORY_SEPARATOR.$file_name); - - if($success) - { - $uploaded_path = $cdn_upload_path; - } - } - } - } - - if(is_object($plugins)) - { - $hook_args = array( - 'file_path' => &$file_path, - 'real_file_path' => &$real_file_path, - 'file_name' => &$file_name, - 'uploaded_path' => &$uploaded_path, - 'success' => &$success, - ); - - $plugins->run_hooks('copy_file_to_cdn_end', $hook_args); - } - } - - return $success; -} - -/** - * Validate an url - * - * @param string $url The url to validate. - * @param bool $relative_path Whether or not the url could be a relative path. - * @param bool $allow_local Whether or not the url could be pointing to local networks. - * - * @return bool Whether this is a valid url. - */ -function my_validate_url($url, $relative_path=false, $allow_local=false) -{ - if($allow_local) - { - $regex = '_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:localhost|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,}))\.?))(?::\d{2,5})?(?:[/?#]\S*)?$_iuS'; - } - else - { - $regex = '_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$_iuS'; - } - - if($relative_path && my_substr($url, 0, 1) == '/' || preg_match($regex, $url)) - { - return true; - } - return false; -} - -/** - * Strip html tags from string, also removes @siu', - ); - $string = preg_replace($pattern, '', $string); - return strip_tags($string, $allowable_tags); -} - -/** - * Escapes a RFC 4180-compliant CSV string. - * Based on https://github.com/Automattic/camptix/blob/f80725094440bf09861383b8f11e96c177c45789/camptix.php#L2867 - * - * @param string $string The string to be escaped - * @param boolean $escape_active_content Whether or not to escape active content trigger characters - * @return string The escaped string - */ -function my_escape_csv($string, $escape_active_content=true) -{ - if($escape_active_content) - { - $active_content_triggers = array('=', '+', '-', '@'); - $delimiters = array(',', ';', ':', '|', '^', "\n", "\t", " "); - - $first_character = mb_substr($string, 0, 1); - - if( - in_array($first_character, $active_content_triggers, true) || - in_array($first_character, $delimiters, true) - ) - { - $string = "'".$string; - } - - foreach($delimiters as $delimiter) - { - foreach($active_content_triggers as $trigger) - { - $string = str_replace($delimiter.$trigger, $delimiter."'".$trigger, $string); - } - } - } - - $string = str_replace('"', '""', $string); - - return $string; -} diff --git a/html/forums/inc/functions_archive.php b/html/forums/inc/functions_archive.php deleted file mode 100644 index e3f9af0..0000000 --- a/html/forums/inc/functions_archive.php +++ /dev/null @@ -1,269 +0,0 @@ -settings['bbname']; - } - else - { - $title = $mybb->settings['bbname']." - ".$title; - } - - // If the language doesn't have a charset, make it UTF-8. - if($lang->settings['charset']) - { - $charset = $lang->settings['charset']; - } - else - { - $charset = "utf-8"; - } - - $dir = ''; - if($lang->settings['rtl'] == 1) - { - $dir = " dir=\"rtl\""; - } - - if($lang->settings['htmllang']) - { - $htmllang = " xml:lang=\"".$lang->settings['htmllang']."\" lang=\"".$lang->settings['htmllang']."\""; - } - else - { - $htmllang = " xml:lang=\"en\" lang=\"en\""; - } -?> - -> - -<?php echo $title; ?> - - - - - - -
    -

    settings['bbname_orig']; ?>

    - -
    archive_fullversion; ?>
    -
    sprintf($lang->archive_note, $fullurl); ?>
    -
    - $navbit) - { - if(!empty($navbits[$key+1])) - { - if(!empty($navbits[$key+2])) - { - $sep = $navsep; - } - else - { - $sep = ""; - } - $nav .= "".$navbit['name']."$sep"; - } - } - } - $navsize = count($navbits); - $navbit = $navbits[$navsize-1]; - if(!empty($nav)) - { - $activesep = $navsep; - } - $nav .= $activesep.$navbit['name']; - - return $nav; -} - -/** - * Output multipage navigation. - * - * @param int $count The total number of items. - * @param int $perpage The items per page. - * @param int $page The current page. - * @param string $url The URL base. -*/ -function archive_multipage($count, $perpage, $page, $url) -{ - global $lang; - if($count > $perpage) - { - $pages = $count / $perpage; - $pages = ceil($pages); - - $mppage = null; - for($i = 1; $i <= $pages; ++$i) - { - if($i == $page) - { - $mppage .= "$i "; - } - else - { - $mppage .= "$i "; - } - } - $multipage = "
    ".$lang->archive_pages." $mppage
    "; - echo $multipage; - } -} - -/** - * Output the archive footer. - * - */ -function archive_footer() -{ - global $mybb, $lang, $db, $nav, $maintimer, $fulltitle, $fullurl, $sent_header; - $totaltime = $maintimer->stop(); - if($mybb->settings['showvernum'] == 1) - { - $mybbversion = ' '.$mybb->version; - } - else - { - $mybbversion = ""; - } -?> -
    - -
    - - - -settings['bbname'], $mybb->settings['bburl']."/index.php"); - } -?> -
    -
    error; ?>
    -
    -
    - '1', - "location1" => 0, - "location2" => 0 - ); - - $db->update_query("sessions", $noperm_array, "sid='{$session->sid}'"); - - archive_error($lang->archive_nopermission); -} - -/** - * Check the password given on a certain forum for validity - * - * @param int $fid The forum ID - * @param int $pid The Parent ID - * @return bool Returns false on failure - */ -function check_forum_password_archive($fid, $pid=0) -{ - global $forum_cache, $mybb; - - if(!is_array($forum_cache)) - { - $forum_cache = cache_forums(); - if(!$forum_cache) - { - return false; - } - } - - // Loop through each of parent forums to ensure we have a password for them too - $parents = explode(',', $forum_cache[$fid]['parentlist']); - rsort($parents); - if(!empty($parents)) - { - foreach($parents as $parent_id) - { - if($parent_id == $fid || $parent_id == $pid) - { - continue; - } - - if($forum_cache[$parent_id]['password'] != "") - { - check_forum_password_archive($parent_id, $fid); - } - } - } - - $password = $forum_cache[$fid]['password']; - if($password) - { - if(!$mybb->cookies['forumpass'][$fid] || ($mybb->cookies['forumpass'][$fid] && md5($mybb->user['uid'].$password) !== $mybb->cookies['forumpass'][$fid])) - { - archive_error_no_permission(); - } - } -} diff --git a/html/forums/inc/functions_calendar.php b/html/forums/inc/functions_calendar.php deleted file mode 100644 index 6f2b8bf..0000000 --- a/html/forums/inc/functions_calendar.php +++ /dev/null @@ -1,1100 +0,0 @@ - my_date("Y")+5) - { - $year = my_date("Y"); - } - - // Then the month - if($month < 1 || $month > 12) - { - $month = my_date("n"); - } - - $weekdays = fetch_weekday_structure($calendar['startofweek']); - - $calendar_permissions = get_calendar_permissions($calendar['cid']); - - $month_link = get_calendar_link($calendar['cid'], $year, $month); - - $next_month = get_next_month($month, $year); - $prev_month = get_prev_month($month, $year); - - $month_start_weekday = gmdate("w", gmmktime(0, 0, 0, $month, $calendar['startofweek']+1, $year)); - - $prev_month_days = gmdate("t", gmmktime(0, 0, 0, $prev_month['month'], 1, $prev_month['year'])); - if($month_start_weekday != $weekdays[0] || $calendar['startofweek'] != 0) - { - $prev_days = $day = gmdate("t", gmmktime(0, 0, 0, $prev_month['month'], 1, $prev_month['year'])); - $day -= array_search(($month_start_weekday), $weekdays); - $day += $calendar['startofweek']+1; - if($day > $prev_month_days+1) - { - // Go one week back - $day -= 7; - } - $calendar_month = $prev_month['month']; - $calendar_year = $prev_month['year']; - } - else - { - $day = $calendar['startofweek']+1; - $calendar_month = $month; - $calendar_year = $year; - } - - // So now we fetch events for this month - $start_timestamp = gmmktime(0, 0, 0, $calendar_month, $day, $year); - $num_days = gmdate("t", gmmktime(0, 0, 0, $month, 1, $year)); - $end_timestamp = gmmktime(23, 59, 59, $month, $num_days, $year); - - if(!$events_cache) - { - $events_cache = get_events($calendar, $start_timestamp, $end_timestamp, $calendar_permissions['canmoderateevents']); - } - - $today = my_date("dnY"); - - // Build weekday headers - $weekday_headers = ''; - foreach($weekdays as $weekday) - { - $weekday_name = fetch_weekday_name($weekday, true); - eval("\$weekday_headers .= \"".$templates->get("calendar_mini_weekdayheader")."\";"); - } - - $in_month = 0; - $day_bits = $calendar_rows = ''; - for($row = 0; $row < 6; ++$row) // Iterate weeks (each week gets a row) - { - foreach($weekdays as $weekday_id => $weekday) - { - // Current month always starts on 1st row - if($row == 0 && $day == $calendar['startofweek']+1) - { - $in_month = 1; - $calendar_month = $month; - $calendar_year = $year; - } - else if($calendar_month == $prev_month['month'] && $day > $prev_month_days) - { - $day = 1; - $in_month = 1; - $calendar_month = $month; - $calendar_year = $year; - } - else if($day > $num_days && $calendar_month != $prev_month['month']) - { - $in_month = 0; - $calendar_month = $next_month['month']; - $calendar_year = $next_month['year']; - $day = 1; - if($calendar_month == $month) - { - $in_month = 1; - } - } - - if($weekday_id == 0) - { - $week_stamp = gmmktime(0, 0, 0, $calendar_month, $day, $calendar_year); - $week_link = get_calendar_week_link($calendar['cid'], $week_stamp); - } - - if($weekday_id == 0 && $calendar_month == $next_month['month']) - { - break; - } - - $link_to_day = false; - // Any events on this specific day? - if(@count($events_cache["$day-$calendar_month-$calendar_year"]) > 0) - { - $link_to_day = true; - } - - // Is the current day - if($day.$calendar_month.$year == $today && $month == $calendar_month) - { - $day_class = "trow_sep"; - } - // Not in this month - else if($in_month == 0) - { - $day_class = "trow1"; - } - // Just a normal day in this month - else - { - $day_class = "trow2"; - } - if($link_to_day) - { - $calendar['link'] = get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day); - eval("\$day_link = \"".$templates->get("calendar_mini_weekrow_day_link")."\";"); - } - else - { - $day_link = $day; - } - eval("\$day_bits .= \"".$templates->get("calendar_mini_weekrow_day")."\";"); - ++$day; - } - if($day_bits) - { - eval("\$calendar_rows .= \"".$templates->get("calendar_mini_weekrow")."\";"); - } - $day_bits = ""; - } - eval("\$mini_calendar = \"".$templates->get("calendar_mini")."\";"); - return $mini_calendar; -} - -/** - * Cache available calendars in to memory or return the cached calendars - * - * @return array Cached calendars - */ -function cache_calendars() -{ - global $db; - static $calendar_cache; - - if(is_array($calendar_cache)) - { - return $calendar_cache; - } - - $query = $db->simple_select("calendars", "*", "", array("order_by" => "disporder", "order_dir" => "asc")); - while($calendar = $db->fetch_array($query)) - { - $calendar_cache[$calendar['cid']] = $calendar; - } - return $calendar_cache; -} - -/** - * Fetch the calendar permissions for the current user for one or more calendars - * - * @param int $cid Optional calendar ID. If none specified, permissions for all calendars are returned - * @return array Array of permissions - */ -function get_calendar_permissions($cid=0) -{ - global $db, $mybb; - static $calendar_permissions; - - $calendars = cache_calendars(); - - $group_permissions = array( - "canviewcalendar" => $mybb->usergroup['canviewcalendar'], - "canaddevents" => $mybb->usergroup['canaddevents'], - "canbypasseventmod" => $mybb->usergroup['canbypasseventmod'], - "canmoderateevents" => $mybb->usergroup['canmoderateevents'] - ); - - if(!is_array($calendars)) - { - return $group_permissions; - } - - $gid = $mybb->user['usergroup']; - - if(isset($mybb->user['additionalgroups'])) - { - $gid .= ",".$mybb->user['additionalgroups']; - } - - if(!is_array($calendar_permissions)) - { - $calendar_permissions = array(); - $query = $db->simple_select("calendarpermissions", "*"); - while($permission = $db->fetch_array($query)) - { - $calendar_permissions[$permission['cid']][$permission['gid']] = $permission; - } - - // Add in our usergroup permissions (if custom ones are set, these aren't added) - if(is_array($calendar_permissions)) - { - foreach($calendar_permissions as $calendar => $permission) - { - if(is_array($calendar_permissions[$calendar][$mybb->user['usergroup']])) - { - // Already has permissions set - continue; - } - - // Use the group permissions! - $calendar_permissions[$calendar][$mybb->user['usergroup']] = $group_permissions; - $calendar_permissions[$calendar][$mybb->user['usergroup']]['cid'] = $calendar; - $calendar_permissions[$calendar][$mybb->user['usergroup']]['gid'] = $mybb->user['usergroup']; - } - } - } - - if($cid > 0) - { - if(isset($calendar_permissions[$cid])) - { - $permissions = fetch_calendar_permissions($cid, $gid, $calendar_permissions[$cid]); - } - if(empty($permissions)) - { - $permissions = $group_permissions; - } - } - else - { - foreach($calendars as $calendar) - { - if(isset($calendar_permissions[$calendar['cid']])) - { - $permissions[$calendar['cid']] = fetch_calendar_permissions($calendar['cid'], $gid, $calendar_permissions[$calendar['cid']]); - } - if(empty($permissions[$calendar['cid']])) - { - $permissions[$calendar['cid']] = $group_permissions; - } - } - } - return $permissions; -} - -/** - * Fetch the calendar permissions - * - * @param int $cid Calendar ID - * @param string $gid User group ID, comma seperated - * @param array Array of permissions for this calendar and group - * @return array|void Array of current permissions or nothing if an error occured - */ -function fetch_calendar_permissions($cid, $gid, $calendar_permissions) -{ - $groups = explode(",", $gid); - - if(!is_array($calendar_permissions)) - { - return; - } - - $current_permissions = array(); - - foreach($groups as $gid) - { - // If this calendar has permissions set for this group - if($calendar_permissions[$gid]) - { - $level_permissions = $calendar_permissions[$gid]; - foreach($level_permissions as $permission => $access) - { - if($access >= $current_permissions[$permission] || ($access == "yes" && $current_permissions[$permission] == "no") || !$current_permissions[$permission]) - { - $current_permissions[$permission] = $access; - } - } - } - } - - if(count($current_permissions) == 0) - { - return; - } - return $current_permissions; -} - -/** - * Build a calendar select list to jump between calendars - * - * @param int $selected The selected calendar ID - * @return string The calendar select - */ -function build_calendar_jump($selected=0) -{ - global $db, $mybb, $templates, $lang, $gobutton; - - $calendar_permissions = get_calendar_permissions(); - - $calendars = cache_calendars(); - - if(!is_array($calendars)) - { - return; - } - - $jump_options = ''; - - foreach($calendars as $calendar) - { - if($calendar_permissions[$calendar['cid']]['canviewcalendar'] == 0) - { - continue; - } - $calendar['name'] = htmlspecialchars_uni($calendar['name']); - $sel = ""; - if($selected == $calendar['cid'] || ($selected == 0 && $calendar['disporder'] == 1)) - { - $sel = "selected=\"selected\""; - } - - eval("\$jump_options .= \"".$templates->get("calendar_jump_option")."\";"); - } - - eval("\$calendar_jump = \"".$templates->get("calendar_jump")."\";"); - return $calendar_jump; -} - -/** - * Fetch the next calendar month from a specified month/year - * - * @param int $month The month - * @param int $year The year - * @return array Array of the next month and next year - */ -function get_next_month($month, $year) -{ - global $monthnames; - - if($month == 12) - { - $nextmonth = 1; - $nextyear = $year+1; - } - else - { - $nextmonth = $month+1; - $nextyear = $year; - } - - return array("month" => $nextmonth, "year" => $nextyear, "name" => $monthnames[$nextmonth]); -} - -/** - * Fetch the previous calendar month from a specified month/year - * - * @param int $month The month - * @param int $year The year - * @return array Array of the previous month and previous year - */ -function get_prev_month($month, $year) -{ - global $monthnames; - - if($month == 1) - { - $prevmonth = 12; - $prevyear = $year-1; - } - else - { - $prevmonth = $month-1; - $prevyear = $year; - } - - return array("month" => $prevmonth, "year" => $prevyear, "name" => $monthnames[$prevmonth]); -} - -/** - * Fetch the events for a specific calendar and date range - * - * @param int $calendar The calendar ID - * @param int $start Start time stamp - * @param int $end End time stmap - * @param int $unapproved 1 to fetch unapproved events too - * @param int $private The user ID to fetch private events for (0 fetches none) - * @return array Array of events - */ -function get_events($calendar, $start, $end, $unapproved=0, $private=1) -{ - global $db, $mybb; - - // We take in to account timezones here - we either add 14 hours or subtract 12 hours from our GMT time ranges - $start -= 12*3600; - $end += 14*3600; - - $visible_where = ''; - if($unapproved != 1) - { - $visible_where = " AND e.visible='1'"; - } - - $events_cache = array(); - $query = $db->query(" - SELECT u.*, e.* - FROM ".TABLE_PREFIX."events e - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=e.uid) - WHERE e.cid='{$calendar['cid']}' {$visible_where} AND ((e.endtime>={$start} AND e.starttime<={$end}) OR (e.endtime=0 AND e.starttime>={$start} AND e.starttime<={$end})) AND ((e.uid='{$mybb->user['uid']}' AND private='1') OR private!='1') - ORDER BY endtime DESC - "); - while($event = $db->fetch_array($query)) - { - if($event['ignoretimezone'] == 0) - { - $offset = (float)$event['timezone']; - } - else - { - $offset = (float)$mybb->user['timezone']; - } - $event['starttime_user'] = $event['starttime']+($offset*3600); - - // Single day event - if($event['endtime'] == 0) - { - $event_date = gmdate("j-n-Y", $event['starttime_user']); - $events_cache[$event_date][] = $event; - } - // Ranged event - else - { - $event_date = explode("-", gmdate("j-n-Y", $event['starttime_user'])); - $event['endtime_user'] = $event['endtime']+($offset*3600); - $event['weekday_start'] = $calendar['startofweek']; - - $start_day = gmmktime(0, 0, 0, $event_date[1], $event_date[0], $event_date[2]); - - $event['repeats'] = my_unserialize($event['repeats']); - - // Event does not repeat - just goes over a few days - if($event['repeats']['repeats'] == 0) - { - if($start_day < $start) - { - $range_start = gmmktime(0, 0, 0, gmdate("n", $start), gmdate("j", $start), gmdate("Y", $start)); - } - else - { - $range_start = $start_day; - } - } - else - { - $range_start = fetch_next_occurance($event, array("start" => $start, "end" => $end), $start_day, true); - } - $first = ""; - $event_date = explode("-", gmdate("j-n-Y", $range_start)); - - // Get rid of hour/minutes because sometimes they cause the events to stretch into the next day - $range_end = gmmktime(23, 59, 59, gmdate("n", $event['endtime_user']), gmdate("j", $event['endtime_user']), gmdate("Y", $event['endtime_user'])); - while($range_start < $range_end) - { - // Outside the dates we care about, break! (No unnecessary looping here!) - if($range_start > $end || !$range_start) - { - break; - } - if($range_start >= $start) - { - $day_date = gmdate("j-n-Y", $range_start); - if($first && $day_date != "{$first}") - { - $events_cache[$day_date][] = &$events_cache["{$first}"][$count]; - } - else if(!$first) - { - if(!isset($events_cache[$day_date])) - { - $events_cache[$day_date] = array(); - } - $count = count($events_cache[$day_date]); - $first = $day_date; - $events_cache[$day_date][] = $event; - } - } - if($event['repeats']['repeats'] == 0) - { - $range_start += 86400; - } - else - { - $range_start = fetch_next_occurance($event, array("start" => $start, "end" => $end), $range_start); - } - } - } - } - return $events_cache; -} - -/** - * Fetch the birthdays for one or more months or a specific day - * - * @param int|array $months Integer of the month or array of months - * @param int $day Day of the specific month (if only one month specified above) - * @return array Array of birthdays - */ -function get_birthdays($months, $day=0) -{ - global $db; - - $year = my_date("Y"); - - if(!is_array($months)) - { - $months = array($months); - } - - foreach($months as $month) - { - if($day) - { - $day_where = "{$day}-{$month}"; - } - else - { - $day_where = "%-{$month}"; - } - if($month == 3 && ($day == 1 || !$day) && my_date("L", gmmktime(0, 0, 0, $month, 1, $year)) != 1) - { - $where[] = "birthday LIKE '29-2%' OR birthday='29-2'"; - $feb_fix = 1; - } - $where[] = "birthday LIKE '{$day_where}-%' OR birthday LIKE '{$day_where}'"; - } - - $where = implode(" OR ", $where); - - $bdays = array(); - - $query = $db->simple_select("users", "uid, username, birthday, birthdayprivacy, usergroup, displaygroup", $where); - while($user = $db->fetch_array($query)) - { - $bday = explode("-", $user['birthday']); - if($bday[2] && $bday[2] < $year) - { - $user['age'] = $year - $bday[2]; - } - if($feb_fix == 1 && $bday[0] == 29 && $bday[1] == 2) - { - $bdays["1-3"][] = $user; - } - else - { - $bdays["$bday[0]-$bday[1]"][] = $user; - } - } - if($day) - { - if(!isset($bdays["$day-$month"])) - { - return array(); - } - return $bdays["$day-$month"]; - } - return $bdays; -} - -/** - * Fetch an ordered list of weekdays depended on a specified starting day - * - * @param int $week_start The weekday we want to start the week with - * @return array Ordered list of weekdays dependant on start of week - */ -function fetch_weekday_structure($week_start) -{ - switch($week_start) - { - case "1": - $weekdays = array(1,2,3,4,5,6,0); - break; - case "2": - $weekdays = array(2,3,4,5,6,0,1); - break; - case "3": - $weekdays = array(3,4,5,6,0,1,2); - break; - case "4": - $weekdays = array(4,5,6,0,1,2,3); - break; - case "5": - $weekdays = array(5,6,0,1,2,3,4); - break; - case "6": - $weekdays = array(6,0,1,2,3,4,5); - break; - default: - $weekdays = array(0,1,2,3,4,5,6); - break; - } - return $weekdays; -} - -/** - * Fetch a weekday name based on a number - * - * @param int $weekday The weekday number - * @param boolean $short True to fetch the short name ('S'), false to fetch full name - * @return string The weekday name - */ -function fetch_weekday_name($weekday, $short=false) -{ - global $lang; - switch($weekday) - { - case 1: - $weekday_name = $lang->monday; - $short_weekday_name = $lang->short_monday; - break; - case 2: - $weekday_name = $lang->tuesday; - $short_weekday_name = $lang->short_tuesday; - break; - case 3: - $weekday_name = $lang->wednesday; - $short_weekday_name = $lang->short_wednesday; - break; - case 4: - $weekday_name = $lang->thursday; - $short_weekday_name = $lang->short_thursday; - break; - case 5: - $weekday_name = $lang->friday; - $short_weekday_name = $lang->short_friday; - break; - case 6: - $weekday_name = $lang->saturday; - $short_weekday_name = $lang->short_saturday; - break; - case 0: - $weekday_name = $lang->sunday; - $short_weekday_name = $lang->short_sunday; - break; - } - - if($short == true) - { - return $short_weekday_name; - } - else - { - return $weekday_name; - } -} - -/** - * Fetches the next occurance for a repeating event. - * - * @param array $event The event array - * @param array $range The range of start/end timestamps - * @param int $last_occurance The last occurance of this event - * @param boolean $first True if this is our first iteration of this function (Does some special optimised calculations on false) - * @return int The next occurance timestamp - */ -function fetch_next_occurance($event, $range, $last_occurance, $first=false) -{ - $new_time = $last_occurance; - - $repeats = $event['repeats']; - - $start_day = explode("-", gmdate("j-n-Y", $event['starttime_user'])); - $start_date = gmmktime(0, 0, 0, $start_day[1], $start_day[0], $start_day[2]); - - if($repeats['repeats'] == 0) - { - $new_time += 86400; - } - // Repeats daily - else if($repeats['repeats'] == 1) - { - // If this isn't the first time we've called this function then we can just tack on the time since $last_occurance - if($first == false) - { - $new_time += 86400*$repeats['days']; - } - else - { - // Need to count it out - if($range['start'] > $event['starttime']) - { - $days_since = ceil(($range['start']-$start_date)/86400); - $occurances = floor($days_since/$repeats['days']); - $next_date = $occurances*$repeats['days']; - $new_time = $event['starttime']+(86400*$next_date); - } - else - { - $new_time = $start_date; - } - } - } - // Repeats on weekdays only - else if($repeats['repeats'] == 2) - { - if($first == false) - { - $last_dow = gmdate("w", $last_occurance); - // Last day of week = friday, +3 gives monday - if($last_dow == 5) - { - $new_time += 86400*3; - } - // Still in week, add a day - else - { - $new_time += 86400; - } - } - // First loop with start date - else - { - if($range['start'] < $event['starttime']) - { - $start = $event['starttime']; - } - else - { - $start = $range['start']; - } - $first_dow = gmdate("w", $start); - if($first_dow == 6) - { - $new_time = $start + (86400*2); - } - else if($first_dow == 0) - { - $new_time = $start + 86400; - } - else - { - $new_time = $start; - } - } - } - // Repeats weekly - else if($repeats['repeats'] == 3) - { - $weekdays = fetch_weekday_structure($event['weekday_start']); - $last_dow = gmdate("w", $last_occurance); - if($first == true) - { - $last_dow = -1; - $start_day = gmdate('w', $last_occurance); - if(in_array($start_day, $weekdays)) - { - $next_dow = 0; - } - } - else - { - foreach($repeats['days'] as $weekday) - { - if($weekday > $last_dow) - { - $next_dow = $weekday; - break; - } - } - } - if(!isset($next_dow)) - { - // Fetch first weekday - $first = $repeats['days'][0]*86400; - $new_time += $first; - // Increase x weeks - $new_time += (7-$last_dow)*86400; - $new_time += (($repeats['weeks']-1)*604800); - } - else - { - // Next day of week exists - if($last_dow > 0) - { - $day_diff = $next_dow-$last_dow; - } - else - { - $day_diff = $next_dow; - } - $new_time += $day_diff*86400; - } - } - // Repeats monthly - else if($repeats['repeats'] == 4) - { - $last_month = gmdate("n", $last_occurance); - $last_year = gmdate("Y", $last_occurance); - $last_day = gmdate("j", $last_occurance); - $last_num_days = gmdate("t", $last_occurance); - - // X of every Y months - if($repeats['day']) - { - if($first == true) - { - if($last_day <= $repeats['day']) - { - $new_time = gmmktime(0, 0, 0, $last_month, $repeats['day'], $last_year); - } - else - { - $new_time = gmmktime(0, 0, 0, $last_month+1, $repeats['day'], $last_year); - if($new_time > $event['endtime']) - { - return false; - } - } - } - else - { - $new_time = gmmktime(0, 0, 0, $last_month+$repeats['months'], $repeats['day'], $last_year); - } - } - // The 1st/etc (weekday) of every X months - else - { - if($first == true) - { - $new_time = fetch_weekday_monthly_repetition($repeats, $last_month, $last_year); - if($new_time < $last_occurance) - { - $new_time = fetch_weekday_monthly_repetition($repeats, $last_month+1, $last_year); - } - } - else - { - $new_time = fetch_weekday_monthly_repetition($repeats, $last_month+$repeats['months'], $last_year); - } - } - } - // Repeats yearly - else if($repeats['repeats'] == 5) - { - $last_year = gmdate("Y", $last_occurance); - - // Repeats on (day) of (month) every (years) - if($repeats['day']) - { - if($first == true) - { - $new_time = gmmktime(0, 0, 0, $repeats['month'], $repeats['day'], $last_year); - if($new_time < $last_occurance) - { - $new_time = gmmktime(0, 0, 0, $repeats['month'], $repeats['day'], $last_year+1); - } - } - else - { - $new_time = gmmktime(0, 0, 0, $repeats['month'], $repeats['day'], $last_year+$repeats['years']); - } - } - // The 1st/etc (weekday) of (month) every (years) - else - { - if($first == true) - { - $new_time = fetch_weekday_monthly_repetition($repeats, $repeats['month'], $last_year); - if($new_time < $last_occurance) - { - $new_time = fetch_weekday_monthly_repetition($repeats, $repeats['month'], $last_year+1); - } - } - else - { - $new_time = fetch_weekday_monthly_repetition($repeats, $repeats['month'], $last_year+$repeats['years']); - } - } - } - return $new_time; -} - -/** - * Fetch a friendly repetition value for a specific event (Repeats every x months etc) - * - * @param array $event The array of the event - * @return string The friendly repetition string - */ -function fetch_friendly_repetition($event) -{ - global $lang; - - $monthnames = array( - "offset", - $lang->month_1, - $lang->month_2, - $lang->month_3, - $lang->month_4, - $lang->month_5, - $lang->month_6, - $lang->month_7, - $lang->month_8, - $lang->month_9, - $lang->month_10, - $lang->month_11, - $lang->month_12 - ); - - if(!is_array($event['repeats'])) - { - $event['repeats'] = my_unserialize($event['repeats']); - if(!is_array($event['repeats'])) - { - return false; - } - } - - $repeats = $event['repeats']; - - switch($repeats) - { - case 1: - if($repeats['days'] <= 1) - { - return $lang->repeats_every_day; - } - return $lang->sprintf($lang->repeats_every_x_days, $event['repeats']['days']); - break; - case 2: - return $lang->repeats_on_weekdays; - break; - case 3: - if($event['repeats']['days'] || count($event['repeats']['days']) == 7) - { - $weekdays = null; - foreach($event['repeats']['days'] as $id => $weekday) - { - $weekday_name = fetch_weekday_name($weekday); - if($event['repeats']['days'][$id+1] && $weekday) - { - $weekdays .= $lang->comma; - } - else if(!$event['repeats']['days'][$id+1] && $weekday) - { - $weekdays .= " {$lang->and} "; - } - $weekdays .= $weekday_name; - } - } - if($event['repeats']['weeks'] == 1) - { - if($weekdays) - { - return $lang->sprintf($lang->every_week_on_days, $weekdays); - } - else - { - return $lang->sprintf($lang->every_week); - } - } - else - { - if($weekdays) - { - return $lang->sprintf($lang->every_x_weeks_on_days, $event['repeats']['weeks'], $weekdays); - } - else - { - return $lang->sprintf($lang->every_x_weeks, $event['repeats']['weeks']); - } - } - break; - case 4: - if($event['repeats']['day']) - { - if($event['repeats']['months'] == 1) - { - return $lang->sprintf($lang->every_month_on_day, $event['repeats']['day']); - } - else - { - return $lang->sprintf($lang->every_x_months_on_day, $event['repeats']['day'], $event['repeats']['months']); - } - } - else - { - $weekday_name = fetch_weekday_name($event['repeats']['weekday']); - $occurance = "weekday_occurance_".$event['repeats']['occurance']; - $occurance = $lang->$occurance; - if($event['repeats']['months'] == 1) - { - return $lang->sprintf($lang->every_month_on_weekday, $occurance, $weekday_name); - } - else - { - return $lang->sprintf($lang->every_x_months_on_weekday, $occurance, $weekday_name, $event['repeats']['months']); - } - } - break; - case 5: - $month = $monthnames[$event['repeats']['month']]; - if($event['repeats']['day']) - { - if($event['repeats']['years'] == 1) - { - return $lang->sprintf($lang->every_year_on_day, $event['repeats']['day'], $month); - } - else - { - return $lang->sprintf($lang->every_x_years_on_day, $event['repeats']['day'], $month, $event['repeats']['years']); - } - } - else - { - $weekday_name = fetch_weekday_name($event['repeats']['weekday']); - $occurance = "weekday_occurance_".$event['repeats']['occurance']; - $occurance = $lang->$occurance; - if($event['repeats']['years'] == 1) - { - return $lang->sprintf($lang->every_year_on_weekday, $occurance, $weekday_name, $month); - } - else - { - return $lang->sprintf($lang->every_x_year_on_weekday, $occurance, $weekday_name, $month, $event['repeats']['years']); - } - } - break; - } -} - -/** - * Fetch a timestamp for "the first/second etc weekday" for a month. - * - * @param array $repeats The repetition array from the event - * @param int $month The month of the year - * @param int $year The year - * @return int The UNIX timestamp - */ -function fetch_weekday_monthly_repetition($repeats, $month, $year) -{ - $first_last = gmmktime(0, 0, 0, $month, 1, $year); - $first_dow = gmdate("w", $first_last); - $day = 1+($repeats['weekday']-$first_dow); - if($day < 1) - { - $day += 7; - } - if($repeats['occurance'] != "last") - { - $day += ($repeats['occurance']-1)*7; - } - else - { - $last_dow = gmdate("w", gmmktime(0, 0, 0, $month, gmdate("t", $first_last), $year)); - $day = (gmdate("t", $first_last)-$last_dow)+$repeats['weekday']; - if($day > gmdate("t", $first_dow)) - { - $day -= 7; - } - } - return gmmktime(0, 0, 0, $month, $day, $year); -} diff --git a/html/forums/inc/functions_forumlist.php b/html/forums/inc/functions_forumlist.php deleted file mode 100644 index 4e3a7af..0000000 --- a/html/forums/inc/functions_forumlist.php +++ /dev/null @@ -1,589 +0,0 @@ - 0 - ); - $forum_viewers_text = ''; - $forum_viewers_text_plain = ''; - - // Get the permissions for this forum - $permissions = $forumpermissions[$forum['fid']]; - - // If this user doesnt have permission to view this forum and we're hiding private forums, skip this forum - if($permissions['canview'] != 1 && $mybb->settings['hideprivateforums'] == 1) - { - continue; - } - - $forum = $plugins->run_hooks("build_forumbits_forum", $forum); - - // Build the link to this forum - $forum_url = get_forum_link($forum['fid']); - - // This forum has a password, and the user isn't authenticated with it - hide post information - $hideinfo = $hidecounters = false; - $hidelastpostinfo = false; - $showlockicon = 0; - if(isset($permissions['canviewthreads']) && $permissions['canviewthreads'] != 1) - { - $hideinfo = true; - } - - if(isset($permissions['canonlyviewownthreads']) && $permissions['canonlyviewownthreads'] == 1) - { - $hidecounters = true; - - // If we only see our own threads, find out if there's a new post in one of them so the lightbulb shows - if(!is_array($private_forums)) - { - $private_forums = $fids = array(); - foreach($fcache as $fcache_p) - { - foreach($fcache_p as $parent_p) - { - foreach($parent_p as $forum_p) - { - if($forumpermissions[$forum_p['fid']]['canonlyviewownthreads']) - { - $fids[] = $forum_p['fid']; - } - } - } - } - - if(!empty($fids)) - { - $fids = implode(',', $fids); - $query = $db->simple_select("threads", "tid, fid, subject, lastpost, lastposter, lastposteruid", "uid = '{$mybb->user['uid']}' AND fid IN ({$fids}) AND visible != '-2'", array("order_by" => "lastpost", "order_dir" => "desc")); - - while($thread = $db->fetch_array($query)) - { - if(!$private_forums[$thread['fid']]) - { - $private_forums[$thread['fid']] = $thread; - } - } - } - } - - if($private_forums[$forum['fid']]['lastpost']) - { - $forum['lastpost'] = $private_forums[$forum['fid']]['lastpost']; - - $lastpost_data = array( - "lastpost" => $private_forums[$forum['fid']]['lastpost'], - "lastpostsubject" => $private_forums[$forum['fid']]['subject'], - "lastposter" => $private_forums[$forum['fid']]['lastposter'], - "lastposttid" => $private_forums[$forum['fid']]['tid'], - "lastposteruid" => $private_forums[$forum['fid']]['lastposteruid'] - ); - } - } - else - { - $lastpost_data = array( - "lastpost" => $forum['lastpost'], - "lastpostsubject" => $forum['lastpostsubject'], - "lastposter" => $forum['lastposter'], - "lastposttid" => $forum['lastposttid'], - "lastposteruid" => $forum['lastposteruid'] - ); - } - - if($forum['password'] != '' && $mybb->cookies['forumpass'][$forum['fid']] !== md5($mybb->user['uid'].$forum['password'])) - { - $hideinfo = true; - $showlockicon = 1; - } - - // Fetch subforums of this forum - if(isset($fcache[$forum['fid']])) - { - $forum_info = build_forumbits($forum['fid'], $depth+1); - - // Increment forum counters with counters from child forums - $forum['threads'] += $forum_info['counters']['threads']; - $forum['posts'] += $forum_info['counters']['posts']; - $forum['unapprovedthreads'] += $forum_info['counters']['unapprovedthreads']; - $forum['unapprovedposts'] += $forum_info['counters']['unapprovedposts']; - - if(!empty($forum_info['counters']['viewing'])) - { - $forum['viewers'] += $forum_info['counters']['viewing']; - } - - // If the child forums' lastpost is greater than the one for this forum, set it as the child forums greatest. - if($forum_info['lastpost']['lastpost'] > $lastpost_data['lastpost']) - { - $lastpost_data = $forum_info['lastpost']; - - /* - // If our subforum is unread, then so must be our parents. Force our parents to unread as well - if(strstr($forum_info['lightbulb']['folder'], "on") !== false) - { - $forum['lastread'] = 0; - } - // Otherwise, if we have an explicit record in the db, we must make sure that it is explicitly set - else - { - $lastpost_data['lastpost'] = $forum['lastpost']; - }*/ - } - - $sub_forums = $forum_info['forum_list']; - } - - // If we are hiding information (lastpost) because we aren't authenticated against the password for this forum, remove them - if($hidelastpostinfo == true) - { - $lastpost_data = array( - 'lastpost' => 0, - 'lastposter' => '' - ); - } - - // If the current forums lastpost is greater than other child forums of the current parent and forum info isn't hidden, overwrite it - if((!isset($parent_lastpost) || $lastpost_data['lastpost'] > $parent_lastpost['lastpost']) && $hideinfo != true) - { - $parent_lastpost = $lastpost_data; - } - - if(is_array($forum_viewers) && isset($forum_viewers[$forum['fid']]) && $forum_viewers[$forum['fid']] > 0) - { - $forum['viewers'] = $forum_viewers[$forum['fid']]; - } - - // Increment the counters for the parent forum (returned later) - if($hideinfo != true && $hidecounters != true) - { - $parent_counters['threads'] += $forum['threads']; - $parent_counters['posts'] += $forum['posts']; - $parent_counters['unapprovedposts'] += $forum['unapprovedposts']; - $parent_counters['unapprovedthreads'] += $forum['unapprovedthreads']; - - if(!empty($forum['viewers'])) - { - $parent_counters['viewers'] += $forum['viewers']; - } - } - - // Done with our math, lets talk about displaying - only display forums which are under a certain depth - if($depth > $showdepth) - { - continue; - } - - // Get the lightbulb status indicator for this forum based on the lastpost - $lightbulb = get_forum_lightbulb($forum, $lastpost_data, $showlockicon); - - // Fetch the number of unapproved threads and posts for this forum - $unapproved = get_forum_unapproved($forum); - - if($hideinfo == true) - { - unset($unapproved); - } - - // Sanitize name and description of forum. - $forum['name'] = preg_replace("#&(?!\#[0-9]+;)#si", "&", $forum['name']); // Fix & but allow unicode - $forum['description'] = preg_replace("#&(?!\#[0-9]+;)#si", "&", $forum['description']); // Fix & but allow unicode - $forum['name'] = preg_replace("#&([^\#])(?![a-z1-4]{1,10};)#i", "&$1", $forum['name']); - $forum['description'] = preg_replace("#&([^\#])(?![a-z1-4]{1,10};)#i", "&$1", $forum['description']); - - // If this is a forum and we've got subforums of it, load the subforums list template - if($depth == 2 && $sub_forums) - { - eval("\$subforums = \"".$templates->get("forumbit_subforums")."\";"); - } - // A depth of three indicates a comma separated list of forums within a forum - else if($depth == 3) - { - if($donecount < $mybb->settings['subforumsindex']) - { - $statusicon = ''; - - // Showing mini status icons for this forum - if($mybb->settings['subforumsstatusicons'] == 1) - { - $lightbulb['folder'] = "mini".$lightbulb['folder']; - eval("\$statusicon = \"".$templates->get("forumbit_depth3_statusicon", 1, 0)."\";"); - } - - // Fetch the template and append it to the list - eval("\$forum_list .= \"".$templates->get("forumbit_depth3", 1, 0)."\";"); - $comma = $lang->comma; - } - - // Have we reached our max visible subforums? put a nice message and break out of the loop - ++$donecount; - if($donecount == $mybb->settings['subforumsindex']) - { - if(subforums_count($fcache[$pid]) > $donecount) - { - $forum_list .= $comma.$lang->sprintf($lang->more_subforums, (subforums_count($fcache[$pid]) - $donecount)); - } - } - continue; - } - - // Forum is a category, set template type - if($forum['type'] == 'c') - { - $forumcat = '_cat'; - } - // Forum is a standard forum, set template type - else - { - $forumcat = '_forum'; - } - - if($forum['linkto'] == '') - { - // No posts have been made in this forum - show never text - if(($lastpost_data['lastpost'] == 0 || $lastpost_data['lastposter'] == '') && $hideinfo != true) - { - eval("\$lastpost = \"".$templates->get("forumbit_depth2_forum_lastpost_never")."\";"); - } - elseif($hideinfo != true) - { - // Format lastpost date and time - $lastpost_date = my_date('relative', $lastpost_data['lastpost']); - - // Set up the last poster, last post thread id, last post subject and format appropriately - $lastpost_data['lastposter'] = htmlspecialchars_uni($lastpost_data['lastposter']); - $lastpost_profilelink = build_profile_link($lastpost_data['lastposter'], $lastpost_data['lastposteruid']); - $lastpost_link = get_thread_link($lastpost_data['lastposttid'], 0, "lastpost"); - $lastpost_subject = $full_lastpost_subject = $parser->parse_badwords($lastpost_data['lastpostsubject']); - if(my_strlen($lastpost_subject) > 25) - { - $lastpost_subject = my_substr($lastpost_subject, 0, 25)."..."; - } - $lastpost_subject = htmlspecialchars_uni($lastpost_subject); - $full_lastpost_subject = htmlspecialchars_uni($full_lastpost_subject); - - // Call lastpost template - if($depth != 1) - { - eval("\$lastpost = \"".$templates->get("forumbit_depth{$depth}_forum_lastpost")."\";"); - } - } - - if($mybb->settings['showforumviewing'] != 0 && $forum['viewers'] > 0) - { - if($forum['viewers'] == 1) - { - $forum_viewers_text = $lang->viewing_one; - } - else - { - $forum_viewers_text = $lang->sprintf($lang->viewing_multiple, $forum['viewers']); - } - $forum_viewers_text_plain = $forum_viewers_text; - eval("\$forum_viewers_text = \"".$templates->get("forumbit_depth2_forum_viewers")."\";"); - } - } - // If this forum is a link or is password protected and the user isn't authenticated, set counters to "-" - if($forum['linkto'] != '' || $hideinfo == true || $hidecounters == true) - { - $posts = "-"; - $threads = "-"; - } - // Otherwise, format thread and post counts - else - { - $posts = my_number_format($forum['posts']); - $threads = my_number_format($forum['threads']); - } - - // If this forum is a link or is password protected and the user isn't authenticated, set lastpost to "-" - if($forum['linkto'] != '' || $hideinfo == true || $hidelastpostinfo == true) - { - eval("\$lastpost = \"".$templates->get("forumbit_depth2_forum_lastpost_hidden")."\";"); - } - - // Moderator column is not off - if($mybb->settings['modlist'] != 0) - { - $done_moderators = array( - "users" => array(), - "groups" => array() - ); - $moderators = ''; - // Fetch list of moderators from this forum and its parents - $parentlistexploded = explode(',', $forum['parentlist']); - foreach($parentlistexploded as $mfid) - { - // This forum has moderators - if(isset($moderatorcache[$mfid]) && is_array($moderatorcache[$mfid])) - { - // Fetch each moderator from the cache and format it, appending it to the list - foreach($moderatorcache[$mfid] as $modtype) - { - foreach($modtype as $moderator) - { - if($moderator['isgroup']) - { - if(in_array($moderator['id'], $done_moderators['groups'])) - { - continue; - } - - $moderator['title'] = htmlspecialchars_uni($moderator['title']); - - eval("\$moderators .= \"".$templates->get("forumbit_moderators_group", 1, 0)."\";"); - $done_moderators['groups'][] = $moderator['id']; - } - else - { - if(in_array($moderator['id'], $done_moderators['users'])) - { - continue; - } - - $moderator['profilelink'] = get_profile_link($moderator['id']); - $moderator['username'] = htmlspecialchars_uni($moderator['username']); - - eval("\$moderators .= \"".$templates->get("forumbit_moderators_user", 1, 0)."\";"); - $done_moderators['users'][] = $moderator['id']; - } - $comma = $lang->comma; - } - } - } - } - $comma = ''; - - // If we have a moderators list, load the template - if($moderators) - { - eval("\$modlist = \"".$templates->get("forumbit_moderators")."\";"); - } - else - { - $modlist = ''; - } - } - - // Descriptions aren't being shown - blank them - if($mybb->settings['showdescriptions'] == 0) - { - $forum['description'] = ''; - } - - // Check if this category is either expanded or collapsed and hide it as necessary. - $expdisplay = ''; - $collapsed_name = "cat_{$forum['fid']}_c"; - if(isset($collapsed[$collapsed_name]) && $collapsed[$collapsed_name] == "display: show;") - { - $expcolimage = "collapse_collapsed.png"; - $expdisplay = "display: none;"; - $expthead = " thead_collapsed"; - $expaltext = "[+]"; - } - else - { - $expcolimage = "collapse.png"; - $expthead = ""; - $expaltext = "[-]"; - } - - // Swap over the alternate backgrounds - $bgcolor = alt_trow(); - - // Add the forum to the list - eval("\$forum_list .= \"".$templates->get("forumbit_depth$depth$forumcat")."\";"); - } - } - - if(!isset($parent_lastpost)) - { - $parent_lastpost = 0; - } - - if(!isset($lightbulb)) - { - $lightbulb = ''; - } - - // Return an array of information to the parent forum including child forums list, counters and lastpost information - return array( - "forum_list" => $forum_list, - "counters" => $parent_counters, - "lastpost" => $parent_lastpost, - "lightbulb" => $lightbulb, - ); -} - -/** - * Fetch the status indicator for a forum based on its last post and the read date - * - * @param array $forum Array of information about the forum - * @param array $lastpost Array of information about the lastpost date - * @param int $locked Whether or not this forum is locked or not - * @return array Array of the folder image to be shown and the alt text - */ -function get_forum_lightbulb($forum, $lastpost, $locked=0) -{ - global $mybb, $lang, $db, $unread_forums; - - // This forum is a redirect, so override the folder icon with the "offlink" icon. - if($forum['linkto'] != '') - { - $folder = "offlink"; - $altonoff = $lang->forum_redirect; - } - // This forum is closed, so override the folder icon with the "offlock" icon. - elseif($forum['open'] == 0 || $locked) - { - $folder = "offlock"; - $altonoff = $lang->forum_locked; - } - else - { - // Fetch the last read date for this forum - if(!empty($forum['lastread'])) - { - $forum_read = $forum['lastread']; - } - elseif(!empty($mybb->cookies['mybb']['readallforums'])) - { - // We've hit the read all forums as a guest, so use the lastvisit of the user - $forum_read = $mybb->cookies['mybb']['lastvisit']; - } - else - { - $forum_read = 0; - $threadcut = TIME_NOW - 60*60*24*$mybb->settings['threadreadcut']; - - // If the user is a guest, do they have a forumsread cookie? - if(!$mybb->user['uid'] && isset($mybb->cookies['mybb']['forumread'])) - { - // If they've visited us before, then they'll have this cookie - otherwise everything is unread... - $forum_read = my_get_array_cookie("forumread", $forum['fid']); - } - else if($mybb->user['uid'] && $mybb->settings['threadreadcut'] > 0 && $threadcut > $lastpost['lastpost']) - { - // We have a user, the forum's unread and we're over our threadreadcut limit for the lastpost - we mark these as read - $forum_read = $lastpost['lastpost'] + 1; - } - } - - //if(!$forum_read) - //{ - //$forum_read = $mybb->user['lastvisit']; - //} - - // If the lastpost is greater than the last visit and is greater than the forum read date, we have a new post - if($lastpost['lastpost'] > $forum_read && $lastpost['lastpost'] != 0) - { - $unread_forums++; - $folder = "on"; - $altonoff = $lang->new_posts; - } - // Otherwise, no new posts - else - { - $folder = "off"; - $altonoff = $lang->no_new_posts; - } - } - - return array( - "folder" => $folder, - "altonoff" => $altonoff - ); -} - -/** - * Fetch the number of unapproved posts, formatted, from a forum - * - * @param array $forum Array of information about the forum - * @return array Array containing formatted string for posts and string for threads - */ -function get_forum_unapproved($forum) -{ - global $lang, $templates; - - $unapproved_threads = $unapproved_posts = ''; - - // If the user is a moderator we need to fetch the count - if(is_moderator($forum['fid'], "canviewunapprove")) - { - // Forum has one or more unaproved posts, format language string accordingly - if($forum['unapprovedposts']) - { - if($forum['unapprovedposts'] > 1) - { - $unapproved_posts_count = $lang->sprintf($lang->forum_unapproved_posts_count, $forum['unapprovedposts']); - } - else - { - $unapproved_posts_count = $lang->sprintf($lang->forum_unapproved_post_count, 1); - } - - $forum['unapprovedposts'] = my_number_format($forum['unapprovedposts']); - eval("\$unapproved_posts = \"".$templates->get("forumbit_depth2_forum_unapproved_posts")."\";"); - } - // Forum has one or more unapproved threads, format language string accordingly - if($forum['unapprovedthreads']) - { - if($forum['unapprovedthreads'] > 1) - { - $unapproved_threads_count = $lang->sprintf($lang->forum_unapproved_threads_count, $forum['unapprovedthreads']); - } - else - { - $unapproved_threads_count = $lang->sprintf($lang->forum_unapproved_thread_count, 1); - } - - $forum['unapprovedthreads'] = my_number_format($forum['unapprovedthreads']); - eval("\$unapproved_threads = \"".$templates->get("forumbit_depth2_forum_unapproved_threads")."\";"); - } - } - return array( - "unapproved_posts" => $unapproved_posts, - "unapproved_threads" => $unapproved_threads - ); -} diff --git a/html/forums/inc/functions_image.php b/html/forums/inc/functions_image.php deleted file mode 100644 index 1677726..0000000 --- a/html/forums/inc/functions_image.php +++ /dev/null @@ -1,260 +0,0 @@ -= $maxwidth) || ($imgheight >= $maxheight)) - { - check_thumbnail_memory($imgwidth, $imgheight, $imgtype, $imgbits, $imgchan); - - if($imgtype == 3) - { - if(@function_exists("imagecreatefrompng")) - { - $im = @imagecreatefrompng($file); - } - } - elseif($imgtype == 2) - { - if(@function_exists("imagecreatefromjpeg")) - { - $im = @imagecreatefromjpeg($file); - } - } - elseif($imgtype == 1) - { - if(@function_exists("imagecreatefromgif")) - { - $im = @imagecreatefromgif($file); - } - } - else - { - $thumb['code'] = 3; - return $thumb; - } - if(!$im) - { - $thumb['code'] = 3; - return $thumb; - } - $scale = scale_image($imgwidth, $imgheight, $maxwidth, $maxheight); - $thumbwidth = $scale['width']; - $thumbheight = $scale['height']; - $thumbim = @imagecreatetruecolor($thumbwidth, $thumbheight); - - if(!$thumbim) - { - $thumbim = @imagecreate($thumbwidth, $thumbheight); - $resized = true; - } - - // Attempt to preserve the transparency if there is any - if($imgtype == 3) - { - // A PNG! - imagealphablending($thumbim, false); - imagefill($thumbim, 0, 0, imagecolorallocatealpha($thumbim, 0, 0, 0, 127)); - - // Save Alpha... - imagesavealpha($thumbim, true); - } - elseif($imgtype == 1) - { - // Transparent GIF? - $trans_color = imagecolortransparent($im); - if($trans_color >= 0 && $trans_color < imagecolorstotal($im)) - { - $trans = imagecolorsforindex($im, $trans_color); - $new_trans_color = imagecolorallocate($thumbim, $trans['red'], $trans['blue'], $trans['green']); - imagefill($thumbim, 0, 0, $new_trans_color); - imagecolortransparent($thumbim, $new_trans_color); - } - } - - if(!isset($resized)) - { - @imagecopyresampled($thumbim, $im, 0, 0, 0, 0, $thumbwidth, $thumbheight, $imgwidth, $imgheight); - } - else - { - @imagecopyresized($thumbim, $im, 0, 0, 0, 0, $thumbwidth, $thumbheight, $imgwidth, $imgheight); - } - @imagedestroy($im); - if(!function_exists("imagegif") && $imgtype == 1) - { - $filename = str_replace(".gif", ".jpg", $filename); - } - switch($imgtype) - { - case 1: - if(function_exists("imagegif")) - { - @imagegif($thumbim, $path."/".$filename); - } - else - { - @imagejpeg($thumbim, $path."/".$filename); - } - break; - case 2: - @imagejpeg($thumbim, $path."/".$filename); - break; - case 3: - @imagepng($thumbim, $path."/".$filename); - break; - } - @my_chmod($path."/".$filename, '0644'); - @imagedestroy($thumbim); - $thumb['code'] = 1; - $thumb['filename'] = $filename; - return $thumb; - } - else - { - return array("code" => 4); - } -} - -/** - * Attempts to allocate enough memory to generate the thumbnail - * - * @param integer $width width dimension - * @param integer $height height dimension - * @param string $type one of the IMAGETYPE_XXX constants indicating the type of the image - * @param string $bitdepth the bits area the number of bits for each color - * @param string $channels the channels - 3 for RGB pictures and 4 for CMYK pictures - * @return bool - */ -function check_thumbnail_memory($width, $height, $type, $bitdepth, $channels) -{ - if(!function_exists("memory_get_usage")) - { - return false; - } - - $memory_limit = @ini_get("memory_limit"); - if(!$memory_limit || $memory_limit == -1) - { - return false; - } - - $limit = preg_match("#^([0-9]+)\s?([kmg])b?$#i", trim(my_strtolower($memory_limit)), $matches); - $memory_limit = 0; - if($matches[1] && $matches[2]) - { - switch($matches[2]) - { - case "k": - $memory_limit = $matches[1] * 1024; - break; - case "m": - $memory_limit = $matches[1] * 1048576; - break; - case "g": - $memory_limit = $matches[1] * 1073741824; - } - } - $current_usage = memory_get_usage(); - $free_memory = $memory_limit - $current_usage; - - $thumbnail_memory = round(($width * $height * $bitdepth * $channels / 8) * 5); - $thumbnail_memory += 2097152; - - if($thumbnail_memory > $free_memory) - { - if($matches[1] && $matches[2]) - { - switch($matches[2]) - { - case "k": - $memory_limit = ceil((($memory_limit+$thumbnail_memory) / 1024))."K"; - break; - case "m": - $memory_limit = ceil((($memory_limit+$thumbnail_memory) / 1048576))."M"; - break; - case "g": - $memory_limit = ceil((($memory_limit+$thumbnail_memory) / 1073741824))."G"; - } - } - - @ini_set("memory_limit", $memory_limit); - } - - return true; -} - -/** - * Figures out the correct dimensions to use - * - * @param integer $width current width dimension - * @param integer $height current height dimension - * @param integer $maxwidth max width dimension - * @param integer $maxheight max height dimension - * @return array correct height & width - */ -function scale_image($width, $height, $maxwidth, $maxheight) -{ - $width = (int)$width; - $height = (int)$height; - - if(!$width) $width = $maxwidth; - if(!$height) $height = $maxheight; - - $newwidth = $width; - $newheight = $height; - - if($width > $maxwidth) - { - $newwidth = $maxwidth; - $newheight = ceil(($height*(($maxwidth*100)/$width))/100); - $height = $newheight; - $width = $newwidth; - } - if($height > $maxheight) - { - $newheight = $maxheight; - $newwidth = ceil(($width*(($maxheight*100)/$height))/100); - } - $ret['width'] = $newwidth; - $ret['height'] = $newheight; - return $ret; -} diff --git a/html/forums/inc/functions_indicators.php b/html/forums/inc/functions_indicators.php deleted file mode 100644 index af5fccc..0000000 --- a/html/forums/inc/functions_indicators.php +++ /dev/null @@ -1,356 +0,0 @@ -settings['threadreadcut'] > 0 && $mybb->user['uid']) - { - // For registered users, store the information in the database. - switch($db->type) - { - case "pgsql": - case "sqlite": - $db->replace_query("threadsread", array('tid' => $tid, 'uid' => $mybb->user['uid'], 'dateline' => TIME_NOW), array("tid", "uid")); - break; - default: - $db->write_query(" - REPLACE INTO ".TABLE_PREFIX."threadsread (tid, uid, dateline) - VALUES('$tid', '{$mybb->user['uid']}', '".TIME_NOW."') - "); - } - } - // Default back to cookie marking - else - { - my_set_array_cookie("threadread", $tid, TIME_NOW, -1); - } - - $unread_count = fetch_unread_count($fid); - if($unread_count == 0) - { - mark_forum_read($fid); - } -} - -/** - * Fetches the number of unread threads for the current user in a particular forum. - * - * @param string $fid The forums (CSV list) - * @return int The number of unread threads - */ -function fetch_unread_count($fid) -{ - global $cache, $db, $mybb; - - $forums_all = $forums_own = array(); - $forums = explode(',', $fid); - foreach($forums as $forum) - { - $permissions = forum_permissions($forum); - if(!empty($permissions['canonlyviewownthreads'])) - { - $forums_own[] = $forum; - } - else - { - $forums_all[] = $forum; - } - } - if(!empty($forums_own)) - { - $where = "(fid IN (".implode(',', $forums_own).") AND uid = {$mybb->user['uid']})"; - $where2 = "(t.fid IN (".implode(',', $forums_own).") AND t.uid = {$mybb->user['uid']})"; - } - if(!empty($forums_all)) - { - if(isset($where)) - { - $where = "({$where} OR fid IN (".implode(',', $forums_all)."))"; - $where2 = "({$where2} OR t.fid IN (".implode(',', $forums_all)."))"; - } - else - { - $where = 'fid IN ('.implode(',', $forums_all).')'; - $where2 = 't.fid IN ('.implode(',', $forums_all).')'; - } - } - $cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - - if(!empty($permissions['canonlyviewownthreads'])) - { - $onlyview = " AND uid = '{$mybb->user['uid']}'"; - $onlyview2 = " AND t.uid = '{$mybb->user['uid']}'"; - } - - if($mybb->user['uid'] == 0) - { - $comma = ''; - $tids = ''; - $threadsread = $forumsread = array(); - - if(isset($mybb->cookies['mybb']['threadread'])) - { - $threadsread = my_unserialize($mybb->cookies['mybb']['threadread']); - } - if(isset($mybb->cookies['mybb']['forumread'])) - { - $forumsread = my_unserialize($mybb->cookies['mybb']['forumread']); - } - - if(!empty($threadsread)) - { - foreach($threadsread as $key => $value) - { - $tids .= $comma.(int)$key; - $comma = ','; - } - } - - if(!empty($tids)) - { - $count = 0; - - // We've read at least some threads, are they here? - $query = $db->simple_select("threads", "lastpost, tid, fid", "visible=1 AND closed NOT LIKE 'moved|%' AND {$where} AND lastpost > '{$cutoff}'", array("limit" => 100)); - - while($thread = $db->fetch_array($query)) - { - if((!isset($threadsread[$thread['tid']]) || $thread['lastpost'] > (int)$threadsread[$thread['tid']]) && (!isset($forumsread[$thread['fid']]) || $thread['lastpost'] > (int)$forumsread[$thread['fid']])) - { - ++$count; - } - } - - return $count; - } - - // Not read any threads? - return false; - } - else - { - switch($db->type) - { - case "pgsql": - $query = $db->query(" - SELECT COUNT(t.tid) AS unread_count - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."threadsread tr ON (tr.tid=t.tid AND tr.uid='{$mybb->user['uid']}') - LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=t.fid AND fr.uid='{$mybb->user['uid']}') - WHERE t.visible=1 AND t.closed NOT LIKE 'moved|%' AND {$where2} AND t.lastpost > COALESCE(tr.dateline,$cutoff) AND t.lastpost > COALESCE(fr.dateline,$cutoff) AND t.lastpost>$cutoff - "); - break; - default: - $query = $db->query(" - SELECT COUNT(t.tid) AS unread_count - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."threadsread tr ON (tr.tid=t.tid AND tr.uid='{$mybb->user['uid']}') - LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=t.fid AND fr.uid='{$mybb->user['uid']}') - WHERE t.visible=1 AND t.closed NOT LIKE 'moved|%' AND {$where2} AND t.lastpost > IFNULL(tr.dateline,$cutoff) AND t.lastpost > IFNULL(fr.dateline,$cutoff) AND t.lastpost>$cutoff - "); - } - return $db->fetch_field($query, "unread_count"); - } -} - -/** - * Mark a particular forum as read. - * - * @param int $fid The forum ID - */ -function mark_forum_read($fid) -{ - global $mybb, $db; - - // Can only do "true" tracking for registered users - if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid']) - { - // Experimental setting to mark parent forums as read - $forums_to_read = array(); - - if($mybb->settings['readparentforums']) - { - $ignored_forums = array(); - $forums = array_reverse(explode(",", get_parent_list($fid))); - - unset($forums[0]); - if(!empty($forums)) - { - $ignored_forums[] = $fid; - - foreach($forums as $forum) - { - $fids = array($forum); - $ignored_forums[] = $forum; - - $children = explode(",", get_parent_list($forum)); - foreach($children as $child) - { - if(in_array($child, $ignored_forums)) - { - continue; - } - - $fids[] = $child; - $ignored_forums[] = $child; - } - - if(fetch_unread_count(implode(",", $fids)) == 0) - { - $forums_to_read[] = $forum; - } - } - } - } - - switch($db->type) - { - case "pgsql": - case "sqlite": - add_shutdown(array($db, "replace_query"), array("forumsread", array('fid' => $fid, 'uid' => $mybb->user['uid'], 'dateline' => TIME_NOW), array("fid", "uid"))); - - if(!empty($forums_to_read)) - { - foreach($forums_to_read as $forum) - { - add_shutdown(array($db, "replace_query"), array("forumsread", array('fid' => $forum, 'uid' => $mybb->user['uid'], 'dateline' => TIME_NOW), array('fid', 'uid'))); - } - } - break; - default: - $child_sql = ''; - if(!empty($forums_to_read)) - { - foreach($forums_to_read as $forum) - { - $child_sql .= ", ('{$forum}', '{$mybb->user['uid']}', '".TIME_NOW."')"; - } - } - - $db->shutdown_query(" - REPLACE INTO ".TABLE_PREFIX."forumsread (fid, uid, dateline) - VALUES('{$fid}', '{$mybb->user['uid']}', '".TIME_NOW."'){$child_sql} - "); - } - } - // Mark in a cookie - else - { - my_set_array_cookie("forumread", $fid, TIME_NOW, -1); - } -} - -/** - * Marks all forums as read. - * - */ -function mark_all_forums_read() -{ - global $mybb, $db, $cache; - - // Can only do "true" tracking for registered users - if($mybb->user['uid'] > 0) - { - $db->update_query("users", array('lastvisit' => TIME_NOW), "uid='".$mybb->user['uid']."'"); - require_once MYBB_ROOT."inc/functions_user.php"; - update_pm_count('', 2); - - if($mybb->settings['threadreadcut'] > 0) - { - // Need to loop through all forums and mark them as read - $forums = $cache->read('forums'); - - $update_count = ceil(count($forums)/20); - - if($update_count < 15) - { - $update_count = 15; - } - - $mark_query = ''; - $done = 0; - foreach(array_keys($forums) as $fid) - { - switch($db->type) - { - case "pgsql": - case "sqlite": - $mark_query[] = array('fid' => $fid, 'uid' => $mybb->user['uid'], 'dateline' => TIME_NOW); - break; - default: - if($mark_query != '') - { - $mark_query .= ','; - } - $mark_query .= "('{$fid}', '{$mybb->user['uid']}', '".TIME_NOW."')"; - } - ++$done; - - // Only do this in loops of $update_count, save query time - if($done % $update_count) - { - switch($db->type) - { - case "pgsql": - case "sqlite": - foreach($mark_query as $replace_query) - { - add_shutdown(array($db, "replace_query"), array("forumsread", $replace_query, array("fid", "uid"))); - } - $mark_query = array(); - break; - default: - $db->shutdown_query(" - REPLACE INTO ".TABLE_PREFIX."forumsread (fid, uid, dateline) - VALUES {$mark_query} - "); - $mark_query = ''; - } - } - } - - if($mark_query != '') - { - switch($db->type) - { - case "pgsql": - case "sqlite": - foreach($mark_query as $replace_query) - { - add_shutdown(array($db, "replace_query"), array("forumsread", $replace_query, array("fid", "uid"))); - } - break; - default: - $db->shutdown_query(" - REPLACE INTO ".TABLE_PREFIX."forumsread (fid, uid, dateline) - VALUES {$mark_query} - "); - } - } - } - } - else - { - my_setcookie("mybb[readallforums]", 1); - my_setcookie("mybb[lastvisit]", TIME_NOW); - - my_unsetcookie("mybb[threadread]"); - my_unsetcookie("mybb[forumread]"); - } -} diff --git a/html/forums/inc/functions_massmail.php b/html/forums/inc/functions_massmail.php deleted file mode 100644 index cf93372..0000000 --- a/html/forums/inc/functions_massmail.php +++ /dev/null @@ -1,222 +0,0 @@ -escape_string_like($conditions[$search_field])."%'"; - } - } - - // LESS THAN or GREATER THAN - $direction_fields = array("postnum"); - foreach($direction_fields as $search_field) - { - $direction_field = $search_field."_dir"; - if(!empty($conditions[$search_field]) && $conditions[$direction_field]) - { - switch($conditions[$direction_field]) - { - case "greater_than": - $direction = ">"; - break; - case "less_than": - $direction = "<"; - break; - default: - $direction = "="; - } - $search_sql .= " AND u.{$search_field}{$direction}'".(int)$conditions[$search_field]."'"; - } - } - - // Time-based search fields - $time_fields = array("regdate", "lastactive"); - foreach($time_fields as $search_field) - { - $time_field = $search_field."_date"; - $direction_field = $search_field."_dir"; - if(!empty($conditions[$search_field]) && $conditions[$time_field] && $conditions[$direction_field]) - { - switch($conditions[$time_field]) - { - case "hours": - $date = $conditions[$search_field]*60*60; - break; - case "days": - $date = $conditions[$search_field]*60*60*24; - break; - case "weeks": - $date = $conditions[$search_field]*60*60*24*7; - break; - case "months": - $date = $conditions[$search_field]*60*60*24*30; - break; - case "years": - $date = $conditions[$search_field]*60*60*24*365; - break; - default: - $date = $conditions[$search_field]*60*60*24; - } - - switch($conditions[$direction_field]) - { - case "less_than": - $direction = ">"; - break; - case "more_than": - $direction = "<"; - break; - default: - $direction = "<"; - } - $search_sql .= " AND u.{$search_field}{$direction}'".(TIME_NOW-$date)."'"; - } - } - - // Usergroup based searching - if($conditions['usergroup']) - { - if(!is_array($conditions['usergroup'])) - { - $conditions['usergroup'] = array($conditions['usergroup']); - } - - $conditions['usergroup'] = array_map('intval', $conditions['usergroup']); - - $additional_sql = ''; - foreach($conditions['usergroup'] as $usergroup) - { - switch($db->type) - { - case "pgsql": - case "sqlite": - $additional_sql .= " OR ','||additionalgroups||',' LIKE '%,{$usergroup},%'"; - break; - default: - $additional_sql .= " OR CONCAT(',',additionalgroups,',') LIKE '%,{$usergroup},%'"; - } - } - $search_sql .= " AND (u.usergroup IN (".implode(",", $conditions['usergroup']).") {$additional_sql})"; - } - - return $search_sql; -} - -/** - * Create a text based version of a HTML mass email. - * - * @param string $message The HTML version. - * @return string The generated text based version. - */ -function create_text_message($message) -{ - // Cut out all current line breaks - // Makes links CONTENT (link) - $message = make_pretty_links($message); - $message = str_replace(array("\r\n", "\n"), "\n", $message); - $message = preg_replace("#

    #i", "\n\n", $message); - $message = preg_replace("##i", "\n", $message); - $message = preg_replace("#]*?>#i", "", $message); - $message = preg_replace("#]*?>\s*#i", "-----------\n", $message); - $message = html_entity_decode($message); - $message = str_replace("\t", "", $message); - do - { - $message = str_replace(" ", " ", $message); - } - while(strpos($message, " ") !== false); - - $search = array('@]*?>.*?@si', // Strip out javascript - '@]*?>.*?@siU', // Strip style tags properly - '@]*?>.*?@siU', // Strip title tags - '@<[\/\!]*?[^<>]*?>@si', // Strip out HTML tags - '@@' // Strip multi-line comments including CDATA - ); - $message = preg_replace($search, '', $message); - $message = preg_replace("#\n\n+#", "\n\n", $message); - $message = preg_replace("#^\s+#is", "", $message); - return $message; -} - -/** - * Generates friendly links for a text based version of a mass email from the HTML version. - * - * @param string $message_html The HTML version. - * @return string The version with the friendly links and all tags stripped. - */ -function make_pretty_links($message_html) -{ - do - { - $start = stripos($message_html, "", $start); - if($end === false) - { - break; - } - - $a_href = substr($message_html, $start, ($end-$start)); - - preg_match("#href=\"?([^\"> ]+)\"?#i", $a_href, $href_matches); - if(!$href_matches[1]) - { - continue; - } - $link = $href_matches[1]; - - $contents = strip_tags($a_href); - if(!$contents) - { - preg_match("#alt=\"?([^\">]+)\"?#i", $a_href, $matches2); - if($matches2[1]) - { - $contents = $matches2[1]; - } - if(!$contents) - { - preg_match("#title=\"?([^\">]+)\"?#i", $a_href, $matches2); - if($matches2[1]) - { - $contents = $matches2[1]; - } - } - } - - $replaced_link = $contents." ({$link}) "; - - $message_html = substr_replace($message_html, $replaced_link, $start, ($end-$start)); - } while(true); - return $message_html; -} diff --git a/html/forums/inc/functions_modcp.php b/html/forums/inc/functions_modcp.php deleted file mode 100644 index a5b8dfd..0000000 --- a/html/forums/inc/functions_modcp.php +++ /dev/null @@ -1,332 +0,0 @@ -usergroup['issupermod'] == 0 && ($user_permissions['issupermod'] == 1 || $user_permissions['cancp'] == 1)) - { - return false; - } - // Current user is a super mod or is an administrator - else if($user_permissions['cancp'] == 1 && ($mybb->usergroup['cancp'] != 1 || (is_super_admin($uid) && !is_super_admin($mybb->user['uid'])))) - { - return false; - } - return true; -} - -/** - * Fetch forums the moderator can manage announcements to - * - * @param int $pid (Optional) The parent forum ID - * @param int $depth (Optional) The depth from parent forum the moderator can manage to - */ -function fetch_forum_announcements($pid=0, $depth=1) -{ - global $mybb, $db, $lang, $theme, $announcements, $templates, $announcements_forum, $moderated_forums, $unviewableforums, $parser; - static $forums_by_parent, $forum_cache, $parent_forums; - - if(!is_array($forum_cache)) - { - $forum_cache = cache_forums(); - } - if(!is_array($parent_forums) && $mybb->usergroup['issupermod'] != 1) - { - // Get a list of parentforums to show for normal moderators - $parent_forums = array(); - foreach($moderated_forums as $mfid) - { - $parent_forums = array_merge($parent_forums, explode(',', $forum_cache[$mfid]['parentlist'])); - } - } - if(!is_array($forums_by_parent)) - { - foreach($forum_cache as $forum) - { - $forums_by_parent[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; - } - } - - if(!is_array($forums_by_parent[$pid])) - { - return; - } - - foreach($forums_by_parent[$pid] as $children) - { - foreach($children as $forum) - { - if($forum['linkto'] || (is_array($unviewableforums) && in_array($forum['fid'], $unviewableforums))) - { - continue; - } - - if($forum['active'] == 0 || !is_moderator($forum['fid'], "canmanageannouncements")) - { - // Check if this forum is a parent of a moderated forum - if(is_array($parent_forums) && in_array($forum['fid'], $parent_forums)) - { - // A child is moderated, so print out this forum's title. RECURSE! - $trow = alt_trow(); - eval("\$announcements_forum .= \"".$templates->get("modcp_announcements_forum_nomod")."\";"); - } - else - { - // No subforum is moderated by this mod, so safely continue - continue; - } - } - else - { - // This forum is moderated by the user, so print out the forum's title, and its announcements - $trow = alt_trow(); - - $padding = 40*($depth-1); - - eval("\$announcements_forum .= \"".$templates->get("modcp_announcements_forum")."\";"); - - if(isset($announcements[$forum['fid']])) - { - foreach($announcements[$forum['fid']] as $aid => $announcement) - { - $trow = alt_trow(); - - if($announcement['enddate'] < TIME_NOW && $announcement['enddate'] != 0) - { - eval("\$icon = \"".$templates->get("modcp_announcements_announcement_expired")."\";"); - } - else - { - eval("\$icon = \"".$templates->get("modcp_announcements_announcement_active")."\";"); - } - - $subject = htmlspecialchars_uni($parser->parse_badwords($announcement['subject'])); - - eval("\$announcements_forum .= \"".$templates->get("modcp_announcements_announcement")."\";"); - } - } - } - - // Build the list for any sub forums of this forum - if(isset($forums_by_parent[$forum['fid']])) - { - fetch_forum_announcements($forum['fid'], $depth+1); - } - } - } -} - -/** - * Send reported content to moderators - * - * @param array $report Array of reported content - * @param string $report_type Type of content being reported - * @return bool|array PM Information or false - */ -function send_report($report, $report_type='post') -{ - global $db, $lang, $forum, $mybb, $post, $thread, $reputation, $user, $plugins; - - $report_reason = ''; - if($report['reasonid']) - { - $query = $db->simple_select("reportreasons", "title", "rid = '".(int)$report['reasonid']."'", array('limit' => 1)); - $reason = $db->fetch_array($query); - - $lang->load('report'); - - $report_reason = $lang->parse($reason['title']); - } - - if($report['reason']) - { - $report_reason = $lang->sprintf($lang->email_report_comment_extra, $report_reason, $report['reason']); - } - - $modsjoin = $modswhere = ''; - if(!empty($forum['parentlist'])) - { - $modswhere = "m.fid IN ({$forum['parentlist']}) OR "; - - if($db->type == 'pgsql' || $db->type == 'sqlite') - { - $modsjoin = "LEFT JOIN {$db->table_prefix}moderators m ON (m.id = u.uid AND m.isgroup = 0) OR ((m.id = u.usergroup OR ',' || u.additionalgroups || ',' LIKE '%,' || m.id || ',%') AND m.isgroup = 1)"; - } - else - { - $modsjoin = "LEFT JOIN {$db->table_prefix}moderators m ON (m.id = u.uid AND m.isgroup = 0) OR ((m.id = u.usergroup OR CONCAT(',', u.additionalgroups, ',') LIKE CONCAT('%,', m.id, ',%')) AND m.isgroup = 1)"; - } - } - - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->query(" - SELECT DISTINCT u.username, u.email, u.receivepms, u.uid - FROM {$db->table_prefix}users u - {$modsjoin} - LEFT JOIN {$db->table_prefix}usergroups g ON (',' || u.additionalgroups || ',' LIKE '%,' || g.gid || ',%' OR g.gid = u.usergroup) - WHERE {$modswhere}g.cancp = 1 OR g.issupermod = 1 - "); - break; - default: - $query = $db->query(" - SELECT DISTINCT u.username, u.email, u.receivepms, u.uid - FROM {$db->table_prefix}users u - {$modsjoin} - LEFT JOIN {$db->table_prefix}usergroups g ON (CONCAT(',', u.additionalgroups, ',') LIKE CONCAT('%,', g.gid, ',%') OR g.gid = u.usergroup) - WHERE {$modswhere}g.cancp = 1 OR g.issupermod = 1 - "); - } - - $lang_string_subject = "emailsubject_report{$report_type}"; - $lang_string_message = "email_report{$report_type}"; - - if(empty($lang->$lang_string_subject) || empty($lang->$lang_string_message)) - { - return false; - } - - global $send_report_subject, $send_report_url; - - switch($report_type) - { - case 'post': - $send_report_subject = $post['subject']; - $send_report_url = str_replace('&', '&', get_post_link($post['pid'], $thread['tid'])."#pid".$post['pid']); - break; - case 'profile': - $send_report_subject = $user['username']; - $send_report_url = str_replace('&', '&', get_profile_link($user['uid'])); - break; - case 'reputation': - $from_user = get_user($reputation['adduid']); - $send_report_subject = $from_user['username']; - $send_report_url = "reputation.php?uid={$reputation['uid']}#rid{$reputation['rid']}"; - break; - } - - $plugins->run_hooks("send_report_report_type"); - - $emailsubject = $lang->sprintf($lang->$lang_string_subject, $mybb->settings['bbname']); - $emailmessage = $lang->sprintf($lang->$lang_string_message, $mybb->user['username'], $mybb->settings['bbname'], $send_report_subject, $mybb->settings['bburl'], $send_report_url, $report_reason); - - while($mod = $db->fetch_array($query)) - { - if($mybb->settings['reportmethod'] == "pms" && $mod['receivepms'] != 0 && $mybb->settings['enablepms'] != 0) - { - $pm_recipients[] = $mod['uid']; - } - else - { - my_mail($mod['email'], $emailsubject, $emailmessage); - } - } - - if(count($pm_recipients) > 0) - { - require_once MYBB_ROOT."inc/datahandlers/pm.php"; - $pmhandler = new PMDataHandler(); - - $pm = array( - "subject" => $emailsubject, - "message" => $emailmessage, - "icon" => 0, - "fromid" => $mybb->user['uid'], - "toid" => $pm_recipients, - "ipaddress" => $mybb->session->packedip - ); - - $pmhandler->admin_override = true; - $pmhandler->set_data($pm); - - // Now let the pm handler do all the hard work. - if(!$pmhandler->validate_pm()) - { - // Force it to valid to just get it out of here - $pmhandler->is_validated = true; - $pmhandler->errors = array(); - } - - $pminfo = $pmhandler->insert_pm(); - return $pminfo; - } - - return false; -} - -/** - * Add a report - * - * @param array $report Array of reported content - * @param string $type Type of content being reported - * @return int Report ID - */ -function add_report($report, $type = 'post') -{ - global $cache, $db, $mybb; - - $insert_array = array( - 'id' => (int)$report['id'], - 'id2' => (int)$report['id2'], - 'id3' => (int)$report['id3'], - 'uid' => (int)$report['uid'], - 'reportstatus' => 0, - 'reasonid' => (int)$report['reasonid'], - 'reason' => $db->escape_string($report['reason']), - 'type' => $db->escape_string($type), - 'reports' => 1, - 'dateline' => TIME_NOW, - 'lastreport' => TIME_NOW, - 'reporters' => $db->escape_string(my_serialize(array($report['uid']))) - ); - - if($mybb->settings['reportmethod'] == "email" || $mybb->settings['reportmethod'] == "pms") - { - send_report($report, $type); - } - - $rid = $db->insert_query("reportedcontent", $insert_array); - $cache->update_reportedcontent(); - - return $rid; -} - -/** - * Update an existing report - * - * @param array $report Array of reported content - * @return bool true - */ -function update_report($report) -{ - global $db; - - $update_array = array( - 'reports' => ++$report['reports'], - 'lastreport' => TIME_NOW, - 'reporters' => $db->escape_string(my_serialize($report['reporters'])) - ); - - $db->update_query("reportedcontent", $update_array, "rid = '{$report['rid']}'"); - return true; -} diff --git a/html/forums/inc/functions_online.php b/html/forums/inc/functions_online.php deleted file mode 100644 index 1bf3bb7..0000000 --- a/html/forums/inc/functions_online.php +++ /dev/null @@ -1,1205 +0,0 @@ - 0) - { - $ann_list[$parameters['aid']] = $parameters['aid']; - } - $user_activity['activity'] = "announcements"; - $user_activity['ann'] = $parameters['aid']; - break; - case "attachment": - if(!isset($parameters['aid'])) - { - $parameters['aid'] = 0; - } - $parameters['aid'] = (int)$parameters['aid']; - if($parameters['aid'] > 0) - { - $aid_list[] = $parameters['aid']; - } - $user_activity['activity'] = "attachment"; - $user_activity['aid'] = $parameters['aid']; - break; - case "calendar": - if(!isset($parameters['action'])) - { - $parameters['action'] = ''; - } - if($parameters['action'] == "event") - { - if(!isset($parameters['eid'])) - { - $parameters['eid'] = 0; - } - $parameters['eid'] = (int)$parameters['eid']; - if($parameters['eid'] > 0) - { - $eid_list[$parameters['eid']] = $parameters['eid']; - } - $user_activity['activity'] = "calendar_event"; - $user_activity['eid'] = $parameters['eid']; - } - elseif($parameters['action'] == "addevent" || $parameters['action'] == "do_addevent") - { - $user_activity['activity'] = "calendar_addevent"; - } - elseif($parameters['action'] == "editevent" || $parameters['action'] == "do_editevent") - { - $user_activity['activity'] = "calendar_editevent"; - } - else - { - $user_activity['activity'] = "calendar"; - } - break; - case "contact": - $user_activity['activity'] = "contact"; - break; - case "editpost": - $user_activity['activity'] = "editpost"; - break; - case "forumdisplay": - if(!isset($parameters['fid'])) - { - $parameters['fid'] = 0; - } - $parameters['fid'] = (int)$parameters['fid']; - if($parameters['fid'] > 0) - { - $fid_list[$parameters['fid']] = $parameters['fid']; - } - $user_activity['activity'] = "forumdisplay"; - $user_activity['fid'] = $parameters['fid']; - break; - case "index": - case '': - $user_activity['activity'] = "index"; - break; - case "managegroup": - $user_activity['activity'] = "managegroup"; - break; - case "member": - if(!isset($parameters['action'])) - { - $parameters['action'] = ''; - } - if($parameters['action'] == "activate") - { - $user_activity['activity'] = "member_activate"; - } - elseif($parameters['action'] == "register" || $parameters['action'] == "do_register") - { - $user_activity['activity'] = "member_register"; - } - elseif($parameters['action'] == "login" || $parameters['action'] == "do_login") - { - $user_activity['activity'] = "member_login"; - } - elseif($parameters['action'] == "logout") - { - $user_activity['activity'] = "member_logout"; - } - elseif($parameters['action'] == "profile") - { - $user_activity['activity'] = "member_profile"; - - if(!isset($parameters['uid'])) - { - $parameters['uid'] = 0; - } - $parameters['uid'] = (int)$parameters['uid']; - - if($parameters['uid'] == 0) - { - global $memprofile; - - // $user is available in Who's Online but not in Member Profile, use $memprofile instead - if(!empty($user['uid'])) - { - $parameters['uid'] = $user['uid']; - } - elseif(!empty($memprofile['uid'])) - { - $parameters['uid'] = $memprofile['uid']; - } - } - - if($parameters['uid'] > 0) - { - $uid_list[$parameters['uid']] = $parameters['uid']; - } - $user_activity['uid'] = $parameters['uid']; - } - elseif($parameters['action'] == "emailuser" || $parameters['action'] == "do_emailuser") - { - $user_activity['activity'] = "member_emailuser"; - } - elseif($parameters['action'] == "rate" || $parameters['action'] == "do_rate") - { - $user_activity['activity'] = "member_rate"; - } - elseif($parameters['action'] == "resendactivation" || $parameters['action'] == "do_resendactivation") - { - $user_activity['activity'] = "member_resendactivation"; - } - elseif($parameters['action'] == "lostpw" || $parameters['action'] == "do_lostpw" || $parameters['action'] == "resetpassword") - { - $user_activity['activity'] = "member_lostpw"; - } - else - { - $user_activity['activity'] = "member"; - } - break; - case "memberlist": - $user_activity['activity'] = "memberlist"; - break; - case "misc": - if(!isset($parameters['action'])) - { - $parameters['action'] = ''; - } - $accepted_parameters = array("markread", "help", "buddypopup", "smilies", "syndication", "imcenter", "dstswitch"); - if($parameters['action'] == "whoposted") - { - if(!isset($parameters['tid'])) - { - $parameters['tid'] = 0; - } - $parameters['tid'] = (int)$parameters['tid']; - if($parameters['tid'] > 0) - { - $tid_list[$parameters['tid']] = $parameters['tid']; - } - $user_activity['activity'] = "misc_whoposted"; - $user_activity['tid'] = $parameters['tid']; - } - elseif(in_array($parameters['action'], $accepted_parameters)) - { - $user_activity['activity'] = "misc_".$parameters['action']; - } - else - { - $user_activity['activity'] = "misc"; - } - break; - case "modcp": - if(!isset($parameters['action'])) - { - $parameters['action'] = 0; - } - - $accepted_parameters = array("modlogs", "announcements", "finduser", "warninglogs", "ipsearch"); - - foreach($accepted_parameters as $action) - { - if($parameters['action'] == $action) - { - $user_activity['activity'] = "modcp_".$action; - break; - } - } - - $accepted_parameters = array(); - $accepted_parameters['report'] = array("do_reports", "reports", "allreports"); - $accepted_parameters['new_announcement'] = array("do_new_announcement", "new_announcement"); - $accepted_parameters['delete_announcement'] = array("do_delete_announcement", "delete_announcement"); - $accepted_parameters['edit_announcement'] = array("do_edit_announcement", "edit_announcement"); - $accepted_parameters['mod_queue'] = array("do_modqueue", "modqueue"); - $accepted_parameters['editprofile'] = array("do_editprofile", "editprofile"); - $accepted_parameters['banning'] = array("do_banuser", "banning", "liftban", "banuser"); - - foreach($accepted_parameters as $name => $actions) - { - if(in_array($parameters['action'], $actions)) - { - $user_activity['activity'] = "modcp_".$name; - break; - } - } - - if(empty($user_activity['activity'])) - { - $user_activity['activity'] = "modcp"; - } - break; - case "moderation": - $user_activity['activity'] = "moderation"; - break; - case "newreply": - if(!isset($parameters['tid'])) - { - $parameters['tid'] = 0; - } - $parameters['tid'] = (int)$parameters['tid']; - if($parameters['tid'] > 0) - { - $tid_list[$parameters['tid']] = $parameters['tid']; - } - $user_activity['activity'] = "newreply"; - $user_activity['tid'] = $parameters['tid']; - break; - case "newthread": - if(!isset($parameters['fid'])) - { - $parameters['fid'] = 0; - } - $parameters['fid'] = (int)$parameters['fid']; - if($parameters['fid'] > 0) - { - $fid_list[$parameters['fid']] = $parameters['fid']; - } - $user_activity['activity'] = "newthread"; - $user_activity['fid'] = $parameters['fid']; - break; - case "online": - if(!isset($parameters['action'])) - { - $parameters['action'] = ''; - } - if($parameters['action'] == "today") - { - $user_activity['activity'] = "woltoday"; - } - else - { - $user_activity['activity'] = "wol"; - } - break; - case "polls": - if(!isset($parameters['action'])) - { - $parameters['action'] = ''; - } - // Make the "do" parts the same as the other one. - if($parameters['action'] == "do_newpoll") - { - $user_activity['activity'] = "newpoll"; - } - elseif($parameters['action'] == "do_editpoll") - { - $user_activity['activity'] = "editpoll"; - } - else - { - $accepted_parameters = array("do_editpoll", "editpoll", "newpoll", "do_newpoll", "showresults", "vote"); - - foreach($accepted_parameters as $action) - { - if($parameters['action'] == $action) - { - $user_activity['activity'] = $action; - break; - } - } - - if(!$user_activity['activity']) - { - $user_activity['activity'] = "showresults"; - } - } - break; - case "printthread": - if(!isset($parameters['tid'])) - { - $parameters['tid'] = 0; - } - $parameters['tid'] = (int)$parameters['tid']; - if($parameters['tid'] > 0) - { - $tid_list[$parameters['tid']] = $parameters['tid']; - } - $user_activity['activity'] = "printthread"; - $user_activity['tid'] = $parameters['tid']; - break; - case "private": - if(!isset($parameters['action'])) - { - $parameters['action'] = ''; - } - if($parameters['action'] == "send" || $parameters['action'] == "do_send") - { - $user_activity['activity'] = "private_send"; - } - elseif($parameters['action'] == "read") - { - $user_activity['activity'] = "private_read"; - } - elseif($parameters['action'] == "folders" || $parameters['action'] == "do_folders") - { - $user_activity['activity'] = "private_folders"; - } - else - { - $user_activity['activity'] = "private"; - } - break; - case "ratethread": - $user_activity['activity'] = "ratethread"; - break; - case "report": - $user_activity['activity'] = "report"; - break; - case "reputation": - if(!isset($parameters['uid'])) - { - $parameters['uid'] = 0; - } - $parameters['uid'] = (int)$parameters['uid']; - if($parameters['uid'] > 0) - { - $uid_list[$parameters['uid']] = $parameters['uid']; - } - $user_activity['uid'] = $parameters['uid']; - - if($parameters['action'] == "add") - { - $user_activity['activity'] = "reputation"; - } - else - { - $user_activity['activity'] = "reputation_report"; - } - break; - case "search": - $user_activity['activity'] = "search"; - break; - case "sendthread": - if(!isset($parameters['tid'])) - { - $parameters['tid'] = 0; - } - $parameters['tid'] = (int)$parameters['tid']; - if($parameters['tid'] > 0) - { - $tid_list[$parameters['tid']] = $parameters['tid']; - } - $user_activity['activity'] = "sendthread"; - $user_activity['tid'] = $parameters['tid']; - break; - case "showteam": - $user_activity['activity'] = "showteam"; - break; - case "showthread": - if(!isset($parameters['action'])) - { - $parameters['action'] = 0; - } - if(!isset($parameters['pid'])) - { - $parameters['pid'] = 0; - } - $parameters['pid'] = (int)$parameters['pid']; - if($parameters['pid'] > 0 && $parameters['action'] == "showpost") - { - $pid_list[$parameters['pid']] = $parameters['pid']; - $user_activity['activity'] = "showpost"; - $user_activity['pid'] = $parameters['pid']; - } - else - { - if(!isset($parameters['page'])) - { - $parameters['page'] = 0; - } - $parameters['page'] = (int)$parameters['page']; - $user_activity['page'] = $parameters['page']; - if(!isset($parameters['tid'])) - { - $parameters['tid'] = 0; - } - $parameters['tid'] = (int)$parameters['tid']; - if($parameters['tid'] > 0) - { - $tid_list[$parameters['tid']] = $parameters['tid']; - } - $user_activity['activity'] = "showthread"; - $user_activity['tid'] = $parameters['tid']; - } - break; - case "stats": - $user_activity['activity'] = "stats"; - break; - case "usercp": - if(!isset($parameters['action'])) - { - $parameters['action'] = ''; - } - if($parameters['action'] == "profile" || $parameters['action'] == "do_profile") - { - $user_activity['activity'] = "usercp_profile"; - } - elseif($parameters['action'] == "options" || $parameters['action'] == "do_options") - { - $user_activity['activity'] = "usercp_options"; - } - elseif($parameters['action'] == "password" || $parameters['action'] == "do_password") - { - $user_activity['activity'] = "usercp_password"; - } - elseif($parameters['action'] == "editsig" || $parameters['action'] == "do_editsig") - { - $user_activity['activity'] = "usercp_editsig"; - } - elseif($parameters['action'] == "avatar" || $parameters['action'] == "do_avatar") - { - $user_activity['activity'] = "usercp_avatar"; - } - elseif($parameters['action'] == "editlists" || $parameters['action'] == "do_editlists") - { - $user_activity['activity'] = "usercp_editlists"; - } - elseif($parameters['action'] == "favorites") - { - $user_activity['activity'] = "usercp_favorites"; - } - elseif($parameters['action'] == "subscriptions") - { - $user_activity['activity'] = "usercp_subscriptions"; - } - elseif($parameters['action'] == "notepad" || $parameters['action'] == "do_notepad") - { - $user_activity['activity'] = "usercp_notepad"; - } - else - { - $user_activity['activity'] = "usercp"; - } - break; - case "usercp2": - if(!isset($parameters['action'])) - { - $parameters['action'] = ''; - } - if($parameters['action'] == "addfavorite" || $parameters['action'] == "removefavorite" || $parameters['action'] == "removefavorites") - { - $user_activity['activity'] = "usercp2_favorites"; - } - else if($parameters['action'] == "addsubscription" || $parameters['action'] == "do_addsubscription" || $parameters['action'] == "removesubscription" || $parameters['action'] == "removesubscriptions") - { - $user_activity['activity'] = "usercp2_subscriptions"; - } - break; - case "portal": - $user_activity['activity'] = "portal"; - break; - case "warnings": - if(!isset($parameters['action'])) - { - $parameters['action'] = ''; - } - if($parameters['action'] == "warn" || $parameters['action'] == "do_warn") - { - $user_activity['activity'] = "warnings_warn"; - } - elseif($parameters['action'] == "do_revoke") - { - $user_activity['activity'] = "warnings_revoke"; - } - elseif($parameters['action'] == "view") - { - $user_activity['activity'] = "warnings_view"; - } - else - { - $user_activity['activity'] = "warnings"; - } - break; - case "nopermission": - $user_activity['activity'] = "nopermission"; - $user_activity['nopermission'] = 1; - break; - default: - $user_activity['activity'] = "unknown"; - break; - } - - // Expects $location to be passed through already sanitized - $user_activity['location'] = $location; - - $user_activity = $plugins->run_hooks("fetch_wol_activity_end", $user_activity); - - return $user_activity; -} - -/** - * Builds a friendly named Who's Online location from an "activity" and array of user data. Assumes fetch_wol_activity has already been called. - * - * @param array $user_activity Array containing activity and essential IDs. - * @return string Location name for the activity being performed. - */ -function build_friendly_wol_location($user_activity) -{ - global $db, $lang, $uid_list, $aid_list, $pid_list, $tid_list, $fid_list, $ann_list, $eid_list, $plugins, $parser, $mybb; - global $threads, $forums, $forums_linkto, $forum_cache, $posts, $announcements, $events, $usernames, $attachments; - - // Fetch forum permissions for this user - $unviewableforums = get_unviewable_forums(); - $inactiveforums = get_inactive_forums(); - $fidnot = ''; - $unviewablefids = $inactivefids = array(); - if($unviewableforums) - { - $fidnot = " AND fid NOT IN ($unviewableforums)"; - $unviewablefids = explode(',', $unviewableforums); - } - if($inactiveforums) - { - $fidnot .= " AND fid NOT IN ($inactiveforums)"; - $inactivefids = explode(',', $inactiveforums); - } - - // Fetch any users - if(!is_array($usernames) && count($uid_list) > 0) - { - $uid_sql = implode(",", $uid_list); - if($uid_sql != $mybb->user['uid']) - { - $query = $db->simple_select("users", "uid,username", "uid IN ($uid_sql)"); - while($user = $db->fetch_array($query)) - { - $usernames[$user['uid']] = htmlspecialchars_uni($user['username']); - } - } - else - { - $usernames[$mybb->user['uid']] = htmlspecialchars_uni($mybb->user['username']); - } - } - - // Fetch any attachments - if(!is_array($attachments) && count($aid_list) > 0) - { - $aid_sql = implode(",", $aid_list); - $query = $db->simple_select("attachments", "aid,pid", "aid IN ($aid_sql)"); - while($attachment = $db->fetch_array($query)) - { - $attachments[$attachment['aid']] = $attachment['pid']; - $pid_list[] = $attachment['pid']; - } - } - - // Fetch any announcements - if(!is_array($announcements) && count($ann_list) > 0) - { - $aid_sql = implode(",", $ann_list); - $query = $db->simple_select("announcements", "aid,subject", "aid IN ({$aid_sql}) {$fidnot}"); - while($announcement = $db->fetch_array($query)) - { - $announcement_title = htmlspecialchars_uni($parser->parse_badwords($announcement['subject'])); - $announcements[$announcement['aid']] = $announcement_title; - } - } - - // Fetch any posts - if(!is_array($posts) && count($pid_list) > 0) - { - $pid_sql = implode(",", $pid_list); - $query = $db->simple_select("posts", "pid,tid", "pid IN ({$pid_sql}) {$fidnot}"); - while($post = $db->fetch_array($query)) - { - $posts[$post['pid']] = $post['tid']; - $tid_list[] = $post['tid']; - } - } - - // Fetch any threads - if(!is_array($threads) && count($tid_list) > 0) - { - $perms = array(); - $tid_sql = implode(",", $tid_list); - $query = $db->simple_select('threads', 'uid, fid, tid, subject, visible, prefix', "tid IN({$tid_sql}) {$fidnot}"); - - $threadprefixes = build_prefixes(); - - while($thread = $db->fetch_array($query)) - { - $thread['threadprefix'] = ''; - if($thread['prefix'] && !empty($threadprefixes[$thread['prefix']])) - { - $thread['threadprefix'] = $threadprefixes[$thread['prefix']]['displaystyle']; - } - if(empty($perms[$thread['fid']])) - { - $perms[$thread['fid']] = forum_permissions($thread['fid']); - } - - if(isset($perms[$thread['fid']]['canonlyviewownthreads']) && $perms[$thread['fid']]['canonlyviewownthreads'] == 1 && $thread['uid'] != $mybb->user['uid'] && !is_moderator($thread['fid'])) - { - continue; - } - - if(is_moderator($thread['fid']) || $thread['visible'] == 1) - { - $thread_title = ''; - if($thread['threadprefix']) - { - $thread_title = $thread['threadprefix'].' '; - } - - $thread_title .= htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); - - $threads[$thread['tid']] = $thread_title; - $fid_list[] = $thread['fid']; - } - } - } - - // Fetch any forums - if(!is_array($forums) && count($fid_list) > 0) - { - $fidnot = array_merge($unviewablefids, $inactivefids); - - foreach($forum_cache as $fid => $forum) - { - if(in_array($fid, $fid_list) && !in_array($fid, $fidnot)) - { - $forums[$fid] = $forum['name']; - $forums_linkto[$fid] = $forum['linkto']; - } - } - } - - // And finaly any events - if(!is_array($events) && count($eid_list) > 0) - { - $eid_sql = implode(",", $eid_list); - $query = $db->simple_select("events", "eid,name", "eid IN ($eid_sql)"); - while($event = $db->fetch_array($query)) - { - $events[$event['eid']] = htmlspecialchars_uni($parser->parse_badwords($event['name'])); - } - } - - // Now we've got everything we need we can put a name to the location - switch($user_activity['activity']) - { - // announcement.php functions - case "announcements": - if(!empty($announcements[$user_activity['ann']])) - { - $location_name = $lang->sprintf($lang->viewing_announcements, get_announcement_link($user_activity['ann']), $announcements[$user_activity['ann']]); - } - else - { - $location_name = $lang->viewing_announcements2; - } - break; - // attachment.php actions - case "attachment": - $pid = $attachments[$user_activity['aid']]; - $tid = $posts[$pid]; - if(!empty($threads[$tid])) - { - $location_name = $lang->sprintf($lang->viewing_attachment2, $user_activity['aid'], $threads[$tid], get_thread_link($tid)); - } - else - { - $location_name = $lang->viewing_attachment; - } - break; - // calendar.php functions - case "calendar": - $location_name = $lang->viewing_calendar; - break; - case "calendar_event": - if(!empty($events[$user_activity['eid']])) - { - $location_name = $lang->sprintf($lang->viewing_event2, get_event_link($user_activity['eid']), $events[$user_activity['eid']]); - } - else - { - $location_name = $lang->viewing_event; - } - break; - case "calendar_addevent": - $location_name = $lang->adding_event; - break; - case "calendar_editevent": - $location_name = $lang->editing_event; - break; - case "contact": - $location_name = $lang->viewing_contact_us; - break; - // editpost.php functions - case "editpost": - $location_name = $lang->editing_post; - break; - // forumdisplay.php functions - case "forumdisplay": - if(!empty($forums[$user_activity['fid']])) - { - if($forums_linkto[$user_activity['fid']]) - { - $location_name = $lang->sprintf($lang->forum_redirect_to, get_forum_link($user_activity['fid']), $forums[$user_activity['fid']]); - } - else - { - $location_name = $lang->sprintf($lang->viewing_forum2, get_forum_link($user_activity['fid']), $forums[$user_activity['fid']]); - } - } - else - { - $location_name = $lang->viewing_forum; - } - break; - // index.php functions - case "index": - $location_name = $lang->sprintf($lang->viewing_index, $mybb->settings['bbname']); - break; - // managegroup.php functions - case "managegroup": - $location_name = $lang->managing_group; - break; - // member.php functions - case "member_activate": - $location_name = $lang->activating_account; - break; - case "member_profile": - if(!empty($usernames[$user_activity['uid']])) - { - $location_name = $lang->sprintf($lang->viewing_profile2, get_profile_link($user_activity['uid']), $usernames[$user_activity['uid']]); - } - else - { - $location_name = $lang->viewing_profile; - } - break; - case "member_register": - $location_name = $lang->registering; - break; - case "member": - case "member_login": - // Guest or member? - if($mybb->user['uid'] == 0) - { - $location_name = $lang->logging_in; - } - else - { - $location_name = $lang->logging_in_plain; - } - break; - case "member_logout": - $location_name = $lang->logging_out; - break; - case "member_emailuser": - $location_name = $lang->emailing_user; - break; - case "member_rate": - $location_name = $lang->rating_user; - break; - case "member_resendactivation": - $location_name = $lang->member_resendactivation; - break; - case "member_lostpw": - $location_name = $lang->member_lostpw; - break; - // memberlist.php functions - case "memberlist": - $location_name = $lang->viewing_memberlist; - break; - // misc.php functions - case "misc_dstswitch": - $location_name = $lang->changing_dst; - break; - case "misc_whoposted": - if(!empty($threads[$user_activity['tid']])) - { - $location_name = $lang->sprintf($lang->viewing_whoposted2, get_thread_link($user_activity['tid']), $threads[$user_activity['tid']]); - } - else - { - $location_name = $lang->viewing_whoposted; - } - break; - case "misc_markread": - $location_name = $lang->sprintf($lang->marking_read, $mybb->post_code); - break; - case "misc_help": - $location_name = $lang->viewing_helpdocs; - break; - case "misc_buddypopup": - $location_name = $lang->viewing_buddylist; - break; - case "misc_smilies": - $location_name = $lang->viewing_smilies; - break; - case "misc_syndication": - $location_name = $lang->viewing_syndication; - break; - case "misc_imcenter": - $location_name = $lang->viewing_imcenter; - break; - // modcp.php functions - case "modcp_modlogs": - $location_name = $lang->viewing_modlogs; - break; - case "modcp_announcements": - $location_name = $lang->managing_announcements; - break; - case "modcp_finduser": - $location_name = $lang->search_for_user; - break; - case "modcp_warninglogs": - $location_name = $lang->managing_warninglogs; - break; - case "modcp_ipsearch": - $location_name = $lang->searching_ips; - break; - case "modcp_report": - $location_name = $lang->viewing_reports; - break; - case "modcp_new_announcement": - $location_name = $lang->adding_announcement; - break; - case "modcp_delete_announcement": - $location_name = $lang->deleting_announcement; - break; - case "modcp_edit_announcement": - $location_name = $lang->editing_announcement; - break; - case "modcp_mod_queue": - $location_name = $lang->managing_modqueue; - break; - case "modcp_editprofile": - $location_name = $lang->editing_user_profiles; - break; - case "modcp_banning": - $location_name = $lang->managing_bans; - break; - case "modcp": - $location_name = $lang->viewing_modcp; - break; - // moderation.php functions - case "moderation": - $location_name = $lang->using_modtools; - break; - // newreply.php functions - case "newreply": - if(!empty($threads[$user_activity['tid']])) - { - $location_name = $lang->sprintf($lang->replying_thread2, get_thread_link($user_activity['tid']), $threads[$user_activity['tid']]); - } - else - { - $location_name = $lang->replying_thread; - } - break; - // newthread.php functions - case "newthread": - if(!empty($forums[$user_activity['fid']])) - { - $location_name = $lang->sprintf($lang->posting_thread2, get_forum_link($user_activity['fid']), $forums[$user_activity['fid']]); - } - else - { - $location_name = $lang->posting_thread; - } - break; - // online.php functions - case "wol": - $location_name = $lang->viewing_wol; - break; - case "woltoday": - $location_name = $lang->viewing_woltoday; - break; - // polls.php functions - case "newpoll": - $location_name = $lang->creating_poll; - break; - case "editpoll": - $location_name = $lang->editing_poll; - break; - case "showresults": - $location_name = $lang->viewing_pollresults; - break; - case "vote": - $location_name = $lang->voting_poll; - break; - // printthread.php functions - case "printthread": - if(!empty($threads[$user_activity['tid']])) - { - $location_name = $lang->sprintf($lang->printing_thread2, get_thread_link($user_activity['tid']), $threads[$user_activity['tid']]); - } - else - { - $location_name = $lang->printing_thread; - } - break; - // private.php functions - case "private_send": - $location_name = $lang->sending_pm; - break; - case "private_read": - $location_name = $lang->reading_pm; - break; - case "private_folders": - $location_name = $lang->editing_pmfolders; - break; - case "private": - $location_name = $lang->using_pmsystem; - break; - /* Ratethread functions */ - case "ratethread": - $location_name = $lang->rating_thread; - break; - // report.php functions - case "report": - $location_name = $lang->reporting_post; - break; - // reputation.php functions - case "reputation": - $location_name = $lang->sprintf($lang->giving_reputation, get_profile_link($user_activity['uid']), $usernames[$user_activity['uid']]); - break; - case "reputation_report": - if(!empty($usernames[$user_activity['uid']])) - { - $location_name = $lang->sprintf($lang->viewing_reputation_report, "reputation.php?uid={$user_activity['uid']}", $usernames[$user_activity['uid']]); - } - else - { - $location_name = $lang->sprintf($lang->viewing_reputation_report2); - } - break; - // search.php functions - case "search": - $location_name = $lang->sprintf($lang->searching_forum, $mybb->settings['bbname']); - break; - // showthread.php functions - case "showthread": - if(!empty($threads[$user_activity['tid']])) - { - $pagenote = ''; - $location_name = $lang->sprintf($lang->reading_thread2, get_thread_link($user_activity['tid']), $threads[$user_activity['tid']], $pagenote); - } - else - { - $location_name = $lang->reading_thread; - } - break; - case "showpost": - if(!empty($posts[$user_activity['pid']]) && !empty($threads[$posts[$user_activity['pid']]])) - { - $pagenote = ''; - $location_name = $lang->sprintf($lang->reading_thread2, get_thread_link($posts[$user_activity['pid']]), $threads[$posts[$user_activity['pid']]], $pagenote); - } - else - { - $location_name = $lang->reading_thread; - } - break; - // showteam.php functions - case "showteam": - $location_name = $lang->viewing_team; - break; - // stats.php functions - case "stats": - $location_name = $lang->viewing_stats; - break; - // usercp.php functions - case "usercp_profile": - $location_name = $lang->updating_profile; - break; - case "usercp_editlists": - $location_name = $lang->managing_buddyignorelist; - break; - case "usercp_options": - $location_name = $lang->updating_options; - break; - case "usercp_editsig": - $location_name = $lang->editing_signature; - break; - case "usercp_avatar": - $location_name = $lang->changing_avatar; - break; - case "usercp_subscriptions": - $location_name = $lang->viewing_subscriptions; - break; - case "usercp_favorites": - $location_name = $lang->viewing_favorites; - break; - case "usercp_notepad": - $location_name = $lang->editing_pad; - break; - case "usercp_password": - $location_name = $lang->editing_password; - break; - case "usercp": - $location_name = $lang->user_cp; - break; - case "usercp2_favorites": - $location_name = $lang->managing_favorites; - break; - case "usercp2_subscriptions": - $location_name = $lang->managing_subscriptions; - break; - case "portal": - $location_name = $lang->viewing_portal; - break; - // sendthread.php functions - case "sendthread": - $location_name = $lang->sending_thread; - break; - // warnings.php functions - case "warnings_revoke": - $location_name = $lang->revoking_warning; - break; - case "warnings_warn": - $location_name = $lang->warning_user; - break; - case "warnings_view": - $location_name = $lang->viewing_warning; - break; - case "warnings": - $location_name = $lang->managing_warnings; - break; - } - - $plugin_array = array('user_activity' => &$user_activity, 'location_name' => &$location_name); - $plugins->run_hooks("build_friendly_wol_location_end", $plugin_array); - - if(isset($user_activity['nopermission']) && $user_activity['nopermission'] == 1) - { - $location_name = $lang->viewing_noperms; - } - - if(!$location_name) - { - $location_name = $lang->sprintf($lang->unknown_location, $user_activity['location']); - } - - return $location_name; -} - -/** - * Build a Who's Online row for a specific user - * - * @param array $user Array of user information including activity information - * @return string Formatted online row - */ -function build_wol_row($user) -{ - global $mybb, $lang, $templates, $theme, $session, $db; - - // We have a registered user - if($user['uid'] > 0) - { - // Only those with "canviewwolinvis" permissions can view invisible users - if($user['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid']) - { - // Append an invisible mark if the user is invisible - if($user['invisible'] == 1) - { - $invisible_mark = "*"; - } - else - { - $invisible_mark = ''; - } - - $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); - $online_name = build_profile_link($user['username'], $user['uid']).$invisible_mark; - } - } - // We have a bot - elseif(!empty($user['bot'])) - { - $online_name = format_name($user['bot'], $user['usergroup']); - } - // Otherwise we've got a plain old guest - else - { - $online_name = format_name($lang->guest, 1); - } - - $online_time = my_date($mybb->settings['timeformat'], $user['time']); - - // Fetch the location name for this users activity - $location = build_friendly_wol_location($user['activity']); - - // Can view IPs, then fetch the IP template - if($mybb->usergroup['canviewonlineips'] == 1) - { - $user['ip'] = my_inet_ntop($db->unescape_binary($user['ip'])); - - if($mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canuseipsearch'] == 1) - { - eval("\$lookup = \"".$templates->get("online_row_ip_lookup")."\";"); - } - - eval("\$user_ip = \"".$templates->get("online_row_ip")."\";"); - } - else - { - $user_ip = $lookup = $user['ip'] = ''; - } - - $online_row = ''; - // And finally if we have permission to view this user, return the completed online row - if($user['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid']) - { - eval("\$online_row = \"".$templates->get("online_row")."\";"); - } - return $online_row; -} diff --git a/html/forums/inc/functions_post.php b/html/forums/inc/functions_post.php deleted file mode 100644 index b4af7d0..0000000 --- a/html/forums/inc/functions_post.php +++ /dev/null @@ -1,1007 +0,0 @@ -settings['pmsallowhtml']; - $parser_options['allow_mycode'] = $mybb->settings['pmsallowmycode']; - $parser_options['allow_smilies'] = $mybb->settings['pmsallowsmilies']; - $parser_options['allow_imgcode'] = $mybb->settings['pmsallowimgcode']; - $parser_options['allow_videocode'] = $mybb->settings['pmsallowvideocode']; - $parser_options['me_username'] = $post['username']; - $parser_options['filter_badwords'] = 1; - $id = $pmid; - break; - case 3: // Announcement - global $announcementarray, $message; - $parser_options['allow_html'] = $announcementarray['allowhtml']; - $parser_options['allow_mycode'] = $announcementarray['allowmycode']; - $parser_options['allow_smilies'] = $announcementarray['allowsmilies']; - $parser_options['allow_imgcode'] = 1; - $parser_options['allow_videocode'] = 1; - $parser_options['me_username'] = $post['username']; - $parser_options['filter_badwords'] = 1; - $id = $announcementarray['aid']; - break; - default: // Regular post - global $forum, $thread, $tid; - $oldforum = $forum; - $id = (int)$post['pid']; - $idtype = 'pid'; - $parser_options['allow_html'] = $forum['allowhtml']; - $parser_options['allow_mycode'] = $forum['allowmycode']; - $parser_options['allow_smilies'] = $forum['allowsmilies']; - $parser_options['allow_imgcode'] = $forum['allowimgcode']; - $parser_options['allow_videocode'] = $forum['allowvideocode']; - $parser_options['filter_badwords'] = 1; - - if(!$post['username']) - { - $post['username'] = $lang->guest; - } - - if($post['userusername']) - { - $parser_options['me_username'] = $post['userusername']; - } - else - { - $parser_options['me_username'] = $post['username']; - } - break; - } - - $post['username'] = htmlspecialchars_uni($post['username']); - $post['userusername'] = htmlspecialchars_uni($post['userusername']); - - if(!$postcounter) - { // Used to show the # of the post - if($page > 1) - { - if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) - { - $mybb->settings['postsperpage'] = 20; - } - - $postcounter = $mybb->settings['postsperpage']*($page-1); - } - else - { - $postcounter = 0; - } - $post_extra_style = "border-top-width: 0;"; - } - elseif($mybb->input['mode'] == "threaded") - { - $post_extra_style = "border-top-width: 0;"; - } - else - { - $post_extra_style = "margin-top: 5px;"; - } - - if(!$altbg) - { // Define the alternate background colour if this is the first post - $altbg = "trow1"; - } - $postcounter++; - - // Format the post date and time using my_date - $post['postdate'] = my_date('relative', $post['dateline']); - - // Dont want any little 'nasties' in the subject - $post['subject'] = $parser->parse_badwords($post['subject']); - - // Pm's have been htmlspecialchars_uni()'ed already. - if($post_type != 2) - { - $post['subject'] = htmlspecialchars_uni($post['subject']); - } - - if(empty($post['subject'])) - { - $post['subject'] = ' '; - } - - $post['author'] = $post['uid']; - $post['subject_title'] = $post['subject']; - - // Get the usergroup - if($post['userusername']) - { - if(!$post['displaygroup']) - { - $post['displaygroup'] = $post['usergroup']; - } - $usergroup = $groupscache[$post['displaygroup']]; - } - else - { - $usergroup = $groupscache[1]; - } - - if(!is_array($titlescache)) - { - $cached_titles = $cache->read("usertitles"); - if(!empty($cached_titles)) - { - foreach($cached_titles as $usertitle) - { - $titlescache[$usertitle['posts']] = $usertitle; - } - } - - if(is_array($titlescache)) - { - krsort($titlescache); - } - unset($usertitle, $cached_titles); - } - - // Work out the usergroup/title stuff - $post['groupimage'] = ''; - if(!empty($usergroup['image'])) - { - $language = $mybb->settings['bblanguage']; - if(!empty($mybb->user['language'])) - { - $language = $mybb->user['language']; - } - - $usergroup['image'] = str_replace("{lang}", $language, $usergroup['image']); - $usergroup['image'] = str_replace("{theme}", $theme['imgdir'], $usergroup['image']); - eval("\$post['groupimage'] = \"".$templates->get("postbit_groupimage")."\";"); - - if($mybb->settings['postlayout'] == "classic") - { - $post['groupimage'] .= "
    "; - } - } - - if($post['userusername']) - { - // This post was made by a registered user - $post['username'] = $post['userusername']; - $post['profilelink_plain'] = get_profile_link($post['uid']); - $post['username_formatted'] = format_name($post['username'], $post['usergroup'], $post['displaygroup']); - $post['profilelink'] = build_profile_link($post['username_formatted'], $post['uid']); - - if(trim($post['usertitle']) != "") - { - $hascustomtitle = 1; - } - - if($usergroup['usertitle'] != "" && !$hascustomtitle) - { - $post['usertitle'] = $usergroup['usertitle']; - } - elseif(is_array($titlescache) && !$usergroup['usertitle']) - { - reset($titlescache); - foreach($titlescache as $key => $titleinfo) - { - if($post['postnum'] >= $key) - { - if(!$hascustomtitle) - { - $post['usertitle'] = $titleinfo['title']; - } - $post['stars'] = $titleinfo['stars']; - $post['starimage'] = $titleinfo['starimage']; - break; - } - } - } - - $post['usertitle'] = htmlspecialchars_uni($post['usertitle']); - - if($usergroup['stars']) - { - $post['stars'] = $usergroup['stars']; - } - - if(empty($post['starimage'])) - { - $post['starimage'] = $usergroup['starimage']; - } - - if($post['starimage'] && $post['stars']) - { - // Only display stars if we have an image to use... - $post['starimage'] = str_replace("{theme}", $theme['imgdir'], $post['starimage']); - - $post['userstars'] = ''; - for($i = 0; $i < $post['stars']; ++$i) - { - eval("\$post['userstars'] .= \"".$templates->get("postbit_userstar", 1, 0)."\";"); - } - - $post['userstars'] .= "
    "; - } - - $postnum = $post['postnum']; - $post['postnum'] = my_number_format($post['postnum']); - $post['threadnum'] = my_number_format($post['threadnum']); - - // Determine the status to show for the user (Online/Offline/Away) - $timecut = TIME_NOW - $mybb->settings['wolcutoff']; - if($post['lastactive'] > $timecut && ($post['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1) && $post['lastvisit'] != $post['lastactive']) - { - eval("\$post['onlinestatus'] = \"".$templates->get("postbit_online")."\";"); - } - else - { - if($post['away'] == 1 && $mybb->settings['allowaway'] != 0) - { - eval("\$post['onlinestatus'] = \"".$templates->get("postbit_away")."\";"); - } - else - { - eval("\$post['onlinestatus'] = \"".$templates->get("postbit_offline")."\";"); - } - } - - $post['useravatar'] = ''; - if(isset($mybb->user['showavatars']) && $mybb->user['showavatars'] != 0 || $mybb->user['uid'] == 0) - { - $useravatar = format_avatar($post['avatar'], $post['avatardimensions'], $mybb->settings['postmaxavatarsize']); - eval("\$post['useravatar'] = \"".$templates->get("postbit_avatar")."\";"); - } - - $post['button_find'] = ''; - if($mybb->usergroup['cansearch'] == 1) - { - eval("\$post['button_find'] = \"".$templates->get("postbit_find")."\";"); - } - - if($mybb->settings['enablepms'] == 1 && (($post['receivepms'] != 0 && $usergroup['canusepms'] != 0 && $mybb->usergroup['cansendpms'] == 1 && my_strpos(",".$post['ignorelist'].",", ",".$mybb->user['uid'].",") === false) || $mybb->usergroup['canoverridepm'] == 1)) - { - eval("\$post['button_pm'] = \"".$templates->get("postbit_pm")."\";"); - } - - $post['button_rep'] = ''; - if($post_type != 3 && $mybb->settings['enablereputation'] == 1 && $mybb->settings['postrep'] == 1 && $mybb->usergroup['cangivereputations'] == 1 && $usergroup['usereputationsystem'] == 1 && ($mybb->settings['posrep'] || $mybb->settings['neurep'] || $mybb->settings['negrep']) && $post['uid'] != $mybb->user['uid'] && (!isset($post['visible']) || $post['visible'] == 1) && (!isset($thread['visible']) || $thread['visible'] == 1)) - { - if(!$post['pid']) - { - $post['pid'] = 0; - } - - eval("\$post['button_rep'] = \"".$templates->get("postbit_rep_button")."\";"); - } - - if($post['website'] != "" && !is_member($mybb->settings['hidewebsite']) && $usergroup['canchangewebsite'] == 1) - { - $post['website'] = htmlspecialchars_uni($post['website']); - eval("\$post['button_www'] = \"".$templates->get("postbit_www")."\";"); - } - else - { - $post['button_www'] = ""; - } - - if($post['hideemail'] != 1 && $mybb->usergroup['cansendemail'] == 1) - { - eval("\$post['button_email'] = \"".$templates->get("postbit_email")."\";"); - } - else - { - $post['button_email'] = ""; - } - - $post['userregdate'] = my_date($mybb->settings['regdateformat'], $post['regdate']); - - // Work out the reputation this user has (only show if not announcement) - if($post_type != 3 && $usergroup['usereputationsystem'] != 0 && $mybb->settings['enablereputation'] == 1) - { - $post['userreputation'] = get_reputation($post['reputation'], $post['uid']); - eval("\$post['replink'] = \"".$templates->get("postbit_reputation")."\";"); - } - - // Showing the warning level? (only show if not announcement) - if($post_type != 3 && $mybb->settings['enablewarningsystem'] != 0 && $usergroup['canreceivewarnings'] != 0 && ($mybb->usergroup['canwarnusers'] != 0 || ($mybb->user['uid'] == $post['uid'] && $mybb->settings['canviewownwarning'] != 0))) - { - if($mybb->settings['maxwarningpoints'] < 1) - { - $mybb->settings['maxwarningpoints'] = 10; - } - - $warning_level = round($post['warningpoints']/$mybb->settings['maxwarningpoints']*100); - if($warning_level > 100) - { - $warning_level = 100; - } - $warning_level = get_colored_warning_level($warning_level); - - // If we can warn them, it's not the same person, and we're in a PM or a post. - if($mybb->usergroup['canwarnusers'] != 0 && $post['uid'] != $mybb->user['uid'] && ($post_type == 0 || $post_type == 2)) - { - eval("\$post['button_warn'] = \"".$templates->get("postbit_warn")."\";"); - $warning_link = "warnings.php?uid={$post['uid']}"; - } - else - { - $post['button_warn'] = ''; - $warning_link = "usercp.php"; - } - eval("\$post['warninglevel'] = \"".$templates->get("postbit_warninglevel")."\";"); - } - - if($post_type != 3 && $post_type != 1 && purgespammer_show($post['postnum'], $post['usergroup'], $post['uid'])) - { - eval("\$post['button_purgespammer'] = \"".$templates->get('postbit_purgespammer')."\";"); - } - - // Display profile fields on posts - only if field is filled in - if(is_array($profile_fields)) - { - foreach($profile_fields as $field) - { - $fieldfid = "fid{$field['fid']}"; - if(!empty($post[$fieldfid])) - { - $post['fieldvalue'] = ''; - $post['fieldname'] = htmlspecialchars_uni($field['name']); - - $thing = explode("\n", $field['type'], "2"); - $type = trim($thing[0]); - $useropts = explode("\n", $post[$fieldfid]); - - if(is_array($useropts) && ($type == "multiselect" || $type == "checkbox")) - { - foreach($useropts as $val) - { - if($val != '') - { - eval("\$post['fieldvalue_option'] .= \"".$templates->get("postbit_profilefield_multiselect_value")."\";"); - } - } - if($post['fieldvalue_option'] != '') - { - eval("\$post['fieldvalue'] .= \"".$templates->get("postbit_profilefield_multiselect")."\";"); - } - } - else - { - $field_parser_options = array( - "allow_html" => $field['allowhtml'], - "allow_mycode" => $field['allowmycode'], - "allow_smilies" => $field['allowsmilies'], - "allow_imgcode" => $field['allowimgcode'], - "allow_videocode" => $field['allowvideocode'], - #"nofollow_on" => 1, - "filter_badwords" => 1 - ); - - if($customfield['type'] == "textarea") - { - $field_parser_options['me_username'] = $post['username']; - } - else - { - $field_parser_options['nl2br'] = 0; - } - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $field_parser_options['allow_imgcode'] = 0; - } - - $post['fieldvalue'] = $parser->parse_message($post[$fieldfid], $field_parser_options); - } - - eval("\$post['profilefield'] .= \"".$templates->get("postbit_profilefield")."\";"); - } - } - } - - eval("\$post['user_details'] = \"".$templates->get("postbit_author_user")."\";"); - } - else - { // Message was posted by a guest or an unknown user - $post['profilelink'] = format_name($post['username'], 1); - - if($usergroup['usertitle']) - { - $post['usertitle'] = $usergroup['usertitle']; - } - else - { - $post['usertitle'] = $lang->guest; - } - - $post['usertitle'] = htmlspecialchars_uni($post['usertitle']); - - $usergroup['title'] = $lang->na; - - $post['userregdate'] = $lang->na; - $post['postnum'] = $lang->na; - $post['button_profile'] = ''; - $post['button_email'] = ''; - $post['button_www'] = ''; - $post['signature'] = ''; - $post['button_pm'] = ''; - $post['button_find'] = ''; - $post['onlinestatus'] = ''; - $post['replink'] = ''; - eval("\$post['user_details'] = \"".$templates->get("postbit_author_guest")."\";"); - } - - $post['button_edit'] = ''; - $post['button_quickdelete'] = ''; - $post['button_quickrestore'] = ''; - $post['button_quote'] = ''; - $post['button_quickquote'] = ''; - $post['button_report'] = ''; - $post['button_reply_pm'] = ''; - $post['button_replyall_pm'] = ''; - $post['button_forward_pm'] = ''; - $post['button_delete_pm'] = ''; - - // For private messages, fetch the reply/forward/delete icons - if($post_type == 2 && $post['pmid']) - { - global $replyall; - - eval("\$post['button_reply_pm'] = \"".$templates->get("postbit_reply_pm")."\";"); - eval("\$post['button_forward_pm'] = \"".$templates->get("postbit_forward_pm")."\";"); - eval("\$post['button_delete_pm'] = \"".$templates->get("postbit_delete_pm")."\";"); - - if($replyall == true) - { - eval("\$post['button_replyall_pm'] = \"".$templates->get("postbit_replyall_pm")."\";"); - } - } - - $post['editedmsg'] = ''; - if(!$post_type) - { - if(!isset($forumpermissions)) - { - $forumpermissions = forum_permissions($fid); - } - - // Figure out if we need to show an "edited by" message - if($post['edituid'] != 0 && $post['edittime'] != 0 && $post['editusername'] != "" && (($mybb->settings['showeditedby'] != 0 && $usergroup['cancp'] == 0) || ($mybb->settings['showeditedbyadmin'] != 0 && $usergroup['cancp'] == 1))) - { - $post['editdate'] = my_date('relative', $post['edittime']); - $post['editnote'] = $lang->sprintf($lang->postbit_edited, $post['editdate']); - $post['editusername'] = htmlspecialchars_uni($post['editusername']); - $post['editedprofilelink'] = build_profile_link($post['editusername'], $post['edituid']); - $editreason = ""; - if($post['editreason'] != "") - { - $post['editreason'] = $parser->parse_badwords($post['editreason']); - $post['editreason'] = htmlspecialchars_uni($post['editreason']); - eval("\$editreason = \"".$templates->get("postbit_editedby_editreason")."\";"); - } - eval("\$post['editedmsg'] = \"".$templates->get("postbit_editedby")."\";"); - } - - $time = TIME_NOW; - if((is_moderator($fid, "caneditposts") || ($forumpermissions['caneditposts'] == 1 && $mybb->user['uid'] == $post['uid'] && $thread['closed'] != 1 && ($mybb->usergroup['edittimelimit'] == 0 || $mybb->usergroup['edittimelimit'] != 0 && $post['dateline'] > ($time-($mybb->usergroup['edittimelimit']*60))))) && $mybb->user['uid'] != 0) - { - eval("\$post['button_edit'] = \"".$templates->get("postbit_edit")."\";"); - } - - // Quick Delete button - $can_delete_thread = $can_delete_post = 0; - if($mybb->user['uid'] == $post['uid'] && $thread['closed'] == 0) - { - if($forumpermissions['candeletethreads'] == 1 && $postcounter == 1) - { - $can_delete_thread = 1; - } - else if($forumpermissions['candeleteposts'] == 1 && $postcounter != 1) - { - $can_delete_post = 1; - } - } - - $postbit_qdelete = $postbit_qrestore = ''; - if($mybb->user['uid'] != 0) - { - if((is_moderator($fid, "candeleteposts") || is_moderator($fid, "cansoftdeleteposts") || $can_delete_post == 1) && $postcounter != 1) - { - $postbit_qdelete = $lang->postbit_qdelete_post; - $display = ''; - if($post['visible'] == -1) - { - $display = "none"; - } - eval("\$post['button_quickdelete'] = \"".$templates->get("postbit_quickdelete")."\";"); - } - else if((is_moderator($fid, "candeletethreads") || is_moderator($fid, "cansoftdeletethreads") || $can_delete_thread == 1) && $postcounter == 1) - { - $postbit_qdelete = $lang->postbit_qdelete_thread; - $display = ''; - if($post['visible'] == -1) - { - $display = "none"; - } - eval("\$post['button_quickdelete'] = \"".$templates->get("postbit_quickdelete")."\";"); - } - - // Restore Post - if(is_moderator($fid, "canrestoreposts") && $postcounter != 1) - { - $display = "none"; - if($post['visible'] == -1) - { - $display = ''; - } - $postbit_qrestore = $lang->postbit_qrestore_post; - eval("\$post['button_quickrestore'] = \"".$templates->get("postbit_quickrestore")."\";"); - } - - // Restore Thread - else if(is_moderator($fid, "canrestorethreads") && $postcounter == 1) - { - $display = "none"; - if($post['visible'] == -1) - { - $display = ""; - } - $postbit_qrestore = $lang->postbit_qrestore_thread; - eval("\$post['button_quickrestore'] = \"".$templates->get("postbit_quickrestore")."\";"); - } - } - - if(!isset($ismod)) - { - $ismod = is_moderator($fid); - } - - // Inline moderation stuff - if($ismod) - { - if(isset($mybb->cookies[$inlinecookie]) && my_strpos($mybb->cookies[$inlinecookie], "|".$post['pid']."|")) - { - $inlinecheck = "checked=\"checked\""; - $inlinecount++; - } - else - { - $inlinecheck = ""; - } - - eval("\$post['inlinecheck'] = \"".$templates->get("postbit_inlinecheck")."\";"); - - if($post['visible'] == 0) - { - $invisiblepost = 1; - } - } - else - { - $post['inlinecheck'] = ""; - } - $post['postlink'] = get_post_link($post['pid'], $post['tid']); - $post_number = my_number_format($postcounter); - eval("\$post['posturl'] = \"".$templates->get("postbit_posturl")."\";"); - global $forum, $thread; - - if($forum['open'] != 0 && ($thread['closed'] != 1 || is_moderator($forum['fid'], "canpostclosedthreads")) && ($thread['uid'] == $mybb->user['uid'] || $forumpermissions['canonlyreplyownthreads'] != 1)) - { - eval("\$post['button_quote'] = \"".$templates->get("postbit_quote")."\";"); - } - - if($forumpermissions['canpostreplys'] != 0 && ($thread['uid'] == $mybb->user['uid'] || $forumpermissions['canonlyreplyownthreads'] != 1) && ($thread['closed'] != 1 || is_moderator($fid, "canpostclosedthreads")) && $mybb->settings['multiquote'] != 0 && $forum['open'] != 0 && !$post_type) - { - eval("\$post['button_multiquote'] = \"".$templates->get("postbit_multiquote")."\";"); - } - - if($mybb->user['uid'] != "0") - { - eval("\$post['button_report'] = \"".$templates->get("postbit_report")."\";"); - } - } - elseif($post_type == 3) // announcement - { - if($mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canmanageannounce'] == 1 && is_moderator($fid, "canmanageannouncements")) - { - eval("\$post['button_edit'] = \"".$templates->get("announcement_edit")."\";"); - eval("\$post['button_quickdelete'] = \"".$templates->get("announcement_quickdelete")."\";"); - } - } - - $post['iplogged'] = ''; - $show_ips = $mybb->settings['logip']; - $ipaddress = my_inet_ntop($db->unescape_binary($post['ipaddress'])); - - // Show post IP addresses... PMs now can have IP addresses too as of 1.8! - if($post_type == 2) - { - $show_ips = $mybb->settings['showpmip']; - } - if(!$post_type || $post_type == 2) - { - if($show_ips != "no" && !empty($post['ipaddress'])) - { - if($show_ips == "show") - { - eval("\$post['iplogged'] = \"".$templates->get("postbit_iplogged_show")."\";"); - } - else if($show_ips == "hide" && (is_moderator($fid, "canviewips") || $mybb->usergroup['issupermod'])) - { - $action = 'getip'; - if($post_type == 2) - { - $action = 'getpmip'; - } - eval("\$post['iplogged'] = \"".$templates->get("postbit_iplogged_hiden")."\";"); - } - } - } - - $post['poststatus'] = ''; - if(!$post_type && $post['visible'] != 1) - { - if(is_moderator($fid, "canviewdeleted") && $postcounter != 1 && $post['visible'] == -1) - { - $status_type = $lang->postbit_post_deleted; - } - else if(is_moderator($fid, "canviewunapprove") && $postcounter != 1 && $post['visible'] == 0) - { - $status_type = $lang->postbit_post_unapproved; - } - else if(is_moderator($fid, "canviewdeleted") && $postcounter == 1 && $post['visible'] == -1) - { - $status_type = $lang->postbit_thread_deleted; - } - else if(is_moderator($fid, "canviewunapprove") && $postcounter == 1 && $post['visible'] == 0) - { - $status_type = $lang->postbit_thread_unapproved; - } - - eval("\$post['poststatus'] = \"".$templates->get("postbit_status")."\";"); - } - - if(isset($post['smilieoff']) && $post['smilieoff'] == 1) - { - $parser_options['allow_smilies'] = 0; - } - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_imgcode'] = 0; - } - - if($mybb->user['showvideos'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestvideos'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_videocode'] = 0; - } - - // If we have incoming search terms to highlight - get it done. - if(!empty($mybb->input['highlight'])) - { - $parser_options['highlight'] = $mybb->input['highlight']; - $post['subject'] = $parser->highlight_message($post['subject'], $parser_options['highlight']); - } - - $post['message'] = $parser->parse_message($post['message'], $parser_options); - - $post['attachments'] = ''; - if($mybb->settings['enableattachments'] != 0) - { - get_post_attachments($id, $post); - } - - if(isset($post['includesig']) && $post['includesig'] != 0 && $post['username'] && $post['signature'] != "" && ($mybb->user['uid'] == 0 || $mybb->user['showsigs'] != 0) - && ($post['suspendsignature'] == 0 || $post['suspendsignature'] == 1 && $post['suspendsigtime'] != 0 && $post['suspendsigtime'] < TIME_NOW) && $usergroup['canusesig'] == 1 - && ($usergroup['canusesigxposts'] == 0 || $usergroup['canusesigxposts'] > 0 && $postnum > $usergroup['canusesigxposts']) && !is_member($mybb->settings['hidesignatures'])) - { - $sig_parser = array( - "allow_html" => $mybb->settings['sightml'], - "allow_mycode" => $mybb->settings['sigmycode'], - "allow_smilies" => $mybb->settings['sigsmilies'], - "allow_imgcode" => $mybb->settings['sigimgcode'], - "me_username" => $parser_options['me_username'], - "filter_badwords" => 1 - ); - - if($usergroup['signofollow']) - { - $sig_parser['nofollow_on'] = 1; - } - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $sig_parser['allow_imgcode'] = 0; - } - - $post['signature'] = $parser->parse_message($post['signature'], $sig_parser); - eval("\$post['signature'] = \"".$templates->get("postbit_signature")."\";"); - } - else - { - $post['signature'] = ""; - } - - $icon_cache = $cache->read("posticons"); - - if(isset($post['icon']) && $post['icon'] > 0 && $icon_cache[$post['icon']]) - { - $icon = $icon_cache[$post['icon']]; - - $icon['path'] = htmlspecialchars_uni($icon['path']); - $icon['path'] = str_replace("{theme}", $theme['imgdir'], $icon['path']); - $icon['name'] = htmlspecialchars_uni($icon['name']); - eval("\$post['icon'] = \"".$templates->get("postbit_icon")."\";"); - } - else - { - $post['icon'] = ""; - } - - $post_visibility = $ignore_bit = $deleted_bit = ''; - switch($post_type) - { - case 1: // Message preview - $post = $plugins->run_hooks("postbit_prev", $post); - break; - case 2: // Private message - $post = $plugins->run_hooks("postbit_pm", $post); - break; - case 3: // Announcement - $post = $plugins->run_hooks("postbit_announcement", $post); - break; - default: // Regular post - $post = $plugins->run_hooks("postbit", $post); - - if(!isset($ignored_users)) - { - $ignored_users = array(); - if($mybb->user['uid'] > 0 && $mybb->user['ignorelist'] != "") - { - $ignore_list = explode(',', $mybb->user['ignorelist']); - foreach($ignore_list as $uid) - { - $ignored_users[$uid] = 1; - } - } - } - - // Has this post been deleted but can be viewed? Hide this post - if($post['visible'] == -1 && is_moderator($fid, "canviewdeleted")) - { - $deleted_message = $lang->sprintf($lang->postbit_deleted_post_user, $post['username']); - eval("\$deleted_bit = \"".$templates->get("postbit_deleted")."\";"); - $post_visibility = "display: none;"; - } - - // Is this author on the ignore list of the current user? Hide this post - if(is_array($ignored_users) && $post['uid'] != 0 && isset($ignored_users[$post['uid']]) && $ignored_users[$post['uid']] == 1 && empty($deleted_bit)) - { - $ignored_message = $lang->sprintf($lang->postbit_currently_ignoring_user, $post['username']); - eval("\$ignore_bit = \"".$templates->get("postbit_ignored")."\";"); - $post_visibility = "display: none;"; - } - break; - } - - if($forumpermissions['canviewdeletionnotice'] == 1 && $post['visible'] == -1 && $post_type == 0 && !is_moderator($fid, "canviewdeleted")) - { - eval("\$postbit = \"".$templates->get("postbit_deleted_member")."\";"); - } - else - { - if($mybb->settings['postlayout'] == "classic") - { - eval("\$postbit = \"".$templates->get("postbit_classic")."\";"); - } - else - { - eval("\$postbit = \"".$templates->get("postbit")."\";"); - } - } - - $GLOBALS['post'] = ""; - - return $postbit; -} - -/** - * Fetch the attachments for a specific post and parse inline [attachment=id] code. - * Note: assumes you have $attachcache, an array of attachments set up. - * - * @param int $id The ID of the item. - * @param array $post The post or item passed by reference. - */ -function get_post_attachments($id, &$post) -{ - global $attachcache, $mybb, $theme, $templates, $forumpermissions, $lang; - - $validationcount = 0; - $tcount = 0; - $post['attachmentlist'] = $post['thumblist'] = $post['imagelist'] = ''; - if(!isset($forumpermissions)) - { - $forumpermissions = forum_permissions($post['fid']); - } - - if(isset($attachcache[$id]) && is_array($attachcache[$id])) - { // This post has 1 or more attachments - foreach($attachcache[$id] as $aid => $attachment) - { - if($attachment['visible']) - { // There is an attachment thats visible! - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - $attachment['filesize'] = get_friendly_size($attachment['filesize']); - $ext = get_extension($attachment['filename']); - if($ext == "jpeg" || $ext == "gif" || $ext == "bmp" || $ext == "png" || $ext == "jpg") - { - $isimage = true; - } - else - { - $isimage = false; - } - $attachment['icon'] = get_attachment_icon($ext); - $attachment['downloads'] = my_number_format($attachment['downloads']); - - if(!$attachment['dateuploaded']) - { - $attachment['dateuploaded'] = $attachment['dateline']; - } - $attachdate = my_date('relative', $attachment['dateuploaded']); - // Support for [attachment=id] code - if(stripos($post['message'], "[attachment=".$attachment['aid']."]") !== false) - { - // Show as thumbnail IF image is big && thumbnail exists && setting=='thumb' - // Show as full size image IF setting=='fullsize' || (image is small && permissions allow) - // Show as download for all other cases - if($attachment['thumbnail'] != "SMALL" && $attachment['thumbnail'] != "" && $mybb->settings['attachthumbnails'] == "yes") - { - eval("\$attbit = \"".$templates->get("postbit_attachments_thumbnails_thumbnail")."\";"); - } - elseif((($attachment['thumbnail'] == "SMALL" && $forumpermissions['candlattachments'] == 1) || $mybb->settings['attachthumbnails'] == "no") && $isimage) - { - eval("\$attbit = \"".$templates->get("postbit_attachments_images_image")."\";"); - } - else - { - eval("\$attbit = \"".$templates->get("postbit_attachments_attachment")."\";"); - } - $post['message'] = preg_replace("#\[attachment=".$attachment['aid']."]#si", $attbit, $post['message']); - } - else - { - // Show as thumbnail IF image is big && thumbnail exists && setting=='thumb' - // Show as full size image IF setting=='fullsize' || (image is small && permissions allow) - // Show as download for all other cases - if($attachment['thumbnail'] != "SMALL" && $attachment['thumbnail'] != "" && $mybb->settings['attachthumbnails'] == "yes") - { - eval("\$post['thumblist'] .= \"".$templates->get("postbit_attachments_thumbnails_thumbnail")."\";"); - if($tcount == 5) - { - $thumblist .= "
    "; - $tcount = 0; - } - ++$tcount; - } - elseif((($attachment['thumbnail'] == "SMALL" && $forumpermissions['candlattachments'] == 1) || $mybb->settings['attachthumbnails'] == "no") && $isimage) - { - eval("\$post['imagelist'] .= \"".$templates->get("postbit_attachments_images_image")."\";"); - } - else - { - eval("\$post['attachmentlist'] .= \"".$templates->get("postbit_attachments_attachment")."\";"); - } - } - } - else - { - $validationcount++; - } - } - if($validationcount > 0 && is_moderator($post['fid'], "canviewunapprove")) - { - if($validationcount == 1) - { - $postbit_unapproved_attachments = $lang->postbit_unapproved_attachment; - } - else - { - $postbit_unapproved_attachments = $lang->sprintf($lang->postbit_unapproved_attachments, $validationcount); - } - eval("\$post['attachmentlist'] .= \"".$templates->get("postbit_attachments_attachment_unapproved")."\";"); - } - if($post['thumblist']) - { - eval("\$post['attachedthumbs'] = \"".$templates->get("postbit_attachments_thumbnails")."\";"); - } - else - { - $post['attachedthumbs'] = ''; - } - if($post['imagelist']) - { - eval("\$post['attachedimages'] = \"".$templates->get("postbit_attachments_images")."\";"); - } - else - { - $post['attachedimages'] = ''; - } - if($post['attachmentlist'] || $post['thumblist'] || $post['imagelist']) - { - eval("\$post['attachments'] = \"".$templates->get("postbit_attachments")."\";"); - } - } -} diff --git a/html/forums/inc/functions_posting.php b/html/forums/inc/functions_posting.php deleted file mode 100644 index 59cf394..0000000 --- a/html/forums/inc/functions_posting.php +++ /dev/null @@ -1,225 +0,0 @@ -settings['maxquotedepth']; - } - $rmdepth = (int)$rmdepth; - - // find all tokens - // note, at various places, we use the prefix "s" to denote "start" (ie [quote]) and "e" to denote "end" (ie [/quote]) - preg_match_all("#\[quote(=(?:"|\"|')?.*?(?:"|\"|')?)?\]#si", $text, $smatches, PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER); - preg_match_all("#\[/quote\]#i", $text, $ematches, PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER); - - if(empty($smatches) || empty($ematches)) - { - return $text; - } - - // make things easier by only keeping offsets - $soffsets = $eoffsets = array(); - foreach($smatches[0] as $id => $match) - { - $soffsets[] = $match[1]; - } - // whilst we loop, also remove unnecessary end tokens at the start of string - $first_token = $soffsets[0]; - foreach($ematches[0] as $id => $match) - { - if($match[1] > $first_token) - { - $eoffsets[] = $match[1]; - } - } - unset($smatches, $ematches); - - - // elmininate malformed quotes by parsing like the parser does (preg_replace in a while loop) - // NOTE: this is slightly inaccurate because the parser considers [quote] and [quote=...] to be different things - $good_offsets = array(); - while(!empty($soffsets) && !empty($eoffsets)) // don't rely on this condition - an end offset before the start offset will cause this to loop indefinitely - { - $last_offset = 0; - foreach($soffsets as $sk => &$soffset) - { - if($soffset >= $last_offset) - { - // search for corresponding eoffset - foreach($eoffsets as $ek => &$eoffset) // use foreach instead of for to get around indexing issues with unset - { - if($eoffset > $soffset) - { - // we've found a pair - $good_offsets[$soffset] = 1; - $good_offsets[$eoffset] = -1; - $last_offset = $eoffset; - - unset($soffsets[$sk], $eoffsets[$ek]); - break; - } - } - } - } - - // remove any end offsets occurring before start offsets - $first_start = reset($soffsets); - foreach($eoffsets as $ek => &$eoffset) - { - if($eoffset < $first_start) - { - unset($eoffsets[$ek]); - } - else - { - break; - } - } - // we don't need to remove start offsets after the last end offset, because the loop will deplete something before that - } - - if(empty($good_offsets)) - { - return $text; - } - ksort($good_offsets); - - - // we now have a list of all the ordered tokens, ready to go through - $depth = 0; - $remove_regions = array(); - $tmp_start = 0; - foreach($good_offsets as $offset => $dincr) - { - if($depth == $rmdepth && $dincr == 1) - { - $tmp_start = $offset; - } - $depth += $dincr; - if($depth == $rmdepth && $dincr == -1) - { - $remove_regions[] = array($tmp_start, $offset); - } - } - - if(empty($remove_regions)) - { - return $text; - } - - // finally, remove the quotes from the string - $newtext = ''; - $cpy_start = 0; - foreach($remove_regions as &$region) - { - $newtext .= substr($text, $cpy_start, $region[0]-$cpy_start); - $cpy_start = $region[1]+8; // 8 = strlen('[/quote]') - // clean up newlines - $next_char = $text{$region[1]+8}; - if($next_char == "\r" || $next_char == "\n") - { - ++$cpy_start; - if($next_char == "\r" && $text{$region[1]+9} == "\n") - { - ++$cpy_start; - } - } - } - // append remaining end text - if(strlen($text) != $cpy_start) - { - $newtext .= substr($text, $cpy_start); - } - - // we're done - return $newtext; -} - -/** - * Performs cleanup of a quoted message, such as replacing /me commands, before presenting quoted post to the user. - * - * @param array $quoted_post quoted post info, taken from the DB (requires the 'message', 'username', 'pid' and 'dateline' entries to be set; will use 'userusername' if present. requires 'quote_is_pm' if quote message is from a private message) - * @param boolean $remove_message_quotes whether to call remove_message_quotes() on the quoted message - * @return string the cleaned up message, wrapped in a quote tag - */ - -function parse_quoted_message(&$quoted_post, $remove_message_quotes=true) -{ - global $parser, $lang, $plugins; - if(!isset($parser)) - { - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - } - - // Swap username over if we have a registered user - if($quoted_post['userusername']) - { - $quoted_post['username'] = $quoted_post['userusername']; - } - // Clean up the message - $quoted_post['message'] = preg_replace(array( - '#(^|\r|\n)/me ([^\r\n<]*)#i', - '#(^|\r|\n)/slap ([^\r\n<]*)#i', - '#\[attachment=([0-9]+?)\]#i' - ), array( - "\\1* {$quoted_post['username']} \\2", - "\\1* {$quoted_post['username']} {$lang->slaps} \\2 {$lang->with_trout}", - "", - ), $quoted_post['message']); - $quoted_post['message'] = $parser->parse_badwords($quoted_post['message']); - - if($remove_message_quotes) - { - global $mybb; - $max_quote_depth = (int)$mybb->settings['maxquotedepth']; - if($max_quote_depth) - { - $quoted_post['message'] = remove_message_quotes($quoted_post['message'], $max_quote_depth-1); // we're wrapping the message in a [quote] tag, so take away one quote depth level - } - } - - $quoted_post = $plugins->run_hooks("parse_quoted_message", $quoted_post); - - $extra = ''; - if(empty($quoted_post['quote_is_pm'])) - { - $extra = " pid='{$quoted_post['pid']}' dateline='{$quoted_post['dateline']}'"; - } - - $quote_char = '"'; - if(strpos($quoted_post['username'], '"') !== false) - { - $quote_char = "'"; - } - - return "[quote={$quote_char}{$quoted_post['username']}{$quote_char}{$extra}]\n{$quoted_post['message']}\n[/quote]\n\n"; -} - diff --git a/html/forums/inc/functions_rebuild.php b/html/forums/inc/functions_rebuild.php deleted file mode 100644 index 8313ca3..0000000 --- a/html/forums/inc/functions_rebuild.php +++ /dev/null @@ -1,134 +0,0 @@ -simple_select("forums", "SUM(threads) AS numthreads, SUM(posts) AS numposts, SUM(unapprovedthreads) AS numunapprovedthreads, SUM(unapprovedposts) AS numunapprovedposts, SUM(deletedthreads) AS numdeletedthreads, SUM(deletedposts) AS numdeletedposts"); - $stats = $db->fetch_array($query); - - $query = $db->simple_select("users", "COUNT(uid) AS users"); - $stats['numusers'] = $db->fetch_field($query, 'users'); - - update_stats($stats, true); -} - -/** - * Completely rebuild the counters for a particular forum (useful if they become out of sync) - * - * @param int $fid The forum ID - */ -function rebuild_forum_counters($fid) -{ - global $db; - - // Fetch the number of threads and replies in this forum (Approved only) - $query = $db->simple_select('threads', 'COUNT(tid) AS threads, SUM(replies) AS replies, SUM(unapprovedposts) AS unapprovedposts, SUM(deletedposts) AS deletedposts', "fid='$fid' AND visible='1'"); - $count = $db->fetch_array($query); - $count['posts'] = $count['threads'] + $count['replies']; - - // Fetch the number of threads and replies in this forum (Unapproved only) - $query = $db->simple_select('threads', 'COUNT(tid) AS threads, SUM(replies)+SUM(unapprovedposts)+SUM(deletedposts) AS impliedunapproved', "fid='$fid' AND visible='0'"); - $count2 = $db->fetch_array($query); - $count['unapprovedthreads'] = $count2['threads']; - $count['unapprovedposts'] += $count2['impliedunapproved']+$count2['threads']; - - // Fetch the number of threads and replies in this forum (Soft deleted only) - $query = $db->simple_select('threads', 'COUNT(tid) AS threads, SUM(replies)+SUM(unapprovedposts)+SUM(deletedposts) AS implieddeleted', "fid='$fid' AND visible='-1'"); - $count3 = $db->fetch_array($query); - $count['deletedthreads'] = $count3['threads']; - $count['deletedposts'] += $count3['implieddeleted']+$count3['threads']; - - update_forum_counters($fid, $count); - update_forum_lastpost($fid); -} - -/** - * Completely rebuild the counters for a particular thread (useful if they become out of sync) - * - * @param int $tid The thread ID - */ -function rebuild_thread_counters($tid) -{ - global $db; - - $thread = get_thread($tid); - $count = array(); - - $query = $db->simple_select("posts", "COUNT(pid) AS replies", "tid='{$tid}' AND pid!='{$thread['firstpost']}' AND visible='1'"); - $count['replies'] = $db->fetch_field($query, "replies"); - - // Unapproved posts - $query = $db->simple_select("posts", "COUNT(pid) AS unapprovedposts", "tid='{$tid}' AND pid != '{$thread['firstpost']}' AND visible='0'"); - $count['unapprovedposts'] = $db->fetch_field($query, "unapprovedposts"); - - // Soft deleted posts - $query = $db->simple_select("posts", "COUNT(pid) AS deletedposts", "tid='{$tid}' AND pid != '{$thread['firstpost']}' AND visible='-1'"); - $count['deletedposts'] = $db->fetch_field($query, "deletedposts"); - - // Attachment count - $query = $db->query(" - SELECT COUNT(aid) AS attachment_count - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (a.pid=p.pid) - WHERE p.tid='$tid' AND a.visible=1 - "); - $count['attachmentcount'] = $db->fetch_field($query, "attachment_count"); - - update_thread_counters($tid, $count); - update_thread_data($tid); -} - -/** - * Completely rebuild poll counters for a particular poll (useful if they become out of sync) - * - * @param int $pid The poll ID - */ -function rebuild_poll_counters($pid) -{ - global $db; - - $query = $db->simple_select("polls", "pid, numoptions", "pid='".(int)$pid."'"); - $poll = $db->fetch_array($query); - - $votes = array(); - $query = $db->simple_select("pollvotes", "voteoption, COUNT(vid) AS vote_count", "pid='{$poll['pid']}'", array('group_by' => 'voteoption')); - while($vote = $db->fetch_array($query)) - { - $votes[$vote['voteoption']] = $vote['vote_count']; - } - - $voteslist = ''; - $numvotes = 0; - for($i = 1; $i <= $poll['numoptions']; ++$i) - { - if(trim($voteslist != '')) - { - $voteslist .= "||~|~||"; - } - - if(!isset($votes[$i]) || (int)$votes[$i] <= 0) - { - $votes[$i] = "0"; - } - $voteslist .= $votes[$i]; - $numvotes = $numvotes + $votes[$i]; - } - - $updatedpoll = array( - "votes" => $db->escape_string($voteslist), - "numvotes" => (int)$numvotes - ); - $db->update_query("polls", $updatedpoll, "pid='{$poll['pid']}'"); -} diff --git a/html/forums/inc/functions_search.php b/html/forums/inc/functions_search.php deleted file mode 100644 index 7e4e7b9..0000000 --- a/html/forums/inc/functions_search.php +++ /dev/null @@ -1,1821 +0,0 @@ -simple_select("forums", "pid,disporder,fid,password,name", "linkto='' AND active!=0", array('order_by' => "pid, disporder")); - while($forum = $db->fetch_array($query)) - { - $pforumcache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; - } - } - if(!is_array($permissioncache)) - { - $permissioncache = forum_permissions(); - } - if(is_array($pforumcache[$pid])) - { - foreach($pforumcache[$pid] as $key => $main) - { - foreach($main as $key => $forum) - { - $perms = $permissioncache[$forum['fid']]; - if(($perms['canview'] == 1 || $mybb->settings['hideprivateforums'] == 0) && $perms['cansearch'] != 0) - { - if($selitem == $forum['fid']) - { - $optionselected = "selected"; - $selecteddone = "1"; - } - else - { - $optionselected = ''; - $selecteddone = "0"; - } - if($forum['password'] != '') - { - if($mybb->cookies['forumpass'][$forum['fid']] === md5($mybb->user['uid'].$forum['password'])) - { - $pwverified = 1; - } - else - { - $pwverified = 0; - } - } - if(empty($forum['password']) || $pwverified == 1) - { - eval("\$forumlistbits .= \"".$templates->get("search_forumlist_forum")."\";"); - } - if(!empty($pforumcache[$forum['fid']])) - { - $newdepth = $depth."    "; - $forumlistbits .= make_searchable_forums($forum['fid'], $selitem, 0, $newdepth); - } - } - } - } - } - if($addselect) - { - eval("\$forumlist = \"".$templates->get("search_forumlist")."\";"); - } - return $forumlist; -} - -/** - * Build a comma separated list of the forums this user cannot search - * - * @param int $pid The parent ID to build from - * @param int $first First rotation or not (leave at default) - * @return string return a CSV list of forums the user cannot search - */ -function get_unsearchable_forums($pid=0, $first=1) -{ - global $db, $forum_cache, $permissioncache, $mybb, $unsearchableforums, $unsearchable, $templates, $forumpass; - - $pid = (int)$pid; - - if(!is_array($forum_cache)) - { - // Get Forums - $query = $db->simple_select("forums", "fid,parentlist,password,active", '', array('order_by' => 'pid, disporder')); - while($forum = $db->fetch_array($query)) - { - $forum_cache[$forum['fid']] = $forum; - } - } - if(!is_array($permissioncache)) - { - $permissioncache = forum_permissions(); - } - foreach($forum_cache as $fid => $forum) - { - if($permissioncache[$forum['fid']]) - { - $perms = $permissioncache[$forum['fid']]; - } - else - { - $perms = $mybb->usergroup; - } - - $pwverified = 1; - if($forum['password'] != '') - { - if($mybb->cookies['forumpass'][$forum['fid']] !== md5($mybb->user['uid'].$forum['password'])) - { - $pwverified = 0; - } - } - - $parents = explode(",", $forum['parentlist']); - if(is_array($parents)) - { - foreach($parents as $parent) - { - if($forum_cache[$parent]['active'] == 0) - { - $forum['active'] = 0; - } - } - } - - if($perms['canview'] != 1 || $perms['cansearch'] != 1 || $pwverified == 0 || $forum['active'] == 0) - { - if($unsearchableforums) - { - $unsearchableforums .= ","; - } - $unsearchableforums .= "'{$forum['fid']}'"; - } - } - $unsearchable = $unsearchableforums; - - // Get our unsearchable password protected forums - $pass_protected_forums = get_password_protected_forums(); - - if($unsearchable && $pass_protected_forums) - { - $unsearchable .= ","; - } - - if($pass_protected_forums) - { - $unsearchable .= implode(",", $pass_protected_forums); - } - - return $unsearchable; -} - -/** - * Build a array list of the forums this user cannot search due to password protection - * - * @param array $fids the fids to check (leave blank to check all forums) - * @return array return a array list of password protected forums the user cannot search - */ -function get_password_protected_forums($fids=array()) -{ - global $forum_cache, $mybb; - - if(!is_array($fids)) - { - return false; - } - - if(!is_array($forum_cache)) - { - $forum_cache = cache_forums(); - if(!$forum_cache) - { - return false; - } - } - - if(empty($fids)) - { - $fids = array_keys($forum_cache); - } - - $pass_fids = array(); - foreach($fids as $fid) - { - if(empty($forum_cache[$fid]['password'])) - { - continue; - } - - if(md5($mybb->user['uid'].$forum_cache[$fid]['password']) !== $mybb->cookies['forumpass'][$fid]) - { - $pass_fids[] = $fid; - $child_list = get_child_list($fid); - } - - if(is_array($child_list)) - { - $pass_fids = array_merge($pass_fids, $child_list); - } - } - return array_unique($pass_fids); -} - -/** - * Clean search keywords and make them safe for querying - * - * @param string $keywords The keywords to be cleaned - * @return string The cleaned keywords - */ -function clean_keywords($keywords) -{ - global $db; - - $keywords = my_strtolower($keywords); - $keywords = $db->escape_string_like($keywords); - $keywords = preg_replace("#\*{2,}#s", "*", $keywords); - $keywords = str_replace("*", "%", $keywords); - $keywords = preg_replace("#\s+#s", " ", $keywords); - $keywords = str_replace('\\"', '"', $keywords); - - // Search for "and" or "or" and remove if it's at the beginning - $keywords = trim($keywords); - if(my_strpos($keywords, "or") === 0) - { - $keywords = substr_replace($keywords, "", 0, 2); - } - - if(my_strpos($keywords, "and") === 0) - { - $keywords = substr_replace($keywords, "", 0, 3); - } - - return $keywords; -} - -/** - * Clean search keywords for fulltext searching, making them safe for querying - * - * @param string $keywords The keywords to be cleaned - * @return string|bool The cleaned keywords or false on failure - */ -function clean_keywords_ft($keywords) -{ - if(!$keywords) - { - return false; - } - $keywords = my_strtolower($keywords); - $keywords = str_replace("%", "\\%", $keywords); - $keywords = preg_replace("#\*{2,}#s", "*", $keywords); - $keywords = preg_replace("#([\[\]\|\.\,:])#s", " ", $keywords); - // Separate braces for further processing - $keywords = preg_replace("#((\+|-|<|>|~)?\(|\))#s", " $1 ", $keywords); - $keywords = preg_replace("#\s+#s", " ", $keywords); - - $words = array(array()); - - // Fulltext search syntax validation: http://dev.mysql.com/doc/refman/5.6/en/fulltext-boolean.html - // Search for phrases - $keywords = explode("\"", $keywords); - $boolean = array('+'); - // Brace depth - $depth = 0; - $phrase_operator = '+'; - foreach($keywords as $phrase) - { - $phrase = trim($phrase); - if($phrase != '') - { - if($inquote) - { - if($phrase_operator) - { - $boolean[$depth] = $phrase_operator; - } - // Phrases do not need further processing - $words[$depth][] = "{$boolean[$depth]}\"{$phrase}\""; - $boolean[$depth] = $phrase_operator = '+'; - } - else - { - // Split words - $split_words = preg_split("#\s{1,}#", $phrase, -1); - if(!is_array($split_words)) - { - continue; - } - if(!$inquote) - { - // Save possible operator in front of phrase - $last_char = substr($phrase, -1); - if($last_char == '+' || $last_char == '-' || $last_char == '<' || $last_char == '>' || $last_char == '~') - { - $phrase_operator = $last_char; - } - } - foreach($split_words as $word) - { - $word = trim($word); - if($word == "or") - { - $boolean[$depth] = ''; - // Remove "and" operator from previous element - $last = array_pop($words[$depth]); - if($last) - { - if(substr($last, 0, 1) == '+') - { - $last = substr($last, 1); - } - $words[$depth][] = $last; - } - } - elseif($word == "and") - { - $boolean[$depth] = "+"; - } - elseif($word == "not") - { - $boolean[$depth] = "-"; - } - // Closing braces - elseif($word == ")") - { - // Ignore when no brace was opened - if($depth > 0) - { - $words[$depth-1][] = $boolean[$depth-1].'('.implode(' ', $words[$depth]).')'; - --$depth; - } - } - // Valid operators for opening braces - elseif($word == '+(' || $word == '-(' || $word == '<(' || $word == '>(' || $word == '~(' || $word == '(') - { - if(strlen($word) == 2) - { - $boolean[$depth] = substr($word, 0, 1); - } - $words[++$depth] = array(); - $boolean[$depth] = '+'; - } - else - { - $operator = substr($word, 0, 1); - switch($operator) - { - // Allowed operators - case '-': - case '+': - case '>': - case '<': - case '~': - $word = substr($word, 1); - break; - default: - $operator = $boolean[$depth]; - break; - } - // Removed operators that are only allowed at the beginning - $word = preg_replace("#(-|\+|<|>|~|@)#s", '', $word); - // Removing wildcards at the beginning http://bugs.mysql.com/bug.php?id=72605 - $word = preg_replace("#^\*#s", '', $word); - $word = $operator.$word; - if(strlen($word) <= 1) - { - continue; - } - $words[$depth][] = $word; - $boolean[$depth] = '+'; - } - } - } - } - $inquote = !$inquote; - } - - // Close mismatching braces - while($depth > 0) - { - $words[$depth-1][] = $boolean[$depth-1].'('.implode(' ', $words[$depth]).')'; - --$depth; - } - - $keywords = implode(' ', $words[0]); - return $keywords; -} - -/* Database engine specific search functions */ - -/** - * Perform a thread and post search under MySQL or MySQLi - * - * @param array $search Array of search data - * @return array Array of search data with results mixed in - */ -function privatemessage_perform_search_mysql($search) -{ - global $mybb, $db, $lang; - - $keywords = clean_keywords($search['keywords']); - if(!$keywords && !$search['sender']) - { - error($lang->error_nosearchterms); - } - - if($mybb->settings['minsearchword'] < 1) - { - $mybb->settings['minsearchword'] = 3; - } - - $subject_lookin = ""; - $message_lookin = ""; - $searchsql = "uid='{$mybb->user['uid']}'"; - - if($keywords) - { - // Complex search - $keywords = " {$keywords} "; - - switch($db->type) - { - case 'mysql': - case 'mysqli': - $sfield = 'subject'; - $mfield = 'message'; - break; - default: - $sfield = 'LOWER(subject)'; - $mfield = 'LOWER(message)'; - break; - } - - if(preg_match("#\s(and|or)\s#", $keywords)) - { - $string = "AND"; - if($search['subject'] == 1) - { - $string = "OR"; - $subject_lookin = " AND ("; - } - - if($search['message'] == 1) - { - $message_lookin = " {$string} ("; - } - - // Expand the string by double quotes - $keywords_exp = explode("\"", $keywords); - $inquote = false; - $boolean = ''; - - foreach($keywords_exp as $phrase) - { - // If we're not in a double quoted section - if(!$inquote) - { - // Expand out based on search operators (and, or) - $matches = preg_split("#\s{1,}(and|or)\s{1,}#", $phrase, -1, PREG_SPLIT_DELIM_CAPTURE); - $count_matches = count($matches); - - for($i=0; $i < $count_matches; ++$i) - { - $word = trim($matches[$i]); - if(empty($word)) - { - continue; - } - // If this word is a search operator set the boolean - if($i % 2 && ($word == "and" || $word == "or")) - { - if($i <= 1) - { - if($search['subject'] && $search['message'] && $subject_lookin == " AND (") - { - // We're looking for anything, check for a subject lookin - continue; - } - elseif($search['subject'] && !$search['message'] && $subject_lookin == " AND (") - { - // Just in a subject? - continue; - } - elseif(!$search['subject'] && $search['message'] && $message_lookin == " {$string} (") - { - // Just in a message? - continue; - } - } - - $boolean = $word; - } - // Otherwise check the length of the word as it is a normal search term - else - { - $word = trim($word); - // Word is too short - show error message - if(my_strlen($word) < $mybb->settings['minsearchword']) - { - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - - // Add terms to search query - if($search['subject'] == 1) - { - $subject_lookin .= " $boolean {$sfield} LIKE '%{$word}%'"; - } - if($search['message'] == 1) - { - $message_lookin .= " $boolean {$mfield} LIKE '%{$word}%'"; - } - $boolean = 'AND'; - } - } - } - // In the middle of a quote (phrase) - else - { - $phrase = str_replace(array("+", "-", "*"), '', trim($phrase)); - if(my_strlen($phrase) < $mybb->settings['minsearchword']) - { - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - // Add phrase to search query - $subject_lookin .= " $boolean {$sfield} LIKE '%{$phrase}%'"; - if($search['message'] == 1) - { - $message_lookin .= " $boolean {$mfield} LIKE '%{$phrase}%'"; - } - $boolean = 'AND'; - } - - // Check to see if we have any search terms and not a malformed SQL string - $error = false; - if($search['subject'] && $search['message'] && $subject_lookin == " AND (") - { - // We're looking for anything, check for a subject lookin - $error = true; - } - elseif($search['subject'] && !$search['message'] && $subject_lookin == " AND (") - { - // Just in a subject? - $error = true; - } - elseif(!$search['subject'] && $search['message'] && $message_lookin == " {$string} (") - { - // Just in a message? - $error = true; - } - - if($error == true) - { - // There are no search keywords to look for - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - - $inquote = !$inquote; - } - - if($search['subject'] == 1) - { - $subject_lookin .= ")"; - } - - if($search['message'] == 1) - { - $message_lookin .= ")"; - } - - $searchsql .= "{$subject_lookin} {$message_lookin}"; - } - else - { - $keywords = str_replace("\"", '', trim($keywords)); - if(my_strlen($keywords) < $mybb->settings['minsearchword']) - { - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - - // If we're looking in both, then find matches in either the subject or the message - if($search['subject'] == 1 && $search['message'] == 1) - { - $searchsql .= " AND ({$sfield} LIKE '%{$keywords}%' OR {$mfield} LIKE '%{$keywords}%')"; - } - else - { - if($search['subject'] == 1) - { - $searchsql .= " AND {$sfield} LIKE '%{$keywords}%'"; - } - - if($search['message'] == 1) - { - $searchsql .= " AND {$mfield} LIKE '%{$keywords}%'"; - } - } - } - } - - if($search['sender']) - { - $userids = array(); - $search['sender'] = my_strtolower($search['sender']); - - switch($db->type) - { - case 'mysql': - case 'mysqli': - $field = 'username'; - break; - default: - $field = 'LOWER(username)'; - break; - } - $query = $db->simple_select("users", "uid", "{$field} LIKE '%".$db->escape_string_like($search['sender'])."%'"); - while($user = $db->fetch_array($query)) - { - $userids[] = $user['uid']; - } - - if(count($userids) < 1) - { - error($lang->error_nosearchresults); - } - else - { - $userids = implode(',', $userids); - $searchsql .= " AND fromid IN (".$userids.")"; - } - } - - if(!is_array($search['folder'])) - { - $search['folder'] = array($search['folder']); - } - - if(!empty($search['folder'])) - { - $folderids = array(); - - $search['folder'] = array_map("intval", $search['folder']); - - $folderids = implode(',', $search['folder']); - - if($folderids) - { - $searchsql .= " AND folder IN (".$folderids.")"; - } - } - - if($search['status']) - { - $searchsql .= " AND ("; - if($search['status']['new']) - { - $statussql[] = " status='0' "; - } - if($search['status']['replied']) - { - $statussql[] = " status='3' "; - } - if($search['status']['forwarded']) - { - $statussql[] = " status='4' "; - } - if($search['status']['read']) - { - $statussql[] = " (status != '0' AND readtime > '0') "; - } - // Sent Folder - if(in_array(2, $search['folder'])) - { - $statussql[] = " status='1' "; - } - $statussql = implode("OR", $statussql); - $searchsql .= $statussql.")"; - } - - // Run the search - $pms = array(); - $query = $db->simple_select("privatemessages", "pmid", $searchsql); - while($pm = $db->fetch_array($query)) - { - $pms[$pm['pmid']] = $pm['pmid']; - } - - if(count($pms) < 1) - { - error($lang->error_nosearchresults); - } - $pms = implode(',', $pms); - - return array( - "querycache" => $pms - ); -} - -/** - * Perform a help document search under MySQL or MySQLi - * - * @param array $search Array of search data - * @return array Array of search data with results mixed in - */ -function helpdocument_perform_search_mysql($search) -{ - global $mybb, $db, $lang; - - $keywords = clean_keywords($search['keywords']); - if(!$keywords && !$search['sender']) - { - error($lang->error_nosearchterms); - } - - if($mybb->settings['minsearchword'] < 1) - { - $mybb->settings['minsearchword'] = 3; - } - - $name_lookin = ""; - $document_lookin = ""; - $searchsql = "enabled='1'"; - - if($keywords) - { - switch($db->type) - { - case 'mysql': - case 'mysqli': - $nfield = 'name'; - $dfield = 'document'; - break; - default: - $nfield = 'LOWER(name)'; - $dfield = 'LOWER(document)'; - break; - } - - // Complex search - $keywords = " {$keywords} "; - if(preg_match("#\s(and|or)\s#", $keywords)) - { - $string = "AND"; - if($search['name'] == 1) - { - $string = "OR"; - $name_lookin = " AND ("; - } - - if($search['document'] == 1) - { - $document_lookin = " {$string} ("; - } - - // Expand the string by double quotes - $keywords_exp = explode("\"", $keywords); - $inquote = false; - - foreach($keywords_exp as $phrase) - { - // If we're not in a double quoted section - if(!$inquote) - { - // Expand out based on search operators (and, or) - $matches = preg_split("#\s{1,}(and|or)\s{1,}#", $phrase, -1, PREG_SPLIT_DELIM_CAPTURE); - $count_matches = count($matches); - - for($i=0; $i < $count_matches; ++$i) - { - $word = trim($matches[$i]); - if(empty($word)) - { - continue; - } - // If this word is a search operator set the boolean - if($i % 2 && ($word == "and" || $word == "or")) - { - if($i <= 1) - { - if($search['name'] && $search['document'] && $name_lookin == " AND (") - { - // We're looking for anything, check for a name lookin - continue; - } - elseif($search['name'] && !$search['document'] && $name_lookin == " AND (") - { - // Just in a name? - continue; - } - elseif(!$search['name'] && $search['document'] && $document_lookin == " {$string} (") - { - // Just in a document? - continue; - } - } - - $boolean = $word; - } - // Otherwise check the length of the word as it is a normal search term - else - { - $word = trim($word); - // Word is too short - show error message - if(my_strlen($word) < $mybb->settings['minsearchword']) - { - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - // Add terms to search query - if($search['name'] == 1) - { - $name_lookin .= " $boolean {$nfield} LIKE '%{$word}%'"; - } - if($search['document'] == 1) - { - $document_lookin .= " $boolean {$dfield} LIKE '%{$word}%'"; - } - } - } - } - // In the middle of a quote (phrase) - else - { - $phrase = str_replace(array("+", "-", "*"), '', trim($phrase)); - if(my_strlen($phrase) < $mybb->settings['minsearchword']) - { - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - // Add phrase to search query - $name_lookin .= " $boolean {$nfield} LIKE '%{$phrase}%'"; - if($search['document'] == 1) - { - $document_lookin .= " $boolean {$dfield} LIKE '%{$phrase}%'"; - } - } - - // Check to see if we have any search terms and not a malformed SQL string - $error = false; - if($search['name'] && $search['document'] && $name_lookin == " AND (") - { - // We're looking for anything, check for a name lookin - $error = true; - } - elseif($search['name'] && !$search['document'] && $name_lookin == " AND (") - { - // Just in a name? - $error = true; - } - elseif(!$search['name'] && $search['document'] && $document_lookin == " {$string} (") - { - // Just in a document? - $error = true; - } - - if($error == true) - { - // There are no search keywords to look for - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - - $inquote = !$inquote; - } - - if($search['name'] == 1) - { - $name_lookin .= ")"; - } - - if($search['document'] == 1) - { - $document_lookin .= ")"; - } - - $searchsql .= "{$name_lookin} {$document_lookin}"; - } - else - { - $keywords = str_replace("\"", '', trim($keywords)); - if(my_strlen($keywords) < $mybb->settings['minsearchword']) - { - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - - // If we're looking in both, then find matches in either the name or the document - if($search['name'] == 1 && $search['document'] == 1) - { - $searchsql .= " AND ({$nfield} LIKE '%{$keywords}%' OR {$dfield} LIKE '%{$keywords}%')"; - } - else - { - if($search['name'] == 1) - { - $searchsql .= " AND {$nfield} LIKE '%{$keywords}%'"; - } - - if($search['document'] == 1) - { - $searchsql .= " AND {$dfield} LIKE '%{$keywords}%'"; - } - } - } - } - - // Run the search - $helpdocs = array(); - $query = $db->simple_select("helpdocs", "hid", $searchsql); - while($help = $db->fetch_array($query)) - { - $helpdocs[$help['hid']] = $help['hid']; - } - - if(count($helpdocs) < 1) - { - error($lang->error_nosearchresults); - } - $helpdocs = implode(',', $helpdocs); - - return array( - "querycache" => $helpdocs - ); -} - -/** - * Perform a thread and post search under MySQL or MySQLi - * - * @param array $search Array of search data - * @return array Array of search data with results mixed in - */ -function perform_search_mysql($search) -{ - global $mybb, $db, $lang, $cache; - - $keywords = clean_keywords($search['keywords']); - if(!$keywords && !$search['author']) - { - error($lang->error_nosearchterms); - } - - if($mybb->settings['minsearchword'] < 1) - { - $mybb->settings['minsearchword'] = 3; - } - - $subject_lookin = $message_lookin = ''; - if($keywords) - { - switch($db->type) - { - case 'mysql': - case 'mysqli': - $tfield = 't.subject'; - $pfield = 'p.message'; - break; - default: - $tfield = 'LOWER(t.subject)'; - $pfield = 'LOWER(p.message)'; - break; - } - - // Complex search - $keywords = " {$keywords} "; - if(preg_match("#\s(and|or)\s#", $keywords)) - { - $subject_lookin = " AND ("; - $message_lookin = " AND ("; - - // Expand the string by double quotes - $keywords_exp = explode("\"", $keywords); - $inquote = false; - $boolean = ''; - - foreach($keywords_exp as $phrase) - { - // If we're not in a double quoted section - if(!$inquote) - { - // Expand out based on search operators (and, or) - $matches = preg_split("#\s{1,}(and|or)\s{1,}#", $phrase, -1, PREG_SPLIT_DELIM_CAPTURE); - $count_matches = count($matches); - - for($i=0; $i < $count_matches; ++$i) - { - $word = trim($matches[$i]); - if(empty($word)) - { - continue; - } - // If this word is a search operator set the boolean - if($i % 2 && ($word == "and" || $word == "or")) - { - if($i <= 1 && $subject_lookin == " AND (") - { - continue; - } - - $boolean = $word; - } - // Otherwise check the length of the word as it is a normal search term - else - { - $word = trim($word); - // Word is too short - show error message - if(my_strlen($word) < $mybb->settings['minsearchword']) - { - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - // Add terms to search query - $subject_lookin .= " $boolean {$tfield} LIKE '%{$word}%'"; - if($search['postthread'] == 1) - { - $message_lookin .= " $boolean {$pfield} LIKE '%{$word}%'"; - } - $boolean = 'AND'; - } - } - } - // In the middle of a quote (phrase) - else - { - $phrase = str_replace(array("+", "-", "*"), '', trim($phrase)); - if(my_strlen($phrase) < $mybb->settings['minsearchword']) - { - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - // Add phrase to search query - $subject_lookin .= " $boolean {$tfield} LIKE '%{$phrase}%'"; - if($search['postthread'] == 1) - { - $message_lookin .= " $boolean {$pfield} LIKE '%{$phrase}%'"; - } - $boolean = 'AND'; - } - - if($subject_lookin == " AND (") - { - // There are no search keywords to look for - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - - $inquote = !$inquote; - } - $subject_lookin .= ")"; - $message_lookin .= ")"; - } - else - { - $keywords = str_replace("\"", '', trim($keywords)); - if(my_strlen($keywords) < $mybb->settings['minsearchword']) - { - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - $subject_lookin = " AND {$tfield} LIKE '%{$keywords}%'"; - if($search['postthread'] == 1) - { - $message_lookin = " AND {$pfield} LIKE '%{$keywords}%'"; - } - } - } - $post_usersql = ''; - $thread_usersql = ''; - if($search['author']) - { - $userids = array(); - $search['author'] = my_strtolower($search['author']); - if($search['matchusername']) - { - $user = get_user_by_username($search['author']); - if($user) - { - $userids[] = $user['uid']; - } - } - else - { - switch($db->type) - { - case 'mysql': - case 'mysqli': - $field = 'username'; - break; - default: - $field = 'LOWER(username)'; - break; - } - $query = $db->simple_select("users", "uid", "{$field} LIKE '%".$db->escape_string_like($search['author'])."%'"); - while($user = $db->fetch_array($query)) - { - $userids[] = $user['uid']; - } - } - - if(count($userids) < 1) - { - error($lang->error_nosearchresults); - } - else - { - $userids = implode(',', $userids); - $post_usersql = " AND p.uid IN (".$userids.")"; - $thread_usersql = " AND t.uid IN (".$userids.")"; - } - } - $datecut = $post_datecut = $thread_datecut = ''; - if($search['postdate']) - { - if($search['pddir'] == 0) - { - $datecut = "<="; - } - else - { - $datecut = ">="; - } - $now = TIME_NOW; - $datelimit = $now-(86400 * $search['postdate']); - $datecut .= "'$datelimit'"; - $post_datecut = " AND p.dateline $datecut"; - $thread_datecut = " AND t.dateline $datecut"; - } - - $thread_replycut = ''; - if($search['numreplies'] != '' && $search['findthreadst']) - { - if((int)$search['findthreadst'] == 1) - { - $thread_replycut = " AND t.replies >= '".(int)$search['numreplies']."'"; - } - else - { - $thread_replycut = " AND t.replies <= '".(int)$search['numreplies']."'"; - } - } - - $thread_prefixcut = ''; - $prefixlist = array(); - if($search['threadprefix'] && $search['threadprefix'][0] != 'any') - { - foreach($search['threadprefix'] as $threadprefix) - { - $threadprefix = (int)$threadprefix; - $prefixlist[] = $threadprefix; - } - } - if(count($prefixlist) == 1) - { - $thread_prefixcut .= " AND t.prefix='$threadprefix' "; - } - else - { - if(count($prefixlist) > 1) - { - $thread_prefixcut = " AND t.prefix IN (".implode(',', $prefixlist).")"; - } - } - - $forumin = ''; - $fidlist = array(); - $searchin = array(); - if(!is_array($search['forums']) || $search['forums'][0] != "all") - { - if(!is_array($search['forums'])) - { - $search['forums'] = array((int)$search['forums']); - } - // Generate a comma separated list of all groups the user belongs to - $user_groups = $mybb->user['usergroup']; - if($mybb->user['additionalgroups']) - { - $user_groups .= ",".$mybb->user['additionalgroups']; - - // Setup some quick permissions for us - $fcache = $cache->read("forumpermissions"); - $add_groups = explode(",", $mybb->user['additionalgroups']); - } - foreach($search['forums'] as $forum) - { - $forum = (int)$forum; - if(empty($searchin[$forum])) - { - if(isset($add_groups) && is_array($add_groups)) - { - $can_search = 0; - foreach($add_groups as $add_group) - { - // Check to make sure that we have sufficient permissions to search this forum - if(!is_array($fcache[$forum][$add_group]) || $fcache[$forum][$add_group]['cansearch'] == 1 || $mybb->usergroup['cansearch'] == 1) - { - $can_search = 1; - } - } - - if($can_search == 0) - { - // We can't search this forum... - continue; - } - } - - switch($db->type) - { - case "pgsql": - $query = $db->simple_select("forums", "DISTINCT fid", "(','||parentlist||',' LIKE ',%{$forum}%,') = true AND active != 0"); - break; - case "sqlite": - $query = $db->simple_select("forums", "DISTINCT fid", "(','||parentlist||',' LIKE ',%{$forum}%,') > 0 AND active != 0"); - break; - default: - $query = $db->simple_select("forums", "DISTINCT fid", "INSTR(CONCAT(',',parentlist,','),',{$forum},') > 0 AND active != 0"); - } - - while($sforum = $db->fetch_array($query)) - { - $fidlist[] = $sforum['fid']; - } - } - } - if(count($fidlist) == 1) - { - $forumin .= " AND t.fid='$forum' "; - $searchin[$forum] = 1; - } - else - { - if(count($fidlist) > 1) - { - $forumin = " AND t.fid IN (".implode(',', $fidlist).")"; - } - } - } - - $permsql = ""; - $onlyusfids = array(); - - // Check group permissions if we can't view threads not started by us - if($group_permissions = forum_permissions()) - { - foreach($group_permissions as $fid => $forum_permissions) - { - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $fid; - } - } - } - if(!empty($onlyusfids)) - { - $permsql .= "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; - } - - $unsearchforums = get_unsearchable_forums(); - if($unsearchforums) - { - $permsql .= " AND t.fid NOT IN ($unsearchforums)"; - } - $inactiveforums = get_inactive_forums(); - if($inactiveforums) - { - $permsql .= " AND t.fid NOT IN ($inactiveforums)"; - } - - $visiblesql = $post_visiblesql = $plain_post_visiblesql = ""; - if(isset($search['visible'])) - { - if($search['visible'] == 1) - { - $visiblesql = " AND t.visible = '1'"; - - if($search['postthread'] == 1) - { - $post_visiblesql = " AND p.visible = '1'"; - $plain_post_visiblesql = " AND visible = '1'"; - } - } - elseif($search['visible'] == -1) - { - $visiblesql = " AND t.visible = '-1'"; - - if($search['postthread'] == 1) - { - $post_visiblesql = " AND p.visible = '-1'"; - $plain_post_visiblesql = " AND visible = '-1'"; - } - } - else - { - $visiblesql = " AND t.visible == '0'"; - - if($search['postthread'] == 1) - { - $post_visiblesql = " AND p.visible == '0'"; - $plain_post_visiblesql = " AND visible == '0'"; - } - } - } - - // Searching a specific thread? - $tidsql = ''; - if(!empty($search['tid'])) - { - $tidsql = " AND t.tid='".(int)$search['tid']."'"; - } - - $limitsql = ''; - if((int)$mybb->settings['searchhardlimit'] > 0) - { - $limitsql = "LIMIT ".(int)$mybb->settings['searchhardlimit']; - } - - // Searching both posts and thread titles - $threads = array(); - $posts = array(); - $firstposts = array(); - if($search['postthread'] == 1) - { - // No need to search subjects when looking for results within a specific thread - if(empty($search['tid'])) - { - $query = $db->query(" - SELECT t.tid, t.firstpost - FROM ".TABLE_PREFIX."threads t - WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} AND t.closed NOT LIKE 'moved|%' {$subject_lookin} - {$limitsql} - "); - while($thread = $db->fetch_array($query)) - { - $threads[$thread['tid']] = $thread['tid']; - if($thread['firstpost']) - { - $posts[$thread['tid']] = $thread['firstpost']; - } - } - } - - $query = $db->query(" - SELECT p.pid, p.tid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE 1=1 {$post_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$post_usersql} {$permsql} {$tidsql} {$visiblesql} {$post_visiblesql} AND t.closed NOT LIKE 'moved|%' {$message_lookin} - {$limitsql} - "); - while($post = $db->fetch_array($query)) - { - $posts[$post['pid']] = $post['pid']; - $threads[$post['tid']] = $post['tid']; - } - - if(count($posts) < 1 && count($threads) < 1) - { - error($lang->error_nosearchresults); - } - $threads = implode(',', $threads); - $posts = implode(',', $posts); - - } - // Searching only thread titles - else - { - $query = $db->query(" - SELECT t.tid, t.firstpost - FROM ".TABLE_PREFIX."threads t - WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} {$subject_lookin} - {$limitsql} - "); - while($thread = $db->fetch_array($query)) - { - $threads[$thread['tid']] = $thread['tid']; - if($thread['firstpost']) - { - $firstposts[$thread['tid']] = $thread['firstpost']; - } - } - if(count($threads) < 1) - { - error($lang->error_nosearchresults); - } - - $threads = implode(',', $threads); - $firstposts = implode(',', $firstposts); - if($firstposts) - { - $query = $db->simple_select("posts", "pid", "pid IN ($firstposts) {$plain_post_visiblesql} {$limitsql}"); - while($post = $db->fetch_array($query)) - { - $posts[$post['pid']] = $post['pid']; - } - $posts = implode(',', $posts); - } - } - return array( - "threads" => $threads, - "posts" => $posts, - "querycache" => '' - ); -} - -/** - * Perform a thread and post search under MySQL or MySQLi using boolean fulltext capabilities - * - * @param array $search Array of search data - * @return array Array of search data with results mixed in - */ -function perform_search_mysql_ft($search) -{ - global $mybb, $db, $lang; - - $keywords = clean_keywords_ft($search['keywords']); - if(!$keywords && !$search['author']) - { - error($lang->error_nosearchterms); - } - - // Attempt to determine minimum word length from MySQL for fulltext searches - $query = $db->query("SHOW VARIABLES LIKE 'ft_min_word_len';"); - $min_length = $db->fetch_field($query, 'Value'); - if(is_numeric($min_length)) - { - $mybb->settings['minsearchword'] = $min_length; - } - // Otherwise, could not fetch - default back to MySQL fulltext default setting - else - { - $mybb->settings['minsearchword'] = 4; - } - - if($keywords) - { - $keywords_exp = explode("\"", $keywords); - $inquote = false; - foreach($keywords_exp as $phrase) - { - if(!$inquote) - { - $split_words = preg_split("#\s{1,}#", $phrase, -1); - foreach($split_words as $word) - { - $word = str_replace(array("+", "-", "*"), '', $word); - if(!$word) - { - continue; - } - if(my_strlen($word) < $mybb->settings['minsearchword']) - { - $all_too_short = true; - } - else - { - $all_too_short = false; - break; - } - } - } - else - { - $phrase = str_replace(array("+", "-", "*"), '', $phrase); - if(my_strlen($phrase) < $mybb->settings['minsearchword']) - { - $all_too_short = true; - } - else - { - $all_too_short = false; - break; - } - } - $inquote = !$inquote; - } - // Show the minimum search term error only if all search terms are too short - if($all_too_short == true) - { - $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); - error($lang->error_minsearchlength); - } - $message_lookin = "AND MATCH(message) AGAINST('".$db->escape_string($keywords)."' IN BOOLEAN MODE)"; - $subject_lookin = "AND MATCH(subject) AGAINST('".$db->escape_string($keywords)."' IN BOOLEAN MODE)"; - } - $post_usersql = ''; - $thread_usersql = ''; - if($search['author']) - { - $userids = array(); - $search['author'] = my_strtolower($search['author']); - if($search['matchusername']) - { - $user = get_user_by_username($search['author']); - if($user) - { - $userids[] = $user['uid']; - } - } - else - { - switch($db->type) - { - case 'mysql': - case 'mysqli': - $field = 'username'; - break; - default: - $field = 'LOWER(username)'; - break; - } - $query = $db->simple_select("users", "uid", "{$field} LIKE '%".$db->escape_string_like($search['author'])."%'"); - - while($user = $db->fetch_array($query)) - { - $userids[] = $user['uid']; - } - } - - if(count($userids) < 1) - { - error($lang->error_nosearchresults); - } - else - { - $userids = implode(',', $userids); - $post_usersql = " AND p.uid IN (".$userids.")"; - $thread_usersql = " AND t.uid IN (".$userids.")"; - } - } - $datecut = ''; - if($search['postdate']) - { - if($search['pddir'] == 0) - { - $datecut = "<="; - } - else - { - $datecut = ">="; - } - $now = TIME_NOW; - $datelimit = $now-(86400 * $search['postdate']); - $datecut .= "'$datelimit'"; - $post_datecut = " AND p.dateline $datecut"; - $thread_datecut = " AND t.dateline $datecut"; - } - - $thread_replycut = ''; - if($search['numreplies'] != '' && $search['findthreadst']) - { - if((int)$search['findthreadst'] == 1) - { - $thread_replycut = " AND t.replies >= '".(int)$search['numreplies']."'"; - } - else - { - $thread_replycut = " AND t.replies <= '".(int)$search['numreplies']."'"; - } - } - - $thread_prefixcut = ''; - $prefixlist = array(); - if($search['threadprefix'] && $search['threadprefix'][0] != 'any') - { - foreach($search['threadprefix'] as $threadprefix) - { - $threadprefix = (int)$threadprefix; - $prefixlist[] = $threadprefix; - } - } - if(count($prefixlist) == 1) - { - $thread_prefixcut .= " AND t.prefix='$threadprefix' "; - } - else - { - if(count($prefixlist) > 1) - { - $thread_prefixcut = " AND t.prefix IN (".implode(',', $prefixlist).")"; - } - } - - $forumin = ''; - $fidlist = array(); - $searchin = array(); - if(!is_array($search['forums']) || $search['forums'][0] != "all") - { - if(!is_array($search['forums'])) - { - $search['forums'] = array((int)$search['forums']); - } - // Generate a comma separated list of all groups the user belongs to - $user_groups = $mybb->user['usergroup']; - if($mybb->user['additionalgroups']) - { - $user_groups .= ",".$mybb->user['additionalgroups']; - } - foreach($search['forums'] as $forum) - { - $forum = (int)$forum; - if(empty($searchin[$forum])) - { - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->query(" - SELECT f.fid - FROM ".TABLE_PREFIX."forums f - LEFT JOIN ".TABLE_PREFIX."forumpermissions p ON (f.fid=p.fid AND p.gid IN (".$user_groups.")) - WHERE INSTR(','||parentlist||',',',$forum,') > 0 AND active!=0 AND ((p.fid) IS NULL OR p.cansearch=1) - "); - break; - default: - $query = $db->query(" - SELECT f.fid - FROM ".TABLE_PREFIX."forums f - LEFT JOIN ".TABLE_PREFIX."forumpermissions p ON (f.fid=p.fid AND p.gid IN (".$user_groups.")) - WHERE INSTR(CONCAT(',',parentlist,','),',$forum,') > 0 AND active!=0 AND ((p.fid) IS NULL OR p.cansearch=1) - "); - } - while($sforum = $db->fetch_array($query)) - { - $fidlist[] = $sforum['fid']; - } - } - } - if(count($fidlist) == 1) - { - $forumin .= " AND t.fid='$forum' "; - $searchin[$forum] = 1; - } - else - { - - if(count($fidlist) > 1) - { - $forumin = " AND t.fid IN (".implode(',', $fidlist).")"; - } - } - } - $permsql = ""; - $onlyusfids = array(); - - // Check group permissions if we can't view threads not started by us - $group_permissions = forum_permissions(); - foreach($group_permissions as $fid => $forum_permissions) - { - if($forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $fid; - } - } - if(!empty($onlyusfids)) - { - $permsql .= "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; - } - - $unsearchforums = get_unsearchable_forums(); - if($unsearchforums) - { - $permsql .= " AND t.fid NOT IN ($unsearchforums)"; - } - $inactiveforums = get_inactive_forums(); - if($inactiveforums) - { - $permsql .= " AND t.fid NOT IN ($inactiveforums)"; - } - - $visiblesql = $post_visiblesql = $plain_post_visiblesql = ""; - if(isset($search['visible'])) - { - if($search['visible'] == 1) - { - $visiblesql = " AND t.visible = '1'"; - - if($search['postthread'] == 1) - { - $post_visiblesql = " AND p.visible = '1'"; - $plain_post_visiblesql = " AND visible = '1'"; - } - } - elseif($search['visible'] == -1) - { - $visiblesql = " AND t.visible = '-1'"; - - if($search['postthread'] == 1) - { - $post_visiblesql = " AND p.visible = '-1'"; - $plain_post_visiblesql = " AND visible = '-1'"; - } - } - else - { - $visiblesql = " AND t.visible != '1'"; - - if($search['postthread'] == 1) - { - $post_visiblesql = " AND p.visible != '1'"; - $plain_post_visiblesql = " AND visible != '1'"; - } - } - } - - // Searching a specific thread? - if($search['tid']) - { - $tidsql = " AND t.tid='".(int)$search['tid']."'"; - } - - $limitsql = ''; - if((int)$mybb->settings['searchhardlimit'] > 0) - { - $limitsql = "LIMIT ".(int)$mybb->settings['searchhardlimit']; - } - - // Searching both posts and thread titles - $threads = array(); - $posts = array(); - $firstposts = array(); - if($search['postthread'] == 1) - { - // No need to search subjects when looking for results within a specific thread - if(!$search['tid']) - { - $query = $db->query(" - SELECT t.tid, t.firstpost - FROM ".TABLE_PREFIX."threads t - WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} AND t.closed NOT LIKE 'moved|%' {$subject_lookin} - {$limitsql} - "); - while($thread = $db->fetch_array($query)) - { - $threads[$thread['tid']] = $thread['tid']; - if($thread['firstpost']) - { - $posts[$thread['tid']] = $thread['firstpost']; - } - } - } - - $query = $db->query(" - SELECT p.pid, p.tid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE 1=1 {$post_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$post_usersql} {$permsql} {$tidsql} {$post_visiblesql} {$visiblesql} AND t.closed NOT LIKE 'moved|%' {$message_lookin} - {$limitsql} - "); - while($post = $db->fetch_array($query)) - { - $posts[$post['pid']] = $post['pid']; - $threads[$post['tid']] = $post['tid']; - } - if(count($posts) < 1 && count($threads) < 1) - { - error($lang->error_nosearchresults); - } - $threads = implode(',', $threads); - $posts = implode(',', $posts); - - } - // Searching only thread titles - else - { - $query = $db->query(" - SELECT t.tid, t.firstpost - FROM ".TABLE_PREFIX."threads t - WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} {$subject_lookin} - {$limitsql} - "); - while($thread = $db->fetch_array($query)) - { - $threads[$thread['tid']] = $thread['tid']; - if($thread['firstpost']) - { - $firstposts[$thread['tid']] = $thread['firstpost']; - } - } - if(count($threads) < 1) - { - error($lang->error_nosearchresults); - } - - $threads = implode(',', $threads); - $firstposts = implode(',', $firstposts); - if($firstposts) - { - $query = $db->simple_select("posts", "pid", "pid IN ($firstposts) {$plain_post_visiblesql} {$limitsql}"); - while($post = $db->fetch_array($query)) - { - $posts[$post['pid']] = $post['pid']; - } - $posts = implode(',', $posts); - } - } - return array( - "threads" => $threads, - "posts" => $posts, - "querycache" => '' - ); -} diff --git a/html/forums/inc/functions_serverstats.php b/html/forums/inc/functions_serverstats.php deleted file mode 100644 index 03cc071..0000000 --- a/html/forums/inc/functions_serverstats.php +++ /dev/null @@ -1,341 +0,0 @@ - array( - 'dom' => array('bitwise' => 1, 'title' => 'DOMElement'), - 'soap' => array('bitwise' => 2, 'title' => 'SoapClient'), - 'xmlwriter' => array('bitwise' => 4, 'title' => 'XMLWriter'), - 'imagemagick' => array('bitwise' => 8, 'title' => 'Imagick'), - ), - - 'extensions' => array( - 'zendopt' => array('bitwise' => 1, 'title' => 'Zend Optimizer'), - 'xcache' => array('bitwise' => 2, 'title' => 'XCache'), - 'eaccelerator' => array('bitwise' => 4, 'title' => 'eAccelerator'), - 'ioncube' => array('bitwise' => 8, 'title' => 'ionCube Loader'), - 'PDO' => array('bitwise' => 16, 'title' => 'PDO'), - 'pdo_mysql' => array('bitwise' => 32, 'title' => 'pdo_mysql'), - 'pdo_pgsql' => array('bitwise' => 64, 'title' => 'pdo_pgsql'), - 'pdo_sqlite' => array('bitwise' => 128, 'title' => 'pdo_sqlite'), - 'pdo_oci' => array('bitwise' => 256, 'title' => 'pdo_oci'), - 'pdo_odbc' => array('bitwise' => 512, 'title' => 'pdo_odbc'), - ), - - 'phpinfo' => array( - 'zlib' => array('bitwise' => 1, 'title' => 'zlib'), - 'mbstring' => array('bitwise' => 2, 'title' => 'mbstring'), - 'exif' => array('bitwise' => 4, 'title' => 'exif'), - 'zlib' => array('bitwise' => 8, 'title' => 'zlib'), - - ), - - 'functions' => array( - 'sockets' => array('bitwise' => 1, 'title' => 'fsockopen'), - 'mcrypt' => array('bitwise' => 2, 'title' => 'mcrypt_encrypt'), - 'simplexml' => array('bitwise' => 4, 'title' => 'simplexml_load_string'), - 'ldap' => array('bitwise' => 8, 'title' => 'ldap_connect'), - 'mysqli' => array('bitwise' => 16, 'title' => 'mysqli_connect'), - 'imap' => array('bitwise' => 32, 'title' => 'imap_open'), - 'ftp' => array('bitwise' => 64, 'title' => 'ftp_login'), - 'pspell' => array('bitwise' => 128, 'title' => 'pspell_new'), - 'apc' => array('bitwise' => 256, 'title' => 'apc_cache_info'), - 'curl' => array('bitwise' => 512, 'title' => 'curl_init'), - 'iconv' => array('bitwise' => 1024, 'title' => 'iconv'), - ), - - 'php_ini' => array( - 'post_max_size' => 'post_max_size', - 'upload_max_filesize' => 'upload_max_filesize', - 'safe_mode' => 'safe_mode', - ), - ); - - foreach($check as $cat_name => $category) - { - foreach($category as $name => $what) - { - if(!isset($info[$cat_name])) - { - $info[$cat_name] = 0; - } - switch($cat_name) - { - case "classes": - if(class_exists($what['title'])) - { - $info[$cat_name] |= $what['bitwise']; - } - break; - case "extensions": - if(extension_loaded($what['title'])) - { - $info[$cat_name] |= $what['bitwise']; - } - break; - case "phpinfo": - if(array_key_exists($what['title'], $phpinfo)) - { - $info[$cat_name] |= $what['bitwise']; - } - break; - case "functions": - if(function_exists($what['title'])) - { - $info[$cat_name] |= $what['bitwise']; - } - break; - case "php_ini": - if(ini_get($what) != 0) - { - $info[$name] = ini_get($what); - } - else - { - $info[$name] = 0; - } - break; - } - } - } - - // Host URL & hostname - $info['hosturl'] = $info['hostname'] = "unknown/local"; - if($_SERVER['HTTP_HOST'] == 'localhost') - { - $info['hosturl'] = $info['hostname'] = "localhost"; - } - - // Check the hosting company - if(strpos($_SERVER['HTTP_HOST'], ".") !== false) - { - $host_url = "http://www.whoishostingthis.com/".str_replace(array('http://', 'https://', 'www.'), '', $_SERVER['HTTP_HOST']); - - $hosting = fetch_remote_file($host_url); - - if($hosting) - { - preg_match('#We believe \
    ([^<]*)\<\/a\>#ism', $hosting, $matches); - - $info['hosturl'] = "unknown/no-url"; - if(isset($matches[1]) && strlen(trim($matches[1])) != 0 && strpos($matches[1], '.') !== false) - { - $info['hosturl'] = strtolower($matches[1]); - } - else if(isset($matches[3]) && strlen(trim($matches[3])) != 0 && strpos($matches[3], '.') !== false) - { - $info['hosturl'] = strtolower($matches[3]); - } - - if(isset($matches[4]) && strlen(trim($matches[4])) != 0) - { - $info['hostname'] = $matches[4]; - } - elseif(isset($matches[3]) && strlen(trim($matches[3])) != 0) - { - $info['hostname'] = $matches[3]; - } - elseif(isset($matches[2]) && strlen(trim($matches[2])) != 0) - { - $info['hostname'] = str_replace(array('title=', '"'), '', $matches[2][0]); - } - elseif(strlen(trim($info['hosturl'])) != 0 && $info['hosturl'] != "unknown/no-url") - { - $info['hostname'] = $info['hosturl']; - } - else - { - $info['hostname'] = "unknown/no-name"; - } - } - } - - if(isset($_SERVER['HTTP_USER_AGENT'])) - { - $info['useragent'] = $_SERVER['HTTP_USER_AGENT']; - } - - // We need a unique ID for the host so hash it to keep it private and send it over - $id = $_SERVER['HTTP_HOST'].time(); - - if(function_exists('sha1')) - { - $info['clientid'] = sha1($id); - } - else - { - $info['clientid'] = md5($id); - } - - $string = ""; - $amp = ""; - foreach($info as $key => $value) - { - $string .= $amp.$key."=".urlencode($value); - $amp = "&"; - } - - $server_stats_url = 'https://community.mybb.com/server_stats.php?'.$string; - - $return = array(); - $return['info_sent_success'] = false; - if(fetch_remote_file($server_stats_url) !== false) - { - $return['info_sent_success'] = true; - } - $return['info_image'] = ""; - $return['info_get_string'] = $string; - - return $return; -} - -/** -* parser_php_info -* Function to get and parse the list of PHP info into a usuable array -* -* @return Array An array of all the extensions installed in PHP -*/ -function parse_php_info() -{ - ob_start(); - phpinfo(INFO_MODULES); - $phpinfo_html = ob_get_contents(); - ob_end_clean(); - - $phpinfo_html = strip_tags($phpinfo_html, "

    "); - $phpinfo_html = preg_replace("#]*>([^<]+)<\/th>#", "$1", $phpinfo_html); - $phpinfo_html = preg_replace("#]*>([^<]+)<\/td>#", "$1", $phpinfo_html); - $phpinfo_html = preg_split("#(]*>[^<]+<\/h2>)#", $phpinfo_html, -1, PREG_SPLIT_DELIM_CAPTURE); - $modules = array(); - - for($i=1; $i < count($phpinfo_html); $i++) - { - if(preg_match("#]*>([^<]+)<\/h2>#", $phpinfo_html[$i], $match)) - { - $name = trim($match[1]); - $tmp2 = explode("\n", $phpinfo_html[$i+1]); - foreach($tmp2 as $one) - { - $pat = '([^<]+)<\/info>'; - $pat3 = "/$pat\s*$pat\s*$pat/"; - $pat2 = "/$pat\s*$pat/"; - - // 3 columns - if(preg_match($pat3, $one, $match)) - { - $modules[$name][trim($match[1])] = array(trim($match[2]), trim($match[3])); - } - // 2 columns - else if(preg_match($pat2, $one, $match)) - { - $modules[$name][trim($match[1])] = trim($match[2]); - } - } - } - } - return $modules; -} - diff --git a/html/forums/inc/functions_task.php b/html/forums/inc/functions_task.php deleted file mode 100644 index 17b0486..0000000 --- a/html/forums/inc/functions_task.php +++ /dev/null @@ -1,383 +0,0 @@ - 0) - { - $query = $db->simple_select("tasks", "*", "tid='{$tid}'"); - $task = $db->fetch_array($query); - } - - // Run the next task due to be run - else - { - $query = $db->simple_select("tasks", "*", "enabled=1 AND nextrun<='".TIME_NOW."'", array("order_by" => "nextrun", "order_dir" => "asc", "limit" => 1)); - $task = $db->fetch_array($query); - } - - // No task? Return - if(!$task['tid']) - { - $cache->update_tasks(); - return false; - } - - // Is this task still running and locked less than 5 minutes ago? Well don't run it now - clearly it isn't broken! - if($task['locked'] != 0 && $task['locked'] > TIME_NOW-300) - { - $cache->update_tasks(); - return false; - } - // Lock it! It' mine, all mine! - else - { - $db->update_query("tasks", array("locked" => TIME_NOW), "tid='{$task['tid']}'"); - } - - // The task file does not exist - if(!file_exists(MYBB_ROOT."inc/tasks/{$task['file']}.php")) - { - if($task['logging'] == 1) - { - add_task_log($task, $lang->missing_task); - } - - // If task file does not exist, disable task and inform the administrator - $updated_task = array( - "enabled" => 0, - "locked" => 0 - ); - $db->update_query("tasks", $updated_task, "tid='{$task['tid']}'"); - - $subject = $lang->sprintf($lang->email_broken_task_subject, $mybb->settings['bbname']); - $message = $lang->sprintf($lang->email_broken_task, $mybb->settings['bbname'], $mybb->settings['bburl'], $task['title']); - - my_mail($mybb->settings['adminemail'], $subject, $message, $mybb->settings['adminemail']); - - $cache->update_tasks(); - return false; - } - // Run the task - else - { - // Update the nextrun time now, so if the task causes a fatal error, it doesn't get stuck first in the queue - $nextrun = fetch_next_run($task); - $db->update_query("tasks", array("nextrun" => $nextrun), "tid='{$task['tid']}'"); - - include_once MYBB_ROOT."inc/tasks/{$task['file']}.php"; - $function = "task_{$task['file']}"; - if(function_exists($function)) - { - $function($task); - } - } - - $updated_task = array( - "lastrun" => TIME_NOW, - "locked" => 0 - ); - $db->update_query("tasks", $updated_task, "tid='{$task['tid']}'"); - - $cache->update_tasks(); - - return true; -} - -/** - * Adds information to the scheduled task log. - * - * @param int $task The task array to create the log entry for - * @param string $message The message to log - */ -function add_task_log($task, $message) -{ - global $db; - - if(!$task['logging']) - { - return; - } - - $log_entry = array( - "tid" => (int)$task['tid'], - "dateline" => TIME_NOW, - "data" => $db->escape_string($message) - ); - $db->insert_query("tasklog", $log_entry); -} - -/** - * Generate the next run time for a particular task. - * - * @param array $task The task array as fetched from the database. - * @return int The next run time as a UNIX timestamp - */ -function fetch_next_run($task) -{ - $time = TIME_NOW; - $next_minute = $current_minute = date("i", $time); - $next_hour = $current_hour = date("H", $time); - $next_day = $current_day = date("d", $time); - $next_weekday = $current_weekday = date("w", $time); - $next_month = $current_month = date("m", $time); - $next_year = $current_year = date("Y", $time); - $reset_day = $reset_hour = $reset_month = $reset_year = 0; - - if($task['minute'] == "*") - { - ++$next_minute; - if($next_minute > 59) - { - $reset_hour = 1; - $next_minute = 0; - } - } - else - { - if(build_next_run_bit($task['minute'], $current_minute) != false) - { - $next_minute = build_next_run_bit($task['minute'], $current_minute); - } - else - { - $next_minute = fetch_first_run_time($task['minute']); - } - if($next_minute <= $current_minute) - { - $reset_hour = 1; - } - } - - if($reset_hour || !run_time_exists($task['hour'], $current_hour)) - { - if($task['hour'] == "*") - { - ++$next_hour; - if($next_hour > 23) - { - $reset_day = 1; - $next_hour = 0; - } - } - else - { - if(build_next_run_bit($task['hour'], $current_hour) != false) - { - $next_hour = build_next_run_bit($task['hour'], $current_hour); - } - else - { - $next_hour = fetch_first_run_time($task['hour']); - $reset_day = 1; - } - if($next_hour < $current_hour) - { - $reset_day = 1; - } - } - $next_minute = fetch_first_run_time($task['minute']); - } - - if($reset_day || ($task['weekday'] == "*" && !run_time_exists($task['day'], $current_day) || $task['day'] == "*" && !run_time_exists($task['weekday'], $current_weekday))) - { - if($task['weekday'] == "*") - { - if($task['day'] == "*") - { - ++$next_day; - if($next_day > date("t", $time)) - { - $reset_month = 1; - $next_day = 1; - } - } - else - { - if(build_next_run_bit($task['day'], $current_day) != false) - { - $next_day = build_next_run_bit($task['day'], $current_day); - } - else - { - $next_day = fetch_first_run_time($task['day']); - $reset_month = 1; - } - if($next_day < $current_day) - { - $reset_month = 1; - } - } - } - else - { - if(build_next_run_bit($task['weekday'], $current_weekday) != false) - { - $next_weekday = build_next_run_bit($task['weekday'], $current_weekday); - } - else - { - $next_weekday = fetch_first_run_time($task['weekday']); - } - $next_day = $current_day + ($next_weekday-$current_weekday); - if($next_day <= $current_day) - { - $next_day += 7; - } - - if($next_day > date("t", $time)) - { - $reset_month = 1; - } - } - $next_minute = fetch_first_run_time($task['minute']); - $next_hour = fetch_first_run_time($task['hour']); - if($next_day == $current_day && $next_hour < $current_hour) - { - $reset_month = 1; - } - } - - if($reset_month || !run_time_exists($task['month'], $current_month)) - { - if($task['month'] == "*") - { - $next_month++; - if($next_month > 12) - { - $reset_year = 1; - $next_month = 1; - } - } - else - { - if(build_next_run_bit($task['month'], $current_month) != false) - { - $next_month = build_next_run_bit($task['month'], $current_month); - } - else - { - $next_month = fetch_first_run_time($task['month']); - $reset_year = 1; - } - if($next_month < $current_month) - { - $reset_year = 1; - } - } - $next_minute = fetch_first_run_time($task['minute']); - $next_hour = fetch_first_run_time($task['hour']); - if($task['weekday'] == "*") - { - $next_day = fetch_first_run_time($task['day']); - if($next_day == 0) $next_day = 1; - } - else - { - $next_weekday = fetch_first_run_time($task['weekday']); - $new_weekday = date("w", mktime($next_hour, $next_minute, 0, $next_month, 1, $next_year)); - $next_day = 1 + ($next_weekday-$new_weekday); - if($next_weekday < $new_weekday) - { - $next_day += 7; - } - } - if($next_month == $current_month && $next_day == $current_day && $next_hour < $current_hour) - { - $reset_year = 1; - } - } - - if($reset_year) - { - $next_year++; - $next_minute = fetch_first_run_time($task['minute']); - $next_hour = fetch_first_run_time($task['hour']); - $next_month = fetch_first_run_time($task['month']); - if($next_month == 0) $next_month = 1; - if($task['weekday'] == "*") - { - $next_day = fetch_first_run_time($task['day']); - if($next_day == 0) $next_day = 1; - } - else - { - $next_weekday = fetch_first_run_time($task['weekday']); - $new_weekday = date("w", mktime($next_hour, $next_minute, 0, $next_month, 1, $next_year)); - $next_day = 1 + ($next_weekday-$new_weekday); - if($next_weekday < $new_weekday) - { - $next_day += 7; - } - } - } - return mktime($next_hour, $next_minute, 0, $next_month, $next_day, $next_year); -} - -/** - * Builds the next run time bit for a particular item (day, hour, month etc). Used by fetch_next_run(). - * - * @param string $data A string containing the run times for this particular item - * @param int $bit The current value (be it current day etc) - * @return int|bool The new or found value or boolean if nothing is found - */ -function build_next_run_bit($data, $bit) -{ - if($data == "*") return $bit; - $data = explode(",", $data); - foreach($data as $thing) - { - if($thing > $bit) - { - return $thing; - } - } - return false; -} - -/** - * Fetches the fist run bit for a particular item (day, hour, month etc). Used by fetch_next_run(). - * - * @param string $data A string containing the run times for this particular item - * @return int The first run time - */ -function fetch_first_run_time($data) -{ - if($data == "*") return "0"; - $data = explode(",", $data); - return $data[0]; -} - -/** - * Checks if a specific run time exists for a particular item (day, hour, month etc). Used by fetch_next_run(). - * - * @param string $data A string containing the run times for this particular item - * @param int $bit The bit we're checking for - * @return boolean True if it exists, false if it does not - */ -function run_time_exists($data, $bit) -{ - if($data == "*") return true; - $data = explode(",", $data); - if(in_array($bit, $data)) - { - return true; - } - return false; -} diff --git a/html/forums/inc/functions_time.php b/html/forums/inc/functions_time.php deleted file mode 100644 index 8dd618f..0000000 --- a/html/forums/inc/functions_time.php +++ /dev/null @@ -1,877 +0,0 @@ - 4 digit year conversion. The maximum is billions of years in the -future, but this is a theoretical limit as the computation of that year -would take too long with the current implementation of adodb_mktime(). - -This library replaces native functions as follows: - -
    -	getdate()  with  adodb_getdate()
    -	date()     with  adodb_date()
    -	gmdate()   with  adodb_gmdate()
    -	mktime()   with  adodb_mktime()
    -	gmmktime() with  adodb_gmmktime()
    -	strftime() with  adodb_strftime()
    -	strftime() with  adodb_gmstrftime()
    -
    - -The parameters are identical, except that adodb_date() accepts a subset -of date()'s field formats. Mktime() will convert from local time to GMT, -and date() will convert from GMT to local time, but daylight savings is -not handled currently. - -This library is independant of the rest of ADOdb, and can be used -as standalone code. - -PERFORMANCE - -For high speed, this library uses the native date functions where -possible, and only switches to PHP code when the dates fall outside -the 32-bit signed integer range. - -GREGORIAN CORRECTION - -Pope Gregory shortened October of A.D. 1582 by ten days. Thursday, -October 4, 1582 (Julian) was followed immediately by Friday, October 15, -1582 (Gregorian). - -Since 0.06, we handle this correctly, so: - -adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582) - == 24 * 3600 (1 day) - -============================================================================= - -COPYRIGHT - -(c) 2003-2005 John Lim and released under BSD-style license except for code by -jackbbs, which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year -and originally found at http://www.php.net/manual/en/function.mktime.php - -============================================================================= - -BUG REPORTS - -These should be posted to the ADOdb forums at - - http://phplens.com/lens/lensforum/topics.php?id=4 - -============================================================================= -*/ - - -/* Initialization */ - -/* - Version Number -*/ -define('ADODB_DATE_VERSION', 0.33); - -$ADODB_DATETIME_CLASS = (PHP_VERSION >= 5.2); - -/* - This code was originally for windows. But apparently this problem happens - also with Linux, RH 7.3 and later! - - glibc-2.2.5-34 and greater has been changed to return -1 for dates < - 1970. This used to work. The problem exists with RedHat 7.3 and 8.0 - echo (mktime(0, 0, 0, 1, 1, 1960)); // prints -1 - - References: - http://bugs.php.net/bug.php?id=20048&edit=2 - http://lists.debian.org/debian-glibc/2002/debian-glibc-200205/msg00010.html -*/ - -if (!defined('ADODB_ALLOW_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS',1); - -/** - Returns day of week, 0 = Sunday,... 6=Saturday. - Algorithm from PEAR::Date_Calc -*/ -function adodb_dow($year, $month, $day) -{ -/* -Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and -proclaimed that from that time onwards 3 days would be dropped from the calendar -every 400 years. - -Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian). -*/ - if ($year <= 1582) { - if ($year < 1582 || - ($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))) $greg_correction = 3; - else - $greg_correction = 0; - } else - $greg_correction = 0; - - if($month > 2) - $month -= 2; - else { - $month += 10; - $year--; - } - - $day = floor((13 * $month - 1) / 5) + - $day + ($year % 100) + - floor(($year % 100) / 4) + - floor(($year / 100) / 4) - 2 * - floor($year / 100) + 77 + $greg_correction; - - return $day - 7 * floor($day / 7); -} - -/** - Checks for leap year, returns true if it is. No 2-digit year check. Also - handles julian calendar correctly. -*/ -function _adodb_is_leap_year($year) -{ - if ($year % 4 != 0) return false; - - if ($year % 400 == 0) { - return true; - // if gregorian calendar (>1582), century not-divisible by 400 is not leap - } else if ($year > 1582 && $year % 100 == 0 ) { - return false; - } - - return true; -} - -/** - checks for leap year, returns true if it is. Has 2-digit year check -*/ -function adodb_is_leap_year($year) -{ - return _adodb_is_leap_year(adodb_year_digit_check($year)); -} - -/** - Fix 2-digit years. Works for any century. - Assumes that if 2-digit is more than 30 years in future, then previous century. -*/ -function adodb_year_digit_check($y) -{ - if ($y < 100) { - - $yr = (integer) date("Y"); - $century = (integer) ($yr /100); - - if ($yr%100 > 50) { - $c1 = $century + 1; - $c0 = $century; - } else { - $c1 = $century; - $c0 = $century - 1; - } - $c1 *= 100; - // if 2-digit year is less than 30 years in future, set it to this century - // otherwise if more than 30 years in future, then we set 2-digit year to the prev century. - if (($y + $c1) < $yr+30) $y = $y + $c1; - else $y = $y + $c0*100; - } - return $y; -} - -function adodb_get_gmt_diff_ts($ts) -{ - if (0 <= $ts && $ts <= 0x7FFFFFFF) { // check if number in 32-bit signed range) { - $arr = getdate($ts); - $y = $arr['year']; - $m = $arr['mon']; - $d = $arr['mday']; - return adodb_get_gmt_diff($y,$m,$d); - } else { - return adodb_get_gmt_diff(false,false,false); - } - -} - -/** - get local time zone offset from GMT. Does not handle historical timezones before 1970. -*/ -function adodb_get_gmt_diff($y,$m,$d) -{ -static $TZ,$tzo; -global $ADODB_DATETIME_CLASS; - - if (!defined('ADODB_TEST_DATES')) $y = false; - else if ($y < 1970 || $y >= 2038) $y = false; - - if ($ADODB_DATETIME_CLASS && $y !== false) { - $dt = new DateTime(); - $dt->setISODate($y,$m,$d); - if (empty($tzo)) { - $tzo = new DateTimeZone(date_default_timezone_get()); - # $tzt = timezone_transitions_get( $tzo ); - } - return -$tzo->getOffset($dt); - } else { - if (isset($TZ)) return $TZ; - $y = date('Y'); - $TZ = mktime(0,0,0,12,2,$y) - gmmktime(0,0,0,12,2,$y); - } - - return $TZ; -} - -/** - Returns an array with date info. -*/ -function adodb_getdate($d=false,$fast=false) -{ - if ($d === false) return getdate(); - if (!defined('ADODB_TEST_DATES')) { - if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range - if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer - return @getdate($d); - } - } - return _adodb_getdate($d); -} - -$_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); -$_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31); - -/** - Low-level function that returns the getdate() array. We have a special - $fast flag, which if set to true, will return fewer array values, - and is much faster as it does not calculate dow, etc. -*/ -function _adodb_getdate($origd=false,$fast=false,$is_gmt=false) -{ -static $YRS; -global $_month_table_normal,$_month_table_leaf; - - $d = $origd - ($is_gmt ? 0 : adodb_get_gmt_diff_ts($origd)); - $_day_power = 86400; - $_hour_power = 3600; - $_min_power = 60; - - if ($d < -12219321600) $d -= 86400*10; // if 15 Oct 1582 or earlier, gregorian correction - - $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); - $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31); - - $d366 = $_day_power * 366; - $d365 = $_day_power * 365; - - if ($d < 0) { - - if (empty($YRS)) $YRS = array( - 1970 => 0, - 1960 => -315619200, - 1950 => -631152000, - 1940 => -946771200, - 1930 => -1262304000, - 1920 => -1577923200, - 1910 => -1893456000, - 1900 => -2208988800, - 1890 => -2524521600, - 1880 => -2840140800, - 1870 => -3155673600, - 1860 => -3471292800, - 1850 => -3786825600, - 1840 => -4102444800, - 1830 => -4417977600, - 1820 => -4733596800, - 1810 => -5049129600, - 1800 => -5364662400, - 1790 => -5680195200, - 1780 => -5995814400, - 1770 => -6311347200, - 1760 => -6626966400, - 1750 => -6942499200, - 1740 => -7258118400, - 1730 => -7573651200, - 1720 => -7889270400, - 1710 => -8204803200, - 1700 => -8520336000, - 1690 => -8835868800, - 1680 => -9151488000, - 1670 => -9467020800, - 1660 => -9782640000, - 1650 => -10098172800, - 1640 => -10413792000, - 1630 => -10729324800, - 1620 => -11044944000, - 1610 => -11360476800, - 1600 => -11676096000); - - if ($is_gmt) $origd = $d; - // The valid range of a 32bit signed timestamp is typically from - // Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT - // - - # old algorithm iterates through all years. new algorithm does it in - # 10 year blocks - - /* - # old algo - for ($a = 1970 ; --$a >= 0;) { - $lastd = $d; - - if ($leaf = _adodb_is_leap_year($a)) $d += $d366; - else $d += $d365; - - if ($d >= 0) { - $year = $a; - break; - } - } - */ - - $lastsecs = 0; - $lastyear = 1970; - foreach($YRS as $year => $secs) { - if ($d >= $secs) { - $a = $lastyear; - break; - } - $lastsecs = $secs; - $lastyear = $year; - } - - $d -= $lastsecs; - if (!isset($a)) $a = $lastyear; - - //echo ' yr=',$a,' ', $d,'.'; - - for (; --$a >= 0;) { - $lastd = $d; - - if ($leaf = _adodb_is_leap_year($a)) $d += $d366; - else $d += $d365; - - if ($d >= 0) { - $year = $a; - break; - } - } - /**/ - - $secsInYear = 86400 * ($leaf ? 366 : 365) + $lastd; - - $d = $lastd; - $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal; - for ($a = 13 ; --$a > 0;) { - $lastd = $d; - $d += $mtab[$a] * $_day_power; - if ($d >= 0) { - $month = $a; - $ndays = $mtab[$a]; - break; - } - } - - $d = $lastd; - $day = $ndays + ceil(($d+1) / ($_day_power)); - - $d += ($ndays - $day+1)* $_day_power; - $hour = floor($d/$_hour_power); - - } else { - for ($a = 1970 ;; $a++) { - $lastd = $d; - - if ($leaf = _adodb_is_leap_year($a)) $d -= $d366; - else $d -= $d365; - if ($d < 0) { - $year = $a; - break; - } - } - $secsInYear = $lastd; - $d = $lastd; - $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal; - for ($a = 1 ; $a <= 12; $a++) { - $lastd = $d; - $d -= $mtab[$a] * $_day_power; - if ($d < 0) { - $month = $a; - $ndays = $mtab[$a]; - break; - } - } - $d = $lastd; - $day = ceil(($d+1) / $_day_power); - $d = $d - ($day-1) * $_day_power; - $hour = floor($d /$_hour_power); - } - - $d -= $hour * $_hour_power; - $min = floor($d/$_min_power); - $secs = $d - $min * $_min_power; - if ($fast) { - return array( - 'seconds' => $secs, - 'minutes' => $min, - 'hours' => $hour, - 'mday' => $day, - 'mon' => $month, - 'year' => $year, - 'yday' => floor($secsInYear/$_day_power), - 'leap' => $leaf, - 'ndays' => $ndays - ); - } - - $dow = adodb_dow($year,$month,$day); - - return array( - 'seconds' => $secs, - 'minutes' => $min, - 'hours' => $hour, - 'mday' => $day, - 'wday' => $dow, - 'mon' => $month, - 'year' => $year, - 'yday' => floor($secsInYear/$_day_power), - 'weekday' => gmdate('l',$_day_power*(3+$dow)), - 'month' => gmdate('F',mktime(0,0,0,$month,2,1971)), - 0 => $origd - ); -} - -function adodb_tz_offset($gmt,$isphp5) -{ - $zhrs = abs($gmt)/3600; - $hrs = floor($zhrs); - if ($isphp5) - return sprintf('%s%02d%02d',($gmt<=0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); - else - return sprintf('%s%02d%02d',($gmt<0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); -} - -function adodb_gmdate($fmt,$d=false) -{ - return adodb_date($fmt,$d,true); -} - -// accepts unix timestamp and iso date format in $d -function adodb_date2($fmt, $d=false, $is_gmt=false) -{ - if ($d !== false) { - if (!preg_match( - "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ -]?(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", - ($d), $rr)) return adodb_date($fmt,false,$is_gmt); - - if ($rr[1] <= 100 && $rr[2]<= 1) return adodb_date($fmt,false,$is_gmt); - - // h-m-s-MM-DD-YY - if (!isset($rr[5])) $d = adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1],false,$is_gmt); - else $d = @adodb_mktime($rr[5],$rr[6],$rr[7],$rr[2],$rr[3],$rr[1],false,$is_gmt); - } - - return adodb_date($fmt,$d,$is_gmt); -} - -/** - Return formatted date based on timestamp $d -*/ -function adodb_date($fmt,$d=false,$is_gmt=false) -{ -static $daylight; -global $ADODB_DATETIME_CLASS; - - if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt); - if (!defined('ADODB_TEST_DATES')) { - if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range - if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer - return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d); - - } - } - $_day_power = 86400; - - $arr = _adodb_getdate($d,true,$is_gmt); - - if (!isset($daylight)) $daylight = function_exists('adodb_daylight_sv'); - if ($daylight) adodb_daylight_sv($arr, $is_gmt); - - $year = $arr['year']; - $month = $arr['mon']; - $day = $arr['mday']; - $hour = $arr['hours']; - $min = $arr['minutes']; - $secs = $arr['seconds']; - - $max = strlen($fmt); - $dates = ''; - - $isphp5 = PHP_VERSION >= 5; - - /* - at this point, we have the following integer vars to manipulate: - $year, $month, $day, $hour, $min, $secs - */ - for ($i=0; $i < $max; $i++) { - switch($fmt[$i]) { - case 'T': - if ($ADODB_DATETIME_CLASS) { - $dt = new DateTime(); - $dt->SetDate($year,$month,$day); - $dates .= $dt->Format('T'); - } else - $dates .= date('T'); - break; - // YEAR - case 'L': $dates .= $arr['leap'] ? '1' : '0'; break; - case 'r': // Thu, 21 Dec 2000 16:01:07 +0200 - - // 4.3.11 uses '04 Jun 2004' - // 4.3.8 uses ' 4 Jun 2004' - $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))).', ' - . ($day<10?'0'.$day:$day) . ' '.date('M',mktime(0,0,0,$month,2,1971)).' '.$year.' '; - - if ($hour < 10) $dates .= '0'.$hour; else $dates .= $hour; - - if ($min < 10) $dates .= ':0'.$min; else $dates .= ':'.$min; - - if ($secs < 10) $dates .= ':0'.$secs; else $dates .= ':'.$secs; - - $gmt = adodb_get_gmt_diff($year,$month,$day); - - $dates .= ' '.adodb_tz_offset($gmt,$isphp5); - break; - - case 'Y': $dates .= $year; break; - case 'y': $dates .= substr($year,strlen($year)-2,2); break; - // MONTH - case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break; - case 'Q': $dates .= ($month+3)>>2; break; - case 'n': $dates .= $month; break; - case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break; - case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break; - // DAY - case 't': $dates .= $arr['ndays']; break; - case 'z': $dates .= $arr['yday']; break; - case 'w': $dates .= adodb_dow($year,$month,$day); break; - case 'l': $dates .= gmdate('l',$_day_power*(3+adodb_dow($year,$month,$day))); break; - case 'D': $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))); break; - case 'j': $dates .= $day; break; - case 'd': if ($day<10) $dates .= '0'.$day; else $dates .= $day; break; - case 'S': - $d10 = $day % 10; - if ($d10 == 1) $dates .= 'st'; - else if ($d10 == 2 && $day != 12) $dates .= 'nd'; - else if ($d10 == 3) $dates .= 'rd'; - else $dates .= 'th'; - break; - - // HOUR - case 'Z': - $dates .= ($is_gmt) ? 0 : -adodb_get_gmt_diff($year,$month,$day); break; - case 'O': - $gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$month,$day); - - $dates .= adodb_tz_offset($gmt,$isphp5); - break; - - case 'H': - if ($hour < 10) $dates .= '0'.$hour; - else $dates .= $hour; - break; - case 'h': - if ($hour > 12) $hh = $hour - 12; - else { - if ($hour == 0) $hh = '12'; - else $hh = $hour; - } - - if ($hh < 10) $dates .= '0'.$hh; - else $dates .= $hh; - break; - - case 'G': - $dates .= $hour; - break; - - case 'g': - if ($hour > 12) $hh = $hour - 12; - else { - if ($hour == 0) $hh = '12'; - else $hh = $hour; - } - $dates .= $hh; - break; - // MINUTES - case 'i': if ($min < 10) $dates .= '0'.$min; else $dates .= $min; break; - // SECONDS - case 'U': $dates .= $d; break; - case 's': if ($secs < 10) $dates .= '0'.$secs; else $dates .= $secs; break; - // AM/PM - // Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM - case 'a': - if ($hour>=12) $dates .= 'pm'; - else $dates .= 'am'; - break; - case 'A': - if ($hour>=12) $dates .= 'PM'; - else $dates .= 'AM'; - break; - default: - $dates .= $fmt[$i]; break; - // ESCAPE - case "\\": - $i++; - if ($i < $max) $dates .= $fmt[$i]; - break; - } - } - return $dates; -} - -/** - Returns a timestamp given a GMT/UTC time. - Note that $is_dst is not implemented and is ignored. -*/ -function adodb_gmmktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false) -{ - return adodb_mktime($hr,$min,$sec,$mon,$day,$year,$is_dst,true); -} - -/** - Return a timestamp given a local time. Originally by jackbbs. - Note that $is_dst is not implemented and is ignored. - - Not a very fast algorithm - O(n) operation. Could be optimized to O(1). - - NOTE: returns time() when the year is > 9999 -*/ -function adodb_mktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false,$is_gmt=false) -{ - if (!defined('ADODB_TEST_DATES')) { - - if ($mon === false) { - return $is_gmt? @gmmktime($hr,$min,$sec): @mktime($hr,$min,$sec); - } - - // for windows, we don't check 1970 because with timezone differences, - // 1 Jan 1970 could generate negative timestamp, which is illegal - $usephpfns = (1971 < $year && $year < 2038 - || !defined('ADODB_NO_NEGATIVE_TS') && (1901 < $year && $year < 2038) - ); - - - if ($usephpfns && ($year + $mon/12+$day/365.25+$hr/(24*365.25) >= 2038)) $usephpfns = false; - - if ($usephpfns) { - return $is_gmt ? - @gmmktime($hr,$min,$sec,$mon,$day,$year): - @mktime($hr,$min,$sec,$mon,$day,$year); - } - } - - $gmt_different = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$mon,$day); - - /* - # disabled because some people place large values in $sec. - # however we need it for $mon because we use an array... - $hr = (int)$hr; - $min = (int)$min; - $sec = (int)$sec; - */ - $mon = (int)$mon; - $day = (int)$day; - $year = (int)$year; - - - $year = adodb_year_digit_check($year); - - if ($mon > 12) { - $y = floor(($mon-1)/ 12); - $year += $y; - $mon -= $y*12; - } else if ($mon < 1) { - $y = ceil((1-$mon) / 12); - $year -= $y; - $mon += $y*12; - } - - $_day_power = 86400; - $_hour_power = 3600; - $_min_power = 60; - - $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); - $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31); - - $_total_date = 0; - if($year > 9999) { - return time(); - } else if ($year >= 1970) { - for ($a = 1970 ; $a <= $year; $a++) { - $leaf = _adodb_is_leap_year($a); - if ($leaf == true) { - $loop_table = $_month_table_leaf; - $_add_date = 366; - } else { - $loop_table = $_month_table_normal; - $_add_date = 365; - } - if ($a < $year) { - $_total_date += $_add_date; - } else { - for($b=1;$b<$mon;$b++) { - $_total_date += $loop_table[$b]; - } - } - } - $_total_date +=$day-1; - $ret = $_total_date * $_day_power + $hr * $_hour_power + $min * $_min_power + $sec + $gmt_different; - - } else { - for ($a = 1969 ; $a >= $year; $a--) { - $leaf = _adodb_is_leap_year($a); - if ($leaf == true) { - $loop_table = $_month_table_leaf; - $_add_date = 366; - } else { - $loop_table = $_month_table_normal; - $_add_date = 365; - } - if ($a > $year) { $_total_date += $_add_date; - } else { - for($b=12;$b>$mon;$b--) { - $_total_date += $loop_table[$b]; - } - } - } - $_total_date += $loop_table[$mon] - $day; - - $_day_time = $hr * $_hour_power + $min * $_min_power + $sec; - $_day_time = $_day_power - $_day_time; - $ret = -( $_total_date * $_day_power + $_day_time - $gmt_different); - if ($ret < -12220185600) $ret += 10*86400; // if earlier than 5 Oct 1582 - gregorian correction - else if ($ret < -12219321600) $ret = -12219321600; // if in limbo, reset to 15 Oct 1582. - } - //print " dmy=$day/$mon/$year $hr:$min:$sec => " .$ret; - return $ret; -} - -function adodb_gmstrftime($fmt, $ts=false) -{ - return adodb_strftime($fmt,$ts,true); -} - -// hack - convert to adodb_date -function adodb_strftime($fmt, $ts=false,$is_gmt=false) -{ -global $ADODB_DATE_LOCALE; - - if (!defined('ADODB_TEST_DATES')) { - if ((abs($ts) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range - if (!defined('ADODB_NO_NEGATIVE_TS') || $ts >= 0) // if windows, must be +ve integer - return ($is_gmt)? @gmstrftime($fmt,$ts): @strftime($fmt,$ts); - - } - } - - if (empty($ADODB_DATE_LOCALE)) { - /* - $tstr = strtoupper(gmstrftime('%c',31366800)); // 30 Dec 1970, 1 am - $sep = substr($tstr,2,1); - $hasAM = strrpos($tstr,'M') !== false; - */ - # see http://phplens.com/lens/lensforum/msgs.php?id=14865 for reasoning, and changelog for version 0.24 - $dstr = gmstrftime('%x',31366800); // 30 Dec 1970, 1 am - $sep = substr($dstr,2,1); - $tstr = strtoupper(gmstrftime('%X',31366800)); // 30 Dec 1970, 1 am - $hasAM = strrpos($tstr,'M') !== false; - - $ADODB_DATE_LOCALE = array(); - $ADODB_DATE_LOCALE[] = strncmp($tstr,'30',2) == 0 ? 'd'.$sep.'m'.$sep.'y' : 'm'.$sep.'d'.$sep.'y'; - $ADODB_DATE_LOCALE[] = ($hasAM) ? 'h:i:s a' : 'H:i:s'; - - } - $inpct = false; - $fmtdate = ''; - for ($i=0,$max = strlen($fmt); $i < $max; $i++) { - $ch = $fmt[$i]; - if ($ch == '%') { - if ($inpct) { - $fmtdate .= '%'; - $inpct = false; - } else - $inpct = true; - } else if ($inpct) { - - $inpct = false; - switch($ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case 'E': - case 'O': - /* ignore format modifiers */ - $inpct = true; - break; - - case 'a': $fmtdate .= 'D'; break; - case 'A': $fmtdate .= 'l'; break; - case 'h': - case 'b': $fmtdate .= 'M'; break; - case 'B': $fmtdate .= 'F'; break; - case 'c': $fmtdate .= $ADODB_DATE_LOCALE[0].$ADODB_DATE_LOCALE[1]; break; - case 'C': $fmtdate .= '\C?'; break; // century - case 'd': $fmtdate .= 'd'; break; - case 'D': $fmtdate .= 'm/d/y'; break; - case 'e': $fmtdate .= 'j'; break; - case 'g': $fmtdate .= '\g?'; break; //? - case 'G': $fmtdate .= '\G?'; break; //? - case 'H': $fmtdate .= 'H'; break; - case 'I': $fmtdate .= 'h'; break; - case 'j': $fmtdate .= '?z'; $parsej = true; break; // wrong as j=1-based, z=0-basd - case 'm': $fmtdate .= 'm'; break; - case 'M': $fmtdate .= 'i'; break; - case 'n': $fmtdate .= "\n"; break; - case 'p': $fmtdate .= 'a'; break; - case 'r': $fmtdate .= 'h:i:s a'; break; - case 'R': $fmtdate .= 'H:i:s'; break; - case 'S': $fmtdate .= 's'; break; - case 't': $fmtdate .= "\t"; break; - case 'T': $fmtdate .= 'H:i:s'; break; - case 'u': $fmtdate .= '?u'; $parseu = true; break; // wrong strftime=1-based, date=0-based - case 'U': $fmtdate .= '?U'; $parseU = true; break;// wrong strftime=1-based, date=0-based - case 'x': $fmtdate .= $ADODB_DATE_LOCALE[0]; break; - case 'X': $fmtdate .= $ADODB_DATE_LOCALE[1]; break; - case 'w': $fmtdate .= '?w'; $parseu = true; break; // wrong strftime=1-based, date=0-based - case 'W': $fmtdate .= '?W'; $parseU = true; break;// wrong strftime=1-based, date=0-based - case 'y': $fmtdate .= 'y'; break; - case 'Y': $fmtdate .= 'Y'; break; - case 'Z': $fmtdate .= 'T'; break; - } - } else if (('A' <= ($ch) && ($ch) <= 'Z' ) || ('a' <= ($ch) && ($ch) <= 'z' )) - $fmtdate .= "\\".$ch; - else - $fmtdate .= $ch; - } - //echo "fmt=",$fmtdate,"
    "; - if ($ts === false) $ts = time(); - $ret = adodb_date($fmtdate, $ts, $is_gmt); - return $ret; -} - diff --git a/html/forums/inc/functions_upload.php b/html/forums/inc/functions_upload.php deleted file mode 100644 index 2da32b6..0000000 --- a/html/forums/inc/functions_upload.php +++ /dev/null @@ -1,801 +0,0 @@ -escape_string($posthash); - if($posthash != "") - { - $query = $db->simple_select("attachments", "aid, attachname, thumbnail, visible", "aid='{$aid}' AND posthash='{$posthash}'"); - $attachment = $db->fetch_array($query); - } - else - { - $query = $db->simple_select("attachments", "aid, attachname, thumbnail, visible", "aid='{$aid}' AND pid='{$pid}'"); - $attachment = $db->fetch_array($query); - } - - $plugins->run_hooks("remove_attachment_do_delete", $attachment); - - $db->delete_query("attachments", "aid='{$attachment['aid']}'"); - - if(defined('IN_ADMINCP')) - { - $uploadpath = '../'.$mybb->settings['uploadspath']; - } - else - { - $uploadpath = $mybb->settings['uploadspath']; - } - - // Check if this attachment is referenced in any other posts. If it isn't, then we are safe to delete the actual file. - $query = $db->simple_select("attachments", "COUNT(aid) as numreferences", "attachname='".$db->escape_string($attachment['attachname'])."'"); - if($db->fetch_field($query, "numreferences") == 0) - { - delete_uploaded_file($uploadpath."/".$attachment['attachname']); - if($attachment['thumbnail']) - { - delete_uploaded_file($uploadpath."/".$attachment['thumbnail']); - } - - $date_directory = explode('/', $attachment['attachname']); - if(@is_dir($uploadpath."/".$date_directory[0])) - { - delete_upload_directory($uploadpath."/".$date_directory[0]); - } - } - - if($attachment['visible'] == 1 && $pid) - { - $post = get_post($pid); - update_thread_counters($post['tid'], array("attachmentcount" => "-1")); - } -} - -/** - * Remove all of the attachments from a specific post - * - * @param int $pid The post ID - * @param string $posthash The posthash if available - */ -function remove_attachments($pid, $posthash="") -{ - global $db, $mybb, $plugins; - - if($pid) - { - $post = get_post($pid); - } - $posthash = $db->escape_string($posthash); - if($posthash != "" && !$pid) - { - $query = $db->simple_select("attachments", "*", "posthash='$posthash'"); - } - else - { - $query = $db->simple_select("attachments", "*", "pid='$pid'"); - } - - if(defined('IN_ADMINCP')) - { - $uploadpath = '../'.$mybb->settings['uploadspath']; - } - else - { - $uploadpath = $mybb->settings['uploadspath']; - } - - $num_attachments = 0; - while($attachment = $db->fetch_array($query)) - { - if($attachment['visible'] == 1) - { - $num_attachments++; - } - - $plugins->run_hooks("remove_attachments_do_delete", $attachment); - - $db->delete_query("attachments", "aid='".$attachment['aid']."'"); - - // Check if this attachment is referenced in any other posts. If it isn't, then we are safe to delete the actual file. - $query2 = $db->simple_select("attachments", "COUNT(aid) as numreferences", "attachname='".$db->escape_string($attachment['attachname'])."'"); - if($db->fetch_field($query2, "numreferences") == 0) - { - delete_uploaded_file($uploadpath."/".$attachment['attachname']); - if($attachment['thumbnail']) - { - delete_uploaded_file($uploadpath."/".$attachment['thumbnail']); - } - - $date_directory = explode('/', $attachment['attachname']); - if(@is_dir($uploadpath."/".$date_directory[0])) - { - delete_upload_directory($uploadpath."/".$date_directory[0]); - } - } - } - - if($post['tid']) - { - update_thread_counters($post['tid'], array("attachmentcount" => "-{$num_attachments}")); - } -} - -/** - * Remove any matching avatars for a specific user ID - * - * @param int $uid The user ID - * @param string $exclude A file name to be excluded from the removal - */ -function remove_avatars($uid, $exclude="") -{ - global $mybb, $plugins; - - if(defined('IN_ADMINCP')) - { - $avatarpath = '../'.$mybb->settings['avataruploadpath']; - } - else - { - $avatarpath = $mybb->settings['avataruploadpath']; - } - - $dir = opendir($avatarpath); - if($dir) - { - while($file = @readdir($dir)) - { - $plugins->run_hooks("remove_avatars_do_delete", $file); - - if(preg_match("#avatar_".$uid."\.#", $file) && is_file($avatarpath."/".$file) && $file != $exclude) - { - delete_uploaded_file($avatarpath."/".$file); - } - } - - @closedir($dir); - } -} - -/** - * Upload a new avatar in to the file system - * - * @param array $avatar Incoming FILE array, if we have one - otherwise takes $_FILES['avatarupload'] - * @param int $uid User ID this avatar is being uploaded for, if not the current user - * @return array Array of errors if any, otherwise filename of successful. - */ -function upload_avatar($avatar=array(), $uid=0) -{ - global $db, $mybb, $lang, $plugins, $cache; - - $ret = array(); - - if(!$uid) - { - $uid = $mybb->user['uid']; - } - - if(!$avatar['name'] || !$avatar['tmp_name']) - { - $avatar = $_FILES['avatarupload']; - } - - if(!is_uploaded_file($avatar['tmp_name'])) - { - $ret['error'] = $lang->error_uploadfailed; - return $ret; - } - - // Check we have a valid extension - $ext = get_extension(my_strtolower($avatar['name'])); - if(!preg_match("#^(gif|jpg|jpeg|jpe|bmp|png)$#i", $ext)) - { - $ret['error'] = $lang->error_avatartype; - return $ret; - } - - if(defined('IN_ADMINCP')) - { - $avatarpath = '../'.$mybb->settings['avataruploadpath']; - $lang->load("messages", true); - } - else - { - $avatarpath = $mybb->settings['avataruploadpath']; - } - - $filename = "avatar_".$uid.".".$ext; - $file = upload_file($avatar, $avatarpath, $filename); - if($file['error']) - { - delete_uploaded_file($avatarpath."/".$filename); - $ret['error'] = $lang->error_uploadfailed; - return $ret; - } - - // Lets just double check that it exists - if(!file_exists($avatarpath."/".$filename)) - { - $ret['error'] = $lang->error_uploadfailed; - delete_uploaded_file($avatarpath."/".$filename); - return $ret; - } - - // Check if this is a valid image or not - $img_dimensions = @getimagesize($avatarpath."/".$filename); - if(!is_array($img_dimensions)) - { - delete_uploaded_file($avatarpath."/".$filename); - $ret['error'] = $lang->error_uploadfailed; - return $ret; - } - - // Check avatar dimensions - if($mybb->settings['maxavatardims'] != '') - { - list($maxwidth, $maxheight) = @explode("x", $mybb->settings['maxavatardims']); - if(($maxwidth && $img_dimensions[0] > $maxwidth) || ($maxheight && $img_dimensions[1] > $maxheight)) - { - // Automatic resizing enabled? - if($mybb->settings['avatarresizing'] == "auto" || ($mybb->settings['avatarresizing'] == "user" && $mybb->input['auto_resize'] == 1)) - { - require_once MYBB_ROOT."inc/functions_image.php"; - $thumbnail = generate_thumbnail($avatarpath."/".$filename, $avatarpath, $filename, $maxheight, $maxwidth); - if(!$thumbnail['filename']) - { - $ret['error'] = $lang->sprintf($lang->error_avatartoobig, $maxwidth, $maxheight); - $ret['error'] .= "

    ".$lang->error_avatarresizefailed; - delete_uploaded_file($avatarpath."/".$filename); - return $ret; - } - else - { - // Copy scaled image to CDN - copy_file_to_cdn($avatarpath . '/' . $thumbnail['filename']); - // Reset filesize - $avatar['size'] = filesize($avatarpath."/".$filename); - // Reset dimensions - $img_dimensions = @getimagesize($avatarpath."/".$filename); - } - } - else - { - $ret['error'] = $lang->sprintf($lang->error_avatartoobig, $maxwidth, $maxheight); - if($mybb->settings['avatarresizing'] == "user") - { - $ret['error'] .= "

    ".$lang->error_avataruserresize; - } - delete_uploaded_file($avatarpath."/".$filename); - return $ret; - } - } - } - - // Check a list of known MIME types to establish what kind of avatar we're uploading - $attachtypes = (array)$cache->read('attachtypes'); - - $allowed_mime_types = array(); - foreach($attachtypes as $attachtype) - { - if(defined('IN_ADMINCP') || is_member($attachtype['groups']) && $attachtype['avatarfile']) - { - $allowed_mime_types[$attachtype['mimetype']] = $attachtype['maxsize']; - } - } - - $avatar['type'] = my_strtolower($avatar['type']); - - switch($avatar['type']) - { - case "image/gif": - $img_type = 1; - break; - case "image/jpeg": - case "image/x-jpg": - case "image/x-jpeg": - case "image/pjpeg": - case "image/jpg": - $img_type = 2; - break; - case "image/png": - case "image/x-png": - $img_type = 3; - break; - case "image/bmp": - case "image/x-bmp": - case "image/x-windows-bmp": - $img_type = 6; - break; - default: - $img_type = 0; - } - - // Check if the uploaded file type matches the correct image type (returned by getimagesize) - if(empty($allowed_mime_types[$avatar['type']]) || $img_dimensions[2] != $img_type || $img_type == 0) - { - $ret['error'] = $lang->error_uploadfailed; - delete_uploaded_file($avatarpath."/".$filename); - return $ret; - } - - // Next check the file size - if(($avatar['size'] > ($mybb->settings['avatarsize']*1024) && $mybb->settings['avatarsize'] > 0) || $avatar['size'] > $allowed_mime_types[$avatar['type']] && !($mybb->settings['avatarsize'] > 0)) - { - delete_uploaded_file($avatarpath."/".$filename); - $ret['error'] = $lang->error_uploadsize; - return $ret; - } - - // Everything is okay so lets delete old avatars for this user - remove_avatars($uid, $filename); - - $ret = array( - "avatar" => $mybb->settings['avataruploadpath']."/".$filename, - "width" => (int)$img_dimensions[0], - "height" => (int)$img_dimensions[1] - ); - $ret = $plugins->run_hooks("upload_avatar_end", $ret); - return $ret; -} - -/** - * Upload an attachment in to the file system - * - * @param array $attachment Attachment data (as fed by PHPs $_FILE) - * @param boolean $update_attachment Whether or not we are updating a current attachment or inserting a new one - * @return array Array of attachment data if successful, otherwise array of error data - */ -function upload_attachment($attachment, $update_attachment=false) -{ - global $mybb, $db, $theme, $templates, $posthash, $pid, $tid, $forum, $mybb, $lang, $plugins, $cache; - - $posthash = $db->escape_string($mybb->get_input('posthash')); - $pid = (int)$pid; - - if(isset($attachment['error']) && $attachment['error'] != 0) - { - $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_detail; - switch($attachment['error']) - { - case 1: // UPLOAD_ERR_INI_SIZE - $ret['error'] .= $lang->error_uploadfailed_php1; - break; - case 2: // UPLOAD_ERR_FORM_SIZE - $ret['error'] .= $lang->error_uploadfailed_php2; - break; - case 3: // UPLOAD_ERR_PARTIAL - $ret['error'] .= $lang->error_uploadfailed_php3; - break; - case 4: // UPLOAD_ERR_NO_FILE - $ret['error'] .= $lang->error_uploadfailed_php4; - break; - case 6: // UPLOAD_ERR_NO_TMP_DIR - $ret['error'] .= $lang->error_uploadfailed_php6; - break; - case 7: // UPLOAD_ERR_CANT_WRITE - $ret['error'] .= $lang->error_uploadfailed_php7; - break; - default: - $ret['error'] .= $lang->sprintf($lang->error_uploadfailed_phpx, $attachment['error']); - break; - } - return $ret; - } - - if(!is_uploaded_file($attachment['tmp_name']) || empty($attachment['tmp_name'])) - { - $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_php4; - return $ret; - } - - $attachtypes = (array)$cache->read('attachtypes'); - $attachment = $plugins->run_hooks("upload_attachment_start", $attachment); - - $allowed_mime_types = array(); - foreach($attachtypes as $ext => $attachtype) - { - if(!is_member($attachtype['groups']) || ($attachtype['forums'] != -1 && strpos(','.$attachtype['forums'].',', ','.$forum['fid'].',') === false)) - { - unset($attachtypes[$ext]); - } - } - - $ext = get_extension($attachment['name']); - // Check if we have a valid extension - if(!isset($attachtypes[$ext])) - { - $ret['error'] = $lang->error_attachtype; - return $ret; - } - else - { - $attachtype = $attachtypes[$ext]; - } - - // Check the size - if($attachment['size'] > $attachtype['maxsize']*1024 && $attachtype['maxsize'] != "") - { - $ret['error'] = $lang->sprintf($lang->error_attachsize, $attachtype['maxsize']); - return $ret; - } - - // Double check attachment space usage - if($mybb->usergroup['attachquota'] > 0) - { - $query = $db->simple_select("attachments", "SUM(filesize) AS ausage", "uid='".$mybb->user['uid']."'"); - $usage = $db->fetch_array($query); - $usage = $usage['ausage']+$attachment['size']; - if($usage > ($mybb->usergroup['attachquota']*1024)) - { - $friendlyquota = get_friendly_size($mybb->usergroup['attachquota']*1024); - $ret['error'] = $lang->sprintf($lang->error_reachedattachquota, $friendlyquota); - return $ret; - } - } - - // Gather forum permissions - $forumpermissions = forum_permissions($forum['fid']); - - // Check if an attachment with this name is already in the post - if($pid != 0) - { - $uploaded_query = "pid='{$pid}'"; - } - else - { - $uploaded_query = "posthash='{$posthash}'"; - } - $query = $db->simple_select("attachments", "*", "filename='".$db->escape_string($attachment['name'])."' AND ".$uploaded_query); - $prevattach = $db->fetch_array($query); - if($prevattach['aid'] && $update_attachment == false) - { - if(!$mybb->usergroup['caneditattachments'] && !$forumpermissions['caneditattachments']) - { - $ret['error'] = $lang->error_alreadyuploaded_perm; - return $ret; - } - - $ret['error'] = $lang->error_alreadyuploaded; - return $ret; - } - - // Check to see how many attachments exist for this post already - if($mybb->settings['maxattachments'] > 0 && $update_attachment == false) - { - $query = $db->simple_select("attachments", "COUNT(aid) AS numattachs", $uploaded_query); - $attachcount = $db->fetch_field($query, "numattachs"); - if($attachcount >= $mybb->settings['maxattachments']) - { - $ret['error'] = $lang->sprintf($lang->error_maxattachpost, $mybb->settings['maxattachments']); - return $ret; - } - } - - $month_dir = ''; - if($mybb->safemode == false) - { - // Check if the attachment directory (YYYYMM) exists, if not, create it - $month_dir = gmdate("Ym"); - if(!@is_dir($mybb->settings['uploadspath']."/".$month_dir)) - { - @mkdir($mybb->settings['uploadspath']."/".$month_dir); - // Still doesn't exist - oh well, throw it in the main directory - if(!@is_dir($mybb->settings['uploadspath']."/".$month_dir)) - { - $month_dir = ''; - } - else - { - $index = @fopen($mybb->settings['uploadspath']."/".$month_dir."/index.html", 'w'); - @fwrite($index, "\n\n\n\n\n \n\n"); - @fclose($index); - } - } - } - - // All seems to be good, lets move the attachment! - $filename = "post_".$mybb->user['uid']."_".TIME_NOW."_".md5(random_str()).".attach"; - - $file = upload_file($attachment, $mybb->settings['uploadspath']."/".$month_dir, $filename); - - // Failed to create the attachment in the monthly directory, just throw it in the main directory - if(!empty($file['error']) && $month_dir) - { - $file = upload_file($attachment, $mybb->settings['uploadspath'].'/', $filename); - } - elseif($month_dir) - { - $filename = $month_dir."/".$filename; - } - - if(!empty($file['error'])) - { - $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_detail; - switch($file['error']) - { - case 1: - $ret['error'] .= $lang->error_uploadfailed_nothingtomove; - break; - case 2: - $ret['error'] .= $lang->error_uploadfailed_movefailed; - break; - } - return $ret; - } - - // Lets just double check that it exists - if(!file_exists($mybb->settings['uploadspath']."/".$filename)) - { - $ret['error'] = $lang->error_uploadfailed.$lang->error_uploadfailed_detail.$lang->error_uploadfailed_lost; - return $ret; - } - - // Generate the array for the insert_query - $attacharray = array( - "pid" => $pid, - "posthash" => $posthash, - "uid" => $mybb->user['uid'], - "filename" => $db->escape_string($file['original_filename']), - "filetype" => $db->escape_string($file['type']), - "filesize" => (int)$file['size'], - "attachname" => $filename, - "downloads" => 0, - "dateuploaded" => TIME_NOW - ); - - // If we're uploading an image, check the MIME type compared to the image type and attempt to generate a thumbnail - if($ext == "gif" || $ext == "png" || $ext == "jpg" || $ext == "jpeg" || $ext == "jpe") - { - // Check a list of known MIME types to establish what kind of image we're uploading - switch(my_strtolower($file['type'])) - { - case "image/gif": - $img_type = 1; - break; - case "image/jpeg": - case "image/x-jpg": - case "image/x-jpeg": - case "image/pjpeg": - case "image/jpg": - $img_type = 2; - break; - case "image/png": - case "image/x-png": - $img_type = 3; - break; - default: - $img_type = 0; - } - - $supported_mimes = array(); - foreach($attachtypes as $attachtype) - { - if(!empty($attachtype['mimetype'])) - { - $supported_mimes[] = $attachtype['mimetype']; - } - } - - // Check if the uploaded file type matches the correct image type (returned by getimagesize) - $img_dimensions = @getimagesize($mybb->settings['uploadspath']."/".$filename); - - $mime = ""; - $file_path = $mybb->settings['uploadspath']."/".$filename; - if(function_exists("finfo_open")) - { - $file_info = finfo_open(FILEINFO_MIME); - list($mime, ) = explode(';', finfo_file($file_info, MYBB_ROOT.$file_path), 1); - finfo_close($file_info); - } - else if(function_exists("mime_content_type")) - { - $mime = mime_content_type(MYBB_ROOT.$file_path); - } - - if(!is_array($img_dimensions) || ($img_dimensions[2] != $img_type && !in_array($mime, $supported_mimes))) - { - delete_uploaded_file($mybb->settings['uploadspath']."/".$filename); - $ret['error'] = $lang->error_uploadfailed; - return $ret; - } - require_once MYBB_ROOT."inc/functions_image.php"; - $thumbname = str_replace(".attach", "_thumb.$ext", $filename); - - $attacharray = $plugins->run_hooks("upload_attachment_thumb_start", $attacharray); - - $thumbnail = generate_thumbnail($mybb->settings['uploadspath']."/".$filename, $mybb->settings['uploadspath'], $thumbname, $mybb->settings['attachthumbh'], $mybb->settings['attachthumbw']); - - if($thumbnail['filename']) - { - $attacharray['thumbnail'] = $thumbnail['filename']; - } - elseif($thumbnail['code'] == 4) - { - $attacharray['thumbnail'] = "SMALL"; - } - } - if($forumpermissions['modattachments'] == 1 && !is_moderator($forum['fid'], "canapproveunapproveattachs")) - { - $attacharray['visible'] = 0; - } - else - { - $attacharray['visible'] = 1; - } - - $attacharray = $plugins->run_hooks("upload_attachment_do_insert", $attacharray); - - if($prevattach['aid'] && $update_attachment == true) - { - unset($attacharray['downloads']); // Keep our download count if we're updating an attachment - $db->update_query("attachments", $attacharray, "aid='".$db->escape_string($prevattach['aid'])."'"); - - // Remove old attachment file - // Check if this attachment is referenced in any other posts. If it isn't, then we are safe to delete the actual file. - $query = $db->simple_select("attachments", "COUNT(aid) as numreferences", "attachname='".$db->escape_string($prevattach['attachname'])."'"); - if($db->fetch_field($query, "numreferences") == 0) - { - delete_uploaded_file($mybb->settings['uploadspath']."/".$prevattach['attachname']); - if($prevattach['thumbnail']) - { - delete_uploaded_file($mybb->settings['uploadspath']."/".$prevattach['thumbnail']); - } - - $date_directory = explode('/', $prevattach['attachname']); - if(@is_dir($mybb->settings['uploadspath']."/".$date_directory[0])) - { - delete_upload_directory($mybb->settings['uploadspath']."/".$date_directory[0]); - } - } - - $aid = $prevattach['aid']; - } - else - { - $aid = $db->insert_query("attachments", $attacharray); - if($pid) - { - update_thread_counters($tid, array("attachmentcount" => "+1")); - } - } - $ret['aid'] = $aid; - return $ret; -} - -/** - * Delete an uploaded file both from the relative path and the CDN path if a CDN is in use. - * - * @param string $path The relative path to the uploaded file. - * - * @return bool Whether the file was deleted successfully. - */ -function delete_uploaded_file($path = '') -{ - global $mybb, $plugins; - - $deleted = false; - - $deleted = @unlink($path); - - $cdn_base_path = rtrim($mybb->settings['cdnpath'], '/'); - $path = ltrim($path, '/'); - $cdn_path = realpath($cdn_base_path . '/' . $path); - - if($mybb->settings['usecdn'] && !empty($cdn_base_path)) - { - $deleted = $deleted && @unlink($cdn_path); - } - - $hook_params = array( - 'path' => &$path, - 'deleted' => &$deleted, - ); - - $plugins->run_hooks('delete_uploaded_file', $hook_params); - - return $deleted; -} - -/** - * Delete an upload directory on both the local filesystem and the CDN filesystem. - * - * @param string $path The directory to delete. - * - * @return bool Whether the directory was deleted. - */ -function delete_upload_directory($path = '') -{ - global $mybb, $plugins; - - $deleted = false; - - $deleted = @rmdir($path); - - $cdn_base_path = rtrim($mybb->settings['cdnpath'], '/'); - $path = ltrim($path, '/'); - $cdn_path = rtrim(realpath($cdn_base_path . '/' . $path), '/'); - - if($mybb->settings['usecdn'] && !empty($cdn_base_path)) - { - $deleted = $deleted && @rmdir($cdn_path); - } - - $hook_params = array( - 'path' => &$path, - 'deleted' => &$deleted, - ); - - $plugins->run_hooks('delete_upload_directory', $hook_params); - - return $deleted; -} - -/** - * Actually move a file to the uploads directory - * - * @param array $file The PHP $_FILE array for the file - * @param string $path The path to save the file in - * @param string $filename The filename for the file (if blank, current is used) - * @return array The uploaded file - */ -function upload_file($file, $path, $filename="") -{ - global $plugins, $mybb; - - $upload = array(); - - if(empty($file['name']) || $file['name'] == "none" || $file['size'] < 1) - { - $upload['error'] = 1; - return $upload; - } - - if(!$filename) - { - $filename = $file['name']; - } - - $upload['original_filename'] = preg_replace("#/$#", "", $file['name']); // Make the filename safe - $filename = preg_replace("#/$#", "", $filename); // Make the filename safe - $moved = @move_uploaded_file($file['tmp_name'], $path."/".$filename); - - $cdn_path = ''; - - $moved_cdn = copy_file_to_cdn($path."/".$filename, $cdn_path); - - if(!$moved) - { - $upload['error'] = 2; - return $upload; - } - @my_chmod($path."/".$filename, '0644'); - $upload['filename'] = $filename; - $upload['path'] = $path; - $upload['type'] = $file['type']; - $upload['size'] = $file['size']; - $upload = $plugins->run_hooks("upload_file_end", $upload); - - if($moved_cdn) - { - $upload['cdn_path'] = $cdn_path; - } - - return $upload; -} diff --git a/html/forums/inc/functions_user.php b/html/forums/inc/functions_user.php deleted file mode 100644 index 7fcddd4..0000000 --- a/html/forums/inc/functions_user.php +++ /dev/null @@ -1,848 +0,0 @@ -simple_select("users", "COUNT(*) as user", "uid='".(int)$uid."'", array('limit' => 1)); - if($db->fetch_field($query, 'user') == 1) - { - return true; - } - else - { - return false; - } -} - -/** - * Checks if $username already exists in the database. - * - * @param string $username The username for check for. - * @return boolean True when exists, false when not. - */ -function username_exists($username) -{ - $options = array( - 'username_method' => 2 - ); - - return (bool)get_user_by_username($username, $options); -} - -/** - * Checks a password with a supplied username. - * - * @param string $username The username of the user. - * @param string $password The plain-text password. - * @return boolean|array False when no match, array with user info when match. - */ -function validate_password_from_username($username, $password) -{ - global $mybb; - - $options = array( - 'fields' => '*', - 'username_method' => $mybb->settings['username_method'], - ); - - $user = get_user_by_username($username, $options); - - if(!$user['uid']) - { - return false; - } - - return validate_password_from_uid($user['uid'], $password, $user); -} - -/** - * Checks a password with a supplied uid. - * - * @param int $uid The user id. - * @param string $password The plain-text password. - * @param array $user An optional user data array. - * @return boolean|array False when not valid, user data array when valid. - */ -function validate_password_from_uid($uid, $password, $user = array()) -{ - global $db, $mybb; - if(isset($mybb->user['uid']) && $mybb->user['uid'] == $uid) - { - $user = $mybb->user; - } - if(!$user['password']) - { - $user = get_user($uid); - } - if(!$user['salt']) - { - // Generate a salt for this user and assume the password stored in db is a plain md5 password - $password_fields = create_password($user['password'], false, $user); - $db->update_query("users", $password_fields, "uid='".$user['uid']."'"); - } - - if(!$user['loginkey']) - { - $user['loginkey'] = generate_loginkey(); - $sql_array = array( - "loginkey" => $user['loginkey'] - ); - $db->update_query("users", $sql_array, "uid = ".$user['uid']); - } - if(verify_user_password($user, $password)) - { - return $user; - } - else - { - return false; - } -} - -/** - * Updates a user's password. - * - * @param int $uid The user's id. - * @param string $password The md5()'ed password. - * @param string $salt (Optional) The salt of the user. - * @return array The new password. - * @deprecated deprecated since version 1.8.6 Please use other alternatives. - */ -function update_password($uid, $password, $salt="") -{ - global $db, $plugins; - - $newpassword = array(); - - // If no salt was specified, check in database first, if still doesn't exist, create one - if(!$salt) - { - $query = $db->simple_select("users", "salt", "uid='$uid'"); - $user = $db->fetch_array($query); - if($user['salt']) - { - $salt = $user['salt']; - } - else - { - $salt = generate_salt(); - } - $newpassword['salt'] = $salt; - } - - // Create new password based on salt - $saltedpw = salt_password($password, $salt); - - // Generate new login key - $loginkey = generate_loginkey(); - - // Update password and login key in database - $newpassword['password'] = $saltedpw; - $newpassword['loginkey'] = $loginkey; - $db->update_query("users", $newpassword, "uid='$uid'"); - - $plugins->run_hooks("password_changed"); - - return $newpassword; -} - -/** - * Salts a password based on a supplied salt. - * - * @param string $password The md5()'ed password. - * @param string $salt The salt. - * @return string The password hash. - * @deprecated deprecated since version 1.8.9 Please use other alternatives. - */ -function salt_password($password, $salt) -{ - return md5(md5($salt).$password); -} - -/** - * Salts a password based on a supplied salt. - * - * @param string $password The input password. - * @param string $salt (Optional) The salt used by the MyBB algorithm. - * @param string $user (Optional) An array containing password-related data. - * @return array Password-related fields. - */ -function create_password($password, $salt = false, $user = false) -{ - global $plugins; - - $fields = null; - - $parameters = compact('password', 'salt', 'user', 'fields'); - - if(!defined('IN_INSTALL') && !defined('IN_UPGRADE')) - { - $plugins->run_hooks('create_password', $parameters); - } - - if(!is_null($parameters['fields'])) - { - $fields = $parameters['fields']; - } - else - { - if(!$salt) - { - $salt = generate_salt(); - } - - $hash = md5(md5($salt).md5($password)); - - $fields = array( - 'salt' => $salt, - 'password' => $hash, - ); - } - - return $fields; -} - -/** - * Compares user's password data against provided input. - * - * @param array $user An array containing password-related data. - * @param string $password The plain-text input password. - * @return bool Result of the comparison. - */ -function verify_user_password($user, $password) -{ - global $plugins; - - $result = null; - - $parameters = compact('user', 'password', 'result'); - - if(!defined('IN_INSTALL') && !defined('IN_UPGRADE')) - { - $plugins->run_hooks('verify_user_password', $parameters); - } - - if(!is_null($parameters['result'])) - { - return $parameters['result']; - } - else - { - $password_fields = create_password($password, $user['salt'], $user); - - return my_hash_equals($user['password'], $password_fields['password']); - } -} - -/** - * Performs a timing attack safe string comparison. - * - * @param string $known_string The first string to be compared. - * @param string $user_string The second, user-supplied string to be compared. - * @return bool Result of the comparison. - */ -function my_hash_equals($known_string, $user_string) -{ - if(version_compare(PHP_VERSION, '5.6.0', '>=')) - { - return hash_equals($known_string, $user_string); - } - else - { - $known_string_length = my_strlen($known_string); - $user_string_length = my_strlen($user_string); - - if($user_string_length != $known_string_length) - { - return false; - } - - $result = 0; - - for($i = 0; $i < $known_string_length; $i++) - { - $result |= ord($known_string[$i]) ^ ord($user_string[$i]); - } - - return $result === 0; - } -} - -/** - * Generates a random salt - * - * @return string The salt. - */ -function generate_salt() -{ - return random_str(8); -} - -/** - * Generates a 50 character random login key. - * - * @return string The login key. - */ -function generate_loginkey() -{ - return random_str(50); -} - -/** - * Updates a user's salt in the database (does not update a password). - * - * @param int $uid The uid of the user to update. - * @return string The new salt. - */ -function update_salt($uid) -{ - global $db; - - $salt = generate_salt(); - $sql_array = array( - "salt" => $salt - ); - $db->update_query("users", $sql_array, "uid='{$uid}'"); - - return $salt; -} - -/** - * Generates a new login key for a user. - * - * @param int $uid The uid of the user to update. - * @return string The new login key. - */ -function update_loginkey($uid) -{ - global $db; - - $loginkey = generate_loginkey(); - $sql_array = array( - "loginkey" => $loginkey - ); - $db->update_query("users", $sql_array, "uid='{$uid}'"); - - return $loginkey; - -} - -/** - * Adds a thread to a user's thread subscription list. - * If no uid is supplied, the currently logged in user's id will be used. - * - * @param int $tid The tid of the thread to add to the list. - * @param int $notification (Optional) The type of notification to receive for replies (0=none, 1=email, 2=pm) - * @param int $uid (Optional) The uid of the user who's list to update. - * @return boolean True when success, false when otherwise. - */ -function add_subscribed_thread($tid, $notification=1, $uid=0) -{ - global $mybb, $db; - - if(!$uid) - { - $uid = $mybb->user['uid']; - } - - if(!$uid) - { - return false; - } - - $query = $db->simple_select("threadsubscriptions", "*", "tid='".(int)$tid."' AND uid='".(int)$uid."'"); - $subscription = $db->fetch_array($query); - if(!$subscription['tid']) - { - $insert_array = array( - 'uid' => (int)$uid, - 'tid' => (int)$tid, - 'notification' => (int)$notification, - 'dateline' => TIME_NOW - ); - $db->insert_query("threadsubscriptions", $insert_array); - } - else - { - // Subscription exists - simply update notification - $update_array = array( - "notification" => (int)$notification - ); - $db->update_query("threadsubscriptions", $update_array, "uid='{$uid}' AND tid='{$tid}'"); - } - return true; -} - -/** - * Remove a thread from a user's thread subscription list. - * If no uid is supplied, the currently logged in user's id will be used. - * - * @param int $tid The tid of the thread to remove from the list. - * @param int $uid (Optional) The uid of the user who's list to update. - * @return boolean True when success, false when otherwise. - */ -function remove_subscribed_thread($tid, $uid=0) -{ - global $mybb, $db; - - if(!$uid) - { - $uid = $mybb->user['uid']; - } - - if(!$uid) - { - return false; - } - $db->delete_query("threadsubscriptions", "tid='".$tid."' AND uid='{$uid}'"); - - return true; -} - -/** - * Adds a forum to a user's forum subscription list. - * If no uid is supplied, the currently logged in user's id will be used. - * - * @param int $fid The fid of the forum to add to the list. - * @param int $uid (Optional) The uid of the user who's list to update. - * @return boolean True when success, false when otherwise. - */ -function add_subscribed_forum($fid, $uid=0) -{ - global $mybb, $db; - - if(!$uid) - { - $uid = $mybb->user['uid']; - } - - if(!$uid) - { - return false; - } - - $fid = (int)$fid; - $uid = (int)$uid; - - $query = $db->simple_select("forumsubscriptions", "*", "fid='".$fid."' AND uid='{$uid}'", array('limit' => 1)); - $fsubscription = $db->fetch_array($query); - if(!$fsubscription['fid']) - { - $insert_array = array( - 'fid' => $fid, - 'uid' => $uid - ); - $db->insert_query("forumsubscriptions", $insert_array); - } - - return true; -} - -/** - * Removes a forum from a user's forum subscription list. - * If no uid is supplied, the currently logged in user's id will be used. - * - * @param int $fid The fid of the forum to remove from the list. - * @param int $uid (Optional) The uid of the user who's list to update. - * @return boolean True when success, false when otherwise. - */ -function remove_subscribed_forum($fid, $uid=0) -{ - global $mybb, $db; - - if(!$uid) - { - $uid = $mybb->user['uid']; - } - - if(!$uid) - { - return false; - } - $db->delete_query("forumsubscriptions", "fid='".$fid."' AND uid='{$uid}'"); - - return true; -} - -/** - * Constructs the usercp navigation menu. - * - */ -function usercp_menu() -{ - global $mybb, $templates, $theme, $plugins, $lang, $usercpnav, $usercpmenu; - - $lang->load("usercpnav"); - - // Add the default items as plugins with separated priorities of 10 - if($mybb->settings['enablepms'] != 0 && $mybb->usergroup['canusepms'] == 1) - { - $plugins->add_hook("usercp_menu", "usercp_menu_messenger", 10); - } - - if($mybb->usergroup['canusercp'] == 1) - { - $plugins->add_hook("usercp_menu", "usercp_menu_profile", 20); - $plugins->add_hook("usercp_menu", "usercp_menu_misc", 30); - } - - // Run the plugin hooks - $plugins->run_hooks("usercp_menu"); - global $usercpmenu; - - if($mybb->usergroup['canusercp'] == 1) - { - eval("\$ucp_nav_home = \"".$templates->get("usercp_nav_home")."\";"); - } - - eval("\$usercpnav = \"".$templates->get("usercp_nav")."\";"); - - $plugins->run_hooks("usercp_menu_built"); -} - -/** - * Constructs the usercp messenger menu. - * - */ -function usercp_menu_messenger() -{ - global $db, $mybb, $templates, $theme, $usercpmenu, $lang, $collapsed, $collapsedimg; - - $usercp_nav_messenger = $templates->get("usercp_nav_messenger"); - // Hide tracking link if no permission - $tracking = ''; - if($mybb->usergroup['cantrackpms']) - { - $tracking = $templates->get("usercp_nav_messenger_tracking"); - } - eval("\$ucp_nav_tracking = \"". $tracking ."\";"); - - // Hide compose link if no permission - $ucp_nav_compose = ''; - if($mybb->usergroup['cansendpms'] == 1) - { - eval("\$ucp_nav_compose = \"".$templates->get("usercp_nav_messenger_compose")."\";"); - } - - $folderlinks = $folder_id = $folder_name = ''; - $foldersexploded = explode("$%%$", $mybb->user['pmfolders']); - foreach($foldersexploded as $key => $folders) - { - $folderinfo = explode("**", $folders, 2); - $folderinfo[1] = get_pm_folder_name($folderinfo[0], $folderinfo[1]); - if($folderinfo[0] == 4) - { - $class = "usercp_nav_trash_pmfolder"; - } - else if($folderlinks) - { - $class = "usercp_nav_sub_pmfolder"; - } - else - { - $class = "usercp_nav_pmfolder"; - } - - $folder_id = $folderinfo[0]; - $folder_name = $folderinfo[1]; - - eval("\$folderlinks .= \"".$templates->get("usercp_nav_messenger_folder")."\";"); - } - - if(!isset($collapsedimg['usercppms'])) - { - $collapsedimg['usercppms'] = ''; - } - - if(!isset($collapsed['usercppms_e'])) - { - $collapsed['usercppms_e'] = ''; - } - - eval("\$usercpmenu .= \"".$usercp_nav_messenger."\";"); -} - -/** - * Constructs the usercp profile menu. - * - */ -function usercp_menu_profile() -{ - global $db, $mybb, $templates, $theme, $usercpmenu, $lang, $collapsed, $collapsedimg; - - $changenameop = ''; - if($mybb->usergroup['canchangename'] != 0) - { - eval("\$changenameop = \"".$templates->get("usercp_nav_changename")."\";"); - } - - $changesigop = ''; - if($mybb->usergroup['canusesig'] == 1 && ($mybb->usergroup['canusesigxposts'] == 0 || $mybb->usergroup['canusesigxposts'] > 0 && $mybb->user['postnum'] > $mybb->usergroup['canusesigxposts'])) - { - if($mybb->user['suspendsignature'] == 0 || $mybb->user['suspendsignature'] == 1 && $mybb->user['suspendsigtime'] > 0 && $mybb->user['suspendsigtime'] < TIME_NOW) - { - eval("\$changesigop = \"".$templates->get("usercp_nav_editsignature")."\";"); - } - } - - if(!isset($collapsedimg['usercpprofile'])) - { - $collapsedimg['usercpprofile'] = ''; - } - - if(!isset($collapsed['usercpprofile_e'])) - { - $collapsed['usercpprofile_e'] = ''; - } - - eval("\$usercpmenu .= \"".$templates->get("usercp_nav_profile")."\";"); -} - -/** - * Constructs the usercp misc menu. - * - */ -function usercp_menu_misc() -{ - global $db, $mybb, $templates, $theme, $usercpmenu, $lang, $collapsed, $collapsedimg; - - $draftstart = $draftend = ''; - $draftcount = $lang->ucp_nav_drafts; - - $query = $db->simple_select("posts", "COUNT(pid) AS draftcount", "visible = '-2' AND uid = '{$mybb->user['uid']}'"); - $count = $db->fetch_field($query, 'draftcount'); - - if($count > 0) - { - $draftcount = $lang->sprintf($lang->ucp_nav_drafts_active, my_number_format($count)); - } - - if($mybb->settings['enableattachments'] != 0) - { - eval("\$attachmentop = \"".$templates->get("usercp_nav_attachments")."\";"); - } - - if(!isset($collapsedimg['usercpmisc'])) - { - $collapsedimg['usercpmisc'] = ''; - } - - if(!isset($collapsed['usercpmisc_e'])) - { - $collapsed['usercpmisc_e'] = ''; - } - - $profile_link = get_profile_link($mybb->user['uid']); - eval("\$usercpmenu .= \"".$templates->get("usercp_nav_misc")."\";"); -} - -/** - * Gets the usertitle for a specific uid. - * - * @param int $uid The uid of the user to get the usertitle of. - * @return string The usertitle of the user. - */ -function get_usertitle($uid=0) -{ - global $db, $mybb; - - if($mybb->user['uid'] == $uid) - { - $user = $mybb->user; - } - else - { - $query = $db->simple_select("users", "usertitle,postnum", "uid='$uid'", array('limit' => 1)); - $user = $db->fetch_array($query); - } - - if($user['usertitle']) - { - return $user['usertitle']; - } - else - { - $usertitles = $mybb->cache->read('usertitles'); - foreach($usertitles as $title) - { - if($title['posts'] <= $user['postnum']) - { - $usertitle = $title; - break; - } - } - - return $usertitle['title']; - } -} - -/** - * Updates a users private message count in the users table with the number of pms they have. - * - * @param int $uid The user id to update the count for. If none, assumes currently logged in user. - * @param int $count_to_update Bitwise value for what to update. 1 = total, 2 = new, 4 = unread. Combinations accepted. - * @return array The updated counters - */ -function update_pm_count($uid=0, $count_to_update=7) -{ - global $db, $mybb; - - // If no user id, assume that we mean the current logged in user. - if((int)$uid == 0) - { - $uid = $mybb->user['uid']; - } - - $uid = (int)$uid; - $pmcount = array(); - if($uid == 0) - { - return $pmcount; - } - - // Update total number of messages. - if($count_to_update & 1) - { - $query = $db->simple_select("privatemessages", "COUNT(pmid) AS pms_total", "uid='".$uid."'"); - $total = $db->fetch_array($query); - $pmcount['totalpms'] = $total['pms_total']; - } - - // Update number of unread messages. - if($count_to_update & 2 && $db->field_exists("unreadpms", "users") == true) - { - $query = $db->simple_select("privatemessages", "COUNT(pmid) AS pms_unread", "uid='".$uid."' AND status='0' AND folder='1'"); - $unread = $db->fetch_array($query); - $pmcount['unreadpms'] = $unread['pms_unread']; - } - - if(!empty($pmcount)) - { - $db->update_query("users", $pmcount, "uid='".$uid."'"); - } - return $pmcount; -} - -/** - * Return the language specific name for a PM folder. - * - * @param int $fid The ID of the folder. - * @param string $name The folder name - can be blank, will use language default. - * @return string The name of the folder. - */ -function get_pm_folder_name($fid, $name="") -{ - global $lang; - - if($name != '') - { - return $name; - } - - switch($fid) - { - case 1: - return $lang->folder_inbox; - break; - case 2: - return $lang->folder_sent_items; - break; - case 3: - return $lang->folder_drafts; - break; - case 4: - return $lang->folder_trash; - break; - default: - return $lang->folder_untitled; - } -} - -/** - * Generates a security question for registration. - * - * @param int $old_qid Optional ID of the old question. - * @return string The question session id. - */ -function generate_question($old_qid=0) -{ - global $db; - - if($db->type == 'pgsql' || $db->type == 'sqlite') - { - $order_by = 'RANDOM()'; - } - else - { - $order_by = 'RAND()'; - } - - if($old_qid) - { - $excl_old = ' AND qid != '.(int)$old_qid; - } - - $query = $db->simple_select('questions', 'qid, shown', "active=1{$excl_old}", array('limit' => 1, 'order_by' => $order_by)); - $question = $db->fetch_array($query); - - if(!$db->num_rows($query)) - { - // No active questions exist - return false; - } - else - { - $sessionid = random_str(32); - - $sql_array = array( - "sid" => $sessionid, - "qid" => $question['qid'], - "dateline" => TIME_NOW - ); - $db->insert_query("questionsessions", $sql_array); - - $update_question = array( - "shown" => $question['shown'] + 1 - ); - $db->update_query("questions", $update_question, "qid = '{$question['qid']}'"); - - return $sessionid; - } -} - -/** - * Check whether we can show the Purge Spammer Feature - * - * @param int $post_count The users post count - * @param int $usergroup The usergroup of our user - * @param int $uid The uid of our user - * @return boolean Whether or not to show the feature - */ -function purgespammer_show($post_count, $usergroup, $uid) -{ - global $mybb, $cache; - - // only show this if the current user has permission to use it and the user has less than the post limit for using this tool - $bangroup = $mybb->settings['purgespammerbangroup']; - $usergroups = $cache->read('usergroups'); - - return ($mybb->user['uid'] != $uid && is_member($mybb->settings['purgespammergroups']) && !is_super_admin($uid) - && !$usergroups[$usergroup]['cancp'] && !$usergroups[$usergroup]['canmodcp'] && !$usergroups[$usergroup]['issupermod'] - && (str_replace($mybb->settings['thousandssep'], '', $post_count) <= $mybb->settings['purgespammerpostlimit'] || $mybb->settings['purgespammerpostlimit'] == 0) - && !is_member($bangroup, $uid) && !$usergroups[$usergroup]['isbannedgroup']); -} diff --git a/html/forums/inc/functions_warnings.php b/html/forums/inc/functions_warnings.php deleted file mode 100644 index 0fdd5f9..0000000 --- a/html/forums/inc/functions_warnings.php +++ /dev/null @@ -1,125 +0,0 @@ - -1, // Ban - 2 => -1, // Revoke posting - 3 => -1 // Moderate posting - ); - $check_levels = array( - 1 => false, // Ban - 2 => false, // Revoke posting - 3 => false // Moderate posting - ); - while($warn_level = $db->fetch_array($query)) - { - // revoke actions taken at this warning level - $action = my_unserialize($warn_level['action']); - if($action['type'] < 1 || $action['type'] > 3) // prevent any freak-ish cases - { - continue; - } - - $check_levels[$action['type']] = true; - - $max_exp_time = &$max_expiration_times[$action['type']]; - if($action['length'] && $max_exp_time != 0) - { - $expiration = $action['length']; - if($expiration > $max_exp_time) - { - $max_exp_time = $expiration; - } - } - else - { - $max_exp_time = 0; - } - } -} - -/** - * Returns a friendly expiration time of a suspension/warning - * - * @param int $time The time period of the suspension/warning - * @return array An array of the time/period remaining - */ -function fetch_friendly_expiration($time) -{ - if($time == 0 || $time == -1) - { - return array("period" => "never"); - } - else if($time % 2592000 == 0) - { - return array("time" => $time/2592000, "period" => "months"); - } - else if($time % 604800 == 0) - { - return array("time" => $time/604800, "period" => "weeks"); - } - else if($time % 86400 == 0) - { - return array("time" => $time/86400, "period" => "days"); - } - else - { - return array("time" => ceil($time/3600), "period" => "hours"); - } -} - -/** - * Figures out the length of a suspension/warning - * - * @param int $time The amount of time to calculate the length of suspension/warning - * @param string $period The period of time to calculate the length of suspension/warning - * @return int Length of the suspension/warning (in seconds) - */ -function fetch_time_length($time, $period) -{ - $time = (int)$time; - - if($period == "hours") - { - $time = $time*3600; - } - else if($period == "days") - { - $time = $time*86400; - } - else if($period == "weeks") - { - $time = $time*604800; - } - else if($period == "months") - { - $time = $time*2592000; - } - else if($period == "never" && $time == 0) - { - // User is permanentely banned - $time = "-1"; - } - else - { - $time = 0; - } - return $time; -} diff --git a/html/forums/inc/index.html b/html/forums/inc/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/init.php b/html/forums/inc/init.php deleted file mode 100644 index 62d06e1..0000000 --- a/html/forums/inc/init.php +++ /dev/null @@ -1,302 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/* Defines the root directory for MyBB. - - Uncomment the below line and set the path manually - if you experience problems. - - Always add a trailing slash to the end of the path. - - * Path to your copy of MyBB - */ -//define('MYBB_ROOT', "./"); - -// Attempt autodetection -if(!defined('MYBB_ROOT')) -{ - define('MYBB_ROOT', dirname(dirname(__FILE__))."/"); -} - -define("TIME_NOW", time()); - -if(function_exists('date_default_timezone_set') && !ini_get('date.timezone')) -{ - date_default_timezone_set('GMT'); -} - -require_once MYBB_ROOT."inc/class_error.php"; -$error_handler = new errorHandler(); - -if(!function_exists('json_encode') || !function_exists('json_decode')) -{ - require_once MYBB_ROOT.'inc/3rdparty/json/json.php'; -} - -require_once MYBB_ROOT."inc/functions.php"; - -require_once MYBB_ROOT."inc/class_timers.php"; -$maintimer = new timer(); - -require_once MYBB_ROOT."inc/class_core.php"; -$mybb = new MyBB; - -$not_installed = false; -if(!file_exists(MYBB_ROOT."inc/config.php")) -{ - $not_installed = true; -} -else -{ - // Include the required core files - require_once MYBB_ROOT."inc/config.php"; - $mybb->config = &$config; - - if(!isset($config['database'])) - { - $not_installed = true; - } -} - -if($not_installed !== false) -{ - if(file_exists(MYBB_ROOT."install/index.php")) - { - if(defined("IN_ARCHIVE") || defined("IN_ADMINCP")) - { - header("Location: ../install/index.php"); - exit; - } - header("Location: ./install/index.php"); - exit; - } - - $mybb->trigger_generic_error("board_not_installed"); -} - -if(!is_array($config['database'])) -{ - $mybb->trigger_generic_error("board_not_upgraded"); -} - -if(empty($config['admin_dir'])) -{ - $config['admin_dir'] = "admin"; -} - -// Trigger an error if the installation directory exists -if(is_dir(MYBB_ROOT."install") && !file_exists(MYBB_ROOT."install/lock")) -{ - $mybb->trigger_generic_error("install_directory"); -} - -// Load DB interface -require_once MYBB_ROOT."inc/db_base.php"; - -require_once MYBB_ROOT."inc/db_".$config['database']['type'].".php"; - -switch($config['database']['type']) -{ - case "sqlite": - $db = new DB_SQLite; - break; - case "pgsql": - $db = new DB_PgSQL; - break; - case "mysqli": - $db = new DB_MySQLi; - break; - default: - $db = new DB_MySQL; -} - -// Check if our DB engine is loaded -if(!extension_loaded($db->engine)) -{ - // Throw our super awesome db loading error - $mybb->trigger_generic_error("sql_load_error"); -} - -require_once MYBB_ROOT."inc/class_templates.php"; -$templates = new templates; - -require_once MYBB_ROOT."inc/class_datacache.php"; -$cache = new datacache; - -require_once MYBB_ROOT."inc/class_plugins.php"; -$plugins = new pluginSystem; - -// Include our base data handler class -require_once MYBB_ROOT."inc/datahandler.php"; - -// Connect to Database -define("TABLE_PREFIX", $config['database']['table_prefix']); -$db->connect($config['database']); -$db->set_table_prefix(TABLE_PREFIX); -$db->type = $config['database']['type']; - -// Language initialisation -require_once MYBB_ROOT."inc/class_language.php"; -$lang = new MyLanguage; -$lang->set_path(MYBB_ROOT."inc/languages"); - -// Load cache -$cache->cache(); - -// Load Settings -if(file_exists(MYBB_ROOT."inc/settings.php")) -{ - require_once MYBB_ROOT."inc/settings.php"; -} - -if(!file_exists(MYBB_ROOT."inc/settings.php") || empty($settings)) -{ - if(function_exists('rebuild_settings')) - { - rebuild_settings(); - } - else - { - $options = array( - "order_by" => "title", - "order_dir" => "ASC" - ); - - $query = $db->simple_select("settings", "value, name", "", $options); - - $settings = array(); - while($setting = $db->fetch_array($query)) - { - $setting['value'] = str_replace("\"", "\\\"", $setting['value']); - $settings[$setting['name']] = $setting['value']; - } - $db->free_result($query); - } -} - -$settings['wolcutoff'] = $settings['wolcutoffmins']*60; -$settings['bbname_orig'] = $settings['bbname']; -$settings['bbname'] = strip_tags($settings['bbname']); -$settings['orig_bblanguage'] = $settings['bblanguage']; - -// Fix for people who for some specify a trailing slash on the board URL -if(substr($settings['bburl'], -1) == "/") -{ - $settings['bburl'] = my_substr($settings['bburl'], 0, -1); -} - -// Setup our internal settings and load our encryption key -$settings['internal'] = $cache->read("internal_settings"); -if(!$settings['internal']['encryption_key']) -{ - $cache->update("internal_settings", array('encryption_key' => random_str(32))); - $settings['internal'] = $cache->read("internal_settings"); -} - -$mybb->settings = &$settings; -$mybb->parse_cookies(); -$mybb->cache = &$cache; -$mybb->asset_url = $mybb->get_asset_url(); - -if($mybb->use_shutdown == true) -{ - register_shutdown_function('run_shutdown'); -} - -// Did we just upgrade to a new version and haven't run the upgrade scripts yet? -$version = $cache->read("version"); -if(!defined("IN_INSTALL") && !defined("IN_UPGRADE") && $version['version_code'] < $mybb->version_code) -{ - $version_history = $cache->read("version_history"); - if(empty($version_history) || file_exists(MYBB_ROOT."install/resources/upgrade".(int)(end($version_history)+1).".php")) - { - $mybb->trigger_generic_error("board_not_upgraded"); - } -} - -// Load plugins -if(!defined("NO_PLUGINS") && !($mybb->settings['no_plugins'] == 1)) -{ - $plugins->load(); -} - -// Set up any shutdown functions we need to run globally -add_shutdown('send_mail_queue'); - -/* URL Definitions */ -if($mybb->settings['seourls'] == "yes" || ($mybb->settings['seourls'] == "auto" && isset($_SERVER['SEO_SUPPORT']) && $_SERVER['SEO_SUPPORT'] == 1)) -{ - $mybb->seo_support = true; - - define('FORUM_URL', "forum-{fid}.html"); - define('FORUM_URL_PAGED', "forum-{fid}-page-{page}.html"); - define('THREAD_URL', "thread-{tid}.html"); - define('THREAD_URL_PAGED', "thread-{tid}-page-{page}.html"); - define('THREAD_URL_ACTION', 'thread-{tid}-{action}.html'); - define('THREAD_URL_POST', 'thread-{tid}-post-{pid}.html'); - define('POST_URL', "post-{pid}.html"); - define('PROFILE_URL', "user-{uid}.html"); - define('ANNOUNCEMENT_URL', "announcement-{aid}.html"); - define('CALENDAR_URL', "calendar-{calendar}.html"); - define('CALENDAR_URL_MONTH', 'calendar-{calendar}-year-{year}-month-{month}.html'); - define('CALENDAR_URL_DAY', 'calendar-{calendar}-year-{year}-month-{month}-day-{day}.html'); - define('CALENDAR_URL_WEEK', 'calendar-{calendar}-week-{week}.html'); - define('EVENT_URL', "event-{eid}.html"); -} -else -{ - define('FORUM_URL', "forumdisplay.php?fid={fid}"); - define('FORUM_URL_PAGED', "forumdisplay.php?fid={fid}&page={page}"); - define('THREAD_URL', "showthread.php?tid={tid}"); - define('THREAD_URL_PAGED', "showthread.php?tid={tid}&page={page}"); - define('THREAD_URL_ACTION', 'showthread.php?tid={tid}&action={action}'); - define('THREAD_URL_POST', 'showthread.php?tid={tid}&pid={pid}'); - define('POST_URL', "showthread.php?pid={pid}"); - define('PROFILE_URL', "member.php?action=profile&uid={uid}"); - define('ANNOUNCEMENT_URL', "announcements.php?aid={aid}"); - define('CALENDAR_URL', "calendar.php?calendar={calendar}"); - define('CALENDAR_URL_MONTH', "calendar.php?calendar={calendar}&year={year}&month={month}"); - define('CALENDAR_URL_DAY', 'calendar.php?action=dayview&calendar={calendar}&year={year}&month={month}&day={day}'); - define('CALENDAR_URL_WEEK', 'calendar.php?action=weekview&calendar={calendar}&week={week}'); - define('EVENT_URL', "calendar.php?action=event&eid={eid}"); -} -define('INDEX_URL', "index.php"); - -// An array of valid date formats (Used for user selections etc) -$date_formats = array( - 1 => "m-d-Y", - 2 => "m-d-y", - 3 => "m.d.Y", - 4 => "m.d.y", - 5 => "d-m-Y", - 6 => "d-m-y", - 7 => "d.m.Y", - 8 => "d.m.y", - 9 => "F jS, Y", - 10 => "l, F jS, Y", - 11 => "jS F, Y", - 12 => "l, jS F, Y", - // ISO 8601 - 13 => "Y-m-d" -); - -// An array of valid time formats (Used for user selections etc) -$time_formats = array( - 1 => "h:i a", - 2 => "h:i A", - 3 => "H:i" -); - diff --git a/html/forums/inc/languages/english.php b/html/forums/inc/languages/english.php deleted file mode 100644 index b278ff2..0000000 --- a/html/forums/inc/languages/english.php +++ /dev/null @@ -1,30 +0,0 @@ - on all pages -$langinfo['htmllang'] = "en"; - -// Sets the character set, blank uses the default. -$langinfo['charset'] = "UTF-8"; diff --git a/html/forums/inc/languages/english/admin/config_attachment_types.lang.php b/html/forums/inc/languages/english/admin/config_attachment_types.lang.php deleted file mode 100644 index a420ed4..0000000 --- a/html/forums/inc/languages/english/admin/config_attachment_types.lang.php +++ /dev/null @@ -1,53 +0,0 @@ -See a list here
    )"; -$l['maximum_file_size'] = "Maximum File Size (Kilobytes)"; -$l['maximum_file_size_desc'] = "The maximum file size for uploads of this attachment type in Kilobytes (1 MB = 1024 KB)"; -$l['limit_intro'] = "Please ensure the maximum file size is below the smallest of the following PHP limits:"; -$l['limit_post_max_size'] = "Max Post Size: {1}"; -$l['limit_upload_max_filesize'] = "Upload Max File Size: {1}"; -$l['attachment_icon'] = "Attachment Icon"; -$l['attachment_icon_desc'] = "If you wish to show a small attachment icon for attachments of this type then enter the path to it here. {theme} will be replaced by the image directory for the viewers theme allowing you to specify per-theme attachment icons."; -$l['save_attachment_type'] = "Save Attachment Type"; - -$l['error_invalid_attachment_type'] = "You have selected an invalid attachment type."; -$l['error_missing_mime_type'] = "You did not enter a MIME type for this attachment type"; -$l['error_missing_extension'] = "You did not enter a file extension for this attachment type"; - -$l['success_attachment_type_created'] = "The attachment type has been created successfully."; -$l['success_attachment_type_updated'] = "The attachment type has been updated successfully."; -$l['success_attachment_type_deleted'] = "The attachment type has been deleted successfully."; - -$l['confirm_attachment_type_deletion'] = "Are you sure you wish to delete this attachment type?"; - -$l['success_activated_attachment_type'] = 'The selected attachment type has been activated successfully.'; -$l['success_deactivated_attachment_type'] = 'The selected attachment type has been deactivated successfully.'; - -$l['enabled'] = "Enabled?"; -$l['avatar_file'] = 'Avatar File'; -$l['avatar_file_desc'] = 'Do you want to allow this attachment type to be used for avatars?'; - -$l['available_to_groups'] = 'Available to groups'; -$l['available_in_forums'] = 'Available in forums'; \ No newline at end of file diff --git a/html/forums/inc/languages/english/admin/config_badwords.lang.php b/html/forums/inc/languages/english/admin/config_badwords.lang.php deleted file mode 100644 index f99a36a..0000000 --- a/html/forums/inc/languages/english/admin/config_badwords.lang.php +++ /dev/null @@ -1,35 +0,0 @@ -{subject} represents the original subject. {username} represents the moderator's username."; - -$l['success_mod_tool_created'] = "The moderation tool has been created successfully."; -$l['success_mod_tool_updated'] = "The moderation tool has been updated successfully."; - -$l['inline_post_moderation'] = "Inline Post Moderation"; -$l['delete_posts'] = "Delete posts permanently?"; -$l['merge_posts'] = "Merge posts?"; -$l['merge_posts_desc'] = "Only if used from inline moderation."; -$l['approve_unapprove_posts'] = "Approve/unapprove posts?"; -$l['softdelete_restore_posts'] = "Soft delete/restore posts?"; - -$l['split_posts'] = "Split Posts"; -$l['split_posts2'] = "Split posts?"; -$l['do_not_split'] = "Do not split posts"; -$l['split_to_same_forum'] = "Split to same forum"; -$l['close_split_thread'] = "Close split thread?"; -$l['stick_split_thread'] = "Stick split thread?"; -$l['unapprove_split_thread'] = "Unapprove split thread?"; -$l['split_thread_prefix'] = "Split thread prefix"; -$l['split_thread_subject'] = "Split thread subject"; -$l['split_thread_subject_desc'] = "{subject} represents the original subject. Only required if splitting posts."; -$l['add_new_split_reply'] = "Add reply to split thread"; -$l['add_new_split_reply_desc'] = "Leave blank for no reply."; -$l['split_reply_subject'] = "Reply subject"; -$l['split_reply_subject_desc'] = "Only used if a reply is made"; -$l['save_post_tool'] = "Save Post Tool"; - -$l['send_private_message'] = 'Send Private Message'; -$l['private_message_message'] = 'Message'; -$l['private_message_message_desc'] = 'Message to send to the author of the thread. Leave empty to disable this feature.'; -$l['private_message_subject'] = 'Subject'; -$l['private_message_subject_desc'] = 'Enter the subject of the Private Message.'; - -$l['error_missing_title'] = "Please enter a name for this tool."; -$l['error_missing_description'] = "Please enter a short description for this tool."; -$l['error_no_forums_selected'] = "Please select the forums in which this tool will be available."; -$l['error_no_groups_selected'] = "Please select the groups to which this tool will be available."; -$l['error_forum_is_category'] = "You can't pick a category-type forum as a destination forum."; diff --git a/html/forums/inc/languages/english/admin/config_module_meta.lang.php b/html/forums/inc/languages/english/admin/config_module_meta.lang.php deleted file mode 100644 index 34b2e5b..0000000 --- a/html/forums/inc/languages/english/admin/config_module_meta.lang.php +++ /dev/null @@ -1,47 +0,0 @@ -inc/plugins directory. To hide a plugin from view, but not lose any stored information from it, click the Deactivate link."; -$l['plugin_updates'] = "Plugin Updates"; -$l['plugin_updates_desc'] = "This section allows you to check for updates on all your plugins."; -$l['browse_plugins'] = "Browse Plugins"; -$l['browse_plugins_desc'] = "Here you may browse the official MyBB modifications site for plugins compatible with your series of MyBB."; -$l['browse_all_plugins'] = "Browse All Plugins"; - -$l['plugin'] = "Plugin"; -$l['active_plugin'] = "Active Plugins"; -$l['inactive_plugin'] = "Inactive Plugins"; -$l['your_version'] = "Your Version"; -$l['latest_version'] = "Latest Version"; -$l['download'] = "Download"; -$l['deactivate'] = "Deactivate"; -$l['activate'] = "Activate"; -$l['install_and_activate'] = "Install & Activate"; -$l['uninstall'] = "Uninstall"; -$l['created_by'] = "Created by"; -$l['no_plugins'] = "There are no plugins on your forum at this time."; -$l['no_active_plugins'] = "There are no active plugins on your forum."; -$l['no_inactive_plugins'] = "There are no inactive plugins available."; - -$l['plugin_incompatible'] = "This plugin is incompatible with MyBB {1}"; - -$l['recommended_plugins_for_mybb'] = "Recommended Plugins for MyBB {1}"; -$l['browse_results_for_mybb'] = "Browse Results for MyBB {1}"; -$l['search_for_plugins'] = "Search for Plugins"; -$l['search'] = "Search"; - -$l['error_vcheck_no_supported_plugins'] = "None of the plugins installed support version checking."; -$l['error_vcheck_communications_problem'] = "There was a problem communicating with the MyBB modifications version server. Please try again in a few minutes."; -$l['error_vcheck_vulnerable'] = "[Vulnerable plugin]:"; -$l['error_vcheck_vulnerable_notes'] = "This submission has currently been marked as vulnerable by the MyBB Staff. We recommend complete removal of this modification. Please see the notes below: "; -$l['error_no_input'] = "Error code 1: No input specified."; -$l['error_no_pids'] = "Error code 2: No plugin ids specified."; -$l['error_communication_problem'] = "There was a problem communicating with the MyBB modifications server. Please try again in a few minutes."; -$l['error_invalid_plugin'] = "The selected plugin does not exist."; -$l['error_no_results_found'] = "No results were found for the specified keywords."; - -$l['success_plugins_up_to_date'] = "Congratulations, all of your plugins are up to date."; -$l['success_plugin_activated'] = "The selected plugin has been activated successfully."; -$l['success_plugin_deactivated'] = "The selected plugin has been deactivated successfully."; -$l['success_plugin_installed'] = "The selected plugin has been installed and activated successfully."; -$l['success_plugin_uninstalled'] = "The selected plugin has been uninstalled successfully."; diff --git a/html/forums/inc/languages/english/admin/config_post_icons.lang.php b/html/forums/inc/languages/english/admin/config_post_icons.lang.php deleted file mode 100644 index d7e36da..0000000 --- a/html/forums/inc/languages/english/admin/config_post_icons.lang.php +++ /dev/null @@ -1,46 +0,0 @@ -{theme} to represent the image directory of each theme."; -$l['save_post_icon'] = "Save Post Icon"; -$l['reset'] = "Reset"; - -$l['path_to_images'] = "Path to Images"; -$l['path_to_images_desc'] = "This is the path to the folder that the images are in."; -$l['show_post_icons'] = "Show Post Icons"; -$l['image'] = "Image"; -$l['add'] = "Add?"; -$l['save_post_icons'] = "Save Post Icons"; - -$l['no_post_icons'] = "There are no post icons on your forum at this time."; - -$l['error_missing_name'] = "You did not enter a name for this post icon"; -$l['error_missing_path'] = "You did not enter a path to this post icon"; -$l['error_missing_path_multiple'] = "You did not enter a path"; -$l['error_invalid_path'] = "You did not enter a valid path"; -$l['error_no_images'] = "There are no post icons in the specified directory, or all post icons in the directory have already been added."; -$l['error_none_included'] = "You did not select any post icons to include."; -$l['error_invalid_post_icon'] = "The specified post icon does not exist."; - -$l['success_post_icon_added'] = "The post icon has been added successfully."; -$l['success_post_icons_added'] = "The selected post icons have been added successfully."; -$l['success_post_icon_updated'] = "The post icon has been updated successfully."; -$l['success_post_icon_deleted'] = "The selected post icon has been deleted successfully."; - -$l['confirm_post_icon_deletion'] = "Are you sure you wish to delete this post icon?"; diff --git a/html/forums/inc/languages/english/admin/config_profile_fields.lang.php b/html/forums/inc/languages/english/admin/config_profile_fields.lang.php deleted file mode 100644 index 56c6aa2..0000000 --- a/html/forums/inc/languages/english/admin/config_profile_fields.lang.php +++ /dev/null @@ -1,75 +0,0 @@ - -Example: ([a-z0-9_\- ,.+]+)"; -$l['selectable_options'] = "Selectable Options?"; -$l['selectable_options_desc'] = "Please enter each option on a separate line. This only applies to the select boxes, check boxes, and radio buttons types."; -$l['required'] = "Required?"; -$l['required_desc'] = "Is this field required to be filled in during registration or profile editing? Note that this does not apply if the field is hidden or the field is not editable."; -$l['show_on_registration'] = "Show on Registration?"; -$l['show_on_registration_desc'] = "Should this field appear on the registration form? Note that this does not apply if the field is not editable. Fields that are required will always appear on registration."; -$l['display_on_profile'] = "Display on profile?"; -$l['display_on_profile_desc'] = "Should this field be displayed on the user's profile? This doesn't apply to administrators/moderators."; -$l['display_on_postbit'] = "Display on postbit?"; -$l['display_on_postbit_desc'] = "Should this field be displayed on the user's posts?"; -$l['viewableby'] = 'Viewable By'; -$l['viewableby_desc'] = 'Select the allowed groups to view this profile field.'; -$l['editableby'] = 'Editable By'; -$l['editableby_desc'] = 'Select the allowed groups to edit this profile field.'; -$l['min_posts_enabled'] = "Minimum post count?"; -$l['min_posts_enabled_desc'] = "Should this field only be available to users with a certain post count? If so, set the minimum amount of posts required here."; -$l['parser_options'] = "Parser Options"; -$l['parse_allowhtml'] = "Yes, allow HTML in this profile field."; -$l['parse_allowmycode'] = "Yes, allow MyCode in this profile field."; -$l['parse_allowsmilies'] = "Yes, allow smilies in this profile field."; -$l['parse_allowimgcode'] = "Yes, allow [img] code in this profile field."; -$l['parse_allowvideocode'] = "Yes, allow [video] code in this profile field."; -$l['save_profile_field'] = "Save Profile Field"; -$l['name'] = "Name"; -$l['registration'] = "Registration?"; -$l['editable'] = "Editable?"; -$l['profile'] = "Profile?"; -$l['postbit'] = "Postbit?"; -$l['edit_field'] = "Edit Field"; -$l['delete_field'] = "Delete Field"; -$l['no_profile_fields'] = "There are no custom profile fields on your forum at this time."; - -$l['error_missing_name'] = "You did not enter a title for this custom profile field"; -$l['error_missing_description'] = "You did not enter a description for this custom profile field"; -$l['error_invalid_fid'] = "The selected profile field does not exist."; - -$l['success_profile_field_added'] = "The custom profile field has been created successfully."; -$l['success_profile_field_saved'] = "The custom profile field has been saved successfully."; -$l['success_profile_field_deleted'] = "The selected custom profile field has been deleted successfully."; - -$l['confirm_profile_field_deletion'] = "Are you sure you wish to delete this profile field?"; diff --git a/html/forums/inc/languages/english/admin/config_questions.lang.php b/html/forums/inc/languages/english/admin/config_questions.lang.php deleted file mode 100644 index 248da5d..0000000 --- a/html/forums/inc/languages/english/admin/config_questions.lang.php +++ /dev/null @@ -1,42 +0,0 @@ -For more information on CHMODing, see the MyBB Docs."; - -$l['success_setting_added'] = "The setting has been created successfully."; -$l['success_setting_updated'] = "The setting has been updated successfully."; -$l['success_setting_deleted'] = "The selected setting has been deleted successfully."; -$l['success_settings_updated'] = "The settings have been updated successfully."; -$l['success_settings_updated_hiddencaptchaimage'] = '
    Please note that the Hidden CAPTCHA field setting was reverted to {1} due to a conflict with the {2} field in the registration form.
    '; -$l['success_settings_updated_username_method'] = '
    Please note that the Allowed Login Methods setting was not updated due to multiple users using the same e-mail address at this time.
    '; -$l['success_settings_updated_allowmultipleemails'] = '
    Please note that the Allow emails to be registered multiple times? setting can\'t be enabled because the Allowed Login Methods setting allows users to login by e-mail address.
    '; -$l['success_settings_updated_captchaimage'] = '
    Please note that the CAPTCHA Images for Registration & Posting setting was reverted to MyBB Default Captcha due to the lack of public/private key(s).
    '; -$l['success_display_orders_updated'] = "The setting display orders have been updated successfully."; -$l['success_setting_group_added'] = "The setting group has been created successfully."; -$l['success_setting_group_updated'] = "The setting group has been updated successfully."; -$l['success_setting_group_deleted'] = "The selected setting group has been deleted successfully."; -$l['success_duplicate_settings_deleted'] = "All duplicate setting groups have been deleted successfully."; - -$l['searching'] = 'Searching...'; -$l['search_error'] = 'There was an error fetching your search results:'; -$l['search_done'] = 'Done!'; - diff --git a/html/forums/inc/languages/english/admin/config_smilies.lang.php b/html/forums/inc/languages/english/admin/config_smilies.lang.php deleted file mode 100644 index 7437e6b..0000000 --- a/html/forums/inc/languages/english/admin/config_smilies.lang.php +++ /dev/null @@ -1,64 +0,0 @@ -{theme} to represent the image directory of each theme."; -$l['order'] = "Order"; -$l['display_order'] = "Display Order"; -$l['display_order_desc'] = "The order on the smilies list that this will appear. This number should not be the same as another smilie's."; -$l['mass_edit_show_clickable'] = "Show on Clickable?"; -$l['show_clickable'] = "Show on clickable list?"; -$l['show_clickable_desc'] = "Do you want this smilie to show on the clickable smilie list on the post editor?"; -$l['include'] = "Add?"; -$l['path_to_images'] = "Path to Images"; -$l['path_to_images_desc'] = "This is the path to the folder that the images are in."; -$l['smilie_delete'] = "Delete?"; -$l['save_smilie'] = "Save Smilie"; -$l['save_smilies'] = "Save Smilies"; -$l['show_smilies'] = "Show Smilies"; -$l['reset'] = "Reset"; - -$l['error_missing_name'] = "You did not enter a name for this smilie."; -$l['error_missing_text_replacement'] = "You did not enter a text replacement for this smilie."; -$l['error_missing_path'] = "You did not enter a path for this smilie."; -$l['error_missing_path_multiple'] = "You did not enter a path."; -$l['error_missing_order'] = "You did not enter a display order for this smilie."; -$l['error_duplicate_order'] = "You did not enter a valid display order for this smilie."; -$l['error_missing_clickable'] = "You did not specify yes or no for the \"Show Clickable\" option."; -$l['error_no_smilies'] = "There are no smilies in the specified directory, or all smilies in the directory have already been added."; -$l['error_no_images'] = "There are no images in the specified directory."; -$l['error_none_included'] = "You did not select any smilies to include."; -$l['error_invalid_path'] = "You did not enter a valid path."; -$l['error_invalid_smilie'] = "The specified smilie does not exist."; - -$l['success_smilie_added'] = "The smilie has been added successfully."; -$l['success_multiple_smilies_added'] = "The selected smilies have been added successfully."; -$l['success_smilie_updated'] = "The smilie has been updated successfully."; -$l['success_multiple_smilies_updated'] = "The smilies have been updated successfully."; -$l['success_smilie_deleted'] = "The selected smilie has been deleted successfully."; -$l['success_mass_edit_updated'] = "The smilies have been updated successfully."; - -$l['confirm_smilie_deletion'] = "Are you sure you wish to delete this smilie?"; - diff --git a/html/forums/inc/languages/english/admin/config_spiders.lang.php b/html/forums/inc/languages/english/admin/config_spiders.lang.php deleted file mode 100644 index d240e8a..0000000 --- a/html/forums/inc/languages/english/admin/config_spiders.lang.php +++ /dev/null @@ -1,42 +0,0 @@ -No. Uploaded Attachments"; -$l['space_used'] = "Attachment Space Used"; -$l['bandwidth_used'] = "Estimated Bandwidth Usage"; -$l['average_size'] = "Average Attachment Size"; -$l['size'] = "Size"; -$l['posted_by'] = "Posted By"; -$l['thread'] = "Thread"; -$l['downloads'] = "Downloads"; -$l['date_uploaded'] = "Date Uploaded"; -$l['popular_attachments'] = "Top 5 Most Popular Attachments"; -$l['largest_attachments'] = "Top 5 Largest Attachments"; -$l['users_diskspace'] = "Top 5 Users Using the Most Disk Space"; -$l['username'] = "Username"; -$l['total_size'] = "Total Size"; - -// = Orphans -$l['orphan_results'] = "Orphaned Attachments Search - Results"; -$l['orphan_attachments_search'] = "Orphaned Attachments Search"; -$l['reason_orphaned'] = "Reason Orphaned"; -$l['reason_not_in_table'] = "Not in attachments table"; -$l['reason_file_missing'] = "Attached file missing"; -$l['reason_thread_deleted'] = "Thread been deleted"; -$l['reason_post_never_made'] = "Post never made"; -$l['unknown'] = "Unknown"; -$l['results'] = "Results"; -$l['step1'] = "Step 1"; -$l['step2'] = "Step 2"; -$l['step1of2'] = "Step 1 of 2 - File System Scan"; -$l['step2of2'] = "Step 2 of 2 - Database Scan"; -$l['step1of2_line1'] = "Please wait, the file system is currently being scanned for orphaned attachments."; -$l['step2of2_line1'] = "Please wait, the database is currently being scanned for orphaned attachments."; -$l['step_line2'] = "You'll automatically be redirected to the next step once this process is complete."; -$l['scanning'] = 'Scanning..'; - -// = Attachments / Index -$l['index_find_attachments'] = "Attachments - Find Attachments"; -$l['find_where'] = "Find attachments where..."; -$l['name_contains'] = "File name contains"; -$l['name_contains_desc'] = "To search by wild card enter *.[file extension]. Example: *.zip."; -$l['type_contains'] = "File type contains"; -$l['forum_is'] = "Forum is"; -$l['username_is'] = "Posters' username is"; -$l['more_than'] = "More than"; -$l['greater_than'] = "Greater than"; -$l['is_exactly'] = "Is exactly"; -$l['less_than'] = "Less than"; -$l['date_posted_is'] = "Date posted is"; -$l['days_ago'] = "days ago"; -$l['file_size_is'] = "File size is"; -$l['kb'] = "KB"; -$l['download_count_is'] = "Download count is"; -$l['display_options'] = "Display Options"; -$l['filename'] = "File Name"; -$l['filesize'] = "File Size"; -$l['download_count'] = "Download Count"; -$l['post_username'] = "Post Username"; -$l['asc'] = "Ascending"; -$l['desc'] = "Descending"; -$l['sort_results_by'] = "Sort results by"; -$l['results_per_page'] = "Results per page"; -$l['in'] = "in"; - -// Buttons -$l['button_delete_orphans'] = "Delete Checked Orphans"; -$l['button_delete_attachments'] = "Delete Checked Attachments"; -$l['button_find_attachments'] = "Find Attachments"; - diff --git a/html/forums/inc/languages/english/admin/forum_management.lang.php b/html/forums/inc/languages/english/admin/forum_management.lang.php deleted file mode 100644 index 50fd1ae..0000000 --- a/html/forums/inc/languages/english/admin/forum_management.lang.php +++ /dev/null @@ -1,279 +0,0 @@ -Recount & Rebuild tools."; -$l['success_moderator_deleted'] = "The selected moderator has been deleted successfully.
    Please remember that this hasn't changed this user's group permission, they may still have moderation powers."; -$l['success_forum_permissions_updated'] = "The forum permissions have been updated successfully."; -$l['success_forum_updated'] = "The forum settings have been updated successfully."; -$l['success_moderator_updated'] = "The selected moderator has been updated successfully."; -$l['success_custom_permission_cleared'] = "The custom permissions for this forum have been cleared successfully."; - -$l['error_invalid_forum'] = "Please select a valid forum."; -$l['error_invalid_moderator'] = "Please select a valid moderator to delete."; -$l['error_invalid_fid'] = "Invalid Forum ID selected."; -$l['error_forum_parent_child'] = "You can't set the parent forum of this forum to one of it's children."; -$l['error_forum_parent_itself'] = "The forum parent cannot be the forum itself."; -$l['error_incorrect_moderator'] = "Please select a valid moderator."; - -$l['confirm_moderator_deletion'] = "Are you sure you wish to remove this moderator from this forum?"; -$l['confirm_forum_deletion'] = "Are you sure you wish to delete this forum?"; -$l['confirm_clear_custom_permission'] = "Are you sure you wish to clear this custom permission?"; - -$l['forum_type'] = "Forum Type"; -$l['forum_type_desc'] = "Select the type of forum you are creating - a forum you can post in, or a category, which contains other forums."; -$l['category'] = "Category"; -$l['title'] = "Title"; -$l['description'] = "Description"; -$l['save_forum'] = "Save Forum"; -$l['parent_forum'] = "Parent Forum"; -$l['parent_forum_desc'] = "The Forum that contains this forum. Categories do not have a parent forum - in this case, select 'None' - however, categories can be specified to have a parent forum."; -$l['none'] = "None"; -$l['display_order'] = "Display Order"; - -$l['show_additional_options'] = "Show Additional Options"; -$l['hide_additional_options'] = "Hide Additional Options"; -$l['additional_forum_options'] = "Additional Forum Options"; -$l['forum_link'] = "Forum Link"; -$l['forum_link_desc'] = "To make a forum redirect to another location, enter the URL to the destination you wish to redirect to. Entering a URL in this field will remove the forum functionality; however, permissions can still be set for it."; -$l['forum_password'] = "Forum Password"; -$l['forum_password_desc'] = "To protect this forum further, you can choose a password that must be entered for access. Note: User groups still need permissions to access this forum."; -$l['access_options'] = "Access Options"; -$l['forum_is_active'] = "Forum is Active?"; -$l['forum_is_active_desc'] = "If unselected, this forum will not be shown to users and will not \"exist\"."; -$l['forum_is_open'] = "Forum is Open?"; -$l['forum_is_open_desc'] = "If unselected, users will not be able to post in this forum regardless of permissions."; - -$l['copy_to_new_forum'] = "Copy to new forum"; -$l['source_forum'] = "Source forum"; -$l['source_forum_desc'] = "Forum to copy settings and/or permissions from."; -$l['destination_forum'] = "Destination forum"; -$l['destination_forum_desc'] = "Forum to copy settings and/or permissions to."; -$l['new_forum_settings'] = "New Forum Settings"; -$l['copy_settings_and_properties'] = "Copy Forum Settings and Properties"; -$l['copy_settings_and_properties_desc'] = "Only applies if the destination forum exists."; -$l['copy_user_group_permissions'] = "Copy User Group Permissions"; -$l['copy_user_group_permissions_desc'] = "Use CTRL to select multiple groups."; - -$l['override_user_style'] = "Yes, override the user's selected style for this forum"; -$l['style_options'] = "Style Options"; -$l['forum_specific_style'] = "Forum-Specific Style:"; -$l['use_default'] = "Use Default"; -$l['dont_display_rules'] = "Don't display rules for this forum"; -$l['display_rules_inline'] = "Display rules for this forum on the thread listing"; -$l['display_rules_inline_new'] = "Display rules in the thread listing and for new threads/replies"; -$l['display_rules_link'] = "Display a link to the rules for this forum"; -$l['display_method'] = "Display Method:"; -$l['rules'] = "Rules:"; -$l['forum_rules'] = "Forum Rules"; -$l['name'] = "Name"; -$l['username'] = "Username"; -$l['moderator_username_desc'] = "Username of the moderator to be added"; -$l['add_user_as_moderator'] = "Add a user as Moderator"; -$l['usergroup'] = "Usergroup"; -$l['add_usergroup_as_moderator'] = "Add a usergroup as Moderators"; -$l['moderator_usergroup_desc'] = "Select a usergroup to add as a Moderator from the list below."; -$l['add_usergroup_moderator'] = "Add Usergroup Moderator"; -$l['add_user_moderator'] = "Add User Moderator"; - -$l['default_view_options'] = "Default View Options"; -$l['default_date_cut'] = "Default Date Cut:"; -$l['default_sort_by'] = "Default Sort By:"; -$l['default_sort_order'] = "Default Sort Order:"; - -$l['board_default'] = "Board Default"; - -$l['datelimit_1day'] = "Last day"; -$l['datelimit_5days'] = "Last 5 days"; -$l['datelimit_10days'] = "Last 10 days"; -$l['datelimit_20days'] = "Last 20 days"; -$l['datelimit_50days'] = "Last 50 days"; -$l['datelimit_75days'] = "Last 75 days"; -$l['datelimit_100days'] = "Last 100 days"; -$l['datelimit_lastyear'] = "Last year"; -$l['datelimit_beginning'] = "The beginning"; - -$l['sort_by_subject'] = "Thread subject"; -$l['sort_by_lastpost'] = "Last post time"; -$l['sort_by_starter'] = "Thread starter"; -$l['sort_by_started'] = "Thread creation time"; -$l['sort_by_rating'] = "Thread rating"; -$l['sort_by_replies'] = "Number of replies"; -$l['sort_by_views'] = "Number of views"; - -$l['sort_order_asc'] = "Ascending"; -$l['sort_order_desc'] = "Descending"; - -$l['misc_options'] = "Miscellaneous Options"; -$l['allow_html'] = "Yes, allow HTML in posts"; -$l['allow_mycode'] = "Yes, allow MyCode in posts"; -$l['allow_smilies'] = "Yes, allow smilies in posts"; -$l['allow_img_code'] = "Yes, allow [img] code in posts (requires MyCode to be turned on)"; -$l['allow_video_code'] = "Yes, allow [video] code in posts (requires MyCode to be turned on)"; -$l['allow_post_icons'] = "Yes, allow post icons to be chosen for posts"; -$l['allow_thread_ratings'] = "Yes, allow threads to be rated"; -$l['show_forum_jump'] = "Yes, show this forum in the 'forum jump' menu"; -$l['use_postcounts'] = "Yes, posts in this forum should count towards user post counts"; -$l['use_threadcounts'] = "Yes, threads in this forum should count towards user thread counts"; -$l['require_thread_prefix'] = "Yes, require a thread prefix for all threads"; - -$l['use_permissions'] = "Use Permissions"; -$l['use_permissions_desc'] = "Select the permissions you would like to use for this user group - inherited permissions (will delete custom permissions) or custom permissions."; -$l['inherit_permissions'] = "Use user group permissions or inherit permissions from parent forums"; -$l['custom_permissions'] = "Use custom permissions (below)"; -$l['custom_permissions_for'] = "Custom Permissions for"; - -$l['inherited_permission'] = "inherited"; -$l['custom_permission'] = "custom"; - -$l['save_permissions'] = "Save Forum Permissions"; - -$l['error_missing_title'] = "You must enter in a title."; -$l['error_no_parent'] = "You must select a parent forum."; -$l['error_not_empty'] = "Forums with threads cannot be converted to categories."; -$l['error_forum_link_not_empty'] = "Forums with threads cannot be redirected to another webpage."; - -$l['success_forum_added'] = "The forum has been created successfully."; -$l['success_moderator_added'] = "The moderator has been added to this forum successfully."; -$l['success_forum_permissions_saved'] = "The forum permissions have been saved successfully."; -$l['success_forum_copied'] = "The selected forum has been copied successfully."; - -$l['error_moderator_already_added'] = "The selected user/group is already a moderator of this forum."; -$l['error_moderator_not_found'] = "The specified username/group was not found."; -$l['error_new_forum_needs_name'] = "You need to give your new forum a name."; -$l['error_invalid_source_forum'] = "Invalid source forum."; -$l['error_invalid_destination_forum'] = "Invalid destination forum."; - -$l['group_viewing'] = "Viewing"; -$l['group_posting_rating'] = "Posting / Rating"; -$l['group_editing'] = "Editing"; -$l['group_moderate'] = "Moderation"; -$l['group_polls'] = "Polls"; -$l['group_misc'] = "Miscellaneous"; - -$l['viewing_field_canview'] = "Can view forum?"; -$l['viewing_field_canviewthreads'] = "Can view threads within forum?"; -$l['viewing_field_canonlyviewownthreads'] = "Can only view own threads?"; -$l['viewing_field_candlattachments'] = "Can download attachments?"; - -$l['posting_rating_field_canpostthreads'] = "Can post threads?"; -$l['posting_rating_field_canpostreplys'] = "Can post replies?"; -$l['posting_rating_field_canonlyreplyownthreads'] = "Can only reply to own threads?"; -$l['posting_rating_field_canpostattachments'] = "Can post attachments?"; -$l['posting_rating_field_canratethreads'] = "Can rate threads?"; - -$l['editing_field_caneditposts'] = "Can edit own posts?"; -$l['editing_field_candeleteposts'] = "Can delete own posts?"; -$l['editing_field_candeletethreads'] = "Can delete own threads?"; -$l['editing_field_caneditattachments'] = "Can update own attachments?"; -$l['editing_field_canviewdeletionnotice'] = "Can view deletion notices?"; - -$l['moderate_field_modposts'] = "Moderate new posts?"; -$l['moderate_field_modthreads'] = "Moderate new threads?"; -$l['moderate_field_modattachments'] = "Moderate new attachments?"; -$l['moderate_field_mod_edit_posts'] = "Moderate posts after they've been edited?"; - -$l['polls_field_canpostpolls'] = "Can post polls?"; -$l['polls_field_canvotepolls'] = "Can vote in polls?"; - -$l['misc_field_cansearch'] = "Can search forum?"; - -$l['confirm_proceed_deletion'] = "Click \"Proceed\" to continue the deletion of the forum."; -$l['automatically_redirecting'] = "Automatically Redirecting..."; diff --git a/html/forums/inc/languages/english/admin/forum_moderation_queue.lang.php b/html/forums/inc/languages/english/admin/forum_moderation_queue.lang.php deleted file mode 100644 index 0a75555..0000000 --- a/html/forums/inc/languages/english/admin/forum_moderation_queue.lang.php +++ /dev/null @@ -1,49 +0,0 @@ -Today"; -$l['yesterday'] = "Yesterday"; - -$l['size_yb'] = "YB"; -$l['size_zb'] = "ZB"; -$l['size_eb'] = "EB"; -$l['size_pb'] = "PB"; -$l['size_tb'] = "TB"; -$l['size_gb'] = "GB"; -$l['size_mb'] = "MB"; -$l['size_kb'] = "KB"; -$l['size_bytes'] = "bytes"; -$l['na'] = "N/A"; - -// Header language strings -$l['mybb_admin_panel'] = "MyBB Control Panel"; -$l['mybb_admin_cp'] = "MyBB Admin CP"; -$l['logged_in_as'] = "Logged in as"; -$l['view_board'] = "View Forum"; -$l['logout'] = "Log Out"; - -// Footer language strings -$l['generated_in'] = "Generated in {1} with {3} queries. Memory Usage: {4}"; - -// Login page -$l['enter_username_and_password'] = "Please enter your {1} and password to continue."; -$l['login_username'] = 'username'; -$l['login_email'] = 'email'; -$l['login_username_and_password'] = 'username/email'; -$l['mybb_admin_login'] = "MyBB Control Panel - Login"; -$l['return_to_forum'] = "Return to forum"; -$l['please_login'] = "Please Login"; -$l['username'] = "Username:"; -$l['username1'] = "Email:"; -$l['username2'] = "Username/Email:"; -$l['password'] = "Password:"; -$l['secret_pin'] = "Secret PIN:"; -$l['login'] = "Login"; -$l['lost_password'] = "Forgot your password?"; - -$l['error_invalid_admin_session'] = "Invalid administration session."; -$l['error_admin_session_expired'] = "Your administration session has expired."; -$l['error_invalid_ip'] = "Your IP address is not valid for this session."; -$l['error_mybb_admin_lockedout'] = "This account has been locked out."; -$l['error_mybb_admin_lockedout_message'] = "Your account is currently locked out after failing to login {1} times. You have been sent an email with instructions on how to unlock your account."; - -$l['error_invalid_username'] = "The username you entered is invalid."; -$l['error_invalid_uid'] = "The user id you entered is invalid."; -$l['error_invalid_token'] = "The activation code you entered is invalid."; - -$l['success_logged_out'] = "You have been logged out successfully."; -$l['error_invalid_username_password'] = "The {1} and password combination you entered is invalid."; - -// Action Confirmation -$l['confirm_action'] = "Are you sure you wish to perform this action?"; - -// Common words and phrases -$l['home'] = "Home"; -$l['name'] = "Name"; -$l['size'] = "Size"; -$l['controls'] = "Controls"; -$l['view'] = "View"; -$l['yes'] = "Yes"; -$l['no'] = "No"; -$l['cancel'] = "Cancel"; -$l['options'] = "Options"; -$l['proceed'] = "Proceed"; -$l['ok'] = "OK"; -$l['error'] = "Error"; -$l['edit'] = "Edit"; -$l['never'] = "Never"; -$l['legend'] = "Legend"; -$l['version'] = "Version"; -$l['languagevar'] = "Language"; -$l['use_default'] = "Use Default"; -$l['file'] = "File"; -$l['go'] = "Go"; -$l['clear'] = "Clear"; -$l['unknown'] = "Unknown"; -$l['year'] = "Year"; -$l['year_short'] = "y"; -$l['years'] = "Years"; -$l['years_short'] = "y"; -$l['month'] = "Month"; -$l['month_short'] = "m"; -$l['months'] = "Months"; -$l['months_short'] = "m"; -$l['week'] = "Week"; -$l['week_short'] = "w"; -$l['weeks'] = "Weeks"; -$l['weeks_short'] = "w"; -$l['day'] = "Day"; -$l['day_short'] = "d"; -$l['days'] = "Days"; -$l['days_short'] = "d"; -$l['hour'] = "Hour"; -$l['hour_short'] = "h"; -$l['hours'] = "Hours"; -$l['hours_short'] = "h"; -$l['minute'] = "Minute"; -$l['minute_short'] = "m"; -$l['minutes'] = "Minutes"; -$l['minutes_short'] = "m"; -$l['second'] = "Second"; -$l['second_short'] = "s"; -$l['seconds'] = "Seconds"; -$l['seconds_short'] = "s"; -$l['permanent'] = "Permanent"; -$l['all_forums'] = "All Forums"; -$l['all_groups'] = "All groups"; -$l['select_forums'] = "Select forums"; -$l['select_groups'] = "Select groups"; -$l['forums_colon'] = "Forums:"; -$l['groups_colon'] = "Groups:"; -$l['none'] = "None"; -$l['mybb_acp'] = "MyBB ACP"; -$l['pages'] = "Pages"; -$l['previous'] = "Previous"; -$l['page'] = "Page"; -$l['next'] = "Next"; -$l['delete'] = "Delete"; -$l['reset'] = "Reset"; -$l['and'] = "and"; -$l['on'] = "On"; -$l['off'] = "Off"; -$l['alt_enabled'] = "Enabled"; -$l['alt_disabled'] = "Disabled"; -$l['enable'] = "Enable"; -$l['disable'] = "Disable"; -$l['saved'] = 'Saved'; - -$l['rel_in'] = "In "; -$l['rel_ago'] = "ago"; -$l['rel_less_than'] = "Less than "; -$l['rel_time'] = "{1}{2} {3} {4}"; -$l['rel_minutes_single'] = "minute"; -$l['rel_minutes_plural'] = "minutes"; -$l['rel_hours_single'] = "hour"; -$l['rel_hours_plural'] = "hours"; - -// Parser bits -$l['quote'] = "Quote:"; -$l['wrote'] = "Wrote:"; -$l['code'] = "Code:"; -$l['php_code'] = "PHP Code:"; -$l['linkback'] = "Original Post"; - -// The months of the year -$l['january'] = "January"; -$l['february'] = "February"; -$l['march'] = "March"; -$l['april'] = "April"; -$l['may'] = "May"; -$l['june'] = "June"; -$l['july'] = "July"; -$l['august'] = "August"; -$l['september'] = "September"; -$l['october'] = "October"; -$l['november'] = "November"; -$l['december'] = "December"; - -// Access Denied -$l['access_denied'] = "Access Denied"; -$l['access_denied_desc'] = "You do not have permission to access this part of the administration control panel."; - -// Super Administrator required -$l['cannot_perform_action_super_admin_general'] = "Sorry, but you cannot perform this action because you are not a super administrator.

    To be able to perform this action, you need to add your user ID to the list of super administrators in inc/config.php."; - -// AJAX -$l['loading_text'] = "Loading
    Please wait..."; - -// Time zone selection boxes -$l['timezone_gmt_minus_1200'] = "(GMT -12:00) Howland and Baker Islands"; -$l['timezone_gmt_minus_1100'] = "(GMT -11:00) Nome, Midway Island"; -$l['timezone_gmt_minus_1000'] = "(GMT -10:00) Hawaii, Papeete"; -$l['timezone_gmt_minus_950'] = "(GMT -9:30) Marquesas Islands"; -$l['timezone_gmt_minus_900'] = "(GMT -9:00) Alaska"; -$l['timezone_gmt_minus_800'] = "(GMT -8:00) Pacific Time"; -$l['timezone_gmt_minus_700'] = "(GMT -7:00) Mountain Time"; -$l['timezone_gmt_minus_600'] = "(GMT -6:00) Central Time, Mexico City"; -$l['timezone_gmt_minus_500'] = "(GMT -5:00) Eastern Time, Bogota, Lima, Quito"; -$l['timezone_gmt_minus_450'] = "(GMT -4:30) Caracas"; -$l['timezone_gmt_minus_400'] = "(GMT -4:00) Atlantic Time, La Paz, Halifax"; -$l['timezone_gmt_minus_350'] = "(GMT -3:30) Newfoundland"; -$l['timezone_gmt_minus_300'] = "(GMT -3:00) Brazil, Buenos Aires, Georgetown, Falkland Is."; -$l['timezone_gmt_minus_200'] = "(GMT -2:00) Mid-Atlantic, South Georgia and the South Sandwich Islands"; -$l['timezone_gmt_minus_100'] = "(GMT -1:00) Azores, Cape Verde Islands"; -$l['timezone_gmt'] = "(GMT) Casablanca, Dublin, Edinburgh, London, Lisbon, Monrovia"; -$l['timezone_gmt_100'] = "(GMT +1:00) Berlin, Brussels, Copenhagen, Madrid, Paris, Rome, Warsaw"; -$l['timezone_gmt_200'] = "(GMT +2:00) Athens, Istanbul, Cairo, Jerusalem, South Africa"; -$l['timezone_gmt_300'] = "(GMT +3:00) Kaliningrad, Minsk, Baghdad, Riyadh, Nairobi"; -$l['timezone_gmt_350'] = "(GMT +3:30) Tehran"; -$l['timezone_gmt_400'] = "(GMT +4:00) Moscow, Abu Dhabi, Baku, Muscat, Tbilisi"; -$l['timezone_gmt_450'] = "(GMT +4:30) Kabul"; -$l['timezone_gmt_500'] = "(GMT +5:00) Islamabad, Karachi, Tashkent"; -$l['timezone_gmt_550'] = "(GMT +5:30) Mumbai, Kolkata, Chennai, New Delhi"; -$l['timezone_gmt_575'] = "(GMT +5:45) Kathmandu"; -$l['timezone_gmt_600'] = "(GMT +6:00) Almaty, Dhakra, Yekaterinburg"; -$l['timezone_gmt_650'] = "(GMT +6:30) Yangon"; -$l['timezone_gmt_700'] = "(GMT +7:00) Bangkok, Hanoi, Jakarta"; -$l['timezone_gmt_800'] = "(GMT +8:00) Beijing, Hong Kong, Perth, Singapore, Taipei, Manila"; -$l['timezone_gmt_850'] = "(GMT +8:30) Pyongyang"; -$l['timezone_gmt_875'] = "(GMT +8:45) Eucla"; -$l['timezone_gmt_900'] = "(GMT +9:00) Osaka, Sapporo, Seoul, Tokyo, Irkutsk"; -$l['timezone_gmt_950'] = "(GMT +9:30) Adelaide, Darwin"; -$l['timezone_gmt_1000'] = "(GMT +10:00) Melbourne, Papua New Guinea, Sydney, Yakutsk"; -$l['timezone_gmt_1050'] = "(GMT +10:30) Lord Howe Island"; -$l['timezone_gmt_1100'] = "(GMT +11:00) Magadan, New Caledonia, Solomon Islands, Vladivostok"; -$l['timezone_gmt_1150'] = "(GMT +11:30) Norfolk Island"; -$l['timezone_gmt_1200'] = "(GMT +12:00) Auckland, Wellington, Fiji, Marshall Islands"; -$l['timezone_gmt_1275'] = "(GMT +12:45) Chatham Islands"; -$l['timezone_gmt_1300'] = "(GMT +13:00) Samoa, Tonga, Tokelau"; -$l['timezone_gmt_1400'] = "(GMT +14:00) Line Islands"; -$l['timezone_gmt_short'] = "GMT {1}({2})"; - -// Global language strings used for log deletion pages -$l['confirm_delete_logs'] = "Prune the selected log entries?"; -$l['confirm_delete_all_logs'] = "Prune all log entries?"; -$l['selected_logs_deleted'] = "The selected log entries have been deleted."; -$l['all_logs_deleted'] = "All log entries have been deleted."; -$l['delete_selected'] = "Delete Selected"; -$l['delete_all'] = "Delete All Filtered"; - -// Misc -$l['encountered_errors'] = "The following errors were encountered:"; -$l['invalid_post_verify_key'] = "An authorization code mismatch occurred. Please confirm that you wish to perform the action below."; -$l['invalid_post_verify_key2'] = "An authorization code mismatch occurred. Please double check that you are accessing this page correctly."; -$l['unknown_error'] = "An unknown error has occurred."; - -// Code buttons editor language strings -$l['editor_bold'] = "Bold"; -$l['editor_italic'] = "Italic"; -$l['editor_underline'] = "Underline"; -$l['editor_strikethrough'] = "Strikethrough"; -$l['editor_subscript'] = "Subscript"; -$l['editor_superscript'] = "Superscript"; -$l['editor_alignleft'] = "Align left"; -$l['editor_center'] = "Center"; -$l['editor_alignright'] = "Align right"; -$l['editor_justify'] = "Justify"; -$l['editor_fontname'] = "Font Name"; -$l['editor_fontsize'] = "Font Size"; -$l['editor_fontcolor'] = "Font Color"; -$l['editor_removeformatting'] = "Remove Formatting"; -$l['editor_cut'] = "Cut"; -$l['editor_copy'] = "Copy"; -$l['editor_paste'] = "Paste"; -$l['editor_cutnosupport'] = "Your browser does not allow the cut command. Please use the keyboard shortcut Ctrl/Cmd-X"; -$l['editor_copynosupport'] = "Your browser does not allow the copy command. Please use the keyboard shortcut Ctrl/Cmd-C"; -$l['editor_pastenosupport'] = "Your browser does not allow the paste command. Please use the keyboard shortcut Ctrl/Cmd-V"; -$l['editor_pasteentertext'] = "Paste your text inside the following box:"; -$l['editor_pastetext'] = "Paste Text"; -$l['editor_numlist'] = "Numbered list"; -$l['editor_bullist'] = "Bullet list"; -$l['editor_undo'] = "Undo"; -$l['editor_redo'] = "Redo"; -$l['editor_rows'] = "Rows:"; -$l['editor_cols'] = "Cols:"; -$l['editor_inserttable'] = "Insert a table"; -$l['editor_inserthr'] = "Insert a horizontal rule"; -$l['editor_code'] = "Code"; -$l['editor_php'] = "PHP"; -$l['editor_width'] = "Width (optional):"; -$l['editor_height'] = "Height (optional):"; -$l['editor_insertimg'] = "Insert an image"; -$l['editor_email'] = "E-mail:"; -$l['editor_insertemail'] = "Insert an email"; -$l['editor_url'] = "URL:"; -$l['editor_insertlink'] = "Insert a link"; -$l['editor_unlink'] = "Unlink"; -$l['editor_more'] = "More"; -$l['editor_insertemoticon'] = "Insert an emoticon"; -$l['editor_videourl'] = "Video URL:"; -$l['editor_videotype'] = "Video Type:"; -$l['editor_insert'] = "Insert"; -$l['editor_insertyoutubevideo'] = "Insert a YouTube video"; -$l['editor_currentdate'] = "Insert current date"; -$l['editor_currenttime'] = "Insert current time"; -$l['editor_print'] = "Print"; -$l['editor_viewsource'] = "View source"; -$l['editor_description'] = "Description (optional):"; -$l['editor_enterimgurl'] = "Enter the image URL:"; -$l['editor_enteremail'] = "Enter the e-mail address:"; -$l['editor_enterdisplayedtext'] = "Enter the displayed text:"; -$l['editor_enterurl'] = "Enter URL:"; -$l['editor_enteryoutubeurl'] = "Enter the YouTube video URL or ID:"; -$l['editor_insertquote'] = "Insert a Quote"; -$l['editor_invalidyoutube'] = "Invalid YouTube video"; -$l['editor_dailymotion'] = "Dailymotion"; -$l['editor_metacafe'] = "MetaCafe"; -$l['editor_veoh'] = "Veoh"; -$l['editor_vimeo'] = "Vimeo"; -$l['editor_youtube'] = "Youtube"; -$l['editor_facebook'] = "Facebook"; -$l['editor_liveleak'] = "LiveLeak"; -$l['editor_insertvideo'] = "Insert a video"; -$l['editor_maximize'] = "Maximize"; - -$l['missing_task'] = "Error: Task file does not exist"; -$l['task_backup_cannot_write_backup'] = "Error: The database backup task cannot write to backups directory."; -$l['task_backup_ran'] = "The database backup task successfully ran."; -$l['task_checktables_ran'] = "The check tables task successfully ran with no corrupted tables found."; -$l['task_checktables_ran_found'] = "Notice: The check tables task successfully ran and repaired the {1} table(s)."; -$l['task_dailycleanup_ran'] = "The daily cleanup task successfully ran."; -$l['task_hourlycleanup_ran'] = "The hourly cleanup task successfully ran."; -$l['task_logcleanup_ran'] = "The log cleanup task successfully ran and pruned any old logs."; -$l['task_promotions_ran'] = "The promotions task successfully ran."; -$l['task_threadviews_ran'] = "The thread views task successfully ran."; -$l['task_usercleanup_ran'] = "The user cleanup task successfully ran."; -$l['task_massmail_ran'] = "The mass mail task successfully ran."; -$l['task_userpruning_ran'] = "The user pruning task successfully ran."; -$l['task_delayedmoderation_ran'] = "The delayed moderation task successfully ran."; -$l['task_massmail_ran_errors'] = "One or more problems occurred sending to \"{1}\": -{2}"; -$l['task_versioncheck_ran'] = "The version check task successfully ran."; -$l['task_versioncheck_ran_errors'] = "Could not connect to MyBB for a version check."; -$l['task_recachestylesheets_ran'] = 'Re-cached {1} stylesheets.'; - -$l['massmail_username'] = "Username"; -$l['email_addr'] = "Email Address"; -$l['board_name'] = "Board Name"; -$l['board_url'] = "Board URL"; - -// Unlock ACP -$l['lockout_unlock'] = "Unlock Admin Control Panel"; -$l['enter_username_and_token'] = "Please enter your username and the activation code to continue."; -$l['unlock_token'] = "Activation code:"; -$l['unlock_account'] = "Unlock Account"; - -// Email message for if an admin account has been locked out -$l['locked_out_subject'] = "Administrator Account Locked Out at {1}"; -$l['locked_out_message'] = "{1}, - -Your administrator account at {2} has been locked after {3} failed login attempts. - -To unlock your account, please go to the URL below in your web browser. - -{4}/{5}/index.php?action=unlock&uid={7}&token={6} - -If the above link does not work correctly, go to - -{4}/{5}/index.php?action=unlock - -You will need to enter the following: -Username: {1} -Activation Code: {6} - -Thank you, -{2} Staff"; - -$l['comma'] = ", "; - -$l['search_for_a_user'] = "Search for a user"; - -$l['mybb_engine'] = "MyBB Engine"; - -// If the language string for "Username" is too cramped in the ACP Login box -// then use this to define how much larger you want the gap to be (in px) -// $l['login_field_width'] = "0"; - -$l['my2fa'] = "Two-Factor Authentication"; -$l['my2fa_failed'] = "The code was incorrect, you're logged out now"; -$l['my2fa_code'] = "Please enter the authentication code"; -$l['my2fa_label'] = "Authentication code:"; -$l['my2fa_no_codes'] = "Note: you've used all of your recovery codes. Please visit the recovery codes page to generate a new set."; diff --git a/html/forums/inc/languages/english/admin/hello.lang.php b/html/forums/inc/languages/english/admin/hello.lang.php deleted file mode 100644 index 591be4d..0000000 --- a/html/forums/inc/languages/english/admin/hello.lang.php +++ /dev/null @@ -1,23 +0,0 @@ -Check for Updates."; -$l['success_credits_updated'] = 'The MyBB credits cache has been successfully updated.'; diff --git a/html/forums/inc/languages/english/admin/home_dashboard.lang.php b/html/forums/inc/languages/english/admin/home_dashboard.lang.php deleted file mode 100644 index 890764c..0000000 --- a/html/forums/inc/languages/english/admin/home_dashboard.lang.php +++ /dev/null @@ -1,54 +0,0 @@ -MyBB version check was more than two weeks ago."; -$l['new_version_available'] = "You are currently running {1} whilst the latest generally available release is {2}."; -$l['version_check_description'] = "Here you can check that you are currently running the latest copy of MyBB and see the latest announcements directly from MyBB."; -$l['latest_mybb_announcements'] = "Latest MyBB Announcements"; -$l['no_announcements'] = "No stored announcements. Check for Updates."; -$l['your_version'] = "Your Version"; -$l['latest_version'] = "Latest Version"; -$l['update_forum'] = "Please upgrade to the latest version of MyBB by visiting the MyBB Website."; -$l['read_more'] = "Read more"; - -$l['success_up_to_date'] = "Congratulations, you are running the latest version of MyBB."; - -$l['error_out_of_date'] = "Your copy of MyBB is out of date."; -$l['error_communication'] = "There was a problem communicating with the version server. Please try again in a few minutes."; -$l['error_fetch_news'] = "MyBB was unable to successfully fetch the latest announcements from the MyBB website."; - -$l['news_description'] = "The latest news from the MyBB Blog."; - -$l['admin_notes_public'] = "These notes are public to all administrators."; -$l['admin_notes'] = "Administrator Notes"; -$l['save_notes'] = "Save Notes"; - -$l['success_notes_updated'] = "The administrator notes have been successfully updated."; diff --git a/html/forums/inc/languages/english/admin/home_module_meta.lang.php b/html/forums/inc/languages/english/admin/home_module_meta.lang.php deleted file mode 100644 index 5ce2d52..0000000 --- a/html/forums/inc/languages/english/admin/home_module_meta.lang.php +++ /dev/null @@ -1,24 +0,0 @@ -like Google Authenticator or Authy. Those apps will generate a token which you need to enter on every acp login."; -$l['my2fa_qr'] = "Two-Factor Authentication Code"; -$l['recovery_codes_desc'] = "View your recovery codes."; -$l['recovery_codes'] = "Recovery Codes"; -$l['recovery_codes_warning'] = "Note: the codes will be regenerated on every page visit and can be only used once."; -$l['print_recovery_codes'] = "Print Recovery Codes"; \ No newline at end of file diff --git a/html/forums/inc/languages/english/admin/index.html b/html/forums/inc/languages/english/admin/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/languages/english/admin/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/languages/english/admin/style_module_meta.lang.php b/html/forums/inc/languages/english/admin/style_module_meta.lang.php deleted file mode 100644 index 3f3ff16..0000000 --- a/html/forums/inc/languages/english/admin/style_module_meta.lang.php +++ /dev/null @@ -1,15 +0,0 @@ -{1}'"; -$l['search_noresults_title'] = "No templates were found with the title '{1}'"; -$l['default_templates'] = "Default Templates"; - -$l['edit_template_breadcrumb'] = "Edit Template: "; - -$l['global_templates'] = "Global Templates"; -$l['master_templates'] = "Master Templates"; - -$l['not_used_by_any_themes'] = "Not used by any themes"; -$l['used_by'] = "Used by: "; -$l['used_by_all_themes'] = "Used by all themes"; - -$l['expand_templates'] = "Expand Templates"; -$l['edit_template_set'] = "Edit Template Set"; -$l['delete_template_set'] = "Delete Template Set"; -$l['empty_template_set'] = "There are no templates in this set."; - -$l['inline_edit'] = "Inline Edit"; -$l['full_edit'] = "Full Edit"; -$l['revert_to_orig'] = "Revert to Original"; -$l['delete_template'] = "Delete Template"; -$l['edit_in'] = "Edit in"; - -$l['group_calendar'] = "Calendar"; -$l['group_forumdisplay'] = "Forum Display"; -$l['group_index'] = "Index Page"; -$l['group_error'] = "Error Message"; -$l['group_memberlist'] = "Member List"; -$l['group_multipage'] = "Multipage Pagination"; -$l['group_private'] = "Private Messaging"; -$l['group_portal'] = "Portal"; -$l['group_postbit'] = "Post Bit"; -$l['group_posticons'] = "Post Icon"; -$l['group_showthread'] = "Show Thread"; -$l['group_usercp'] = "User Control Panel"; -$l['group_online'] = "Who's Online"; -$l['group_forumbit'] = "Forum Bit"; -$l['group_editpost'] = "Edit Post"; -$l['group_forumjump'] = "Forum Jump"; -$l['group_moderation'] = "Moderation"; -$l['group_nav'] = "Navigation"; -$l['group_search'] = "Search"; -$l['group_showteam'] = "Show Forum Team"; -$l['group_reputation'] = "Reputation"; -$l['group_newthread'] = "New Thread"; -$l['group_newreply'] = "New Reply"; -$l['group_member'] = "Member"; -$l['group_warning'] = "Warning System"; -$l['group_global'] = "Global"; -$l['group_header'] = "Header"; -$l['group_managegroup'] = "Manage Group"; -$l['group_misc'] = "Miscellaneous"; -$l['group_modcp'] = "Moderator Control Panel"; -$l['group_announcement'] = "Announcement"; -$l['group_polls'] = "Poll"; -$l['group_post'] = "Post"; -$l['group_printthread'] = "Print Thread"; -$l['group_report'] = "Report"; -$l['group_smilieinsert'] = "Smilie Inserter"; -$l['group_stats'] = "Statistics"; -$l['group_xmlhttp'] = "XMLHTTP"; -$l['group_footer'] = "Footer"; -$l['group_video'] = "Video MyCode"; -$l['group_sendthread'] = "Send Thread"; -$l['group_mycode'] = "MyCode"; - -$l['expand'] = "Expand"; -$l['collapse'] = "Collapse"; - -$l['save_continue'] = "Save and Continue Editing"; -$l['save_close'] = "Save and Return to Listing"; - -$l['template_name'] = "Template Name"; -$l['template_name_desc'] = "Name of the template. If you change this on the default template, it will save the template as a custom template under the new name."; -$l['template_set_desc'] = "Which template set should this template be in?"; - -$l['template_group_prefix'] = "Template Group Prefix"; -$l['template_group_prefix_desc'] = "The prefix name to group templates. This must not already exist. For example, to group templates hello_world, hello_foobar and hello_foo, enter hello here."; -$l['template_group_title'] = "Template Group Title"; -$l['template_group_title_desc'] = "The title of the prefix group. This will be shown in the templates list. For example, for our hello templates, enter Hello here."; - -$l['edit_template_group'] = "Edit Template Group"; -$l['editing_template_group'] = "Editing Template Group {1}"; -$l['delete_template_group'] = "Delete Template Group"; -$l['save_template_group'] = "Save Template Group"; - -$l['templates_the_same'] = "The two templates you've selected are both the same and cannot be compared."; -$l['master_updated_ins'] = "Changes that have been made between your previous version and this one are highlighted like this."; -$l['master_updated_del'] = "Any customizations you've made to your templates (the old ones) are highlighted like this."; -$l['template_diff_analysis'] = "Template Difference Analysis"; -$l['search_names_header'] = "Searching template names containing \"{1}\""; - -$l['updated_template_welcome1'] = "Edit - Allows you to edit the current template for this template set to incorporate updates made between the versions."; -$l['updated_template_welcome2'] = "Revert - Will revert the customized template back to the master revision, however you'll lose any custom changes you have made."; -$l['updated_template_welcome3'] = "Diff - Performs a difference analysis between the templates and shows you exactly what changes have been made between your customized copy and the latest master copy."; - -$l['no_global_templates'] = "There are currently no global templates."; -$l['no_updated_templates'] = "There are currently no templates which have been updated since you last upgraded."; - -$l['confirm_template_set_deletion'] = "Are you sure you want to delete this template set?"; -$l['confirm_template_group_delete'] = "Are you sure you want to delete this template group? This action does not remove the templates in the group."; -$l['confirm_template_deletion'] = "Are you sure you want to delete this template?"; -$l['confirm_template_revertion'] = "Are you sure you want to revert this template?"; - -$l['error_security_problem'] = "A potential security issue was found in the template. Please review your changes or contact the MyBB Group for support."; -$l['error_missing_input'] = "Please make sure you have all the input required to edit this template (tid and sid)"; -$l['error_already_exists'] = "The template title is already in use. Please use a different title."; -$l['error_invalid_template'] = "Please select a valid template."; -$l['error_missing_set_title'] = "Please select a template set title."; -$l['error_invalid_input'] = "Please make sure you have the correct template set ID."; -$l['error_invalid_set'] = "Please select a valid template set."; -$l['error_invalid_template_set'] = "Invalid template set selected."; -$l['error_themes_attached_template_set'] = "This template set cannot be deleted as there are themes attached to this template set."; -$l['error_missing_group_prefix'] = "Please enter a prefix for the template group."; -$l['error_invalid_group_title'] = "As underscores (_) are used as delimiter those are forbidden in template group prefixes. Please select another prefix."; -$l['error_missing_group_title'] = "Please enter a title for the template group."; -$l['error_duplicate_group_prefix'] = "A template group already exists with this prefix. Please enter another prefix."; -$l['error_missing_template_group'] = "The template group could not be found."; -$l['error_default_template_group'] = "You cannot edit or remove a default template group."; - -$l['success_template_saved'] = "The selected template has successfully been saved."; -$l['success_template_deleted'] = "The selected template has successfully been deleted."; -$l['success_template_reverted'] = "The selected template has successfully been reverted."; -$l['success_template_set_saved'] = "The selected template set has successfully been saved."; -$l['success_template_set_deleted'] = "The selected template set has successfully been deleted."; -$l['success_template_group_saved'] = "The selected template group has successfully been saved."; -$l['success_template_group_deleted'] = "The selected template group has successfully been deleted."; diff --git a/html/forums/inc/languages/english/admin/style_themes.lang.php b/html/forums/inc/languages/english/admin/style_themes.lang.php deleted file mode 100644 index 0d71ebe..0000000 --- a/html/forums/inc/languages/english/admin/style_themes.lang.php +++ /dev/null @@ -1,220 +0,0 @@ -Template sets, stylesheets, and other settings are inherited from the parent theme."; - -$l['import_a_theme'] = "Import a Theme"; -$l['import_a_theme_desc'] = "Here you can import new themes. You may import a theme from your computer, or a remote URL."; - -$l['edit_stylesheets'] = "Edit Stylesheets"; -$l['edit_stylesheets_desc'] = "Here you can easily manage the stylesheets in use by this theme. Stylesheets are based on CSS and define the fonts, colors and other visual aspects for this theme. A list of stylesheets attached to this theme is below."; - -$l['add_stylesheet'] = "Add Stylesheet"; -$l['add_stylesheet_desc'] = "Here you can add a new stylesheet to this theme. A stylesheet contains CSS that allows you to customize the appearance of this theme. You will be taken to the stylesheet edit page following creation."; - -$l['browse_themes'] = "Browse Themes"; -$l['browse_themes_desc'] = "Here you may browse the official MyBB modifications site for themes compatible with your series of MyBB."; - -$l['browse_all_themes'] = "Browse All Themes"; - -$l['export_theme'] = "Export Theme"; -$l['export_theme_desc'] = "Here you can export your themes and customized templates. Exporting themes is useful if you wish to share them with others or import them to another forum."; - -$l['duplicate_theme'] = "Duplicate Theme"; -$l['duplicate_theme_desc'] = "Here you can duplicate your themes. This helps you if you want to develop another version of it."; - -$l['colors_manage'] = "Manage Colors"; -$l['colors_attached_to'] = "color setting"; -$l['colors_setting'] = "Base Color"; -$l['colors_setting_desc'] = "Select the color this theme should use as its base color. Stylesheets attached to this color will be used."; -$l['colors_no_color_setting'] = "There are no colors available. Please create a list of colors below to use this feature."; -$l['colors_add'] = "Manage Colors"; -$l['colors_add_desc'] = "A list of colors available for this theme. This should be a list of key paired (key=item) colors, for example, blue=Blue. Separate items with a new line."; -$l['colors_please_select'] = "None"; -$l['colors_add_edit_desc'] = "Select a color to attach this stylesheet to. You can select more than one color."; -$l['colors_specific_color'] = "Specific color"; - -$l['include_custom_only'] = "Include customized items only?"; -$l['include_custom_only_desc'] = "If you wish to include items (css and stylesheets) inherited from parent themes select \"no\", otherwise only customized elements will be exported."; -$l['include_templates'] = "Include templates in the export as well?"; -$l['include_templates_desc'] = "If you want to export the customized templates used in this theme as well, select yes."; - -$l['edit_stylesheet_simple_mode'] = "Edit Stylesheet: Simple Mode"; -$l['edit_stylesheet_simple_mode_desc'] = "Here you can easily edit your theme's stylesheet. Simple mode allows you to customize the CSS in this stylesheet with little or no knowledge of CSS. Begin by selecting an item below."; -$l['edit_stylesheet_advanced_mode'] = "Edit Stylesheet: Advanced Mode"; -$l['edit_stylesheet_advanced_mode_desc'] = "Here you can edit this stylesheet like a flat file. The contents of the CSS stylesheet is shown in the text area below."; - -$l['theme'] = "Theme"; -$l['num_users'] = "# Users"; -$l['edit_theme'] = "Edit Theme"; -$l['delete_theme'] = "Delete Theme"; -$l['set_as_default'] = "Set as Default"; -$l['default_theme'] = "Default Theme"; -$l['force_on_users'] = "Force on Users"; -$l['delete_revert'] = "Delete / Revert"; - -$l['local_file'] = "Local File"; -$l['url'] = "URL"; -$l['import_from'] = "Import from"; -$l['import_from_desc'] = "Select a file to import. You can either import the theme file from your computer or from a URL."; -$l['parent_theme'] = "Parent Theme"; -$l['parent_theme_desc'] = "Select the theme this theme should be a child of."; -$l['new_name'] = "New Name"; -$l['new_name_desc'] = "A new name for the imported theme. If left blank, the name in the theme file will be used."; -$l['advanced_options'] = "Advanced Options"; -$l['ignore_version_compatibility'] = "Ignore Version Compatibility"; -$l['ignore_version_compat_desc'] = "Should this theme be installed regardless of the version of MyBB it was created for?"; -$l['import_stylesheets'] = "Import Stylesheets"; -$l['import_stylesheets_desc'] = "If this theme contains custom stylesheets should they be imported?"; -$l['import_templates'] = "Import Templates"; -$l['import_templates_desc'] = "If this theme contains custom templates should they be imported?"; -$l['import_theme'] = "Import Theme"; - -$l['new_name_duplicate_desc'] = "A new name for the duplicated theme."; -$l['duplicate_stylesheets'] = "Duplicate Stylesheets"; -$l['duplicate_stylesheets_desc'] = "If this theme contains custom stylesheets should they be duplicated?"; -$l['duplicate_templates'] = "Duplicate Templates"; -$l['duplicate_templates_desc'] = "If this theme contains custom templates should they be duplicated?"; - -$l['create_a_theme'] = "Create a Theme"; -$l['name'] = "Name"; -$l['name_desc'] = "Specify a name for the new theme."; -$l['display_order'] = "Order"; - -$l['edit_theme_properties'] = "Edit Theme Properties"; -$l['name_desc_edit'] = "Specify a name for the theme."; -$l['allowed_user_groups'] = "Allowed User Groups"; -$l['allowed_user_groups_desc'] = "Specify which user groups are allowed to use this theme. Selecting 'All User Groups' will override any other selection. Hold down the CTRL key to select multiple user groups."; -$l['all_user_groups'] = "All User Groups"; -$l['template_set'] = "Template Set"; -$l['template_set_desc'] = "Specify the template set the theme should use. The selected template set defines the markup (HTML) used in presenting the theme."; -$l['editor_theme'] = "Editor Style"; -$l['editor_theme_desc'] = "Specify the style to be used for the MyCode editor in this theme. Editor styles can be found in the jscripts/editor_themes folder."; -$l['img_directory'] = "Image Directory"; -$l['img_directory_desc'] = "The root directory for the location of the images used in this theme. Note that this only specifies the directory for the images used in templates, not the stylesheets."; -$l['logo'] = "Board Logo"; -$l['logo_desc'] = "Location of the board logo used in this theme (this is the logo that appears at the top of each page)."; -$l['table_spacing'] = "Table Spacing"; -$l['table_spacing_desc'] = "The width of the inner padding of table cells, in pixels. This is HTML's cellpadding attribute of the table tag."; -$l['inner_border'] = "Inner Table Border Width"; -$l['inner_border_desc'] = "The amount of padding between each table cell, in pixels. This is HTML's cellspacing attribute of the table tag."; -$l['save_theme_properties'] = "Save Theme Properties"; -$l['save_stylesheet_order'] = "Save Stylesheet Orders"; - -$l['background'] = "Background"; -$l['extra_css_atribs'] = "Extra CSS Attributes"; -$l['color'] = "Color"; -$l['width'] = "Width"; -$l['text_decoration'] = "Text Decoration"; -$l['font_family'] = "Font Family"; -$l['font_size'] = "Font Size"; -$l['font_style'] = "Font Style"; -$l['font_weight'] = "Font Weight"; - -$l['stylesheets'] = "Stylesheets"; -$l['inherited_from'] = "Inherited from"; -$l['attached_to'] = "Attached to"; -$l['attached_to_nothing'] = "Attached to nothing"; -$l['attached_to_desc'] = "You can either attach stylesheets globally or to specific files. If you attach it to specific files you can attach it to specific actions within each file."; -$l['actions'] = "actions"; -$l['of'] = "of"; -$l['attached_to_all_pages'] = "Attached to all pages"; -$l['properties'] = "Properties"; -$l['edit_style'] = "Edit Style"; -$l['stylesheets_in'] = "Stylesheets in"; -$l['stylesheet_properties'] = "Stylesheet Properties"; -$l['stylesheet_inherited_default'] = "This stylesheet is currently being inherited from {1}. Any changes you make will break the inheritance, and the stylesheet will be copied to this theme."; -$l['stylesheet_inherited'] = "This stylesheet is currently being inherited from {1}. Any changes you make will break the inheritance, and the stylesheet will be copied to this theme. Edit this stylesheet in {1} to keep the inheritance."; -$l['globally'] = "Globally"; -$l['specific_files'] = "Specific files"; -$l['specific_actions'] = "Specific actions"; -$l['specific_actions_desc'] = "Actions are separated by commas"; -$l['file'] = "File"; -$l['add_another'] = "Add another"; -$l['edit_stylesheet_properties_for'] = "Edit Stylesheet Properties for"; -$l['file_name'] = "File Name"; -$l['file_name_desc'] = "Name for the stylesheet, usually ending in [.css]"; -$l['save_stylesheet_properties'] = "Save Stylesheet Properties"; -$l['saved'] = "Saved"; -$l['editing'] = "Editing"; -$l['selector'] = "Selector"; -$l['save_changes'] = "Save Changes"; -$l['save_changes_and_close'] = "Save Changes & Close"; -$l['save_changes_js'] = "Do you want to save your changes first?"; -$l['delete_confirm_js'] = "Are you sure you want to delete this?"; -$l['import_stylesheet_from'] = "Import from another stylesheet in this theme"; -$l['write_own'] = "Write my own content"; -$l['save_stylesheet'] = "Save Stylesheet"; -$l['add_stylesheet_to'] = "Add Stylesheet to"; - -$l['full_stylesheet_for'] = "Full Stylesheet for"; - -$l['recommended_themes_for_mybb'] = "Recommended Themes for MyBB {1}"; -$l['browse_results_for_mybb'] = "Browse Results for MyBB {1}"; -$l['search_for_themes'] = "Search for Themes"; -$l['search'] = "Search"; -$l['download'] = "Download"; -$l['created_by'] = "Created by"; - -$l['error_invalid_stylesheet'] = "You have selected an invalid stylesheet."; -$l['error_invalid_theme'] = "You have selected an invalid theme."; -$l['error_missing_name'] = "Please enter a name for this theme."; -$l['error_missing_url'] = "Please enter a valid url to import a theme from."; -$l['error_theme_already_exists'] = "A theme with the same name already exists. Please specify a different name."; -$l['error_theme_security_problem'] = "A potential security issue was found in the theme. It was not imported. Please contact the Author or MyBB Group for support."; - -$l['error_local_file'] = "Could not open the local file. Does it exist? Please check and try again."; -$l['error_uploadfailed'] = "Upload failed. Please try again."; -$l['error_uploadfailed_detail'] = "Error details: "; -$l['error_uploadfailed_php1'] = "PHP returned: Uploaded file exceeded upload_max_filesize directive in php.ini. Please contact your forum administrator with this error."; -$l['error_uploadfailed_php2'] = "The uploaded file exceeded the maximum file size specified."; -$l['error_uploadfailed_php3'] = "The uploaded file was only partially uploaded."; -$l['error_uploadfailed_php4'] = "No file was uploaded."; -$l['error_uploadfailed_php6'] = "PHP returned: Missing a temporary folder. Please contact your forum administrator with this error."; -$l['error_uploadfailed_php7'] = "PHP returned: Failed to write the file to disk. Please contact your forum administrator with this error."; -$l['error_uploadfailed_phpx'] = "PHP returned error code: {1}. Please contact your forum administrator with this error."; -$l['error_uploadfailed_lost'] = "The file could not be found on the server."; -$l['error_uploadfailed_nocontents'] = "MyBB could not find the theme with the file you uploaded. Please check the file is the correct and is not corrupt."; -$l['error_invalid_version'] = "This theme has been written for another version of MyBB. Please check the \"Ignore Version Compatibility\" to ignore this error."; -$l['error_missing_stylesheet_name'] = "Please enter a name for this stylesheet."; -$l['error_missing_stylesheet_extension'] = "This stylesheet must end with the correct file extension, for example, {1}.css"; -$l['error_invalid_parent_theme'] = "The selected parent theme does not exist. Please select a valid parent theme."; -$l['error_invalid_templateset'] = "The selected template set does not exist. Please select a valid template set."; -$l['error_invalid_editortheme'] = "The selected editor theme does not exist. Please select a valid editor theme."; -$l['error_inheriting_stylesheets'] = "You cannot delete this theme because there are still other themes that are inheriting stylesheets from it."; -$l['error_cannot_parse'] = "MyBB cannot parse this stylesheet for the simple editor. It can only be edited in advanced mode."; -$l['error_communication_problem'] = "There was a problem communicating with the MyBB themes server. Please try again in a few minutes."; -$l['error_no_results_found'] = "No results were found for the specified keyword(s)."; -$l['error_no_color_picked'] = "You didn't specify which colors to attach this stylesheet to."; -$l['error_no_display_order'] = "There was an error finding the display orders for the stylesheets. Please refresh the page and try again."; - -$l['success_duplicated_theme'] = "The selected theme has been duplicated successfully."; -$l['success_imported_theme'] = "The selected theme has been imported successfully."; -$l['success_theme_created'] = "The theme has been created successfully."; -$l['success_theme_deleted'] = "The selected theme has been deleted successfully."; -$l['success_stylesheet_properties_updated'] = "The properties for the selected stylesheet have been updated successfully."; -$l['success_stylesheet_updated'] = "The selected stylesheet has been updated successfully."; -$l['success_stylesheet_deleted'] = "The selected stylesheet has been deleted / reverted successfully."; -$l['success_theme_set_default'] = "The selected theme is now the forum default."; -$l['success_theme_forced'] = "All users have been forced to use the selected theme successfully."; -$l['success_theme_properties_updated'] = "The properties for the select theme have been updated successfully."; -$l['success_stylesheet_added'] = "The stylesheet for this theme has been created successfully."; -$l['success_stylesheet_order_updated'] = "The display orders for the stylesheets have been updated successfully."; - -$l['confirm_theme_deletion'] = "Are you sure you want to delete this theme?"; -$l['confirm_stylesheet_deletion'] = "Are you sure you want to delete / revert this stylesheet?"; -$l['confirm_theme_forced'] = "Are you sure you want to force this theme on all users?"; - -$l['theme_info_fetch_error'] = 'There was an error fetching the style info.'; -$l['theme_info_save_error'] = 'There was an error saving the style info.'; - -$l['saving'] = 'Saving...'; - diff --git a/html/forums/inc/languages/english/admin/tools_adminlog.lang.php b/html/forums/inc/languages/english/admin/tools_adminlog.lang.php deleted file mode 100644 index 45f8334..0000000 --- a/html/forums/inc/languages/english/admin/tools_adminlog.lang.php +++ /dev/null @@ -1,311 +0,0 @@ - Please note, this process can not differentiate between custom modifications and actual corruption in files. Therefore you should take caution in reverting files this process returns as \"corrupt\"."; - -$l['error_communication'] = "There was a problem communicating with the MyBB server. Please try again in a few minutes."; -$l['file'] = "File"; -$l['no_corrupt_files_found'] = "Congratulations! No corrupt files have been found on your installation."; -$l['found_problems'] = "Found Problems"; -$l['no_problems_found'] = "No Problems Detected"; -$l['changed'] = "Changed"; -$l['missing'] = "Missing"; -$l['status'] = "Status"; - diff --git a/html/forums/inc/languages/english/admin/tools_mailerrors.lang.php b/html/forums/inc/languages/english/admin/tools_mailerrors.lang.php deleted file mode 100644 index 20dc01d..0000000 --- a/html/forums/inc/languages/english/admin/tools_mailerrors.lang.php +++ /dev/null @@ -1,31 +0,0 @@ -(requires MySQL 5.5.3 or above)"; -$l['not_available'] = "Not available"; -$l['all_tables'] = "All Tables"; -$l['convert_now'] = "Convert Now"; -$l['totals'] = "Totals"; -$l['attachments'] = "Attachments"; -$l['total_database_size'] = "Total Database Size"; -$l['attachment_space_used'] = "Attachment Space used"; -$l['total_cache_size'] = "Total Cache Size"; -$l['estimated_attachment_bandwidth_usage'] = "Estimated Attachment Bandwidth Usage"; -$l['max_upload_post_size'] = "Max Upload / POST Size"; -$l['average_attachment_size'] = "Average Attachment Size"; -$l['stats'] = "Stats"; -$l['task'] = "Task"; -$l['run_time'] = "Run Time"; -$l['next_3_tasks'] = "Next 3 Tasks"; -$l['no_tasks'] = "There are no tasks running at this time."; -$l['backup_time'] = "Backup Time"; -$l['no_backups'] = "There are currently no backups made yet."; -$l['existing_db_backups'] = "Existing Database Backups"; -$l['writable'] = "Writable"; -$l['not_writable'] = "Not Writable"; -$l['please_chmod_777'] = "Please CHMOD to 777."; -$l['chmod_info'] = "Please change the CHMOD settings to the ones specified with the file below. For more information on CHMODing, see the"; -$l['file'] = "File"; -$l['location'] = "Location"; -$l['settings_file'] = "Settings File"; -$l['config_file'] = "Configuration File"; -$l['file_upload_dir'] = "File Uploads Directory"; -$l['avatar_upload_dir'] = "Avatar Uploads Directory"; -$l['language_files'] = "Language Files"; -$l['backup_dir'] = "Backups Directory"; -$l['cache_dir'] = "Cache Directory"; -$l['themes_dir'] = "Themes Directory"; -$l['chmod_files_and_dirs'] = "CHMOD Files and Directories"; - -$l['notice_process_long_time'] = "This process may take up to several hours depending on the size of your forum and this table. It is highly recommend to create a database backup as this process can't be undone."; -$l['notice_mb4_warning'] = "4-Byte UTF-8 Support requires MySQL 5.5.3 or above. You will not be able to import your database on a MySQL server with another version."; - -$l['check_templates'] = "Check Templates"; -$l['check_templates_desc'] = "Checks all installed templates for known security issues."; -$l['check_templates_title'] = "Check Template Security"; -$l['check_templates_info'] = "This process will check your templates against security issues that could affect your forum and the server it runs on. This might take a while if you've installed many themes. -

    To start the process, press the 'Proceed' button below."; -$l['check_templates_info_desc'] = "The templates below matched known security issues. Please review them."; -$l['full_edit'] = "Full Edit"; - -$l['error_chmod'] = "of the required files and directories do not have proper CHMOD settings."; -$l['error_invalid_table'] = "The specified table does not exist."; -$l['error_db_encoding_not_set'] = "Your current setup of MyBB is not setup to use this tool yet. Please see the MyBB Docs for more information on how to set it up."; -$l['error_not_supported'] = "Your current Database Engine is not supported by the UTF-8 Conversion Tool."; -$l['error_invalid_input'] = "There was a problem checking the templates. Please try again or contact the MyBB Group for support."; -$l['error_master_templates_altered'] = "The Master Templates have been altered. Please contact the MyBB Group for support on how to alter these."; -$l['error_utf8mb4_version'] = "Your MySQL version doesn't support 4-Byte UTF-8 encoding."; - - -$l['warning_multiple_encodings'] = "It is recommend not to use different encodings in your database. This may cause unexpected behavior or MySQL errors."; -$l['warning_utf8mb4_config'] = "For full 4-Byte UTF-8 support you need to change \$config['database']['encoding'] = 'utf8'; to \$config['database']['encoding'] = 'utf8mb4'; in your inc/config.php."; - -$l['success_templates_checked'] = "Templates checked successfully - no security issues were found!"; -$l['success_all_tables_already_converted'] = "All tables have already been converted or are already in UTF-8 format."; -$l['success_table_converted'] = "The selected table \"{1}\" has been converted to UTF-8 successfully."; -$l['success_chmod'] = "All of the required files and directories have the proper CHMOD settings."; diff --git a/html/forums/inc/languages/english/admin/tools_tasks.lang.php b/html/forums/inc/languages/english/admin/tools_tasks.lang.php deleted file mode 100644 index a1729ac..0000000 --- a/html/forums/inc/languages/english/admin/tools_tasks.lang.php +++ /dev/null @@ -1,76 +0,0 @@ -WARNING: You are about to enable a task that is only meant to be run via cron (Please see the MyBB Docs for more information). Continue?"; -$l['no_tasks'] = "There are no tasks on your forum at this time."; - diff --git a/html/forums/inc/languages/english/admin/tools_warninglog.lang.php b/html/forums/inc/languages/english/admin/tools_warninglog.lang.php deleted file mode 100644 index 0e89b82..0000000 --- a/html/forums/inc/languages/english/admin/tools_warninglog.lang.php +++ /dev/null @@ -1,51 +0,0 @@ -*"; -$l['autocomplete_enabled'] = "Auto-complete is enabled in this field."; -$l['ban_reason'] = "Ban Reason"; -$l['ban_group'] = "Banned Group *"; -$l['ban_group_desc'] = "In order for this user to be banned they must be moved to a banned group."; -$l['ban_time'] = "Ban Length *"; - -//= Index -$l['user'] = "User"; -$l['moderation'] = "Moderation"; -$l['ban_lifts_on'] = "Ban Lifts On"; -$l['time_left'] = "Time Left"; -$l['permenantly'] = "permanently"; -$l['na'] = "N/A"; -$l['for'] = "for"; -$l['bannedby_x_on_x'] = "{1}
    Banned by {2} on {3} {4}"; -$l['lift'] = "Lift"; -$l['no_banned_users'] = "You don't have any banned users at the moment."; -$l['prune_threads_and_posts'] = "Prune Threads & Posts"; - -// Buttons -$l['ban_user'] = "Ban User"; -$l['update_ban'] = "Update Ban"; diff --git a/html/forums/inc/languages/english/admin/user_group_promotions.lang.php b/html/forums/inc/languages/english/admin/user_group_promotions.lang.php deleted file mode 100644 index 17ca67c..0000000 --- a/html/forums/inc/languages/english/admin/user_group_promotions.lang.php +++ /dev/null @@ -1,91 +0,0 @@ -Use {username} to represent the user's name."; -$l['user_title'] = "Default User Title"; -$l['user_title_desc'] = "If the user has nothing entered in their custom user title field, the user title entered here will be displayed. If you leave this option blank, users will have their title and stars taken from the User Titles configuration."; -$l['do_not_copy_permissions'] = "Don't copy permissions from another group"; -$l['copy_permissions_from'] = "Copy Permissions From..."; -$l['copy_permissions_from_desc'] = "If you wish, you can copy the forum and group permissions from another group. To make use of this, select a group to copy permissions from."; -$l['save_user_group'] = "Save User Group"; -$l['list_users'] = "List Users"; - -$l['general'] = "General"; -$l['forums_posts'] = "Forums and Posts"; -$l['users_permissions'] = "Users and Permissions"; -$l['misc'] = "Miscellaneous"; -$l['mod_cp'] = "Moderator CP"; -$l['stars'] = "# of Stars"; -$l['star_image'] = "Star Image"; -$l['user_stars'] = "User Stars"; -$l['user_stars_desc'] = "If you enter a number of stars and the location of a star image, this star image will be shown for this particular user group. If you want to use different star images for different themes, please use {theme} to represent the image directory of each theme. The number of stars only takes effect if Default User Title is not blank."; -$l['group_image'] = "Group Image"; -$l['group_image_desc'] = "Here you can set a group image which will show on each post made by users in this group. Please use {lang} to represent the user's chosen language if translated group images are available"; -$l['general_options'] = "General Options"; -$l['member_list'] = "Yes, show users of this group on the member list"; -$l['forum_team'] = "Yes, show this group on the 'forum team' page"; -$l['is_banned_group'] = "Yes, this is a banned group
    If this group is a 'banned' user group, users will be able to be 'banned' in to this user group."; -$l['publicly_joinable_options'] = "Publicly Joinable Options"; -$l['user_joinable'] = "Yes, users can freely join and leave this group"; -$l['moderate_join_requests'] = "Yes, all new join requests need to be moderated first
    Users must be able to freely join and leave this group for this to take effect."; -$l['invite_only'] = "Yes, users must be invited in order to join this group
    Users must be able to freely join and leave this group for this to take effect."; -$l['can_set_as_display_group'] = "Yes, users can set this group as their display group
    If set to yes, users will be able to set this user group as their display group for user titles, stars, name style and group images."; -$l['moderation_administration_options'] = "Moderation/Administration Options"; -$l['is_super_mod'] = "Yes, users of this group are super moderators"; -$l['can_access_mod_cp'] = "Yes, users of this group can access the moderator CP"; -$l['can_access_admin_cp'] = "Yes, users of this group can access the admin CP"; -$l['viewing_options'] = "Viewing Options"; -$l['can_view_board'] = "Can view board?"; -$l['can_view_threads'] = "Can view threads?"; -$l['can_search_forums'] = "Can search forums?"; -$l['can_view_profiles'] = "Can view user profiles?"; -$l['can_download_attachments'] = "Can download attachments?"; -$l['can_view_board_closed'] = "Can view board when closed?"; -$l['posting_rating_options'] = "Posting/Rating Options"; -$l['can_post_threads'] = "Can post new threads?"; -$l['can_post_replies'] = "Can post replies to threads?"; -$l['can_rate_threads'] = "Can rate threads?"; -$l['moderation_options'] = "Moderation Options"; -$l['mod_new_posts'] = "Moderate new posts?"; -$l['mod_new_threads'] = "Moderate new threads?"; -$l['mod_new_attachments'] = "Moderate new attachments?"; -$l['mod_after_edit'] = "Moderate posts after they've been edited?"; -$l['poll_options'] = "Poll Options"; -$l['max_posts_per_day'] = "Maximum Posts Per Day"; -$l['max_posts_per_day_desc'] = "This is the total number of posts allowed per user per day. 0 for unlimited."; -$l['can_post_polls'] = "Can post polls?"; -$l['can_vote_polls'] = "Can vote in polls?"; -$l['can_undo_votes'] = "Can undo votes in polls?"; -$l['attachment_options'] = "Attachment Options"; -$l['can_post_attachments'] = "Can post attachments?"; -$l['attach_quota'] = "Attachment Quota:"; -$l['attach_quota_desc'] = "Here you can set the attachment quota that each user in this group will receive. If set to 0, there is no limit."; -$l['editing_deleting_options'] = "Editing/Deleting Options"; -$l['can_edit_posts'] = "Can edit own posts?"; -$l['can_delete_posts'] = "Can delete own posts?"; -$l['can_delete_threads'] = "Can delete own threads?"; -$l['can_edit_attachments'] = "Can update own attachments?"; -$l['can_view_deletion_notices'] = "Can view deletion notices?"; -$l['account_management'] = "Account Management"; -$l['edit_time_limit'] = "Edit Time Limit"; -$l['edit_time_limit_desc'] = "The number of minutes until regular users cannot edit their own posts (if they have the permission). Enter 0 (zero) for no limit."; -$l['can_be_reported'] = "Can be reported?"; -$l['can_access_usercp'] = "Can access User CP?"; -$l['can_change_username'] = "Can change username?"; -$l['can_change_website'] = "Can change website?"; -$l['can_use_usertitles'] = "Can use custom user titles?"; -$l['can_upload_avatars'] = "Can upload avatars?"; -$l['can_use_signature'] = "Can add a signature?"; -$l['can_use_signature_posts'] = "Can add a signature after x posts?"; -$l['required_posts'] = "Required Post Count Before Signature Can Be Added:"; -$l['required_posts_desc'] = "Here you can enter the minimum number of posts a user must have before they can add a signature. If set to 0, users can add a signature at any post count."; -$l['uses_no_follow'] = "Signature links have nofollow enabled?"; -$l['reputation_system'] = "Reputation System"; -$l['can_use_pms'] = "Can use private messaging?"; -$l['can_send_pms'] = "Can send private messages?"; -$l['can_track_pms'] = "Can track sent private messages?"; -$l['can_deny_reciept'] = "Can deny message receipt notifications?"; -$l['can_override_pms'] = "Can send private messages even if recipients have them disabled?"; -$l['message_quota'] = "Message Quota:"; -$l['message_quota_desc'] = "Maximum number of private messages that can be stored by users in this group. If empty, users can store unlimited messages."; -$l['max_recipients'] = "Maximum Recipients Per Message:"; -$l['max_recipients_desc'] = "Maximum number of recipients a user can send a private message to at one time. If empty, users can send private messages to an unlimited number of recipients."; -$l['show_reputations'] = "Show reputations for users in this group?"; -$l['can_give_reputation'] = "Can give reputations to users?"; -$l['can_delete_own_reputation'] = "Can delete own given reputations?"; -$l['points_to_award_take'] = "Points to Award/Take Away:"; -$l['points_to_award_take_desc'] = "Here you need to enter the number of points to give or take away on each reputation given by users of this group."; -$l['max_reputations_daily'] = "Maximum Reputations Allowed Per Day:"; -$l['max_reputations_daily_desc'] = "Here you can enter the maximum number of reputations that users in this group can give per day. To allow unlimited reputations per day, enter 0."; -$l['max_reputations_perthread'] = "Maximum Reputations Allowed Per Thread:"; -$l['max_reputations_perthread_desc'] = "When 'Allow Post Reputation' is allowed, you can set the maximum amount of reputations that users in this group can give to the same user, in the same thread, per day, in the box below. To allow unlimited reputations for a user, per thread, enter 0."; -$l['max_reputations_peruser'] = "Maximum Reputations Allowed Per User:"; -$l['max_reputations_peruser_desc'] = "Along with a per thread maximum, you can enter a maximum number of reputations that users in this group can give to the same user per day. To allow unlimited reputations for a user, enter 0."; -$l['warning_system'] = "Warning System"; -$l['can_send_warnings'] = "Can send warnings to other users?"; -$l['can_receive_warnings'] = "Can receive warnings from other users?"; -$l['warnings_per_day'] = "Maximum Warnings Allowed Per Day:"; -$l['private_messaging'] = "Private Messaging"; -$l['calendar'] = "Calendar"; -$l['can_view_calendar'] = "Can view calendar?"; -$l['can_post_events'] = "Can post calendar events?"; -$l['can_bypass_event_moderation'] = "Can bypass calendar event moderation queue?"; -$l['can_moderate_events'] = "Can moderate calendar events?"; -$l['whos_online'] = "Who's Online"; -$l['can_view_whos_online'] = "Can view who's online?"; -$l['can_view_invisible'] = "Can view invisible users?"; -$l['can_view_ips'] = "Can view IP addresses on who's online?"; -$l['can_view_member_list'] = "Can view member list?"; -$l['show_in_birthday_list'] = "Can be shown in the birthday list?"; -$l['can_email_users'] = "Can send threads to friends and email users?"; -$l['can_email_users_override'] = "Can email users even if they appear on their ignore list?"; -$l['max_emails_per_day'] = "Maximum Emails Per Day:"; -$l['max_emails_per_day_desc'] = "The maximum number of emails users can send using the 'Email User' and 'Send Thread to Friend' features. If set to 0, there is no limit."; -$l['email_flood_time'] = "Email Flood Time:"; -$l['email_flood_time_desc'] = "The number of minutes a user must wait after sending an email before they can send another. If set to 0, there is no wait."; -$l['forum_post_options'] = "Forums & Posts"; -$l['user_options'] = "Users"; -$l['can_manage_announce'] = "Can manage announcements?
    Please note that forum moderators must be assigned to at least one forum in order to manage announcements."; -$l['can_manage_mod_queue'] = "Can manage moderator queue?
    Please note that forum moderators must be assigned to at least one forum in order to manage the moderator queue."; -$l['can_manage_reported_content'] = "Can manage reported content?
    Please note that forum moderators must be assigned to at least one forum in order to manage reported content."; -$l['can_view_mod_logs'] = "Can view moderator logs?
    Please note that forum moderators must be assigned to at least one forum in order to view the moderator logs."; -$l['can_edit_profiles'] = "Can edit profiles?
    Please note that forum moderators cannot edit the profiles of super moderators or administrators regardless of this permission."; -$l['can_ban_users'] = "Can ban users?
    Please note that forum moderators cannot ban super moderators or administrators regardless of this permission."; -$l['can_view_warnlogs'] = "Can view warning logs?"; -$l['can_use_ipsearch'] = "Can use IP search?"; -$l['outstanding_join_request'] = "outstanding join requests"; - -$l['no_join_requests'] = "There are no outstanding join requests for this user group."; -$l['no_assigned_leaders'] = "You haven't assigned any users as leaders of this group yet. To create a leader for this group, fill in the form below."; - -$l['error_missing_title'] = "You did not enter a title for this new user group."; -$l['error_invalid_user_group'] = "You have selected an invalid user group."; -$l['error_invalid_join_request'] = "You have selected an invalid join request."; -$l['error_invalid_username'] = "The username you entered is invalid."; -$l['error_already_leader'] = "The user is already a leader of this user group."; -$l['error_invalid_group_leader'] = "You specified an invalid group leader."; -$l['error_missing_namestyle_username'] = "The username style must contain {username}"; -$l['error_disallowed_namestyle_username'] = "You can't use script, meta or base tags in the username style."; -$l['error_default_group_delete'] = "Default groups cannot be deleted"; -$l['error_cannot_have_both_types'] = "You cannot have a joinable group that is both moderated and invite only. Please choose one or the other."; - -$l['success_group_created'] = "The new user group has been created successfully."; -$l['success_group_updated'] = "The selected user group has been updated successfully."; -$l['success_group_deleted'] = "The selected user group has been deleted successfully."; -$l['success_groups_disporder_updated'] = "The user group display orders have been updated successfully."; -$l['success_join_request_approved'] = "The selected join request has been approved successfully. The user is now a member of this user group."; -$l['success_join_request_denied'] = "The selected join request has been denied successfully."; -$l['success_selected_requests_approved'] = "The selected join requests have been approved successfully. The users are now part of this group."; -$l['success_selected_requests_denied'] = "The selected join requests have been denied successfully."; -$l['success_user_made_leader'] = "was successfully made a group leader for this user group."; -$l['success_group_leader_updated'] = "The selected group leader has been updated successfully."; -$l['success_group_leader_deleted'] = "The selected user has been removed from the group leaders list for this group successfully."; - -$l['confirm_group_deletion'] = "Are you sure you want to delete this user group?"; -$l['confirm_group_leader_deletion'] = "Are you sure you want to delete this group leader?"; - diff --git a/html/forums/inc/languages/english/admin/user_mass_mail.lang.php b/html/forums/inc/languages/english/admin/user_mass_mail.lang.php deleted file mode 100644 index 2beda5c..0000000 --- a/html/forums/inc/languages/english/admin/user_mass_mail.lang.php +++ /dev/null @@ -1,120 +0,0 @@ -Note: This is not the promotion system."; - -$l['error_missing_title'] = "You did not enter a title for this user title"; -$l['error_missing_posts'] = "You did not enter the minimum number of posts for this user title"; -$l['error_cannot_have_same_posts'] = "This user title cannot have the same minimum number of posts as another title"; -$l['error_invalid_user_title'] = "You have specified an invalid user title"; - -$l['success_user_title_created'] = "The new user title has been created successfully."; -$l['success_user_title_updated'] = "The user title has been updated successfully."; -$l['success_user_title_deleted'] = "The specified user title has been deleted successfully."; - -$l['title_to_assign'] = "Title to Assign"; -$l['title_to_assign_desc'] = "This title will be shown for users underneath their name if they do not have a custom title set."; -$l['minimum_posts'] = "Minimum Posts"; -$l['minimum_posts_desc'] = "The minimum number of posts for a user to have before they're assigned this user title."; -$l['number_of_stars'] = "Number of Stars"; -$l['number_of_stars_desc'] = "Enter the number of stars to be shown under this user title. Set to 0 to show no stars."; -$l['star_image'] = "Star Image"; -$l['star_image_desc'] = "If this user title should show stars, enter the path to the star image here. If empty, the user group star image will be shown. Use {theme} to specify the image directory for the viewers current theme."; -$l['save_user_title'] = "Save User Title"; -$l['edit_user_title'] = "Edit User Title"; -$l['edit_user_title_desc'] = "This section allows you to edit a user title."; -$l['user_title_deletion_confirmation'] = "Are you sure you want to delete this user title?"; -$l['manage_user_titles'] = "Manage User Titles"; -$l['user_title'] = "User Title"; -$l['no_user_titles'] = "You do not have any user titles defined at the moment"; - diff --git a/html/forums/inc/languages/english/admin/user_users.lang.php b/html/forums/inc/languages/english/admin/user_users.lang.php deleted file mode 100644 index e191c0b..0000000 --- a/html/forums/inc/languages/english/admin/user_users.lang.php +++ /dev/null @@ -1,411 +0,0 @@ -only the destination account. The source accounts posts, threads, private messages, calendar events, post count and buddy list will be merged in to the destination account.
    Please be aware that this process cannot be undone."; -$l['edit_user'] = "Edit User"; -$l['edit_user_desc'] = "Here you can edit this users profile, settings, and signature; see general statistics; and visit other pages for further information relating to this user."; -$l['show_referrers'] = "Show Referrers"; -$l['show_referrers_desc'] = "The results to your search criteria are shown below. You can view the results in either a table view or business card view."; -$l['show_ip_addresses'] = "Show IP Addresses"; -$l['show_ip_addresses_desc'] = "The registration IP address and the post IPs for the selected users are shown below. The first IP address is the registration IP (it is marked as such). Any other IP addresses are IP addresses the user has posted with."; -$l['manage_users'] = "Manage Users"; -$l['manage_users_desc'] = "Mass-managing users makes it a lot easier to do common tasks."; -$l['inline_edit'] = "Inline User Moderation:"; -$l['inline_activate'] = "Activate User(s)"; -$l['inline_ban'] = "Ban User(s)"; -$l['inline_usergroup'] = "Change Users' Usergroup"; -$l['inline_delete'] = "Delete User(s)"; -$l['inline_prune'] = "Prune/Delete Users' Posts"; -$l['inline_activated'] = "{1} user(s) were successfully activated."; -$l['inline_activated_more'] = "{1} user(s) you selected were already activated."; -$l['inline_activated_failed'] = "All the users you selected were already activated."; -$l['ban_time'] = "Ban Length *"; -$l['ban_reason'] = "Ban Reason"; -$l['mass_ban'] = "Mass Ban Users"; -$l['important'] = "Important"; -$l['mass_ban_info'] = "This action will affect {1} user(s). Only continue if you are sure you want to do this."; -$l['ban_users'] = "Ban Users"; -$l['users_banned'] = "{1} user(s) have been banned."; -$l['confirm_multilift'] = "Are you sure you want to lift bans for the user(s) you selected?"; -$l['success_ban_lifted'] = "Bans for {1} user(s) you selected have been lifted."; -$l['edit_ban'] = "Edit Ban"; -$l['lift_ban'] = "Lift Ban"; -$l['lift_bans'] = "Lift Bans"; -$l['confirm_multidelete'] = "Are you sure you want to delete these {1} user(s)? This cannot be undone."; -$l['users_deleted'] = "{1} user(s) have been deleted."; -$l['mass_prune_info'] = "This action will affect {1} user(s). If you continue, it will remove all the users' posts older than the date you enter below.

    Please note that if any users' post is the first post of a thread, the entire thread will be removed."; -$l['mass_prune_posts'] = "Mass Prune Posts"; -$l['manual_date'] = "Enter a manual date"; -$l['relative_date'] = "Or select a delete option"; -$l['multi_selected_dates'] = "You've selected both a manual date and a set option. Please select either a manual date or a set option."; -$l['incorrect_date'] = "The date you entered is invalid. Please enter a valid date, or leave blank and select a set option."; -$l['prune_complete'] = "Prune completed successfully."; -$l['prune_fail'] = "No posts were found for the selected user(s). No posts were pruned."; -$l['no_prune_option'] = "Please enter a date or select an option to continue."; -$l['prune_posts'] = "Prune Posts"; -$l['delete_posts'] = "Delete Posts"; -$l['usergroup_info'] = "The following action will affect {1} user(s). By choosing the options below, you will be overwriting the selected users' primary / additional / display usergroup."; -$l['mass_usergroups'] = "Mass Usergroup Change"; -$l['success_mass_usergroups'] = "User(s) updated successfully."; -$l['alter_usergroups'] = "Save Changes"; -$l['no_usergroup_changed'] = "None of the user(s) you selected can have their usergroups changed."; -$l['no_set_option'] = "A valid set date was not selected. Please select an option from the dropdown box or enter a manual date."; -$l['select_an_option'] = "(Select an Option)"; - -$l['month_1'] = "January"; -$l['month_2'] = "February"; -$l['month_3'] = "March"; -$l['month_4'] = "April"; -$l['month_5'] = "May"; -$l['month_6'] = "June"; -$l['month_7'] = "July"; -$l['month_8'] = "August"; -$l['month_9'] = "September"; -$l['month_10'] = "October"; -$l['month_11'] = "November"; -$l['month_12'] = "December"; - -$l['option_1'] = "More than a month old"; -$l['option_2'] = "More than 3 months old"; -$l['option_3'] = "More than 6 months old"; -$l['option_4'] = "More than a year old"; -$l['option_5'] = "More than 18 months old"; -$l['option_6'] = "More than 2 years old"; - -$l['error_avatartoobig'] = "Sorry, but we cannot change your avatar as the new avatar you specified is too big. The maximum dimensions are {1}x{2} (width x height)"; -$l['error_invalidavatarurl'] = "The URL you entered for your avatar does not appear to be valid. Please ensure you enter a valid URL."; -$l['error_remote_avatar_not_allowed'] = "Remote avatar URLs have been disabled by the forum administrator."; -$l['error_invalid_user'] = "You have selected an invalid user."; -$l['error_no_perms_super_admin'] = "You do not have permission to edit this user because you are not a super administrator."; -$l['error_invalid_user_source'] = "The source account username you entered does not exist"; -$l['error_invalid_user_destination'] = "The destination account username you entered does not exist"; -$l['error_cannot_merge_same_account'] = "The source and destination accounts must be different"; -$l['error_no_users_found'] = "No users were found matching the specified search criteria. Please modify your search criteria and try again."; -$l['error_invalid_admin_view'] = "You selected an invalid administration view."; -$l['error_missing_view_title'] = "You did not enter a title for this view."; -$l['error_no_view_fields'] = "You did not select any fields to display on this view"; -$l['error_invalid_view_perpage'] = "You have entered an invalid number of results to show per page"; -$l['error_invalid_view_sortby'] = "You have selected an invalid field to sort results by"; -$l['error_invalid_view_sortorder'] = "You have selected an invalid sort order"; -$l['error_invalid_view_delete'] = "You selected an invalid administration view to delete"; -$l['error_cannot_delete_view'] = "You must have at least 1 administration view."; -$l['error_inline_no_users_selected'] = "Sorry, but you did not select any users. Please select some users and try again."; -$l['error_cannot_delete_user'] = "This user cannot be deleted."; -$l['error_no_referred_users'] = "The selected user does not have any referred users."; - -$l['user_deletion_confirmation'] = "Are you sure you wish to delete this user?"; - -$l['success_coppa_activated'] = "The selected COPPA user has been activated successfully."; -$l['success_activated'] = "The selected user has been activated successfully."; -$l['success_user_created'] = "The user has been created successfully."; -$l['success_user_updated'] = "The selected user has been updated successfully."; -$l['success_user_deleted'] = "The selected user has been deleted successfully."; -$l['success_merged'] = "has successfully been merged in to"; -$l['succuss_view_set_as_default'] = "The selected administration view has been set as your default successfully"; -$l['success_view_created'] = "The administration view has been created successfully."; -$l['success_view_updated'] = "The selected administration view has been updated successfully."; -$l['success_view_deleted'] = "The selected administration view has been deleted successfully."; - -$l['confirm_view_deletion'] = "Are you sure you want to delete the selected view?"; - -$l['warning_coppa_user'] = "

    Warning: This user is awaiting COPPA validation. Activate Account

    "; - -$l['required_profile_info'] = "Required Profile Information"; -$l['password'] = "Password"; -$l['confirm_password'] = "Confirm Password"; -$l['email_address'] = "Email Address"; -$l['use_primary_user_group'] = "Use Primary User Group"; -$l['primary_user_group'] = "Primary User Group"; -$l['additional_user_groups'] = "Additional User Groups"; -$l['additional_user_groups_desc'] = "Use CTRL to select multiple groups"; -$l['display_user_group'] = "Display User Group"; -$l['save_user'] = "Save User"; - -$l['overview'] = "Overview"; -$l['profile'] = "Profile"; -$l['account_settings'] = "Account Settings"; -$l['signature'] = "Signature"; -$l['avatar'] = "Avatar"; -$l['mod_options'] = "Moderator Options"; -$l['general_account_stats'] = "General Account Statistics"; -$l['local_time'] = "Local Time"; -$l['local_time_format'] = "{1} at {2}"; -$l['posts'] = "Posts"; -$l['age'] = "Age"; -$l['posts_per_day'] = "Posts per day"; -$l['percent_of_total_posts'] = "Percent of total posts"; -$l['user_overview'] = "User Overview"; - -$l['new_password'] = "New Password"; -$l['new_password_desc'] = "Only required if changing"; -$l['confirm_new_password'] = "Confirm New Password"; - -$l['optional_profile_info'] = "Optional Profile Information"; -$l['custom_user_title'] = "Custom User Title"; -$l['custom_user_title_desc'] = "If empty, the group user title will be used"; -$l['website'] = "Website"; -$l['icq_number'] = "ICQ Number"; -$l['aim_handle'] = "AIM Handle"; -$l['yahoo_messanger_handle'] = "Yahoo! Messenger Handle"; -$l['skype_handle'] = "Skype Handle"; -$l['google_handle'] = "Google Hangouts Handle"; -$l['birthday'] = "Date of Birth"; - -$l['away_information'] = "Away Information"; -$l['away_status'] = "Away Status:"; -$l['away_status_desc'] = "Allows you to leave an away message if you are going away for a while."; -$l['im_away'] = "I'm Away"; -$l['im_here'] = "I'm Here"; -$l['away_reason'] = "Away Reason:"; -$l['away_reason_desc'] = "Allows you to enter a small description of why you are away (max 200 characters)."; -$l['return_date'] = "Return Date:"; -$l['return_date_desc'] = "If you know when you will be back, you can enter your return date here."; -$l['error_acp_return_date_past'] = "You cannot return in the past!"; - -$l['hide_from_whos_online'] = "Hide from the Who's Online list"; -$l['login_cookies_privacy'] = "Login, Cookies & Privacy"; -$l['recieve_admin_emails'] = "Receive emails from administrators"; -$l['hide_email_from_others'] = "Hide email address from other members"; -$l['recieve_pms_from_others'] = "Receive private messages from other users"; -$l['recieve_pms_from_buddy'] = "Only receive private messages from buddy list (this setting has no effect unless there is at least one buddy on the list)"; -$l['alert_new_pms'] = "Alert with notice when new private message is received"; -$l['email_notify_new_pms'] = "Notify by email when new private message is received"; -$l['buddy_requests_pm'] = "Receive PM notifications for new buddy requests"; -$l['buddy_requests_auto'] = "Automatically accept buddy requests (if the above checkbox is ticked, a PM is sent informing of the new buddy connection)"; -$l['default_thread_subscription_mode'] = "Default thread subscription mode"; -$l['do_not_subscribe'] = "Do not subscribe"; -$l['no_email_notification'] = "No email notification"; -$l['instant_email_notification'] = "Instant email notification"; -$l['messaging_and_notification'] = "Messaging & Notification"; -$l['use_default'] = "Use Default"; -$l['date_format'] = "Date Format"; -$l['time_format'] = "Time Format"; -$l['time_zone'] = "Time Zone"; -$l['daylight_savings_time_correction'] = "Daylight Saving Time correction"; -$l['automatically_detect'] = "Automatically detect DST settings"; -$l['always_use_dst_correction'] = "Always use DST correction"; -$l['never_use_dst_correction'] = "Never use DST correction"; -$l['date_and_time_options'] = "Date & Time Options"; -$l['show_threads_last_day'] = "Show threads from the last day"; -$l['show_threads_last_5_days'] = "Show threads from the last 5 days"; -$l['show_threads_last_10_days'] = "Show threads from the last 10 days"; -$l['show_threads_last_20_days'] = "Show threads from the last 20 days"; -$l['show_threads_last_50_days'] = "Show threads from the last 50 days"; -$l['show_threads_last_75_days'] = "Show threads from the last 75 days"; -$l['show_threads_last_100_days'] = "Show threads from the last 100 days"; -$l['show_threads_last_year'] = "Show threads from the last year"; -$l['show_all_threads'] = "Show all threads"; -$l['threads_per_page'] = "Threads Per Page"; -$l['default_thread_age_view'] = "Default Thread Age View"; -$l['forum_display_options'] = "Forum Display Options"; -$l['show_classic_postbit'] = "Display posts in classic mode"; -$l['display_images'] = "Display images in posts"; -$l['display_videos'] = "Display videos in posts"; -$l['display_users_sigs'] = "Display users' signatures in their posts"; -$l['display_users_avatars'] = "Display users' avatars in their posts"; -$l['show_quick_reply'] = "Show the quick reply box at the bottom of the thread view"; -$l['posts_per_page'] = "Posts Per Page"; -$l['default_thread_view_mode'] = "Default Thread View Mode"; -$l['linear_mode'] = "Linear Mode"; -$l['threaded_mode'] = "Threaded Mode"; -$l['thread_view_options'] = "Thread View Options"; -$l['show_redirect'] = "Show friendly redirection pages"; -$l['show_code_buttons'] = "Show MyCode formatting options on posting pages"; -$l['source_editor'] = "Put the editor in source mode by default"; -$l['theme'] = "Theme"; -$l['board_language'] = "Board Language"; -$l['other_options'] = "Other Options"; -$l['signature_desc'] = "Formatting options: MyCode is {1}, smilies are {2}, IMG code is {3}, HTML is {4}"; -$l['enable_sig_in_all_posts'] = "Enable signature in all posts"; -$l['disable_sig_in_all_posts'] = "Disable signature in all posts"; -$l['do_nothing'] = "Do not change signature preferences"; -$l['signature_preferences'] = "Signature Preferences"; -$l['suspend_sig'] = "Suspend Signature"; -$l['suspend_sig_box'] = "Suspend this user's signature"; -$l['suspend_sig_perm'] = "Suspended permanently."; -$l['suspend_sig_info'] = "If a signature is suspended, the user can't edit it and it won't be shown on their profile or in their posts"; -$l['suspend_sig_extend'] = "Enter a new time below to change, or untick this option to remove this suspension."; -$l['suspend_expire_info'] = "Remaining: {1}"; -$l['suspend_never_expire'] = "{1}'s suspension will never expire (permanently suspended)."; -$l['suspend_sig_error'] = "You entered an incorrect time to suspend this user's signature for. Please enter a correct time."; - -$l['moderate_posts'] = "Moderate Posts"; -$l['moderate_posts_info'] = "Moderate new posts made by {1}."; -$l['moderate_for'] = "Moderate for:"; -$l['moderated_perm'] = "

    Moderated permanently.
    Enter a new time below to change or untick this option to remove this moderation.

    "; -$l['moderate_length'] = "

    Remaining Moderation: {1}.
    Enter a new time below to change or untick this option to remove this moderation.

    "; - -$l['suspend_posts'] = "Suspend Posts"; -$l['suspend_posts_info'] = "Suspend {1} from making new posts."; -$l['suspend_for'] = "Suspend for:"; -$l['suspended_perm'] = "

    Suspended permanently.
    Enter a new time below to change or untick this option to remove this suspension.

    "; -$l['suspend_length'] = "

    Remaining Suspension: {1}.
    Enter a new time below to change or untick this option to remove this suspension.

    "; - -$l['suspendsignature_error'] = "You selected to suspend this user's signature, but didn't enter a valid time period. Please enter a valid time to continue or untick the option to cancel."; -$l['moderateposting_error'] = "You selected to moderate this user's posts, but didn't enter a valid time period. Please enter a valid time to continue or untick the option to cancel."; -$l['suspendposting_error'] = "You selected to suspend this user's posts, but didn't enter a valid time period. Please enter a valid time to continue or untick the option to cancel."; -$l['suspendmoderate_error'] = "You've selected to suspend and moderate the user's posts. Please select only one type of moderation."; - -$l['expire_length'] = "Suspension length:"; -$l['expire_hours'] = "hour(s)"; -$l['expire_days'] = "day(s)"; -$l['expire_weeks'] = "week(s)"; -$l['expire_months'] = "month(s)"; -$l['expire_never'] = "Never"; -$l['expire_permanent'] = "Permanent"; - -$l['username'] = "Username"; -$l['email'] = "Email"; -$l['primary_group'] = "Primary Group"; -$l['additional_groups'] = "Additional Groups"; -$l['registered'] = "Registered"; -$l['last_active'] = "Last Active"; -$l['post_count'] = "Post Count"; -$l['thread_count'] = "Thread Count"; -$l['reputation'] = "Reputation"; -$l['warning_level'] = "Warning Level"; -$l['registration_ip'] = "Registration IP"; -$l['last_known_ip'] = "Last Known IP"; -$l['registration_date'] = "Registration Date"; -$l['info_on_ip'] = "Information on this IP address"; - -$l['current_avatar'] = "Current Avatar"; -$l['user_current_using_uploaded_avatar'] = "This user is currently using an uploaded avatar."; -$l['user_currently_using_remote_avatar'] = "This user is currently using a remotely linked avatar."; -$l['max_dimensions_are'] = "The maximum dimensions for avatars are"; -$l['avatar_max_size'] = "Avatars can be a maximum of"; -$l['remove_avatar'] = "Remove current avatar?"; -$l['avatar_desc'] = "Below you can manage the avatar for this user. Avatars are small identifying images which are placed under the authors username when they make a post."; -$l['avatar_auto_resize'] = "If the avatar is too large, it will automatically be resized"; -$l['attempt_to_auto_resize'] = "Attempt to resize this avatar if it is too large?"; -$l['specify_custom_avatar'] = "Specify Custom Avatar"; -$l['upload_avatar'] = "Upload Avatar"; -$l['or_specify_avatar_url'] = "or Specify Avatar/Gravatar URL"; - -$l['user_notes'] = "User Notes"; - -$l['ip_addresses'] = "IP Addresses"; -$l['ip_address'] = "IP Address"; -$l['show_users_regged_with_ip'] = "Show users who have registered with this IP"; -$l['show_users_posted_with_ip'] = "Show users who have posted with this IP"; -$l['ban_ip'] = "Ban IP"; -$l['ip_address_for'] = "IP Addresses for"; - -$l['source_account'] = "Source Account"; -$l['source_account_desc'] = "This is the account that will be merged in to the destination account. It will be removed after this process."; -$l['destination_account'] = "Destination Account"; -$l['destination_account_desc'] = "This is the account that the source account will be merged in to. It will remain after this process."; -$l['merge_user_accounts'] = "Merge User Accounts"; - -$l['display_options'] = "Display Options"; -$l['ascending'] = "Ascending"; -$l['descending'] = "Descending"; -$l['sort_results_by'] = "Sort results by"; -$l['in'] = "in"; -$l['results_per_page'] = "Results per page"; -$l['display_results_as'] = "Display results as"; -$l['business_card'] = "Business cards"; -$l['views'] = "Views"; -$l['views_desc'] = "The view manager allows you to create different kinds of views for this specific area. Different views are useful for generating a variety of reports."; -$l['manage_views'] = "Manage Views"; -$l['none'] = "None"; -$l['search'] = "Search"; - -$l['view_profile'] = "View Profile"; -$l['edit_profile_and_settings'] = "Edit Profile & Settings"; -$l['ban_user'] = "Ban User"; -$l['approve_coppa_user'] = "Activate COPPA User"; -$l['approve_user'] = "Activate User"; -$l['delete_user'] = "Delete User"; -$l['show_referred_users'] = "Show Referred Users"; -$l['show_attachments'] = "Show Attachments"; -$l['table_view'] = "Table View"; -$l['card_view'] = "Card View"; - -$l['find_users_where'] = "Find users where..."; -$l['username_contains'] = "Username contains"; -$l['email_address_contains'] = "Email address contains"; -$l['is_member_of_groups'] = "Is member of one or more of these user groups"; -$l['website_contains'] = "Website contains"; -$l['icq_number_contains'] = "ICQ number contains"; -$l['aim_handle_contains'] = "AIM handle contains"; -$l['yahoo_contains'] = "Yahoo! Messenger handle contains"; -$l['skype_contains'] = "Skype handle contains"; -$l['google_contains'] = "Google Hangouts handle contains"; -$l['signature_contains'] = "Signature contains"; -$l['user_title_contains'] = "Custom user title contains"; -$l['greater_than'] = "Greater than"; -$l['is_exactly'] = "Is exactly"; -$l['less_than'] = "Less than"; -$l['post_count_is'] = "Post count is"; -$l['thread_count_is'] = "Thread count is"; -$l['reg_ip_matches'] = "Registration IP address matches"; -$l['wildcard'] = "To search for ranges of IP addresses use * (Ex: 127.0.0.*) or CIDR notation (Ex: 127.0.0.0/8)"; -$l['posted_with_ip'] = "Has posted with the IP address"; -$l['custom_profile_fields_match'] = "Where custom profile fields match..."; -$l['is_not_blank'] = " is not empty"; -$l['or'] = "or"; -$l['reg_in_x_days'] = "Registered in the last"; -$l['days'] = "days"; - -$l['view'] = "View"; -$l['create_new_view'] = "Create New View"; -$l['create_new_view_desc'] = "Here you can define a new view for this area. You can define which fields you want to be shown, any search criteria and sorting options."; -$l['view_manager'] = "View Manager"; -$l['set_as_default_view'] = "Set as Default View?"; -$l['enabled'] = "Enabled"; -$l['disabled'] = "Disabled"; -$l['fields_to_show'] = "Fields to Show"; -$l['fields_to_show_desc'] = "Please select the fields you wish to display"; -$l['edit_view'] = "Edit View"; -$l['edit_view_desc'] = "Whilst editing a view you can define which fields you want to be shown, any search criteria and sorting options."; -$l['private'] = "Private"; -$l['private_desc'] = "This view is only visible to you"; -$l['public'] = "Public"; -$l['public_desc'] = "All other administrators can see this view"; -$l['visibility'] = "Visibility"; -$l['save_view'] = "Save View"; -$l['created_by'] = "Created by"; -$l['default'] = "Default"; -$l['this_is_a_view'] = "This is a {1} view"; -$l['set_as_default'] = "Set as Default"; -$l['delete_view'] = "Delete View"; -$l['default_view_desc'] = "Default view created by MyBB. Cannot be edited or removed."; -$l['public_view_desc'] = "Public view visible to all administrators."; -$l['private_view_desc'] = "Private view visible only to yourself."; -$l['table'] = "Table"; -$l['title'] = "Title"; - -$l['view_title_1'] = "All Users"; - -$l['emailsubject_activateaccount'] = "Account Activation at {1}"; -$l['email_adminactivateaccount'] = "{1}, - -The administrator has activated your forum account on {2}. - -To proceed, please go to - -{3} - -You will be able to login with the credentials you registered with. - -Thank you, -{2} Staff"; - -$l['ipaddress_misc_info'] = "Misc. Information for '{1}'"; -$l['ipaddress_host_name'] = "Host Name"; -$l['ipaddress_location'] = "GeoIP Location"; diff --git a/html/forums/inc/languages/english/announcements.lang.php b/html/forums/inc/languages/english/announcements.lang.php deleted file mode 100644 index 7c468a8..0000000 --- a/html/forums/inc/languages/english/announcements.lang.php +++ /dev/null @@ -1,16 +0,0 @@ -View the full version with proper formatting."; -$l['archive_nopermission'] = "Sorry, you do not have permission to access this resource."; -$l['error_nothreads'] = "There are currently no threads in this forum."; -$l['error_nopermission'] = "You do not have permission to view threads in this forum."; -$l['error_unapproved_thread'] = "This thread is unapproved. Please view the full version to view the contents of this thread."; -$l['archive_not_found'] = "The requested page was not found on this server."; -$l['error_mustlogin'] = "This bulletin board requires all users to login."; \ No newline at end of file diff --git a/html/forums/inc/languages/english/calendar.lang.php b/html/forums/inc/languages/english/calendar.lang.php deleted file mode 100644 index 855e036..0000000 --- a/html/forums/inc/languages/english/calendar.lang.php +++ /dev/null @@ -1,144 +0,0 @@ -Private Only you will be able to view this event. (Registered Users Only)."; -$l['delete_option'] = "Delete: Delete this event."; -$l['post_event'] = "Post Event"; -$l['day_view'] = "Day View"; -$l['birthday'] = "Birthday"; -$l['birthdays'] = "Birthdays"; -$l['event_author'] = "Event Author:"; -$l['edit_event'] = "Edit Event"; -$l['view_event'] = "View Event"; -$l['no_events'] = "This day does not have any events associated with it.

    Post an Event.

    "; -$l['years_old'] = "{1} Years Old"; -$l['alt_edit'] = "Edit this event"; -$l['alt_delete'] = "Delete this event"; -$l['moderator_options'] = "Moderator Options"; -$l['approve_event'] = "Approve Event"; -$l['unapprove_event'] = "Unapprove Event"; -$l['move_event'] = "Move Event"; -$l['repeats_every_day'] = "Repeats every day"; -$l['repeats_every_x_days'] = "Repeats every {1} days"; -$l['repeats_on_weekdays'] = "Repeats Monday through Friday"; -$l['every_week_on_days'] = "Repeats every week on {1}"; -$l['every_week'] = "Repeats every week"; -$l['every_x_weeks_on_days'] = "Repeats every {1} weeks on
    {2}"; -$l['every_x_weeks'] = "Repeats every {1} weeks"; -$l['every_month_on_day'] = "Repeats on day {1}
    of every month"; -$l['every_x_months_on_day'] = "Repeats on day {1}
    of every {2} months"; -$l['every_month_on_weekday'] = "Repeats on the {1} {2}
    of every month"; -$l['every_x_months_on_weekday'] = "Repeats on the {1} {2}
    of every {3} months"; -$l['weekday_occurance_1'] = "first"; -$l['weekday_occurance_2'] = "second"; -$l['weekday_occurance_3'] = "third"; -$l['weekday_occurance_4'] = "fourth"; -$l['weekday_occurance_last'] = "last"; -$l['every_year_on_day'] = "Repeats every year on {1} {2}"; -$l['every_x_years_on_day'] = "Repeats every {3} years on {1} {2}"; -$l['every_year_on_weekday'] = "Repeats on the {1} {2} in {3} of every year"; -$l['every_x_year_on_weekday'] = "Repeats on the {1} {2} in {3} every {4} years"; -$l['delete_event'] = "Delete Event"; -$l['delete_q'] = "Delete?"; -$l['delete_1'] = "To delete this event, check the checkbox to the left and then click the button to the right."; -$l['delete_2'] = "Note: This process cannot be undone."; -$l['delete_now'] = "Delete Now"; -$l['delete_no_checkbox'] = "The event was not deleted because you didn't check the \"Delete\" checkbox."; -$l['jump_to_calendar'] = "Jump to calendar:"; -$l['select_calendar'] = "Calendar:"; -$l['type_single'] = "Single day event"; -$l['type_ranged'] = "Ranged or recurring event"; -$l['enter_time'] = "Time:"; -$l['start_time'] = "Starts:"; -$l['end_time'] = "Finishes:"; -$l['timezone'] = "Time Zone:"; -$l['ignore_timezone'] = "Ignore time zone: This event should use the time zone of the viewer."; -$l['repeats'] = "Repeats:"; -$l['does_not_repeat'] = "Does not repeat"; -$l['repeats_daily'] = "Daily"; -$l['repeats_weekdays'] = "Every weekday (Mon-Fri)"; -$l['repeats_weekly'] = "Weekly"; -$l['repeats_every'] = "Repeats every"; -$l['day_or_days'] = "day(s)"; -$l['week_or_weeks_on'] = "week(s) on"; -$l['repeats_monthly'] = "Monthly"; -$l['repeats_yearly'] = "Yearly"; -$l['repeats_on_day'] = "Repeats on day"; -$l['of_every'] = "of every"; -$l['month_or_months'] = "month(s)"; -$l['repeats_on_the'] = "Repeats on the"; -$l['day_of_every'] = "day every"; -$l['repeats_on'] = "Repeats on"; -$l['every'] = "every"; -$l['year_or_years'] = "year(s)"; -$l['of'] = "of"; -$l['move_to_calendar'] = "Move to Calendar:"; -$l['weekly_overview'] = "Weekly Overview"; -$l['previous_week'] = "Previous Week"; -$l['next_week'] = "Next Week"; -$l['first'] = "First"; -$l['second'] = "Second"; -$l['third'] = "Third"; -$l['fourth'] = "Fourth"; -$l['last'] = "Last"; -$l['all_day'] = "All Day"; -$l['starts'] = "Starts: "; -$l['finishes'] = "Finishes: "; - -$l['error_incorrectday'] = "The day you have entered does not appear to exist. Please go back and try again."; -$l['error_invalidevent'] = "The event you specified is either invalid or doesn't exist."; -$l['invalid_calendar'] = "The specified calendar does not exist. Are you sure you are visiting the correct page?"; -$l['redirect_eventdeleted'] = "The event has successfully been deleted.
    You will now be taken back to the calendar."; -$l['redirect_eventupdated'] = "The event has been successfully updated.
    You will now be returned to it."; -$l['redirect_eventadded'] = "Your event has been added successfully.
    You will now be taken to it."; -$l['redirect_eventadded_moderation'] = "Your event has been added successfully but requires moderation by a forum moderator before it is visible.
    You will now be taken back to the calendar."; -$l['redirect_eventunapproved'] = "The event has been unapproved successfully.
    You will now be taken to it."; -$l['redirect_eventapproved'] = "The event has been approved successfully.
    You will now be taken to it."; -$l['redirect_eventmoved'] = "The event has been moved successfully.
    You will now be taken to it."; diff --git a/html/forums/inc/languages/english/contact.lang.php b/html/forums/inc/languages/english/contact.lang.php deleted file mode 100644 index 92924f0..0000000 --- a/html/forums/inc/languages/english/contact.lang.php +++ /dev/null @@ -1,26 +0,0 @@ -
    If you have forgotten your password please retrieve a new one."; -$l['logindata_invalidpwordusernameemail'] = "You have entered an invalid email/password combination.

    If you have forgotten your password please retrieve a new one."; -$l['logindata_invalidpwordusernamecombo'] = "You have entered an invalid username/password or email/password combination.

    If you have forgotten your password please retrieve a new one."; - -$l['logindata_regimageinvalid'] = "The image verification code that you entered was incorrect. Please enter the code exactly how it appears in the image."; -$l['logindata_regimagerequired'] = "Please fill out the image verification code to continue the login process. Please enter the code exactly how it appears in the image."; diff --git a/html/forums/inc/languages/english/datahandler_pm.lang.php b/html/forums/inc/languages/english/datahandler_pm.lang.php deleted file mode 100644 index 72a9397..0000000 --- a/html/forums/inc/languages/english/datahandler_pm.lang.php +++ /dev/null @@ -1,21 +0,0 @@ -Note: The maximum amount of images for signatures is {1}."; -$l['userdata_sig_too_long'] = "You cannot update your signature because it is too long. The maximum length for signatures is {1} characters. "; -$l['userdata_sig_remove_chars_plural'] = "Please remove {1} characters and try again."; -$l['userdata_sig_remove_chars_singular'] = "Please remove 1 character and try again."; diff --git a/html/forums/inc/languages/english/datahandler_warnings.lang.php b/html/forums/inc/languages/english/datahandler_warnings.lang.php deleted file mode 100644 index deb1f02..0000000 --- a/html/forums/inc/languages/english/datahandler_warnings.lang.php +++ /dev/null @@ -1,18 +0,0 @@ -
    The maximum number of warnings you can give out per day is {1}."'; -$l['warnings_error_invalid_user'] = "Selected user doesn't exist."; -$l['warnings_error_invalid_post'] = "Selected post doesn't exist."; -$l['warnings_error_cannot_warn_self'] = "You cannot add to your own warning level."; -$l['warnings_error_user_reached_max_warning'] = "This user cannot be warned as they have already reached the maximum warning level."; -$l['warnings_error_no_note'] = "You did not enter any administrative notes for this warning."; -$l['warnings_error_invalid_type'] = "You have selected an invalid warning type."; -$l['warnings_error_cant_custom_warn'] = "You do not have permission to give custom warnings to users."; -$l['warnings_error_no_custom_reason'] = "You did not enter a reason for your custom warning."; -$l['warnings_error_invalid_custom_points'] = "You did not enter a valid number of points to add to this users warning level. You need to enter a numeric value greater than 0 but not greater than {1}."; -$l['warnings_error_invalid_expires_period'] = "You entered an invalid expiry type."; diff --git a/html/forums/inc/languages/english/editpost.lang.php b/html/forums/inc/languages/english/editpost.lang.php deleted file mode 100644 index 1725727..0000000 --- a/html/forums/inc/languages/english/editpost.lang.php +++ /dev/null @@ -1,54 +0,0 @@ -Note: If this post is the first post in a thread deleting it will result in deletion of the whole thread."; -$l['subject'] = "Subject"; -$l['your_message'] = "Your Message"; -$l['post_options'] = "Post Options:"; -$l['editreason'] = "Edit Reason:"; -$l['options_sig'] = "Signature: include your signature. (registered users only)"; -$l['options_emailnotify'] = "Email Notification: receive an email whenever there is a new reply. (registered users only)"; -$l['options_disablesmilies'] = "Disable Smilies: disable smilies from showing in this post."; -$l['preview_post'] = "Preview Post"; -$l['update_post'] = "Update Post"; -$l['poll'] = "Poll:"; -$l['poll_desc'] = "Optionally you may attach a poll to this thread."; -$l['poll_check'] = "I want to post a poll"; -$l['num_options'] = "Number of options:"; -$l['max_options'] = "(Maximum: {1})"; -$l['delete_now'] = "Delete Now"; -$l['edit_time_limit'] = "Sorry but you cannot edit your post. The Administrator has set it so that posts can only be edited within {1} minutes of posting."; -$l['no_prefix'] = "No Prefix"; - -$l['redirect_nodelete'] = "The post was not deleted because you didn't check the \"Delete\" checkbox."; -$l['redirect_norestore'] = "The post was not restored because you didn't check the \"Restore\" checkbox."; -$l['redirect_postedited'] = "Thank you, this post has been edited.
    "; -$l['redirect_postedited_redirect'] = "You will now be returned to the thread."; -$l['redirect_postedited_poll'] = "Thank you, this post has been edited.
    Because you opted to post a poll, you'll now be taken to the poll creation page."; -$l['error_invalidpost'] = "Sorry, but you seem to have followed an invalid address. Please be sure the specified post exists and try again."; -$l['redirect_threaddeleted'] = "Thank you, the thread has been deleted.
    You will now be returned to the forum."; -$l['redirect_postdeleted'] = "Thank you, the post has been deleted.
    You will now be returned to the thread."; -$l['redirect_threadrestored'] = "Thank you, the thread has been restored.
    You will now be returned to the forum."; -$l['redirect_postrestored'] = "Thank you, the post has been restored.
    You will now be returned to the thread."; -$l['redirect_threadclosed'] = "You cannot edit existing posts in this thread because it has been closed by a moderator."; -$l['redirect_post_moderation'] = "The administrator has specified that all editing of posts require moderation. You will now be returned to the thread."; -$l['redirect_thread_moderation'] = "The administrator has specified that all editing of threads require moderation. You will now be returned to the forum index."; -$l['error_already_delete'] = "Sorry, but this post is already deleted."; - -$l['thread_deleted'] = "Deleted Thread Permanently"; -$l['post_deleted'] = "Deleted Post Permanently"; -$l['thread_soft_deleted'] = "Soft Deleted Thread"; -$l['post_soft_deleted'] = "Soft Deleted Post"; -$l['thread_restored'] = "Restored Thread"; -$l['post_restored'] = "Restored Post"; - -$l['error_already_deleted'] = 'The selected post has already been deleted.'; diff --git a/html/forums/inc/languages/english/forumdisplay.lang.php b/html/forums/inc/languages/english/forumdisplay.lang.php deleted file mode 100644 index fa22c66..0000000 --- a/html/forums/inc/languages/english/forumdisplay.lang.php +++ /dev/null @@ -1,102 +0,0 @@ -{1} threads on this page are selected."; -$l['all_selected'] = "All {1} threads in this forum are selected."; -$l['select_all'] = "Select all {1} threads in this forum."; -$l['clear_selection'] = "Clear Selection."; -$l['deleted_thread'] = "Deleted Thread"; - -$l['error_containsnoforums'] = "Sorry, but the forum you are currently viewing does not contain any child forums."; - -$l['inline_edit_description'] = '(Click and hold to edit)'; - diff --git a/html/forums/inc/languages/english/global.lang.php b/html/forums/inc/languages/english/global.lang.php deleted file mode 100644 index 233a4bf..0000000 --- a/html/forums/inc/languages/english/global.lang.php +++ /dev/null @@ -1,577 +0,0 @@ -Welcome back, {1}. You last visited: {2}"; -$l['welcome_guest'] = "Hello There, Guest!"; -$l['welcome_current_time'] = "Current time: {1}"; - -$l['moved_prefix'] = "Moved:"; -$l['poll_prefix'] = "Poll:"; - -$l['forumbit_announcements'] = "Announcements"; -$l['forumbit_stickies'] = "Important Threads"; -$l['forumbit_forum'] = "Forum"; -$l['forumbit_threads'] = "Threads"; -$l['forumbit_posts'] = "Posts"; -$l['forumbit_lastpost'] = "Last Post"; -$l['forumbit_moderated_by'] = "Moderated By:"; -$l['new_posts'] = "Forum Contains New Posts"; -$l['no_new_posts'] = "Forum Contains No New Posts"; -$l['click_mark_read'] = "Click to mark this forum as read"; -$l['forum_locked'] = "Forum is Locked"; -$l['forum_redirect'] = "Redirect Forum"; -$l['lastpost_never'] = "Never"; -$l['viewing_one'] = " (1 user browsing)"; -$l['viewing_multiple'] = " ({1} users browsing)"; -$l['by'] = "by"; -$l['more_subforums'] = "and {1} more."; - -$l['password_required'] = "Password Required"; -$l['forum_password_note'] = "The administrator has required it so that a password is required for access to this forum."; -$l['enter_password_below'] = "Please enter the password below:"; -$l['verify_forum_password'] = "Verify Forum Password"; -$l['wrong_forum_password'] = "The password you entered is incorrect. Please try again."; - -$l['reset_button'] = "Reset"; -$l['username'] = "Username:"; -$l['username1'] = "Email:"; -$l['username2'] = "Username/Email:"; -$l['password'] = "Password:"; -$l['login_username'] = "Username:"; -$l['login_username1'] = "Email:"; -$l['login_username2'] = "Username/Email:"; -$l['login_password'] = "Password:"; -$l['lost_password'] = "Lost Password?"; -$l['remember_me'] = "Remember me"; -$l['remember_me_desc'] = "If ticked, your login details will be remembered on this computer, otherwise, you will be logged out as soon as you close your browser."; - -$l['month_1'] = "January"; -$l['month_2'] = "February"; -$l['month_3'] = "March"; -$l['month_4'] = "April"; -$l['month_5'] = "May"; -$l['month_6'] = "June"; -$l['month_7'] = "July"; -$l['month_8'] = "August"; -$l['month_9'] = "September"; -$l['month_10'] = "October"; -$l['month_11'] = "November"; -$l['month_12'] = "December"; - -$l['sunday'] = "Sunday"; -$l['monday'] = "Monday"; -$l['tuesday'] = "Tuesday"; -$l['wednesday'] = "Wednesday"; -$l['thursday'] = "Thursday"; -$l['friday'] = "Friday"; -$l['saturday'] = "Saturday"; -$l['short_monday'] = "M"; -$l['short_tuesday'] = "T"; -$l['short_wednesday'] = "W"; -$l['short_thursday'] = "T"; -$l['short_friday'] = "F"; -$l['short_saturday'] = "S"; -$l['short_sunday'] = "S"; - -$l['yes'] = "Yes"; -$l['no'] = "No"; - -$l['and'] = "and"; -$l['date'] = "Date"; - -$l['nobody'] = "Nobody"; - -$l['attachments'] = "Attachments"; -$l['attachments_desc'] = "Optionally you may attach one or more attachments to this post. Please select the file on the right and click 'Add Attachment' to upload it."; -$l['remove_attachment'] = "Remove"; -$l['approve_attachment'] = "Approve"; -$l['unapprove_attachment'] = "Unapprove"; -$l['insert_attachment_post'] = "Insert Into Post"; -$l['new_attachment'] = "New Attachment:"; -$l['add_attachment'] = "Add Attachment"; -$l['update_attachment'] = "Update Attachment"; -$l['post_preview'] = "Preview"; -$l['change_user'] = "change user"; -$l['post_icon'] = "Post Icon:"; -$l['no_post_icon'] = "no icon"; -$l['thread_subscription_method'] = "Thread Subscription:"; -$l['thread_subscription_method_desc'] = "Specify the type of notification and thread subscription you'd like to have to this thread. (Registered users only)"; -$l['no_subscribe'] = "Do not subscribe to this thread"; -$l['no_subscribe_notification'] = "Subscribe without receiving any notification of new replies"; -$l['instant_email_subscribe'] = "Subscribe and receive email notification of new replies"; -$l['instant_pm_subscribe'] = "Subscribe and receive PM notification of new replies"; - -$l['today'] = "Today"; -$l['yesterday'] = "Yesterday"; -$l['error'] = "Board Message"; - -$l['multipage_pages'] = "Pages ({1}):"; -$l['multipage_last'] = "Last"; -$l['multipage_first'] = "First"; -$l['multipage_next'] = "Next"; -$l['multipage_previous'] = "Previous"; -$l['multipage_link_start'] = " ..."; -$l['multipage_link_end'] = "... "; -$l['multipage_jump'] = "Jump to page"; - -$l['editor_bold'] = "Bold"; -$l['editor_italic'] = "Italic"; -$l['editor_underline'] = "Underline"; -$l['editor_strikethrough'] = "Strikethrough"; -$l['editor_subscript'] = "Subscript"; -$l['editor_superscript'] = "Superscript"; -$l['editor_alignleft'] = "Align left"; -$l['editor_center'] = "Center"; -$l['editor_alignright'] = "Align right"; -$l['editor_justify'] = "Justify"; -$l['editor_fontname'] = "Font Name"; -$l['editor_fontsize'] = "Font Size"; -$l['editor_fontcolor'] = "Font Color"; -$l['editor_removeformatting'] = "Remove Formatting"; -$l['editor_cut'] = "Cut"; -$l['editor_copy'] = "Copy"; -$l['editor_paste'] = "Paste"; -$l['editor_cutnosupport'] = "Your browser does not allow the cut command. Please use the keyboard shortcut Ctrl/Cmd-X"; -$l['editor_copynosupport'] = "Your browser does not allow the copy command. Please use the keyboard shortcut Ctrl/Cmd-C"; -$l['editor_pastenosupport'] = "Your browser does not allow the paste command. Please use the keyboard shortcut Ctrl/Cmd-V"; -$l['editor_pasteentertext'] = "Paste your text inside the following box:"; -$l['editor_pastetext'] = "Paste Text"; -$l['editor_numlist'] = "Numbered list"; -$l['editor_bullist'] = "Bullet list"; -$l['editor_undo'] = "Undo"; -$l['editor_redo'] = "Redo"; -$l['editor_rows'] = "Rows:"; -$l['editor_cols'] = "Cols:"; -$l['editor_inserttable'] = "Insert a table"; -$l['editor_inserthr'] = "Insert a horizontal rule"; -$l['editor_code'] = "Code"; -$l['editor_php'] = "PHP"; -$l['editor_width'] = "Width (optional):"; -$l['editor_height'] = "Height (optional):"; -$l['editor_insertimg'] = "Insert an image"; -$l['editor_email'] = "E-mail:"; -$l['editor_insertemail'] = "Insert an email"; -$l['editor_url'] = "URL:"; -$l['editor_insertlink'] = "Insert a link"; -$l['editor_unlink'] = "Unlink"; -$l['editor_more'] = "More"; -$l['editor_insertemoticon'] = "Insert an emoticon"; -$l['editor_videourl'] = "Video URL:"; -$l['editor_videotype'] = "Video Type:"; -$l['editor_insert'] = "Insert"; -$l['editor_insertyoutubevideo'] = "Insert a YouTube video"; -$l['editor_currentdate'] = "Insert current date"; -$l['editor_currenttime'] = "Insert current time"; -$l['editor_print'] = "Print"; -$l['editor_viewsource'] = "View source"; -$l['editor_description'] = "Description (optional):"; -$l['editor_enterimgurl'] = "Enter the image URL:"; -$l['editor_enteremail'] = "Enter the e-mail address:"; -$l['editor_enterdisplayedtext'] = "Enter the displayed text:"; -$l['editor_enterurl'] = "Enter URL:"; -$l['editor_enteryoutubeurl'] = "Enter the YouTube video URL or ID:"; -$l['editor_insertquote'] = "Insert a Quote"; -$l['editor_invalidyoutube'] = "Invalid YouTube video"; -$l['editor_dailymotion'] = "Dailymotion"; -$l['editor_metacafe'] = "MetaCafe"; -$l['editor_veoh'] = "Veoh"; -$l['editor_vimeo'] = "Vimeo"; -$l['editor_youtube'] = "Youtube"; -$l['editor_twitch'] = "Twitch"; -$l['editor_facebook'] = "Facebook"; -$l['editor_liveleak'] = "LiveLeak"; -$l['editor_insertvideo'] = "Insert a video"; -$l['editor_maximize'] = "Maximize"; - -$l['quote'] = "Quote:"; -$l['wrote'] = "Wrote:"; -$l['code'] = "Code:"; -$l['php_code'] = "PHP Code:"; -$l['posted_image'] = "[Image: {1}]"; -$l['posted_video'] = "[Video: {1}]"; -$l['linkback'] = "Original Post"; - -$l['at'] = "at"; -$l['na'] = "N/A"; -$l['guest'] = "Guest"; -$l['unknown'] = "Unknown"; -$l['never'] = "Never"; -$l['postbit_posts'] = "Posts:"; -$l['postbit_threads'] = "Threads:"; -$l['postbit_group'] = "Group:"; -$l['postbit_joined'] = "Joined:"; -$l['postbit_status'] = "Status:"; -$l['postbit_attachments'] = "Attached Files"; -$l['postbit_attachment_filename'] = "Filename:"; -$l['postbit_attachment_size'] = "Size:"; -$l['postbit_attachment_downloads'] = "Downloads:"; -$l['postbit_attachments_images'] = "Image(s)"; -$l['postbit_attachments_thumbnails'] = "Thumbnail(s)"; -$l['postbit_unapproved_attachments'] = "{1} unapproved attachments."; -$l['postbit_unapproved_attachment'] = "1 unapproved attachment."; -$l['postbit_status_online'] = "Online"; -$l['postbit_status_offline'] = "Offline"; -$l['postbit_status_away'] = "Away"; -$l['postbit_edited'] = "This post was last modified: {1} by"; -$l['postbit_editreason'] = "Edit Reason"; -$l['postbit_ipaddress'] = "IP Address:"; -$l['postbit_ipaddress_logged'] = "Logged"; -$l['postbit_post'] = "Post:"; -$l['postbit_reputation'] = "Reputation:"; -$l['postbit_reputation_add'] = "Give Reputation to this user"; -$l['postbit_website'] = "Visit this user's website"; -$l['postbit_email'] = "Send this user an email"; -$l['postbit_find'] = "Find all posts by this user"; -$l['postbit_report'] = "Report this post to a moderator"; -$l['postbit_quote'] = "Quote this message in a reply"; -$l['postbit_qdelete_post'] = "Delete this post"; -$l['postbit_qdelete_thread'] = "Delete this thread"; -$l['postbit_qrestore_post'] = "Restore this post"; -$l['postbit_qrestore_thread'] = "Restore this thread"; -$l['postbit_profile'] = "View this users profile"; -$l['postbit_pm'] = "Send this user a private message"; -$l['postbit_edit'] = "Edit this post"; -$l['postbit_multiquote'] = "Quote this post"; -$l['postbit_quick_edit'] = "Quick Edit"; -$l['postbit_full_edit'] = "Full Edit"; -$l['postbit_show_ignored_post'] = "Show this Post"; -$l['postbit_currently_ignoring_user'] = "The contents of this message are hidden because {1} is on your ignore list."; -$l['postbit_warning_level'] = "Warning Level:"; -$l['postbit_warn'] = "Warn the author for this post"; -$l['postbit_purgespammer'] = "Purge Spammer"; -$l['postbit_post_deleted'] = "This post has been deleted."; -$l['postbit_post_unapproved'] = "This post is awaiting approval."; -$l['postbit_thread_deleted'] = "This thread has been deleted."; -$l['postbit_thread_unapproved'] = "This thread is awaiting approval."; -$l['postbit_deleted_post_user'] = "This post by {1} has been deleted."; - -$l['postbit_button_reputation_add'] = 'Rate'; -$l['postbit_button_website'] = 'Website'; -$l['postbit_button_email'] = 'Email'; -$l['postbit_button_find'] = 'Find'; -$l['postbit_button_report'] = 'Report'; -$l['postbit_button_quote'] = 'Reply'; -$l['postbit_button_qdelete'] = 'Delete'; -$l['postbit_button_qrestore'] = 'Restore'; -$l['postbit_button_profile'] = 'Profile'; -$l['postbit_button_pm'] = 'PM'; -$l['postbit_button_warn'] = 'Warn'; -$l['postbit_button_edit'] = 'Edit'; -$l['postbit_button_multiquote'] = 'Quote'; -$l['postbit_button_reply_pm'] = 'Reply'; -$l['postbit_button_reply_all'] = 'Reply All'; -$l['postbit_button_forward'] = 'Forward'; -$l['postbit_button_delete_pm'] = 'Delete'; -$l['postbit_button_purgespammer'] = "Purge Spammer"; - -$l['forumjump'] = "Forum Jump:"; -$l['forumjump_pms'] = "Private Messages"; -$l['forumjump_usercp'] = "User Control Panel"; -$l['forumjump_wol'] = "Who's Online"; -$l['forumjump_search'] = "Search"; -$l['forumjump_home'] = "Forum Home"; - -$l['redirect'] = "You will now be redirected"; -$l['unknown_error'] = "An unknown error has occurred."; -$l['post_fetch_error'] = 'There was an error fetching the posts.'; - -$l['smilieinsert'] = "Smilies"; -$l['smilieinsert_getmore'] = "get more"; -$l['on'] = "On"; -$l['off'] = "Off"; -$l['remote_avatar_disabled_default_avatar'] = "You are currently using a remote avatar, which has been disabled. The default avatar will be used instead."; -$l['unread_report'] = "Moderator Notice: There is 1 unread report."; -$l['unread_reports'] = "Moderator Notice: There are {1} unread reports."; -$l['pending_joinrequest'] = "Group Leader Notice: You have 1 pending group membership join request."; -$l['pending_joinrequests'] = "Group Leader Notice: You have {1} pending group membership join requests."; - -$l['search_user'] = "Search for a user"; - -$l['year'] = "Year"; -$l['year_short'] = "y"; -$l['years'] = "Years"; -$l['years_short'] = "y"; -$l['month'] = "Month"; -$l['month_short'] = "m"; -$l['months'] = "Months"; -$l['months_short'] = "m"; -$l['week'] = "Week"; -$l['week_short'] = "w"; -$l['weeks'] = "Weeks"; -$l['weeks_short'] = "w"; -$l['day'] = "Day"; -$l['day_short'] = "d"; -$l['days'] = "Days"; -$l['days_short'] = "d"; -$l['hour'] = "Hour"; -$l['hour_short'] = "h"; -$l['hours'] = "Hours"; -$l['hours_short'] ="h"; -$l['minute'] = "Minute"; -$l['minute_short'] ="m"; -$l['minutes'] = "Minutes"; -$l['minutes_short'] = "m"; -$l['second'] = "Second"; -$l['second_short'] ="s"; -$l['seconds'] = "Seconds"; -$l['seconds_short'] = "s"; - -$l['rel_in'] = "In "; -$l['rel_ago'] = "ago"; -$l['rel_less_than'] = "Less than "; -$l['rel_time'] = "{1}{2} {3} {4}"; -$l['rel_minutes_single'] = "minute"; -$l['rel_minutes_plural'] = "minutes"; -$l['rel_hours_single'] = "hour"; -$l['rel_hours_plural'] = "hours"; - -$l['permanent'] = "Permanent"; -$l['save_draft'] = "Save as Draft"; -$l['go'] = "Go"; -$l['bbclosed_warning'] = "Your board status is currently set to closed."; -$l['banned_warning'] = "Your forum account is currently banned."; -$l['banned_warning2'] = "Ban Reason"; -$l['banned_warning3'] = "Ban will be lifted"; -$l['banned_lifted_never'] = "Never"; -$l['banned_email_warning'] = "You are currently using an email that is not allowed to be used on this forum. Please reset it before continuing."; -$l['powered_by'] = "Powered By"; -$l['copyright'] = "Copyright"; -$l['attach_quota'] = "You are currently using {1} of your allocated attachment usage ({2})"; -$l['view_attachments'] = "[View My Attachments]"; -$l['unlimited'] = "Unlimited"; - -$l['click_hold_edit'] = "(Click and hold to edit)"; - -$l['guest_count'] = "1 Guest"; -$l['guest_count_multiple'] = "{1} Guests"; - -$l['size_yb'] = "YB"; -$l['size_zb'] = "ZB"; -$l['size_eb'] = "EB"; -$l['size_pb'] = "PB"; -$l['size_tb'] = "TB"; -$l['size_gb'] = "GB"; -$l['size_mb'] = "MB"; -$l['size_kb'] = "KB"; -$l['size_bytes'] = "bytes"; - -$l['slaps'] = "slaps"; -$l['with_trout'] = "around a bit with a large trout."; - -$l['mybb_engine'] = "MyBB Engine"; -$l['quickdelete_confirm'] = "Are you sure you want to delete this post?"; -$l['quickrestore_confirm'] = "Are you sure you want to restore this post?"; -$l['newpm_notice_one'] = "You have one unread private message from {1} titled {4}"; -$l['newpm_notice_multiple'] = "You have {1} unread private messages. The most recent is from {2} titled {5}"; -$l['deleteevent_confirm'] = "Are you sure you want to delete this event?"; -$l['removeattach_confirm'] = "Are you sure you want to remove the selected attachment from this post?"; - -$l['latest_threads'] = "Latest Threads"; - -$l['folder_inbox'] = "Inbox"; -$l['folder_sent_items'] = "Sent Items"; -$l['folder_drafts'] = "Drafts"; -$l['folder_trash'] = "Trash Can"; -$l['folder_untitled'] = "Untitled Folder"; - -$l['standard_mod_tools'] = "Standard Tools"; -$l['custom_mod_tools'] = "Custom Tools"; - -$l['error_loadlimit'] = "The maximum server load limit has been reached. Please check back later once the server is less busy."; -$l['error_boardclosed'] = "This bulletin board is currently closed. The Administrator has specified the reason as to why below."; -$l['error_banned'] = "I'm sorry, but you are banned. You may not post, read threads, or access the forum. Please contact your forum administrator should you have any questions."; -$l['error_cannot_upload_php_post'] = "Can not upload file - Too large for php post_max_size directive. Please press the back button."; -$l['error_database_repair'] = "MyBB is automatically repairing a crashed table."; - -$l['unknown_user_trigger'] = "An unknown error has been triggered."; -$l['warnings'] = "The following warnings occurred:"; - -$l['ajax_loading'] = "Loading.
    Please Wait.."; -$l['saving_changes'] = "Saving changes.."; -$l['refresh'] = "Refresh"; -$l['select_language'] = "Quick Language Select"; -$l['select_theme'] = "Quick Theme Select"; - -$l['invalid_post_code'] = "Authorization code mismatch. Are you accessing this function correctly? Please go back and try again."; -$l['invalid_captcha'] = "Please fill out the image verification code to continue. Please enter the code exactly how it appears in the image."; -$l['invalid_nocaptcha'] = "Please solve the reCAPTCHA to verify that you're not a robot."; -$l['invalid_captcha_verify'] = "The image verification code that you entered was incorrect. Please enter the code exactly how it appears in the image."; -$l['image_verification'] = "Image Verification"; -$l['human_verification'] = "Human Verification"; -$l['verification_note'] = "Please enter the text contained within the image into the text box below it. This process is used to prevent automated spam bots."; -$l['verification_note_nocaptcha'] = "Please tick the checkbox that you see below. This process is used to prevent automated spam bots."; -$l['verification_subnote'] = "(case insensitive)"; -$l['invalid_captcha_transmit'] = "An error occurred with the image verification. Please try again."; -$l['invalid_nocaptcha_transmit'] = "An error occurred with the human verification. Please try again."; -$l['captcha_fetch_failure'] = 'There was an error fetching the new captcha.'; -$l['question_fetch_failure'] = 'There was an error fetching the new question.'; - -$l['timezone_gmt_minus_1200'] = "(GMT -12:00) Howland and Baker Islands"; -$l['timezone_gmt_minus_1100'] = "(GMT -11:00) Nome, Midway Island"; -$l['timezone_gmt_minus_1000'] = "(GMT -10:00) Hawaii, Papeete"; -$l['timezone_gmt_minus_950'] = "(GMT -9:30) Marquesas Islands"; -$l['timezone_gmt_minus_900'] = "(GMT -9:00) Alaska"; -$l['timezone_gmt_minus_800'] = "(GMT -8:00) Pacific Time"; -$l['timezone_gmt_minus_700'] = "(GMT -7:00) Mountain Time"; -$l['timezone_gmt_minus_600'] = "(GMT -6:00) Central Time, Mexico City"; -$l['timezone_gmt_minus_500'] = "(GMT -5:00) Eastern Time, Bogota, Lima, Quito"; -$l['timezone_gmt_minus_450'] = "(GMT -4:30) Caracas"; -$l['timezone_gmt_minus_400'] = "(GMT -4:00) Atlantic Time, La Paz, Halifax"; -$l['timezone_gmt_minus_350'] = "(GMT -3:30) Newfoundland"; -$l['timezone_gmt_minus_300'] = "(GMT -3:00) Brazil, Buenos Aires, Georgetown, Falkland Is."; -$l['timezone_gmt_minus_200'] = "(GMT -2:00) Mid-Atlantic, South Georgia and the South Sandwich Islands"; -$l['timezone_gmt_minus_100'] = "(GMT -1:00) Azores, Cape Verde Islands"; -$l['timezone_gmt'] = "(GMT) Casablanca, Dublin, Edinburgh, London, Lisbon, Monrovia"; -$l['timezone_gmt_100'] = "(GMT +1:00) Berlin, Brussels, Copenhagen, Madrid, Paris, Rome, Warsaw"; -$l['timezone_gmt_200'] = "(GMT +2:00) Athens, Istanbul, Cairo, Jerusalem, South Africa"; -$l['timezone_gmt_300'] = "(GMT +3:00) Kaliningrad, Minsk, Baghdad, Riyadh, Nairobi"; -$l['timezone_gmt_350'] = "(GMT +3:30) Tehran"; -$l['timezone_gmt_400'] = "(GMT +4:00) Moscow, Abu Dhabi, Baku, Muscat, Tbilisi"; -$l['timezone_gmt_450'] = "(GMT +4:30) Kabul"; -$l['timezone_gmt_500'] = "(GMT +5:00) Islamabad, Karachi, Tashkent"; -$l['timezone_gmt_550'] = "(GMT +5:30) Mumbai, Kolkata, Chennai, New Delhi"; -$l['timezone_gmt_575'] = "(GMT +5:45) Kathmandu"; -$l['timezone_gmt_600'] = "(GMT +6:00) Almaty, Dhakra, Yekaterinburg"; -$l['timezone_gmt_650'] = "(GMT +6:30) Yangon"; -$l['timezone_gmt_700'] = "(GMT +7:00) Bangkok, Hanoi, Jakarta"; -$l['timezone_gmt_800'] = "(GMT +8:00) Beijing, Hong Kong, Perth, Singapore, Taipei, Manila"; -$l['timezone_gmt_850'] = "(GMT +8:30) Pyongyang"; -$l['timezone_gmt_875'] = "(GMT +8:45) Eucla"; -$l['timezone_gmt_900'] = "(GMT +9:00) Osaka, Sapporo, Seoul, Tokyo, Irkutsk"; -$l['timezone_gmt_950'] = "(GMT +9:30) Adelaide, Darwin"; -$l['timezone_gmt_1000'] = "(GMT +10:00) Melbourne, Papua New Guinea, Sydney, Yakutsk"; -$l['timezone_gmt_1050'] = "(GMT +10:30) Lord Howe Island"; -$l['timezone_gmt_1100'] = "(GMT +11:00) Magadan, New Caledonia, Solomon Islands, Vladivostok"; -$l['timezone_gmt_1150'] = "(GMT +11:30) Norfolk Island"; -$l['timezone_gmt_1200'] = "(GMT +12:00) Auckland, Wellington, Fiji, Marshall Islands"; -$l['timezone_gmt_1275'] = "(GMT +12:45) Chatham Islands"; -$l['timezone_gmt_1300'] = "(GMT +13:00) Samoa, Tonga, Tokelau"; -$l['timezone_gmt_1400'] = "(GMT +14:00) Line Islands"; -$l['timezone_gmt_short'] = "GMT {1}({2})"; - -$l['missing_task'] = "Error: Task file does not exist"; -$l['task_backup_cannot_write_backup'] = "Error: The database backup task cannot write to backups directory."; -$l['task_backup_ran'] = "The database backup task successfully ran."; -$l['task_checktables_ran'] = "The check tables task successfully ran with no corrupted tables found."; -$l['task_checktables_ran_found'] = "Notice: The check tables task successfully ran and repaired the {1} table(s)."; -$l['task_dailycleanup_ran'] = "The daily cleanup task successfully ran."; -$l['task_hourlycleanup_ran'] = "The hourly cleanup task successfully ran."; -$l['task_logcleanup_ran'] = "The log cleanup task successfully ran and pruned any old logs."; -$l['task_promotions_ran'] = "The promotions task successfully ran."; -$l['task_threadviews_ran'] = "The thread views task successfully ran."; -$l['task_usercleanup_ran'] = "The user cleanup task successfully ran."; -$l['task_massmail_ran'] = "The mass mail task successfully ran."; -$l['task_userpruning_ran'] = "The user pruning task successfully ran."; -$l['task_delayedmoderation_ran'] = "The delayed moderation task successfully ran."; -$l['task_massmail_ran_errors'] = "One or more problems occurred sending to \"{1}\": -{2}"; -$l['task_versioncheck_ran'] = "The version check task successfully ran."; -$l['task_versioncheck_ran_errors'] = "Could not connect to MyBB for a version check."; -$l['task_recachestylesheets_ran'] = 'Re-cached {1} stylesheets.'; - -$l['dismiss_notice'] = "Dismiss this notice"; - -$l['next'] = "Next"; -$l['previous'] = "Previous"; -$l['delete'] = "Delete"; - -$l['massmail_username'] = "Username"; -$l['email_addr'] = "Email Address"; -$l['board_name'] = "Board Name"; -$l['board_url'] = "Board URL"; - -$l['comma'] = ", "; - -$l['debug_generated_in'] = "Generated in {1}"; -$l['debug_weight'] = "({1}% PHP / {2}% {3})"; -$l['debug_sql_queries'] = "SQL Queries: {1}"; -$l['debug_server_load'] = "Server Load: {1}"; -$l['debug_memory_usage'] = "Memory Usage: {1}"; -$l['debug_advanced_details'] = "Advanced Details"; - -$l['error_emailflooding_1_second'] = "Sorry, but you can only send one email every {1} minutes. Please wait another 1 second before attempting to email again."; -$l['error_emailflooding_seconds'] = "Sorry, but you can only send one email every {1} minutes. Please wait another {2} seconds before attempting to email again."; -$l['error_emailflooding_1_minute'] = "Sorry, but you can only send one email every {1} minutes. Please wait another 1 minute before attempting to email again."; -$l['error_emailflooding_minutes'] = "Sorry, but you can only send one email every {1} minutes. Please wait another {2} minutes before attempting to email again."; -$l['error_invalidfromemail'] = "You did not enter a valid from email address."; -$l['error_noname'] = "You did not enter a valid name."; -$l['your_email'] = "Your Email:"; -$l['email_note'] = "Enter your email address here."; -$l['your_name'] = "Your Name:"; -$l['name_note'] = "Enter your name here."; - -$l['january'] = "January"; -$l['february'] = "February"; -$l['march'] = "March"; -$l['april'] = "April"; -$l['may'] = "May"; -$l['june'] = "June"; -$l['july'] = "July"; -$l['august'] = "August"; -$l['september'] = "September"; -$l['october'] = "October"; -$l['november'] = "November"; -$l['december'] = "December"; - -$l['moderation_forum_attachments'] = "Please note that new attachments in this forum must be approved by a moderator before becoming visible."; -$l['moderation_forum_posts'] = "Please note that new posts in this forum must be approved by a moderator before becoming visible."; -$l['moderation_user_posts'] = "Please note that new posts you make must be approved by a moderator before becoming visible."; -$l['moderation_forum_thread'] = "Please note that new threads in this forum must be approved by a moderator before becoming visible."; -$l['moderation_forum_edits'] = "Please note that edited posts in this forum must be approved by a moderator before becoming visible."; -$l['moderation_forum_edits_quick'] = "Please note that edited posts in this forum must be approved by a moderator before becoming visible."; -$l['awaiting_message_link'] = " Go to the ACP."; -$l['awaiting_message_single'] = "There is 1 account awaiting activation. Please go to your ACP to activate the user."; -$l['awaiting_message_plural'] = "There are {1} accounts awaiting activation. Please go to your ACP to activate the users."; - -$l['select2_match'] = "One result is available, press enter to select it."; -$l['select2_matches'] = "{1} results are available, use up and down arrow keys to navigate."; -$l['select2_nomatches'] = "No matches found"; -$l['select2_inputtooshort_single'] = "Please enter one or more character"; -$l['select2_inputtooshort_plural'] = "Please enter {1} or more characters"; -$l['select2_inputtoolong_single'] = "Please delete one character"; -$l['select2_inputtoolong_plural'] = "Please delete {1} characters"; -$l['select2_selectiontoobig_single'] = "You can only select one item"; -$l['select2_selectiontoobig_plural'] = "You can only select {1} items"; -$l['select2_loadmore'] = "Loading more results…"; -$l['select2_searching'] = "Searching…"; - -$l['stopforumspam_error_decoding'] = 'Error decoding data from StopForumSpam.com.'; -$l['stopforumspam_error_retrieving'] = 'Error retrieving data from StopForumSpam.com.'; - -$l['sfs_error_username'] = 'username'; -$l['sfs_error_ip'] = 'IP'; -$l['sfs_error_email'] = 'email'; -$l['sfs_error_or'] = 'or'; - -$l['boardclosed_reason'] = 'These forums are currently closed for maintenance. Please check back later'; diff --git a/html/forums/inc/languages/english/hello.lang.php b/html/forums/inc/languages/english/hello.lang.php deleted file mode 100644 index 6e02a9c..0000000 --- a/html/forums/inc/languages/english/hello.lang.php +++ /dev/null @@ -1,16 +0,0 @@ -
    You are encouraged to register; once you register you will be able to post messages, set your own preferences, and maintain a profile. -

    Some of the features that generally require registration are subscriptions, changing of styles, accessing of your Personal Notepad and emailing forum members."; - -// Help Document 2 -$l['d2_name'] = "Updating Profile"; -$l['d2_desc'] = "Changing your data currently on record."; -$l['d2_document'] = "At some point during your stay, you may decide you need to update some information such as your instant messenger information, your password, or your email address. You may change any of this information from your user control panel. To access this control panel, simply click on the link in the upper right hand corner of most any page entitled \"User CP\". From there, simply choose the appropriate link under the \"Your Profile\" section and change or update any desired items, then proceed to click the submit button located at the bottom of the page for changes to take effect."; - -// Help Document 3 -$l['d3_name'] = "Use of Cookies on MyBB"; -$l['d3_desc'] = "MyBB uses cookies to store certain information about your registration."; -$l['d3_document'] = "MyBB makes use of cookies to store your login information if you are registered, and your last visit if you are not. -

    Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. -

    Cookies on this forum also track the specific topics you have read and when you last read them. -

    To clear all cookies set by this forum, you can click here."; - -// Help Document 4 -$l['d4_name'] = "Logging In and Out"; -$l['d4_desc'] = "How to login and log out."; -$l['d4_document'] = "When you login, you set a cookie on your machine so that you can browse the forums without having to enter in your username and password each time. Logging out clears that cookie to ensure nobody else can browse the forum as you. -

    To login, simply click the login link at the top right hand corner of the forum. To log out, click the log out link in the same place. In the event you cannot log out, clearing cookies on your machine will take the same effect."; - -// Help Document 5 -$l['d5_name'] = "Posting a New Thread"; -$l['d5_desc'] = "Starting a new thread in a forum."; -$l['d5_document'] = "When you go to a forum you are interested in and you wish to create a new thread (or topic), simply choose the button at the top and bottom of the forums entitled \"New Thread\". Please take note that you may not have permission to post a new thread in every forum as your administrator may have restricted posting in that forum to staff or archived the forum entirely."; - -// Help Document 6 -$l['d6_name'] = "Posting a Reply"; -$l['d6_desc'] = "Replying to a topic within a forum."; -$l['d6_document'] = "During the course of your visit, you may encounter a thread to which you would like to make a reply. To do so, simply click the \"New Reply\" button at the bottom or top of the thread. Please take note that your administrator may have restricted posting to certain individuals in that particular forum. -

    Additionally, a moderator of a forum may have closed a thread meaning that users cannot reply to it. There is no way for a user to open such a thread without the help of a moderator or administrator."; - -// Help Document 7 -$l['d7_name'] = "MyCode"; -$l['d7_desc'] = "Learn how to use MyCode to enhance your posts."; -$l['d7_document'] = "You can use MyCode, a simplified version of HTML, in your posts to create certain effects. -


    [b]This text is bold[/b]
       This text is bold -

    [i]This text is italicized[/i]
       This text is italicized -

    [u]This text is underlined[/u]
       This text is underlined -

    [s]This text is struck out[/s]
       This text is struck out -


    [url]http://www.example.com/[/url]
       http://www.example.com/ -

    [url=http://www.example.com/]Example.com[/url]
       Example.com -

    [email]example@example.com[/email]
       example@example.com -

    [email=example@example.com]E-mail Me![/email]
       E-mail Me! -

    [email=example@example.com?subject=spam]E-mail with subject[/email]
       E-mail with subject -


    [quote]Quoted text will be here[/quote]
       Quoted text will be here -

    [code]Text with preserved formatting[/code]
       Text with preserved formatting -


    [img]http://www.php.net/images/php.gif[/img]
        -

    [img=50x50]http://www.php.net/images/php.gif[/img]
        -


    [color=red]This text is red[/color]
       This text is red -

    [size=3]This text is size 3[/size]
       This text is size 3 -

    [font=Tahoma]This font is Tahoma[/font]
       This font is Tahoma -


    [align=center]This is centered[/align]

    This is centered
    -

    [align=right]This is right-aligned[/align]

    This is right-aligned
    -


    [list]
    [*]List Item #1
    [*]List Item #2
    [*]List Item #3
    [/list]

    • List item #1
    • List item #2
    • List Item #3
    • -
    -

    You can make an ordered list by using [list=1] for a numbered, and [list=a] for an alphabetical list.

    "; diff --git a/html/forums/inc/languages/english/helpsections.lang.php b/html/forums/inc/languages/english/helpsections.lang.php deleted file mode 100644 index 3ba4237..0000000 --- a/html/forums/inc/languages/english/helpsections.lang.php +++ /dev/null @@ -1,14 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/languages/english/index.lang.php b/html/forums/inc/languages/english/index.lang.php deleted file mode 100644 index 7fc4b5e..0000000 --- a/html/forums/inc/languages/english/index.lang.php +++ /dev/null @@ -1,40 +0,0 @@ -{1}"; -$l['stats_mostonline'] = "The most users online at one time was {1} on {2} at {3}"; -$l['whos_online'] = "Who's Online"; -$l['complete_list'] = "Complete List"; -$l['online_online_plural'] = "users"; -$l['online_online_singular'] = "user"; -$l['online_member_plural'] = "members"; -$l['online_member_singular'] = "member"; -$l['online_anon_plural'] = "are"; -$l['online_anon_singular'] = "is"; -$l['online_guest_plural'] = "guests"; -$l['online_guest_singular'] = "guest"; -$l['online_note'] = "{1} {2} active in the past {3} minutes ({4} {5}, {6} of whom {7} invisible, and {8} {9})."; -$l['subforums'] = "Sub Forums:"; diff --git a/html/forums/inc/languages/english/mailhandler.lang.php b/html/forums/inc/languages/english/mailhandler.lang.php deleted file mode 100644 index 638785b..0000000 --- a/html/forums/inc/languages/english/mailhandler.lang.php +++ /dev/null @@ -1,16 +0,0 @@ -'; diff --git a/html/forums/inc/languages/english/managegroup.lang.php b/html/forums/inc/languages/english/managegroup.lang.php deleted file mode 100644 index 2035415..0000000 --- a/html/forums/inc/languages/english/managegroup.lang.php +++ /dev/null @@ -1,64 +0,0 @@ -{1} pending join requests for this user group."; -$l['group_management'] = "Group Management"; -$l['members_of'] = "Members in \"{1}\""; -$l['user_name'] = "Username"; -$l['contact'] = "Contact"; -$l['reg_date'] = "Registered"; -$l['post_count'] = "Posts"; -$l['remove_selected'] = "Remove Selected Users from Group"; -$l['add_member'] = "Add Member to \"{1}\""; -$l['add_member_submit'] = "Add Member to Group"; -$l['invite_member'] = "Invite Member to \"{1}\""; -$l['invite_member_submit'] = "Invite Member to Group"; -$l['join_requests'] = "Join Requests"; -$l['join_requests_title'] = "Join Requests for \"{1}\""; -$l['leader'] = "(Leader)"; -$l['reason'] ="Reason"; -$l['accept'] = "Accept"; -$l['ignore'] = "Ignore"; -$l['decline'] = "Decline"; -$l['action_requests'] = "Perform Actions"; -$l['join_requests_moderated'] = "The join requests have been moderated.
    You will now be taken to the request listing."; -$l['no_requests'] = "There are currently no pending join requests for this group."; -$l['no_users'] = "There are no users in this group."; -$l['user_added'] = "The user has been added to the user group."; -$l['users_removed'] = "The selected users have been removed from the user group."; -$l['group_no_members'] = "There are currently no members in this group.
    To return to the group management page, click here."; -$l['group_public_moderated'] = "This user group is a public user group that anyone can join. All join requests must be moderated by a group leader."; -$l['group_public_not_moderated'] = "This user group is a public user group that anyone can join freely."; -$l['group_public_invite'] = "This user group is a public user group that requires an invitation from a group leader in order to join."; -$l['group_private'] = "This user group is a private user group. Only users added by the group leader can be part of this group."; -$l['group_default'] = "This user group is a core user group."; -$l['group_leaders'] = "Group Leaders"; -$l['no_users_selected'] = "Sorry, but no users seemed to be selected for removal.
    Please go back and select the users you want to remove from this group."; - -$l['error_alreadyingroup'] = "The user specified is already part of the user group."; -$l['error_alreadyinvited'] = "The user specified has already been invited."; - -$l['user_invited'] = "The user has been invited to join the user group."; -$l['invite_pm_subject'] = "You have been invited to join \"{1}\""; -$l['invite_pm_message'] = "You have received an invitation to join the user group \"{1}\". - -To join, please proceed to your [url={2}/usercp.php?action=usergroups]Group Memberships[/url] page and click 'Accept Invite'. - -This invitation does not expire."; -$l['invite_pm_message_expires'] = "You have received an invitation to join the user group \"{1}\". - -To join, please proceed to your [url={2}/usercp.php?action=usergroups]Group Memberships[/url] page and click 'Accept Invite'. - -This invite will expire {3} days from now."; - diff --git a/html/forums/inc/languages/english/member.lang.php b/html/forums/inc/languages/english/member.lang.php deleted file mode 100644 index c08cbca..0000000 --- a/html/forums/inc/languages/english/member.lang.php +++ /dev/null @@ -1,256 +0,0 @@ -Complex Password:"; -$l['confirm_email'] = "Confirm Email:"; -$l['optional_fields'] = "Optional Fields"; -$l['website_url'] = "Your Website URL:"; -$l['birthdate'] = "Birthdate:"; -$l['additional_info'] = "Additional Information"; -$l['required_info'] = "Required Information"; -$l['i_agree'] = "I Agree"; -$l['account_details'] = "Account Details"; -$l['account_prefs'] = "Account Preferences:"; -$l['invisible_mode'] = "Hide me from the Who's Online list."; -$l['allow_notices'] = "Receive emails from the Administrators."; -$l['hide_email'] = "Hide your email from other members."; -$l['email_notify'] = "Automatically subscribe to threads you post in."; -$l['receive_pms'] = "Receive private messages from other users."; -$l['pm_notice'] = "Alert me with a notice when I receive a Private Message."; -$l['email_notify_newpm'] = "Notify me by email when I receive a new Private Message."; -$l['time_offset'] = "Time Zone (DST correction excluded):"; -$l['time_offset_desc'] = "If you live in a time zone which differs to what this board is set at, you can select it from the list below."; -$l['dst_correction'] = "Daylight Saving Time correction:"; -$l['dst_correction_auto'] = "Automatically detect DST settings"; -$l['dst_correction_enabled'] = "Always use DST correction"; -$l['dst_correction_disabled'] = "Never use DST correction"; -$l['redirect_registered_coppa_activate'] = "Thank you for registering on {1}, {2}. Your account has successfully been created, however, as the owner of this account is under the age of 13, parental permission needs to be sought before this account can be used.

    A parent or legal guardian will need to download, fill in and submit to us a completed copy of our COPPA Compliance & Permission form.

    Once we receive a completed copy of this form, the account will be activated."; -$l['coppa_compliance'] = "COPPA Compliance"; -$l['coppa_desc'] = "In order to register on these forums, we require you to verify your age to comply with COPPA. Please enter your date of birth below.

    If you are under the age of 13, parental permission must be obtained prior to registration. A parent or legal guardian will need to download, fill in and submit to us a completed copy of our COPPA Compliance & Permission form."; -$l['hide_dob'] = "You can choose to hide your date of birth and age by editing your profile after registering."; -$l['signature'] = "Signature:"; -$l['continue_registration'] = "Continue with Registration"; -$l['birthdayprivacy'] = "Date of Birth Privacy:"; -$l['birthdayprivacyall'] = "Display Age and Date of Birth"; -$l['birthdayprivacynone'] = "Hide Age and Date of Birth"; -$l['birthdayprivacyage'] = "Display Only Age"; -$l['leave_this_field_empty'] = "Leave this field empty:"; -$l['error_need_to_be_thirteen'] = "You need to be of thirteen years or older to register on this forum."; -$l['coppa_registration'] = "COPPA Registration Form"; -$l['coppa_form_instructions'] = "Please print this form, fill it in and either fax it to the number below or mail it to the provided mailing address."; -$l['fax_number'] = "Fax Number:"; -$l['mailing_address'] = "Mailing Address:"; -$l['account_information'] = "Account Information"; -$l['parent_details'] = "Parent / Guardian Details"; -$l['full_name'] = "Full Name:"; -$l['relation'] = "Relation:"; -$l['phone_no'] = "Phone #:"; -$l['coppa_parent_agreement'] = "I understand that the information I have provided is truthful, that any information may be changed in the future by entering the supplied password and this user account can be removed by request."; - -$l['coppa_agreement_1'] = "Users under the age of 13 must receive permission from their parent or legal guardian in order to register on {1}."; -$l['coppa_agreement_2'] = "A parent or legal guardian will need to download, fill in and submit to us a completed copy of our COPPA Compliance & Permission form before membership will be granted."; -$l['coppa_agreement_3'] = "If you'd like to, you can begin the registration process now, however the account will be inaccessible until the above compliance form is received."; - -$l['error_invalid_birthday'] = 'The birthday you entered is invalid. Please enter a valid birthday.'; -$l['error_awaitingcoppa'] = "You cannot login using this account as it is still awaiting COPPA validation from a parent or guardian.

    A parent or legal guardian will need to download, fill in and submit to us a completed copy of our COPPA Compliance & Permission form.

    Once we receive a completed copy of this form, the account will be activated."; - -$l['lang_select'] = "Language Settings:"; -$l['lang_select_desc'] = "If you live in a country that speaks a language other than the forums default, you may be able to select an installed, read-able language pack below."; -$l['lang_select_default'] = "Use Default"; - -$l['submit_registration'] = "Submit Registration!"; -$l['confirm_password'] = "Confirm Password:"; -$l['referrer'] = "Referrer:"; -$l['referrer_desc'] = "If you were referred to these forums by another member you can enter their name below. If not, simply leave this field blank."; -$l['resend_activation'] = "Resend Account Activation"; -$l['request_activation'] = "Request Activation Code"; -$l['ppp'] = "Posts Per Page:"; -$l['ppp_desc'] = "Allows you to select the amount of posts to be shown per page in a thread."; -$l['tpp'] = "Threads Per Page:"; -$l['tpp_desc'] = "Allows you to select the amount of threads to be shown per page in the thread listing."; -$l['reset_password'] = "Reset Password"; -$l['send_password'] = "Send New Password!"; -$l['registration_errors'] = "The following errors occurred with your registration:"; -$l['timeonline'] = "Time Spent Online:"; -$l['timeonline_hidden'] = "(Hidden)"; -$l['registrations_disabled'] = "Sorry, but you cannot register at this time because the administrator has disabled new account registrations."; -$l['error_username_length'] = "Your username is invalid. Usernames have to be within {1} to {2} characters."; -$l['error_stop_forum_spam_spammer'] = 'Sorry, your {1} matches that of a known spammer. If you feel this is a mistake, please contact an administrator.'; -$l['error_stop_forum_spam_fetching'] = 'Sorry, something went wrong verifying your account against a spammer database. Most likely the database couldn\'t be accessed. Please try again later.'; - -$l['none_registered'] = "None Registered"; -$l['not_specified'] = "Not Specified"; -$l['membdayage'] = "({1} years old)"; -$l['mod_options'] = "Moderator Options"; -$l['edit_in_mcp'] = "Edit this user in Mod CP"; -$l['ban_in_mcp'] = "Ban this user in Mod CP"; -$l['purgespammer'] = "Purge Spammer"; -$l['edit_usernotes'] = "Edit user notes in Mod CP"; -$l['no_usernotes'] = "There are currently no notes on this user"; -$l['view_all_notes'] = "View all notes"; -$l['view_notes_for'] = "View notes for {1}"; -$l['registration_ip'] = "Registration IP:"; -$l['last_known_ip'] = "Last Known IP:"; -$l['reputation'] = "Reputation:"; -$l['reputation_vote'] = "Rate"; -$l['reputation_details'] = "Details"; -$l['already_logged_in'] = "Notice: You are already currently logged in as {1}."; -$l['admin_edit_in_acp'] = "Edit this user in Admin CP"; -$l['admin_ban_in_acp'] = "Ban this user in Admin CP"; -$l['admin_options'] = "Administrator Options"; - -$l['redirect_registered_activation'] = "Thank you for registering on {1}, {2}.

    To complete your registration, please check your email for account activation instructions. Until you activate your account you may not be able to post on these forums"; -$l['redirect_emailupdated'] = "Your email has been successfully changed.
    You will now be taken back to the main page."; -$l['redirect_accountactivated'] = "Your account has successfully been activated.
    You will now be taken back to the main page."; -$l['redirect_accountactivated_admin'] = "Your email has successfully validated.
    Your registration must now be activated by an administrator. Until then, you may not be able to post on these forums.
    You will now be taken back to the main page."; -$l['redirect_registered'] = "Thank you for registering on {1}, {2}.
    You will now be taken back to the main page."; -$l['redirect_registered_admin_activate'] = "Thank you for registering on {1}, {2}.
    Your registration must be activated by an administrator. Until then, you may not be able to post on these forums."; -$l['redirect_loggedout'] = "You have successfully been logged out.
    You will now be taken back to the forum index."; -$l['redirect_alreadyloggedout'] = "You were already logged out or have not logged in yet.
    You will now be taken back to the forum index."; -$l['redirect_lostpwsent'] = "Thank you, all accounts pertaining to that email address have now been sent an email with details on how to reset the passwords.

    You will now be taken to the forums' index."; -$l['redirect_activationresent'] = "Your activation e-mail has been resent."; -$l['redirect_passwordreset'] = "Thank you, the password for your account has been reset. The new randomly generated password has been emailed to the email address in your account."; -$l['redirect_memberrated'] = "The member has successfully been rated."; -$l['redirect_registered_passwordsent'] = "A random password has been generated and sent to your email address. Before you can login on these forums, you will need to check your email for this password."; -$l['redirect_validated'] = "Thank you, your account has been validated.
    You will now be taken to the forums."; - -$l['error_activated_by_admin'] = "You cannot resend your account activation email as all registrations must be approved by an Administrator."; -$l['error_alreadyregistered'] = "Sorry, but our system shows that you have already registered on these forums and the registration of multiple accounts has been disabled."; -$l['error_alreadyregisteredtime'] = "We cannot process your registration because there has already been {1} new registration(s) from your ip address in the past {2} hours. Please try again later."; -$l['error_badlostpwcode'] = "You seem to have entered an invalid password reset code. Please re-read the email you were sent or contact the forum administrators for more help."; -$l['error_badactivationcode'] = "You have entered an invalid account activation code. To resend all activation emails to the email address on file, please click here."; -$l['error_alreadyactivated'] = "It appears your account is already activated or does not require email verification."; -$l['error_alreadyvalidated'] = "Your email have already been validated."; -$l['error_nothreadurl'] = "Your message does not contain the URL of the thread. Please use the \"send to friend\" feature for it's intended purpose."; -$l['error_bannedusername'] = "You have entered a username that is banned from registration. Please choose another username."; -$l['error_notloggedout'] = "Your user ID could not be verified to log you out. This may have been because a malicious Javascript was attempting to log you out automatically. If you intended to log out, please click the Log Out button at the top menu."; -$l['error_regimageinvalid'] = "The image verification code that you entered was incorrect. Please enter the code exactly how it appears in the image."; -$l['error_regimagerequired'] = "Please fill out the image verification code to continue the login process. Please enter the code exactly how it appears in the image."; -$l['error_spam_deny'] = "Our systems detect that you may be a spammer and therefore you have been denied registration. If you feel this is a mistake, please contact the Administrator."; -$l['error_spam_deny_time'] = "Our systems detect that you may be a spammer and therefore you have been denied registration. Registration must take a minimum time of {1} seconds to prevent automated signups, you registered in {2} seconds. If you feel this is a mistake, please contact the Administrator."; - -$l['js_validator_no_username'] = "You must enter a username"; -$l['js_validator_invalid_email'] = "You need to enter a valid email address"; -$l['js_validator_email_match'] = "You need to enter the same email address again"; -$l['js_validator_no_image_text'] = "You need to enter the text in the image above"; -$l['js_validator_no_security_question'] = "You need to enter the answer to the question above"; -$l['js_validator_password_matches'] = "The passwords you enter must match"; -$l['js_validator_password_complexity'] = "Checking password complexity"; -$l['js_validator_password_length'] = "Your password must be {1} or more characters long"; -$l['js_validator_not_empty'] = "You must select or enter a value for this field"; -$l['js_validator_checking_username'] = "Checking if username is available"; -$l['js_validator_username_length'] = "Usernames must be between {1} and {2} characters long"; -$l['js_validator_checking_referrer'] = "Checking if referrer username exists."; -$l['js_validator_captcha_valid'] = "Checking whether or not you entered the correct image verification code."; - -$l['security_question'] = "Security Question"; -$l['question_note'] = "Please answer the question provided. This process is used to prevent automated processes."; -$l['error_question_wrong'] = "The answer you provided for the security question is wrong. Please try again."; - -$l['subscription_method'] = "Default Thread Subscription Mode:"; -$l['no_auto_subscribe'] = "Do not subscribe"; -$l['no_subscribe'] = "No notification"; -$l['instant_email_subscribe'] = "Instant email notification"; -$l['instant_pm_subscribe'] = "Instant PM notification"; - -$l['remove_from_buddy_list'] = "Remove from Buddy List"; -$l['add_to_buddy_list'] = "Add to Buddy List"; -$l['remove_from_ignore_list'] = "Remove from Ignore List"; -$l['add_to_ignore_list'] = "Add to Ignore List"; -$l['report_user'] = "Report User"; - -$l['newregistration_subject'] = "New registration at {1}"; -$l['newregistration_message'] = "{1}, - -There is a new user at {2} who is pending admin activation. - -Username: {3} - -Thank you, -{2} Staff"; diff --git a/html/forums/inc/languages/english/memberlist.lang.php b/html/forums/inc/languages/english/memberlist.lang.php deleted file mode 100644 index f294e49..0000000 --- a/html/forums/inc/languages/english/memberlist.lang.php +++ /dev/null @@ -1,79 +0,0 @@ -There were no members found with the search criteria you entered.

    Please enter a different search term and try again.

    "; - -$l['a'] = 'A'; -$l['b'] = 'B'; -$l['c'] = 'C'; -$l['d'] = 'D'; -$l['e'] = 'E'; -$l['f'] = 'F'; -$l['g'] = 'G'; -$l['h'] = 'H'; -$l['i'] = 'I'; -$l['j'] = 'J'; -$l['k'] = 'K'; -$l['l'] = 'L'; -$l['m'] = 'M'; -$l['n'] = 'N'; -$l['o'] = 'O'; -$l['p'] = 'P'; -$l['q'] = 'Q'; -$l['r'] = 'R'; -$l['s'] = 'S'; -$l['t'] = 'T'; -$l['u'] = 'U'; -$l['v'] = 'V'; -$l['w'] = 'W'; -$l['x'] = 'X'; -$l['y'] = 'Y'; -$l['z'] = 'Z'; - diff --git a/html/forums/inc/languages/english/messages.lang.php b/html/forums/inc/languages/english/messages.lang.php deleted file mode 100644 index 8aa97af..0000000 --- a/html/forums/inc/languages/english/messages.lang.php +++ /dev/null @@ -1,505 +0,0 @@ -
    Alternatively, return to the forum."; -$l['redirect_emailsent'] = "Your e-mail message has been sent successfully."; -$l['redirect_loggedin'] = "You have successfully been logged in.
    You will now be taken back to where you came from."; - -$l['error_invalidpworusername'] = "You have entered an invalid username/password combination.

    If you have forgotten your password please retrieve a new one."; -$l['error_invalidpworusername1'] = "You have entered an invalid email/password combination.

    If you have forgotten your password please retrieve a new one."; -$l['error_invalidpworusername2'] = "You have entered an invalid username/password or email/password combination.

    If you have forgotten your password please retrieve a new one."; -$l['error_incompletefields'] = "It appears you have left one or more required fields blank. Please go back and enter the required fields."; -$l['error_alreadyuploaded'] = "This post already contains an attachment with the same name. Please rename the file and upload it again. Alternatively you may click \"Update Attachment\"."; -$l['error_alreadyuploaded_perm'] = "This post already contains an attachment with the same name. Please either remove the existing file or rename the file and upload it again."; -$l['error_nomessage'] = "Sorry, we cannot proceed because you did not enter a valid message. Please go back and do so."; -$l['error_invalidemail'] = "You did not enter a valid email address."; -$l['error_nomember'] = "The member you specified is either invalid or doesn't exist."; -$l['error_maxposts'] = "I'm sorry, but your daily post limit has been exceeded. Please wait till tomorrow to post further or contact your administrator.

    The maximum amount of posts you may make in a day is {1}"; -$l['error_nohostname'] = "No hostname could be found for the IP you entered."; -$l['error_invalidthread'] = "The specified thread does not exist."; -$l['error_invalidpost'] = "The specified post does not exist."; -$l['error_invalidannouncement'] = "The specified announcement does not exist."; -$l['error_invalidattachment'] = "The specified attachment does not exist."; -$l['error_invalidforum'] = "Invalid forum"; -$l['error_closedinvalidforum'] = "You may not post in this forum because either the forum is closed, it is a redirect to another webpage, or it is a category."; -$l['error_attachtype'] = "The type of file that you attached is not allowed. Please remove the attachment or choose a different type."; -$l['error_attachsize'] = "The file you attached is too large. The maximum size for that type of file is {1} kilobytes."; -$l['error_uploadempty'] = "The file specified is empty."; -$l['error_uploadsize'] = "The size of the uploaded file is too large."; -$l['error_uploadfailed'] = "The file upload failed. Please choose a valid file and try again. "; -$l['error_uploadfailed_detail'] = "Error details: "; -$l['error_uploadfailed_php1'] = "PHP returned: Uploaded file exceeded upload_max_filesize directive in php.ini. Please contact your forum administrator with this error."; -$l['error_uploadfailed_php2'] = "The uploaded file exceeded the maximum file size specified."; -$l['error_uploadfailed_php3'] = "The uploaded file was only partially uploaded."; -$l['error_uploadfailed_php4'] = "No file was uploaded."; -$l['error_uploadfailed_php6'] = "PHP returned: Missing a temporary folder. Please contact your forum administrator with this error."; -$l['error_uploadfailed_php7'] = "PHP returned: Failed to write the file to disk. Please contact your forum administrator with this error."; -$l['error_uploadfailed_phpx'] = "PHP returned error code: {1}. Please contact your forum administrator with this error."; -$l['error_uploadfailed_nothingtomove'] = "An invalid file was specified, so the uploaded file could not be moved to its destination."; -$l['error_uploadfailed_movefailed'] = "There was a problem moving the uploaded file to its destination."; -$l['error_uploadfailed_lost'] = "The attachment could not be found on the server."; -$l['error_emailmismatch'] = "The email addresses you entered do not match. Please go back and try again"; -$l['error_nopassword'] = "You did not enter a valid password."; -$l['error_usernametaken'] = "The username you have chosen is already registered. If you have previously registered on these forums, please login."; -$l['error_nousername'] = "You did not enter a username."; -$l['error_invalidusername'] = "The username you have entered appears to be invalid."; -$l['error_invalidpassword'] = "The password you entered is incorrect. If you have forgotten your password, click here. Otherwise, go back and try again."; -$l['error_postflooding'] = "We are sorry but we cannot process your post. The administrator has specified you are only allowed to post once every {1} seconds."; -$l['error_nopermission_guest_1'] = "You are either not logged in or do not have permission to view this page. This could be because one of the following reasons:"; -$l['error_nopermission_guest_2'] = "You are not logged in or registered. Please use the form at the bottom of this page to login."; -$l['error_nopermission_guest_3'] = "You do not have permission to access this page. Are you trying to access administrative pages or a resource that you shouldn't be? Check in the forum rules that you are allowed to perform this action."; -$l['error_nopermission_guest_4'] = "Your account may have been disabled by an administrator, or it may be awaiting account activation."; -$l['error_nopermission_guest_5'] = "You have accessed this page directly rather than using appropriate forms or links."; -$l['login'] = "Login"; -$l['need_reg'] = "Need to register?"; -$l['forgot_password'] = "Forgotten your password?"; -$l['error_nopermission_user_1'] = "You do not have permission to access this page. This could be because of one of the following reasons:"; -$l['error_nopermission_user_ajax'] = "You do not have permission to access this page."; -$l['error_nopermission_user_2'] = "Your account has either been suspended or you have been banned from accessing this resource."; -$l['error_nopermission_user_3'] = "You do not have permission to access this page. Are you trying to access administrative pages or a resource that you shouldn't be? Check in the forum rules that you are allowed to perform this action."; -$l['error_nopermission_user_4'] = "Your account may still be awaiting activation or moderation."; -$l['error_nopermission_user_5'] = "You have accessed this page directly rather than using appropriate forms or link."; -$l['error_nopermission_user_resendactivation'] = "Resend Activation Code"; -$l['error_nopermission_user_username'] = "You are currently logged in with the username: '{1}'"; -$l['logged_in_user'] = "Logged In User"; -$l['error_too_many_images'] = "Too Many Images."; -$l['error_too_many_images2'] = "We are sorry, but we cannot process your post because it contains too many images. Please remove some images from your post to continue."; -$l['error_too_many_images3'] = "Note: The maximum amount of images per post is"; -$l['error_attach_file'] = "Error Attaching File"; -$l['please_correct_errors'] = "Please correct the following errors before continuing:"; -$l['error_reachedattachquota'] = "Sorry, but you cannot attach this file because you have reached your attachment quota of {1}"; -$l['error_maxattachpost'] = "Sorry but you cannot attach this file because you have reached the maximum number of attachments allowed per post of {1}"; -$l['error_invaliduser'] = "The specified user is invalid or does not exist."; -$l['error_invalidaction'] = "Invalid action"; -$l['error_messagelength'] = "Sorry, your message is too long and cannot be posted. Please try shortening your message and try again."; -$l['error_message_too_short'] = "Sorry, your message is too short and cannot be posted."; -$l['failed_login_wait'] = "You have failed to login within the required number of attempts. You must now wait {1}h {2}m {3}s before you can login again."; -$l['failed_login_again'] = "
    You have {1} more login attempts."; -$l['error_max_emails_day'] = "You cannot use the 'Send Thread to a Friend' or the 'Email User' features because you've already used up your allocated quota of sending {1} messages in the past 24 hours."; -$l['attachments_disabled'] = "You cannot use the attachment system as it has been disabled by the Administrator."; - -$l['emailsubject_lostpw'] = "Password Reset at {1}"; -$l['emailsubject_passwordreset'] = "New password at {1}"; -$l['emailsubject_subscription'] = "New Reply to {1}"; -$l['emailsubject_randompassword'] = "Your Password for {1}"; -$l['emailsubject_activateaccount'] = "Account Activation at {1}"; -$l['emailsubject_forumsubscription'] = "New Thread in {1}"; -$l['emailsubject_reportpost'] = "Reported post at {1}"; -$l['emailsubject_reportprofile'] = "Reported user at {1}"; -$l['emailsubject_reportreputation'] = "Reported reputation at {1}"; -$l['emailsubject_reachedpmquota'] = "Private Messaging Quota Reached at {1}"; -$l['emailsubject_changeemail'] = "Change of Email at {1}"; -$l['emailsubject_newpm'] = "New Private Message at {1} - {2}"; -$l['emailsubject_newjoinrequest'] = "New Join Request at {1}"; -$l['emailsubject_sendtofriend'] = "Interesting discussion at {1}"; -$l['emailsubject_changepassword'] = "Change of Password at {1}"; -$l['emailbit_viewthread'] = "... (visit the thread to read more..)"; - -$l['email_lostpw'] = "{1}, - -To complete the phase of resetting your account password at {2}, you will need to go to the URL below in your web browser. - -{3}/member.php?action=resetpassword&uid={4}&code={5} - -If the above link does not work correctly, go to - -{3}/member.php?action=resetpassword - -You will need to enter the following: -Username: {1} -Activation Code: {5} - -Thank you, -{2} Staff"; -$l['email_lostpw1'] = "{1}, - -To complete the phase of resetting your account password at {2}, you will need to go to the URL below in your web browser. - -{3}/member.php?action=resetpassword&uid={4}&code={5} - -If the above link does not work correctly, go to - -{3}/member.php?action=resetpassword - -You will need to enter the following: -Your email address -Activation Code: {5} - -Thank you, -{2} Staff"; -$l['email_lostpw2'] = "{1}, - -To complete the phase of resetting your account password at {2}, you will need to go to the URL below in your web browser. - -{3}/member.php?action=resetpassword&uid={4}&code={5} - -If the above link does not work correctly, go to - -{3}/member.php?action=resetpassword - -You will need to enter the following: -Username: {1} (Or your email address) -Activation Code: {5} - -Thank you, -{2} Staff"; - -$l['email_reportpost'] = "{1} from {2} has reported the following post: - -{3} -{4}/{5} - -The reason this user gave for reporting this post: -{6} - -This message has been sent to all moderators of this forum, or all administrators and super moderators if there are no moderators. - -Please check this post out as soon as possible."; - -$l['email_reportprofile'] = "{1} from {2} has reported the following user: - -{3} -{4}/{5} - -The reason this user gave for reporting this user: -{6} - -This message has been sent to all moderators of this forum, or all administrators and super moderators if there are no moderators. - -Please check this user out as soon as possible."; - -$l['email_reportreputation'] = "{1} from {2} has reported the following reputation: - -{3} -{4}/{5} - -The reason this user gave for reporting this reputation: -{6} - -This message has been sent to all moderators of this forum, or all administrators and super moderators if there are no moderators. - -Please check this reputation out as soon as possible."; - -$l['email_report_comment_extra'] = "{1}: {2}"; - -$l['email_passwordreset'] = "{1}, - -Your password at {2} has been reset. - -Your new password is: {3} - -You will need this password to login to the forums, once you login you should change it by going to your User Control Panel. - -Thank you, -{2} Staff"; - -$l['email_randompassword'] = "{1}, - -Thank you for registering on {2}. Below is your username and the randomly generated password. To login to {2}, you will need these details. - -Username: {3} -Password: {4} - -It is recommended you change your password immediately after you login. You can do this by going to your User CP then clicking Change Password on the left menu. - -Thank you, -{2} Staff"; - -$l['email_randompassword1'] = "{1}, - -Thank you for registering on {2}. Below is your username and the randomly generated password. To login to {2}, you will need these details. - -Your email address -Password: {4} - -It is recommended you change your password immediately after you login. You can do this by going to your User CP then clicking Change Password on the left menu. - -Thank you, -{2} Staff"; - -$l['email_randompassword2'] = "{1}, - -Thank you for registering on {2}. Below is your username and the randomly generated password. To login to {2}, you will need these details. - -Username: {3} (Or your email address) -Password: {4} - -It is recommended you change your password immediately after you login. You can do this by going to your User CP then clicking Change Password on the left menu. - -Thank you, -{2} Staff"; - -$l['email_sendtofriend'] = "Hello, - -{1} from {2} thought you may be interested in reading the following web page: - -{3} - -{1} included the following message: ------------------------------------------- -{4} ------------------------------------------- - -Thank you, -{2} Staff -"; - -$l['email_forumsubscription'] = "{1}, - -{2} has just started a new thread in {3}. This is a forum you have subscribed to at {4}. - -The thread is titled {5} - -Here is an excerpt of the message: --- -{6} --- - -To view the thread, you can go to the following URL: -{7}/{8} - -There may also be other new threads and replies but you will not receive anymore notifications until you visit the board again. - -Thank you, -{4} Staff - ------------------------------------------- -Unsubscription Information: - -If you would not like to receive any more notifications of new threads in this forum, visit the following URL in your browser: -{7}/usercp2.php?action=removesubscription&type=forum&fid={9}&my_post_key={10} - -------------------------------------------"; - -$l['email_activateaccount'] = "{1}, - -To complete the registration process on {2}, you will need to go to the URL below in your web browser. - -{3}/member.php?action=activate&uid={4}&code={5} - -If the above link does not work correctly, go to - -{3}/member.php?action=activate - -You will need to enter the following: -Username: {1} -Activation Code: {5} - -Thank you, -{2} Staff"; - -$l['email_activateaccount1'] = "{1}, - -To complete the registration process on {2}, you will need to go to the URL below in your web browser. - -{3}/member.php?action=activate&uid={4}&code={5} - -If the above link does not work correctly, go to - -{3}/member.php?action=activate - -You will need to enter the following: -Your email address -Activation Code: {5} - -Thank you, -{2} Staff"; - -$l['email_activateaccount2'] = "{1}, - -To complete the registration process on {2}, you will need to go to the URL below in your web browser. - -{3}/member.php?action=activate&uid={4}&code={5} - -If the above link does not work correctly, go to - -{3}/member.php?action=activate - -You will need to enter the following: -Username: {1} (Or your email address) -Activation Code: {5} - -Thank you, -{2} Staff"; - -$l['email_subscription'] = "{1}, - -{2} has just replied to a thread which you have subscribed to at {3}. This thread is titled {4}. - -Here is an excerpt of the message: ------------------------------------------- -{5} ------------------------------------------- - -To view the thread, you can go to the following URL: -{6}/{7} - -There may also be other replies to this thread but you will not receive anymore notifications until you visit the board again. - -Thank you, -{3} Staff - ------------------------------------------- -Unsubscription Information: - -If you would not like to receive any more notifications of replies to this thread, visit the following URL in your browser: -{6}/usercp2.php?action=removesubscription&tid={8}&my_post_key={9} - -------------------------------------------"; -$l['email_reachedpmquota'] = "{1}, - -This is an automated email from {2} to let you know that your Private Messaging inbox has reached its capacity. - -One or more users may have tried to send you private messages and were unsuccessful in doing so because of this. - -Please delete some of your private messages you currently have stored, remembering to also delete them from the 'Trash Can'. - -Thank you, -{2} Staff -{3}"; -$l['email_changeemail'] = "{1}, - -We have received a request on {2} to change your email address (see details below). - -Old Email Address: {3} -New Email Address: {4} - -If these changes are correct, please complete the validation process on {2} by going to the following URL in your web browser. - -{5}/member.php?action=activate&uid={8}&code={6} - -If the above link does not work correctly, go to - -{5}/member.php?action=activate - -You will need to enter the following: -Username: {7} -Activation Code: {6} - -If you choose not to validate your new email address your profile will not be updated and will still contain your existing email address. - -Thank you, -{2} Staff -{5}"; - -$l['email_changeemail_noactivation'] = "{1}, - -We have received a request on {2} to change your email address (see details below). - -Old Email Address: {3} -New Email Address: {4} - -This change has been automatically processed. If you did not request this change, please get in touch with an Administrator. - -Thank you, -{2} Staff -{5}"; - -$l['email_changepassword'] = "{1}, - -You are receiving this email because you, or someone with access to your password, recently changed your account password. - -Username: {1} -Email address: {2} - -If you did not request this change, please get in touch with an Administrator. - -Thank you, -{3} Staff -{4}"; - -$l['email_newpm'] = "{1}, - -You have received a new private message on {3} from {2}: - ------------------------------------------- -{5} ------------------------------------------- - -To view, reply or forward this message, you can follow this link: - -{4}/private.php - -Please note that you will not receive any further notifications of new messages until you visit {3}. - -You can disable new message notifications on your account options page: - -{4}/usercp.php?action=options - -Thank you, -{3} Staff -{4}"; - -$l['email_emailuser'] = "{1}, - -{2} from {3} has sent you the following message: ------------------------------------------- -{5} ------------------------------------------- - -Thank you, -{3} Staff -{4} - ------------------------------------------- -Don't want to receive email messages from other members? - -If you don't want other members to be able to email you please visit your User Control Panel and enable the option 'Hide your email from other members': -{4}/usercp.php?action=options - -------------------------------------------"; - -$l['email_groupleader_joinrequest'] = "{1}, - -{2} has requested to join {3} on {4} (see below). - -Reason: {5} - -To accept or decline this request, go to - -{6}/managegroup.php?gid={7} - -Thank you, -{4} Staff"; - -$l['email_contact_subject'] = "Contact: {1}"; -$l['email_contact'] = "E-mail: {1} -Forum profile: {2} -IP Address: {3} -Message: -{4}"; - -$l['pmsubject_subscription'] = "New Reply to {1}"; -$l['pm_subscription'] = "{1}, - -{2} has just replied to a thread which you have subscribed to. This thread is titled {3}. - -Here is an excerpt of the message: ------------------------------------------- -{4} ------------------------------------------- - -To view the thread, you can go to the following URL: -[url]{5}/{6}[/url] - -There may also be other replies to this thread but you will not receive anymore notifications until you visit the thread again. - ------------------------------------------- -Unsubscription Information: - -If you would not like to receive any more notifications of replies to this thread, visit the following URL in your browser: -[url]{5}/usercp2.php?action=removesubscription&tid={7}&my_post_key={8}[/url] - -------------------------------------------"; - -$l['email_broken_task_subject'] = "MyBB task error on {1}"; -$l['email_broken_task'] = "Your copy of MyBB running on {1} ({2}) has experienced an error with the task system. - -The task file for {3} is missing. - -This task has been disabled until issue is resolved."; diff --git a/html/forums/inc/languages/english/misc.lang.php b/html/forums/inc/languages/english/misc.lang.php deleted file mode 100644 index 9b9980e..0000000 --- a/html/forums/inc/languages/english/misc.lang.php +++ /dev/null @@ -1,98 +0,0 @@ -You have no online buddies"; -$l['offline'] = "Offline"; -$l['offline_none'] = "You have no offline buddies"; -$l['delete_buddy'] = "X"; -$l['pm_buddy'] = "Send Private Message"; -$l['last_active'] = "Last Active: {1}"; -$l['close'] = "Close"; -$l['no_buddies'] = "Your buddy list is currently empty. Use your User CP or visit a user profile to add users to your buddy list."; - -$l['help_docs'] = "Help Documents"; - -$l['search_help_documents'] = "Search Help Documents"; -$l['search_by_name'] = "Search by Name"; -$l['search_by_document'] = "Search by Document"; -$l['enter_keywords'] = "Enter Keywords"; -$l['search'] = "Search"; -$l['redirect_searchresults'] = "Thank you, your search has been submitted and you will now be taken to the results list."; -$l['search_results'] = "Search Results"; -$l['help_doc_results'] = "Help Document Results"; -$l['document'] = "Document"; -$l['error_nosearchresults'] = "Sorry, but no results were returned using the query information you provided. Please redefine your search terms and try again."; -$l['no_help_results'] = "Sorry, but no results were returned using the query information you provided."; -$l['error_helpsearchdisabled'] = "The ability to search the help documents has been disabled by the Administrator."; - -$l['smilies_listing'] = "Smilies Listing"; -$l['name'] = "Name"; -$l['abbreviation'] = "Abbreviation"; -$l['click_to_add'] = "Click a smilie to insert it into your message"; -$l['close_window'] = "close window"; -$l['no_smilies'] = "There are currently no smilies available."; - -$l['who_posted'] = "Who Posted?"; -$l['total_posts'] = "Total Posts:"; -$l['user'] = "User"; -$l['num_posts'] = "# Posts"; - -$l['forum_rules'] = "{1} - Rules"; - -$l['error_invalid_limit'] = "The feed item limit you entered is invalid. Please specify a valid limit."; - -$l['syndication'] = "Latest Thread Syndication"; -$l['syndication_generated_url'] = "Your Generated Syndication URL:"; -$l['syndication_note'] = "Below you can generate links to specific RSS syndication feeds. Links can be generated for all forums, per forum, or for a specific number of forums. You will then be presented with a link which you can copy in to an RSS reader. What is RSS?"; -$l['syndication_forum'] = "Forum to Syndicate:"; -$l['syndication_forum_desc'] = "Please select a forum from the right. Use the CTRL key to select multiple forums."; -$l['syndication_version'] = "Feed Version:"; -$l['syndication_version_desc'] = "Please select the version of the feeds you wish to generate."; -$l['syndication_version_atom1'] = "Atom 1.0"; -$l['syndication_version_rss2'] = "RSS 2.00 (Default)"; -$l['syndication_generate'] = "Generate Syndication URL"; -$l['syndication_limit'] = "Limit:"; -$l['syndication_limit_desc'] = "The amount of threads to download at one time. 50 at once is maximum limit."; -$l['syndication_threads_time'] = "threads at a time"; -$l['syndicate_all_forums'] = "Syndicate All Forums"; - -$l['redirect_markforumread'] = "The selected forum has been marked as read."; -$l['redirect_markforumsread'] = "All the forums have been marked as read."; -$l['redirect_forumpasscleared'] = "The stored password for this forum has been cleared."; -$l['redirect_cookiescleared'] = "All cookies have been cleared."; - -$l['error_invalidforum'] = "Invalid forum"; -$l['error_invalidhelpdoc'] = "The specified help document does not appear to exist."; -$l['error_invalidimtype'] = "This user does not have this type of instant messenger account specified in their profile."; -$l['error_invalidsearch'] = "An invalid search was specified. Please go back and try again."; -$l['error_no_search_support'] = "This database engine does not support searching."; -$l['error_searchflooding'] = "Sorry, but you can only perform one search every {1} seconds. Please wait another {2} seconds before attempting to search again."; -$l['error_searchflooding_1'] = "Sorry, but you can only perform one search every {1} seconds. Please wait another 1 second before attempting to search again."; - -$l['dst_settings_updated'] = "Your daylight saving time settings have automatically been adjusted.

    You will now be taken back to the forum index."; diff --git a/html/forums/inc/languages/english/modcp.lang.php b/html/forums/inc/languages/english/modcp.lang.php deleted file mode 100644 index 99e5675..0000000 --- a/html/forums/inc/languages/english/modcp.lang.php +++ /dev/null @@ -1,329 +0,0 @@ -Post by {2}"; -$l['report_info_post_thread'] = "
    In {2}"; -$l['report_info_profile'] = "Profile of {1}"; -$l['report_info_reputation'] = "Reputation from {2}"; -$l['report_info_rep_profile'] = "
    On {1}'s profile"; -$l['report_info_lastreporter'] = "{1}
    by {2}"; - -$l['moderator_notes'] = "Moderator Notes"; -$l['notes_public_all'] = "These notes are public to all moderators."; -$l['save_notes'] = "Save Notes"; -$l['bans_ending_soon'] = "Bans Ending Soon"; -$l['latest_5_modactions'] = "5 Latest Moderator Actions"; -$l['awaiting_moderation'] = "Awaiting Moderation"; -$l['type'] = "Type"; -$l['number_awaiting'] = "Number Awaiting"; -$l['latest'] = "Latest"; -$l['ipsearch'] = "IP Search"; -$l['ipsearch_results'] = "IP Search Results for '{1}'"; -$l['ipaddress_search'] = "IP Address Search"; -$l['ipaddress_misc_info'] = "Misc. Information for '{1}'"; -$l['ipaddress_host_name'] = "Host Name:"; -$l['ipaddress_location'] = "GeoIP Location:"; -$l['search_users'] = "Search Users"; -$l['search_posts'] = "Search Posts"; -$l['ip_address'] = "IP Address:"; -$l['result'] = "Result"; -$l['ipresult_regip'] = "Registration IP:"; -$l['ipresult_lastip'] = "Last Known IP:"; -$l['ipresult_post'] = "Post:"; -$l['subject'] = "Subject"; -$l['username'] = "Username"; -$l['ipaddress'] = "IP Address"; -$l['options'] = "Options:"; -$l['find'] = "Find"; -$l['modlogs'] = "Moderator Logs"; -$l['action'] = "Action"; -$l['all_moderators'] = "All Moderators"; -$l['ip'] = "IP Address"; -$l['info_on_ip'] = "Information on this IP Address"; -$l['search_ip_sfs'] = "Search this IP on Stop Forum Spam"; -$l['information'] = "Information"; -$l['filter_modlogs'] = "Filter Moderator Logs"; -$l['forum'] = "Forum"; -$l['post'] = "Post"; -$l['from_moderator'] = "From Moderator:"; -$l['na_deleted'] = "N/A - Been Deleted"; -$l['sort_by'] = "Sort by:"; -$l['forum_name'] = "Forum Name"; -$l['thread_subject'] = "Thread Subject"; -$l['in'] = "in"; -$l['order'] = "order"; -$l['asc'] = "Ascending"; -$l['desc'] = "Descending"; -$l['per_page'] = "Results Per Page:"; -$l['filter_logs'] = "Filter Logs"; -$l['error_no_log_results'] = "Sorry, there were no results found with the criteria you selected."; -$l['find_users'] = "Search for Users"; -$l['users'] = "Users"; -$l['regdate'] = "Registration Date"; -$l['lastvisit'] = "Last Visit"; -$l['postnum'] = "Post Count"; -$l['username_contains'] = "Username contains:"; -$l['no_user_results'] = "No users were found with the specified search criteria."; -$l['edit_profile'] = "Edit Profile of {1}"; -$l['birthday'] = "Date of Birth:"; -$l['title'] = "User Title:"; -$l['profile_required'] = "Required Fields"; -$l['remove_avatar'] = "Remove user's avatar?"; -$l['profile_optional'] = "Optional Fields"; -$l['website_url'] = "Website URL:"; -$l['birthdate'] = "Birthdate:"; -$l['icq_number'] = "ICQ Number:"; -$l['aim_screenname'] = "AIM Screen Name:"; -$l['yahoo_id'] = "Yahoo ID:"; -$l['skype_id'] = "Skype ID:"; -$l['google_id'] = "Google Hangouts ID:"; -$l['away_notice'] = "This option will allow you to select whether you are away or not."; -$l['additional_information'] = "Additional Information"; -$l['update_profile'] = "Update Profile"; -$l['custom_usertitle'] = "Custom User Title"; -$l['new_custom_usertitle'] = "New Custom User Title: (leave blank to use existing)"; -$l['custom_usertitle_note'] = "Here you can assign a custom user title which will overwrite the one based on users display group."; -$l['default_usertitle'] = "Default User Title:"; -$l['current_custom_usertitle'] = "Current Custom User Title:"; -$l['revert_usertitle'] = "Revert to group default"; -$l['additional_contact_details'] = "Additional Contact Details"; -$l['current_username'] = "Username:"; -$l['away_information'] = "Away Information"; -$l['away_status'] = "Away Status:"; -$l['away_status_desc'] = "Allows you to leave an away message if you are going away for a while."; -$l['im_away'] = "I'm Away"; -$l['im_here'] = "I'm Here"; -$l['away_reason'] = "Away Reason:"; -$l['away_reason_desc'] = "Allows you to enter a small description of why you are away (max 200 characters)."; -$l['return_date'] = "Return Date:"; -$l['return_date_desc'] = "If you know when you will be back, you can enter your return date here."; -$l['error_modcp_return_date_past'] = "You cannot return in the past!"; -$l['usergroup'] = "Primary Group"; -$l['redirect_user_updated'] = "The users profile has successfully been updated."; -$l['posts_awaiting_moderation'] = "Posts Awaiting Moderation"; -$l['threads_awaiting_moderation'] = "Threads Awaiting Moderation"; -$l['attachments_awaiting_moderation'] = "Attachments Awaiting Moderation"; -$l['mod_queue'] = "Moderation Queue"; -$l['approve'] = "Approve"; -$l['ignore'] = "Ignore"; -$l['perform_actions'] = "Perform Actions"; -$l['author'] = "Author"; -$l['threads'] = "Threads"; -$l['posts'] = "Posts"; -$l['filename'] = "Filename"; -$l['thread_post'] = "Thread / Post"; -$l['permanent'] = "Permanent"; -$l['ban_error'] = "Error"; -$l['ban_banned'] = "Banned Users"; -$l['ban_user'] = "Ban a User"; -$l['reason'] = "Reason"; -$l['ban_username'] = "Username:"; -$l['ban_reason'] = "Reason:"; -$l['ban_length'] = "Length"; -$l['ban_remaining'] = "remaining"; -$l['ban_ending_imminently'] = "Ban Ending Imminently"; -$l['ban_bannedby'] = "Banned By"; -$l['ban_movegroup'] = "Move to Banned Group:"; -$l['ban_liftafter'] = "Lift Ban After:"; -$l['no_banned'] = "There are currently no banned users."; -$l['no_banned_group'] = "There are currently no banned groups."; -$l['redirect_banuser'] = "The user has successfully been banned."; -$l['redirect_banuser_updated'] = "The user's ban has successfully been updated."; -$l['invalid_username'] = "The username you entered was invalid. Please ensure you enter a valid username."; -$l['error_useralreadybanned'] = "This user is already banned. You cannot ban a user more than once."; -$l['error_cannotbanuser'] = "You cannot ban this user because they have higher permissions than you. Please contact your administrator if you wish to ban this user."; -$l['error_cannotbanself'] = "You cannot ban yourself. Please enter another username."; -$l['error_no_perm_to_ban'] = "You do not have permission to ban this user."; -$l['error_nobanreason'] = "You did not enter a reason for this ban. Please enter a valid reason below."; -$l['error_nobangroup'] = "You did not select a valid group to move this user to."; -$l['edit_ban'] = "Edit Ban"; -$l['lift_ban'] = "Lift Ban"; -$l['ban'] = "Ban"; -$l['error_invalidban'] = "You have selected an invalid ban."; -$l['redirect_banlifted'] = "The ban has successfully been lifted."; -$l['mark_all_ignored'] = "Mark all as ignored"; -$l['mark_all_deletion'] = "Mark all for deletion"; -$l['mark_all_approved'] = "Mark all as approved"; -$l['meta_forum'] = "Forum:"; -$l['meta_thread'] = "Thread:"; -$l['mod_queue_empty'] = "All of the moderation queues are currently empty."; -$l['mod_queue_threads_empty'] = "The thread moderation queue is currently empty."; -$l['mod_queue_posts_empty'] = "The posts moderation queue is currently empty."; -$l['mod_queue_attachments_empty'] = "The attachment moderation queue is currently empty."; -$l['redirect_threadsmoderated'] = "The selected threads have been moderated."; -$l['redirect_postsmoderated'] = "The selected posts have been moderated."; -$l['redirect_attachmentsmoderated'] = "The selected attachments have been moderated."; -$l['multi_approve_posts'] = "Selected Posts Approved"; -$l['multi_delete_posts'] = "Selected Posts Deleted Permanently"; -$l['multi_soft_delete_posts'] = "Selected Posts Soft Deleted"; -$l['multi_approve_threads'] = "Selected Threads Approved"; -$l['multi_delete_threads'] = "Selected Threads Deleted Permanently"; -$l['multi_soft_delete_threads'] = "Selected Threads Soft Deleted"; -$l['edited_user'] = "Edited User's Profile"; -$l['edited_user_info'] = "User: {1}"; -$l['edited_user_ban'] = "Edited User Ban"; -$l['banned_user'] = "Banned User"; -$l['lifted_ban'] = "Lifted User Ban"; -$l['no_bans_ending'] = "There are no bans ending soon."; - -$l['warning_logs'] = "Warning Logs"; -$l['warned_user'] = "Warned User"; -$l['warning'] = "Warning"; -$l['date_issued'] = "Date Issued"; -$l['expires'] = "Expires"; -$l['expiry_date'] = "Expiry Date"; -$l['issued_date'] = "Issued Date"; -$l['issued_by'] = "Issued By"; -$l['details'] = "Details"; -$l['filter_warning_logs'] = "Filter Warning Logs"; -$l['filter_warned_user'] = "Warned user:"; -$l['filter_issued_by'] = "Warning issued by:"; -$l['filter_reason'] = "Reason contains:"; -$l['view'] = "View"; -$l['no_warning_logs'] = "There are no warning logs to view."; -$l['revoked'] = "Revoked "; -$l['signature'] = "Signature"; -$l['suspend_signature'] = "Suspend this user's signature"; -$l['suspend_length'] = "Suspension length:"; -$l['mod_notes'] = "Moderator Notes"; -$l['moderation'] = "Moderator Options"; -$l['moderate_posts'] = "Moderate this user's posts"; -$l['suspend_posts'] = "Suspend this user's posting privileges"; -$l['modpost_length'] = "Moderate for:"; -$l['suspost_length'] = "Suspend for:"; - -$l['moderateposts_for'] = "Moderated until {1}.
    Untick this option to remove, or extend below."; -$l['suspendposting_for'] = "Suspended until {1}.
    Untick this option to remove, or extend below."; -$l['suspendsignature_for'] = "Suspended until {1}.
    Untick this option to remove, or extend below."; -$l['suspendposting_perm'] = "Suspended permanently.
    Untick this option to remove, or change below."; -$l['moderateposts_perm'] = "Moderated permanently.
    Untick this option to remove, or change below."; -$l['suspendsignature_perm'] = "Suspended permanently.
    Untick this option to remove, or change below."; -$l['suspendsignature_error'] = "You selected to suspend this user's signature, but didn't enter a valid time period. Please enter a valid time to continue or untick the option to cancel."; -$l['moderateposting_error'] = "You selected to moderate this user's posts, but didn't enter a valid time period. Please enter a valid time to continue or untick the option to cancel."; -$l['suspendposting_error'] = "You selected to suspend this user's posts, but didn't enter a valid time period. Please enter a valid time to continue or untick the option to cancel."; -$l['suspendmoderate_error'] = "You've selected to suspend and moderate the user's posts. Please select only one type of moderation."; - -$l['expire_hours'] = "hour(s)"; -$l['expire_days'] = "day(s)"; -$l['expire_weeks'] = "week(s)"; -$l['expire_months'] = "month(s)"; -$l['expire_permanent'] = "Permanent"; - -$l['manage_announcement'] = "Manage Announcements"; -$l['forum_announcements'] = "Forum Announcements"; -$l['announcement'] = "Announcement"; -$l['controls'] = "Controls"; -$l['expired_announcement'] = "Expired Announcement"; -$l['active_announcement'] = "Active Announcement"; -$l['active'] = "Active"; -$l['expired'] = "Expired"; -$l['edit'] = "Edit"; -$l['add_announcement'] = "Add Announcement"; -$l['edit_announcement'] = "Edit Announcement"; -$l['no_forum_announcements'] = "There are currently no forum announcements on your board."; -$l['no_global_announcements'] = "There are currently no global announcements on your board."; -$l['add_global_announcement'] = "Add Global Announcement"; -$l['global_announcements'] = "Global Announcements"; -$l['title'] = "Title"; -$l['start_date'] = "Start Date"; -$l['time'] = "Time:"; -$l['end_date'] = "End Date"; -$l['never'] = "Never"; -$l['allow_html'] = "Allow HTML"; -$l['allow_mycode'] = "Allow MyCode"; -$l['allow_smilies'] = "Allow Smilies"; -$l['reset'] = "Reset"; -$l['january'] = "January"; -$l['february'] = "February"; -$l['march'] = "March"; -$l['april'] = "April"; -$l['may'] = "May"; -$l['june'] = "June"; -$l['july'] = "July"; -$l['august'] = "August"; -$l['september'] = "September"; -$l['october'] = "October"; -$l['november'] = "November"; -$l['december'] = "December"; -$l['delete_announcement'] = "Delete Announcement"; -$l['confirm_delete_announcement'] = "Are you sure you want to delete this announcement?"; -$l['redirect_add_announcement'] = "The announcement has been created."; -$l['redirect_edit_announcement'] = "The announcement has been edited."; -$l['redirect_delete_announcement'] = "The announcement has been deleted."; -$l['error_missing_title'] = "You did not enter a title."; -$l['error_missing_message'] = "You did not enter a message."; -$l['error_missing_forum'] = "You did not select a forum."; -$l['error_invalid_start_date'] = "The starting date for the announcement is invalid."; -$l['error_invalid_end_date'] = "The ending date for the announcement is invalid."; -$l['error_end_before_start'] = "The ending date must be after the start date."; -$l['error_invalid_announcement'] = "The specified announcement is invalid."; - -$l['announcement_added'] = "Announcement Added"; -$l['announcement_edited'] = "Announcement Edited"; -$l['announcement_deleted'] = "Announcement Deleted"; - -$l['preview'] = 'Preview'; - -$l['you_cannot_view_mod_logs'] = "You do not have sufficient permission to view the Moderator Logs."; -$l['you_cannot_view_reported_posts'] = "You do not have sufficient permission to view Reported Posts."; -$l['you_cannot_manage_announcements'] = "You do not have sufficient permission to manage Announcements."; -$l['you_cannot_moderate_threads'] = "You do not have sufficient permission to moderate threads."; -$l['you_cannot_moderate_posts'] = "You do not have sufficient permission to moderate posts."; -$l['you_cannot_moderate_attachments'] = "You do not have sufficient permission to moderate attachments."; -$l['you_cannot_use_mod_queue'] = "You do not have sufficient permission to use the Mod Queue."; - -$l['post'] = 'Post'; diff --git a/html/forums/inc/languages/english/moderation.lang.php b/html/forums/inc/languages/english/moderation.lang.php deleted file mode 100644 index 34b2a9b..0000000 --- a/html/forums/inc/languages/english/moderation.lang.php +++ /dev/null @@ -1,221 +0,0 @@ -The thread on the right will be deleted and all posts will be merged in to this one."; -$l['merge_posts'] = "Merge Posts"; -$l['merge_posts_note'] ="All selected posts will be merged in to the first selected post."; -$l['move_copy_thread'] = "Move / Copy Thread"; -$l['new_forum'] = "New Forum:"; -$l['method'] = "Method"; -$l['method_move'] = "Move thread"; -$l['method_move_redirect'] = "Move thread and leave redirect in existing forum for days:"; -$l['redirect_expire_note'] = "(leave blank for 'infinite')"; -$l['method_copy'] = "Copy thread to the new forum"; -$l['split_thread_subject'] = "[split]"; -$l['split_thread'] = "Split Thread"; -$l['move_posts'] = "Move Posts"; -$l['thread_to_move_to'] = "Thread to move the posts to:"; -$l['move_post_note'] = "Copy the URL of the thread to move these posts to into the textbox on the right."; -$l['new_thread_info'] = "New Thread Information"; -$l['posts_to_split'] = "Posts to Split"; -$l['thread_notes_editor'] = "Thread Notes Editor"; -$l['below_notes'] = "Below you can edit the notes for this thread."; -$l['update_notes'] = "Update Thread Notes"; -$l['mod_logs'] = "Moderator Logs (showing last 20 actions)"; -$l['mod_username'] = "Username"; -$l['mod_date'] = "Date"; -$l['mod_actions'] = "Action"; -$l['mod_information'] = "Information"; -$l['read'] = "Read:"; -$l['thread'] = "Thread:"; -$l['post'] = "Post:"; -$l['forum'] = "Forum:"; -$l['confirm_execute_tool'] = "Execute Tool"; -$l['confirm_execute_tool_desc'] = "Are you sure you wish to execute the {1} custom moderation tool? Once a tool is executed it may not be able to revert the applied changes."; -$l['delete_threads'] = "Delete Threads Permanently"; -$l['confirm_delete_threads'] = "Are you sure you wish to delete the selected threads? Once a thread has been deleted it cannot be restored and any posts, attachments or polls within that thread are also deleted."; -$l['move_threads'] = "Move Threads"; -$l['confirm_delete_posts'] = "Are you sure you wish to delete the selected posts from the thread? Once they have been deleted they cannot be restored. If there are no posts left in the thread, the thread will also be deleted."; -$l['post_separator'] = "Post Separator"; -$l['new_line'] = "New Line"; -$l['horizontal_rule'] = "Horizontal Rule"; -$l['resolve_fail'] = "N/A (Unable to resolve)"; -$l['time'] = "Time:"; - -$l['opened'] = "Opened"; -$l['closed'] = "Closed"; -$l['stuck'] = "Stuck"; -$l['unstuck'] = "Unstuck"; -$l['mod_process'] = "Thread {1}"; -$l['redirects_removed'] = "Thread Redirects Removed"; -$l['thread_deleted'] = "Thread Deleted Permanently: {1}"; -$l['poll_deleted'] = "Poll Deleted: {1}"; -$l['thread_approved'] = "Thread Approved: {1}"; -$l['thread_unapproved'] = "Thread Unapproved: {1}"; -$l['thread_restored'] = "Thread Restored: {1}"; -$l['thread_soft_deleted'] = "Thread Soft Deleted: {1}"; -$l['deleted_selective_posts'] = "Deleted Selective Posts ({1})"; -$l['merged_selective_posts'] = "Merged Selective Posts"; -$l['split_selective_posts'] = "Split posts (PIDs: {1}) to thread (TID: {2})"; -$l['move_selective_posts'] = "Moved posts (PIDs: {1}) to thread (TID: {2})"; -$l['removed_subscriptions'] = "Removed All Subscriptions"; -$l['thread_moved'] = "Thread Moved"; -$l['thread_copied'] = "Thread Copied"; -$l['thread_merged'] = "Threads Merged"; -$l['thread_split'] = "Thread Split"; -$l['thread_notes_edited'] = "Thread Notes Edited"; -$l['multi_deleted_threads'] = "Threads Deleted Permanently"; -$l['multi_opened_threads'] = "Threads Opened"; -$l['multi_closed_threads'] = "Threads Closed"; -$l['multi_approved_threads'] = "Threads Approved"; -$l['multi_unapproved_threads'] = "Threads Unapproved"; -$l['multi_restored_threads'] = "Threads Restored"; -$l['multi_soft_deleted_threads'] = "Threads Soft Deleted"; -$l['multi_approve_posts'] = "Selected Posts Approved"; -$l['multi_unapprove_posts'] = "Selected Posts Unapproved"; -$l['multi_restore_posts'] = "Selected Posts Restored"; -$l['multi_soft_delete_posts'] = "Selected Posts Soft Deleted"; -$l['multi_stuck_threads'] = "Threads Stuck"; -$l['multi_unstuck_threads'] = "Threads Unstuck"; -$l['multi_moved_threads'] = "Threads Moved"; -$l['multi_copied_threads'] = "Threads Copied"; -$l['custom_tool'] = "Custom Moderator Tool: {1}"; - -$l['delayed_moderation'] = "Delayed Moderation"; -$l['delayed_moderation_desc'] = "Here you can delay a moderation action for a selected number of days."; -$l['threads'] = "Threads:"; -$l['threads_selected'] = "{1} thread(s) selected"; -$l['run_moderation_time'] = "Run moderation time:"; -$l['days'] = "day(s)"; -$l['moderation_action'] = "Moderation Action:"; -$l['open_close_thread'] = "Open/Close Thread"; -$l['remove_redirects'] = "Remove Redirects"; -$l['remove_subscriptions'] = "Remove Subscriptions"; -$l['approve_unapprove_thread'] = "Approve/Unapprove Thread"; -$l['softdelete_restore_thread'] = "Soft Delete/Restore Thread"; -$l['stick_unstick_thread'] = "Stick/Unstick Thread"; -$l['save_delayed_moderation'] = "Save Delayed Moderation"; -$l['custom'] = "custom"; -$l['delayed_mod_queue'] = "Delayed Moderation Queue"; -$l['days_to_perform_action'] = "Days to Perform Action"; -$l['leave_redirect'] = "Lead Redirect:"; -$l['multiple_threads'] = "Multiple Threads"; -$l['actions'] = "Actions"; -$l['cancel'] = "Cancel"; -$l['leave_redirect_for'] = "Leave redirect for:"; -$l['redirect_forever'] = "Forever"; -$l['view_notes_for'] = "Viewing Notes for {1}"; - -$l['purgespammer'] = "Purge Spammer"; -$l['purgespammer_purge'] = "Purge spammer {1}"; -$l['purgespammer_purge_desc'] = "This will delete user's whole content (posts, private messages, events, etc.) and {1} them."; -$l['purgespammer_ban'] = "ban"; -$l['purgespammer_delete'] = "delete"; -$l['purgespammer_submit'] = "Purge Spammer"; -$l['purgespammer_success'] = "The user has been purged."; -$l['purgespammer_invalid_user'] = "You have specified an invalid user."; -$l['purgespammer_modlog'] = "Purged Spammer"; - -$l['error_invalidpm'] = "Invalid PM"; -$l['error_nomergeposts'] = "You need to select one or more posts to be able to merge posts together."; -$l['error_cantsplitonepost'] = "You cannot split a thread that contains only one post."; -$l['error_badmergeurl'] = "The URL for the thread to be merged seems to be invalid or empty. Please copy the exact URL into the textbox.
    Please go back and try again."; -$l['error_badmovepostsurl'] = "The URL for the thread to move to seems to be invalid or empty. Please copy the exact URL into the textbox.
    Please go back and try again."; -$l['error_inline_nothreadsselected'] = "Sorry, but you did not select any threads to perform inline moderation on, or your previous moderation session has expired (Automatically after 1 hour of inactivity). Please select some threads and try again."; -$l['error_inline_nopostsselected'] = "Sorry, but you did not select any posts to perform inline moderation on, or your previous moderation session has expired (Automatically after 1 hour of inactivity). Please select some posts and try again."; -$l['error_movetocategory'] = "This tool is trying to move the thread into a category. Please alter the tool and select a valid forum."; -$l['error_cantsplitall'] = "You cannot split all of the posts out of this thread! If you did, what would be left in the thread?"; -$l['error_cantmoveall'] = "You cannot move all of the posts out of this thread! If you did, what would be left in the thread?"; -$l['error_nosplitposts'] = "You cannot split this thread as you did not select any posts to split from this thread."; -$l['error_movetosameforum'] = "You cannot move this thread into the forum it is currently situated in. Please select a different forum."; -$l['error_mergewithself'] = "Threads cannot be merged with themselves.
    Please go back and enter a valid URL."; -$l['error_movetoself'] = "Posts cannot be moved to the thread they are in.
    Please go back and enter a valid URL."; -$l['error_delayedmoderation_unsupported_type'] = "Sorry, but you did not select a valid type for this delayed moderation action."; -$l['error_delayedmoderation_unsupported_method'] = "Sorry, but you did not select a valid move method for this delayed moderation action."; -$l['error_delayedmoderation_invalid_date_day'] = "Sorry, but you did not select a valid delay date day for this delayed moderation action."; -$l['error_delayedmoderation_invalid_date_month'] = "Sorry, but you did not select a valid delay date month for this delayed moderation action."; -$l['error_delayedmoderation_invalid_date_year'] = "Sorry, but you did not select a valid delay date year for this delayed moderation action."; - -$l['redirect_pollnotdeleted'] = "The poll was not deleted because you did not check the \"Delete\" checkbox."; -$l['redirect_polldeleted'] = "Thank you, the poll has successfully been removed from the thread.
    You will now be taken back to the thread."; -$l['redirect_mergeposts'] = "The selected posts have now been merged together. You will now be returned to the thread."; -$l['redirect_openthread'] = "Thank you, the thread has successfully been opened.
    You will now be returned to the thread."; -$l['redirect_closethread'] = "Thank you, the thread has successfully been closed.
    You will now be returned to the thread."; -$l['redirect_stickthread'] = "Thank you, the thread has successfully been stuck.
    You will now be returned to the thread."; -$l['redirect_unstickthread'] = "Thank you, the thread has successfully been unstuck.
    You will now be returned to the thread."; -$l['redirect_threaddeleted'] = "Thank you, the thread has been deleted permanently.
    You will now be returned to the forum."; -$l['redirect_threadmoved'] = "The thread has been moved or copied to the selected forum successfully.
    You will now be returned to it."; -$l['redirect_redirectsremoved'] = "All move redirects to this thread have now been removed.
    You will now be returned to the thread."; -$l['redirect_threadapproved'] = "The thread has been approved successfully."; -$l['redirect_threadunapproved'] = "The thread has been unapproved successfully."; -$l['redirect_threadrestored'] = "The thread has been restored successfully."; -$l['redirect_threadsoftdeleted'] = "The thread has been soft deleted successfully."; -$l['redirect_threadsplit'] = "The thread has been split successfully.
    You will now be taken to the new thread."; -$l['redirect_moveposts'] = "The posts have been moved successfully.
    You will now be taken to the new thread the posts are in."; -$l['redirect_threadnotesupdated'] = "Thank you, the notes for this thread have successfully been updated.
    You will now be returned to the thread."; -$l['redirect_threadsmerged'] = "Thank you, the two threads have successfully been merged together.
    You will now be taken to the new thread."; -$l['redirect_inline_threadsdeleted'] = "The selected threads have been deleted permanently.
    You will now be returned to your previous location."; -$l['redirect_inline_threadsopened'] = "The selected threads have been opened.
    You will now be returned to your previous location."; -$l['redirect_inline_threadsclosed'] = "The selected threads have been closed.
    You will now be returned to your previous location."; -$l['redirect_inline_threadsstuck'] = "The selected threads have been stuck.
    You will now be returned to your previous location."; -$l['redirect_inline_threadsunstuck'] = "The selected threads have been unstuck.
    You will now be returned to your previous location."; -$l['redirect_inline_threadsmoved'] = "The selected threads have been moved.
    You will now be taken to the new forum the threads are in."; -$l['redirect_inline_threadsapproved'] = "The selected threads have been approved.
    You will now be returned to your previous location."; -$l['redirect_inline_threadsunapproved'] = "The selected threads have been unapproved.
    You will now be returned to your previous location."; -$l['redirect_inline_threadsrestored'] = "The selected threads have been restored.
    You will now be returned to your previous location."; -$l['redirect_inline_threadssoftdeleted'] = "The selected threads have been soft deleted.
    You will now be returned to your previous location."; -$l['redirect_inline_postsmerged'] = "The selected posts have been merged together.
    You will now be returned to your previous location."; -$l['redirect_inline_postsapproved'] = "The selected posts have been approved.
    You will now be returned to your previous location."; -$l['redirect_inline_postsunapproved'] = "The selected posts have been unapproved.
    You will now be returned to your previous location."; -$l['redirect_inline_postsrestored'] = "The selected posts have been restored.
    You will now be returned to your previous location."; -$l['redirect_inline_postssoftdeleted'] = "The selected posts have been soft deleted.
    You will now be returned to your previous location."; -$l['redirect_postsdeleted'] = "The selected posts have been deleted permanently.
    You will now be returned to your previous location."; -$l['redirect_removed_subscriptions'] = "All subscriptions for this thread have been removed successfully.
    You will now be returned to the thread."; -$l['redirect_customtool_thread'] = "\"{1}\" moderation tool executed successfully.
    You will now be returned to the thread."; -$l['redirect_customtool_forum'] = "\"{1}\" moderation tool executed successfully.
    You will now be returned to the forum."; -$l['redirect_customtool_search'] = "\"{1}\" moderation tool executed successfully.
    You will now be returned to the search."; -$l['redirect_delayed_moderation_thread'] = "The selected moderation tool has been saved and delayed till {1}.
    You will now be returned to the thread."; -$l['redirect_delayed_moderation_forum'] = "The selected moderation tool has been saved and delayed till {1}.
    You will now be returned to the forum."; -$l['redirect_delayed_moderation_search'] = "The selected moderation tool has been saved and delayed till {1}.
    You will now be returned to the search."; -$l['redirect_delayed_moderation_cancelled'] = "The selected delayed moderation action has been canceled.
    You will now be returned to the delayed moderation page."; diff --git a/html/forums/inc/languages/english/newreply.lang.php b/html/forums/inc/languages/english/newreply.lang.php deleted file mode 100644 index 1cde563..0000000 --- a/html/forums/inc/languages/english/newreply.lang.php +++ /dev/null @@ -1,53 +0,0 @@ -Signature: include your signature. (registered users only)"; -$l['options_emailnotify'] = "Email Notification: receive an email whenever there is a new reply. (registered users only)"; -$l['options_disablesmilies'] = "Disable Smilies: disable smilies from showing in this post."; -$l['post_reply'] = "Post Reply"; -$l['preview_post'] = "Preview Post"; -$l['mod_options'] ="Moderator Options:"; -$l['close_thread'] = "Close Thread: prevent further posting in this thread."; -$l['stick_thread'] = "Stick Thread: stick this thread to the top of the forum."; -$l['forum_rules'] = "{1} - Rules"; -$l['thread_review'] = "Thread Review (Newest First)"; -$l['thread_review_more'] = "This thread has more than {1} replies. Read the whole thread."; -$l['posted_by'] = "Posted by"; -$l['draft_saved'] = "The new post has successfully been saved as a draft.
    You will now be taken to your draft listing."; -$l['error_post_already_submitted'] = "You have already posted this reply to the specified thread. Please visit the thread to see your reply."; -$l['multiquote_external_one'] = "You have selected one post outside of this thread."; -$l['multiquote_external'] = "You have selected {1} posts outside of this thread."; -$l['multiquote_external_one_deselect'] = "deselect this post"; -$l['multiquote_external_deselect'] = "deselect these posts"; -$l['multiquote_external_one_quote'] = "Quote this post too"; -$l['multiquote_external_quote'] = "Quote these posts too"; - -$l['redirect_newreply'] = "Thank you, your reply has been posted."; -$l['redirect_newreply_moderation'] = "The administrator has specified that all new posts require moderation. You will now be returned to the thread."; -$l['redirect_newreply_post'] = "
    You will now be taken to your post."; -$l['redirect_newreplyerror'] = "Sorry, but your reply has been rejected for lack of content.
    You will now be returned to the thread."; -$l['redirect_threadclosed'] = "You cannot post replies in this thread because it has been closed by a moderator."; -$l['error_post_noperms'] = "You don't have permission to edit this draft."; - - -$l['error_stop_forum_spam_spammer'] = 'Sorry, your {1} matches that of a known spammer. If you feel this is a mistake, please contact an administrator'; -$l['error_stop_forum_spam_fetching'] = 'Sorry, something went wrong verifying your reply against a spammer database. Most likely the database couldn\'t be accessed. Please try again later.'; - -$l['error_suspendedposting'] = "Your posting privileges are currently suspended {1}.

    - -Suspension Date: {2}"; -$l['error_suspendedposting_temporal'] = "until {1}"; -$l['error_suspendedposting_permanent'] = "permanently"; - diff --git a/html/forums/inc/languages/english/newthread.lang.php b/html/forums/inc/languages/english/newthread.lang.php deleted file mode 100644 index d42990b..0000000 --- a/html/forums/inc/languages/english/newthread.lang.php +++ /dev/null @@ -1,54 +0,0 @@ -Signature: include your signature. (registered users only)"; -$l['options_emailnotify'] = "Email Notification: receive an email whenever there is a new reply. (registered users only)"; -$l['options_disablesmilies'] = "Disable Smilies: disable smilies from showing in this post."; -$l['post_thread'] = "Post Thread"; -$l['preview_post'] = "Preview Post"; -$l['poll'] = "Poll:"; -$l['poll_desc'] = "Optionally you may attach a poll to this thread."; -$l['poll_check'] = "I want to post a poll"; -$l['num_options'] = "Number of options:"; -$l['max_options'] = "(Maximum: {1})"; -$l['mod_options'] ="Moderator Options:"; -$l['close_thread'] = "Close Thread: prevent further posting in this thread."; -$l['stick_thread'] = "Stick Thread: stick this thread to the top of the forum."; -$l['draft_saved'] = "The new thread has successfully been saved as a draft.
    You will now be taken to your draft listing."; -$l['error_post_already_submitted'] = "You have already posted this thread in this forum. Please visit the forum to see your thread."; -$l['no_prefix'] = "No Prefix"; -$l['forum_rules'] = "{1} - Rules"; - -$l['multiquote_external_one'] = "You have selected one post from another thread."; -$l['multiquote_external'] = "You have selected {1} posts from other threads."; -$l['multiquote_external_one_deselect'] = "deselect this post"; -$l['multiquote_external_deselect'] = "deselect these posts"; -$l['multiquote_external_one_quote'] = "Quote this post too"; -$l['multiquote_external_quote'] = "Quote these posts too"; - -$l['redirect_newthread'] = "Thank you, your thread has been posted."; -$l['redirect_newthread_poll'] = "
    You will now be taken to the poll options and configuration page."; -$l['redirect_newthread_moderation'] = "
    The administrator has specified that all new threads require moderation. You will now be returned to the thread listing."; -$l['redirect_newthread_unviewable'] = "
    You do not have permission to view threads in this forum. You will now be returned to the forum."; -$l['redirect_newthread_thread'] = "
    You will now be taken to the new thread."; -$l['invalidthread'] = "The specified draft does not exist or you don't have permission to view it."; - -$l['error_stop_forum_spam_spammer'] = 'Sorry, your {1} matches that of a known spammer. If you feel this is a mistake, please contact an administrator'; -$l['error_stop_forum_spam_fetching'] = 'Sorry, something went wrong verifying your thread against a spammer database. Most likely the database couldn\'t be accessed. Please try again later.'; - -$l['error_suspendedposting'] = "Your posting privileges are currently suspended {1}.

    - -Suspension Date: {2}"; -$l['error_suspendedposting_temporal'] = "until {1}"; -$l['error_suspendedposting_permanent'] = "permanently"; - diff --git a/html/forums/inc/languages/english/online.lang.php b/html/forums/inc/languages/english/online.lang.php deleted file mode 100644 index c47e32d..0000000 --- a/html/forums/inc/languages/english/online.lang.php +++ /dev/null @@ -1,134 +0,0 @@ -{2}"; -$l['viewing_announcements2'] = "Viewing Announcement"; -$l['viewing_attachment'] = "Viewing Attachment"; -$l['viewing_attachment2'] = "Viewing Attachment in Thread {2}"; -$l['viewing_calendar'] = "Viewing Calendar"; -$l['viewing_event'] = "Viewing Event"; -$l['viewing_event2'] = "Viewing Event {2}"; -$l['adding_event'] = "Adding Event"; -$l['editing_event'] = "Editing Event"; -$l['viewing_contact_us'] = "Viewing Contact Us"; -$l['editing_post'] = "Editing Post"; -$l['viewing_forum'] = "Viewing Forum"; -$l['viewing_forum2'] = "Viewing Forum {2}"; -$l['forum_redirect_to'] = "Being Redirected To {2}"; -$l['viewing_index'] = "{1} Main Index"; -$l['activating_account'] = "Activating Account"; -$l['viewing_profile'] = "Viewing Profile"; -$l['viewing_profile2'] = "Viewing Profile of {2}"; -$l['registering'] = "Registering"; -$l['logging_in'] = "Logging In"; -$l['logging_in_plain'] = "Logging In"; -$l['logging_out'] = "Logging Out"; -$l['emailing_user'] = "Emailing a User"; -$l['rating_user'] = "Rating User"; -$l['viewing_memberlist'] = "Viewing Member List"; -$l['viewing_whoposted'] = "Viewing Who Posted"; -$l['viewing_whoposted2'] = "Viewing Who Posted in Thread {2}"; -$l['marking_read'] = "Marking Forums as Read"; -$l['viewing_helpdocs'] = "Viewing Help Documents"; -$l['viewing_buddylist'] = 'Viewing Buddy List'; -$l['viewing_smilies'] = "Viewing Smilie List"; -$l['viewing_syndication'] = "Viewing RSS Syndication Page"; -$l['replying_thread'] = "Replying to Thread"; -$l['replying_thread2'] = "Replying to Thread {2}"; -$l['posting_thread'] = "Posting New Thread"; -$l['posting_thread2'] = "Posting New Thread in {2}"; -$l['viewing_wol'] = "Viewing Who's Online"; -$l['viewing_woltoday'] = "Viewing Who Was Online Today"; -$l['creating_poll'] = "Creating New Poll"; -$l['editing_poll'] = "Editing a Poll"; -$l['viewing_pollresults'] = "Viewing Poll Results"; -$l['voting_poll'] = "Voting on a Poll"; -$l['using_modtools'] = "Using Moderator Tools"; -$l['sending_pm'] = "Sending Private Message"; -$l['reading_pm'] = "Reading Private Message"; -$l['editing_pmfolders'] = "Editing PM Folders"; -$l['using_pmsystem'] = "Using PM System"; -$l['reporting_post'] = "Reporting a Post"; -$l['searching_forum'] = "Searching {1}"; -$l['reading_thread'] = "Reading Thread"; -$l['reading_thread2'] = "Reading Thread {2} {3}"; -$l['viewing_team'] = "Viewing Forum Team"; -$l['viewing_stats'] = "Viewing Forum Statistics"; -$l['updating_profile'] = "Updating Profile"; -$l['updating_options'] = "Updating Options"; -$l['editing_signature'] = "Editing Signature"; -$l['changing_avatar'] = "Changing Avatar"; -$l['viewing_subscriptions'] = "Viewing Thread Subscriptions"; -$l['editing_pad'] = 'Editing Personal Pad'; -$l['editing_password'] = "Editing Password"; -$l['user_cp'] = "Viewing User Control Panel"; -$l['viewing_portal'] = "Viewing Portal Page"; -$l['viewing_noperms'] = "Viewing No Permissions Page"; -$l['unknown_location'] = "Unknown Location"; -$l['giving_reputation'] = "Giving Reputation to {2}"; -$l['viewing_reputation_report'] = "Viewing {2}'s Reputation"; -$l['viewing_reputation_report2'] = "Viewing Reputation"; -$l['member_resendactivation'] = "Resending Account Activation Email"; -$l['member_lostpw'] = "Retrieving Lost Password"; -$l['sending_thread'] = "Sending a thread to a friend"; -$l['guest'] = "Guest"; -$l['page'] = "Page"; -$l['users_online'] = "Who's Online"; -$l['on_username'] = "Username"; -$l['time'] = "Time"; -$l['location'] = "Location"; -$l['online_today'] = "Who Was Online Today"; -$l['refresh_page'] = "Refresh this Page"; -$l['online_online_plural'] = "users"; -$l['online_online_singular'] = "user"; -$l['online_member_plural'] = "members"; -$l['online_member_singular'] = "member"; -$l['online_anon_plural'] = "are"; -$l['online_anon_singular'] = "is"; -$l['online_guest_plural'] = "guests"; -$l['online_guest_singular'] = "guest"; -$l['online_count'] = "{1} {2} active in the past {3} minutes ({4} {5}, {6} of whom {7} invisible, and {8} {9})."; -$l['ip'] = "IP:"; -$l['resolves_to'] = "Host Name:"; -$l['if_resolvable'] = "(if resolvable)"; -$l['admin_options'] = "Admin Options"; -$l['search_regip_users'] = "Search for users who have registered with this IP"; -$l['search_postip_users'] = "Search for users who have posted with this IP"; -$l['lookup'] = "[Lookup]"; -$l['member_online_today'] = "1 Member Was Online Today"; -$l['members_were_online_today'] = "{1} Members Were Online Today"; -$l['member_online_hidden'] = " ({1} member was invisible)"; -$l['members_online_hidden'] = " ({1} members were invisible)"; -$l['rating_thread'] = "Rating thread"; -$l['viewing_imcenter'] = "Viewing IM Center"; -$l['managing_favorites'] = "Managing Favorite Threads"; -$l['managing_subscriptions'] = "Managing Subscribed Threads"; -$l['managing_group'] = "Managing a User Group"; -$l['viewing_modcp'] = "Viewing Moderator CP"; -$l['viewing_modlogs'] = "Viewing Moderator Logs"; -$l['managing_announcements'] = "Managing Announcements"; -$l['search_for_user'] = "Searching for users"; -$l['managing_warninglogs'] = "Managing Warning Logs"; -$l['searching_ips'] = "Searching IPs"; -$l['viewing_reports'] = "Viewing Reported Posts"; -$l['adding_announcement'] = "Adding an Announcement"; -$l['deleting_announcement'] = "Deleting an Announcement"; -$l['editing_announcement'] = "Editing an Announcement"; -$l['managing_modqueue'] = "Managing Moderation Queue"; -$l['editing_user_profiles'] = "Editing User Profiles"; -$l['managing_bans'] = "Managing Bans"; -$l['revoking_warning'] = "Revoking a warning"; -$l['warning_user'] = "Warning a user"; -$l['viewing_warning'] = "Viewing a warning"; -$l['managing_warnings'] = "Managing warnings"; -$l['changing_dst'] = "Changing DST Switch"; -$l['printing_thread'] = "Printing a Thread"; -$l['printing_thread2'] = "Printing Thread {2}"; -$l['managing_buddyignorelist'] = "Managing Buddy/Ignore List"; diff --git a/html/forums/inc/languages/english/polls.lang.php b/html/forums/inc/languages/english/polls.lang.php deleted file mode 100644 index 945ec39..0000000 --- a/html/forums/inc/languages/english/polls.lang.php +++ /dev/null @@ -1,60 +0,0 @@ -Note: Once this poll has been deleted there is no way of restoring it."; -$l['question'] = "Question:"; -$l['num_options'] = "Number of Options:"; -$l['max_options'] = "Maximum:"; -$l['poll_options'] = "Poll Options:"; -$l['update_options'] = "Update Options"; -$l['poll_options_note'] = "Poll options should be short and to the point."; -$l['options'] = "Options:"; -$l['option_multiple'] = "Allow multiple choice: Users have the ability to vote on more than one option."; -$l['option_multiple_maxoptions'] = "Maximum number of options per user (0 for no limit):"; -$l['option_public'] = "Public Poll: Give users the ability to see which user voted on which option(s)."; -$l['option_closed'] = "Poll is Closed: If checked the poll will be closed from voting."; -$l['poll_timeout'] = "Poll Timeout:"; -$l['timeout_note'] = "The number of day(s) which people can vote on this poll.
    (Set to 0 to if this poll should not timeout.)"; -$l['days_after'] = "days after:"; -$l['update_poll'] = "Update Poll"; -$l['option'] = "Option"; -$l['votes'] = "Votes:"; -$l['post_new_poll'] = "Post New Poll"; -$l['days'] = "days"; -$l['poll_results'] = "Poll Results"; -$l['poll_total'] = "Total:"; -$l['poll_votes'] = "vote(s)"; - -$l['redirect_pollposted'] = "Your poll has been posted.
    You will now be returned to the thread."; -$l['redirect_pollpostedmoderated'] = "Your poll has been posted, but your thread is still pending moderation.
    You will be returned to the forum."; -$l['redirect_pollupdated'] = "The poll has been updated.
    You will now be returned to the thread."; -$l['redirect_votethanks'] = "Thank you for voting.
    You will now be returned to the thread."; -$l['redirect_unvoted'] = "Your vote(s) in this thread have been removed.
    You will now be returned to the thread."; -$l['redirect_polldeleted'] = "Thank you, the poll has successfully been removed from the thread.
    You will now be taken back to the thread."; - -$l['error_polloptiontoolong'] = "One or more poll options you entered are longer than the acceptable limit. Please go back and shorten them."; -$l['error_polloptionsequence'] = "One or more poll options you entered contain a sequence which should not be used in them: ||~|~||. Please go back and remove it."; -$l['error_noquestionoptions'] = "You either did not enter a question for your poll or do not have enough options. The minimum number of options a poll can have is 2.
    Please go back and correct this error."; -$l['error_pollalready'] = "Thread already has poll!"; -$l['error_nopolloptions'] = "The specified poll option is invalid or does not exist."; -$l['error_maxpolloptions'] = "You have voted for too many options. You are only allowed to vote for {1} options.
    Please go back and try again."; -$l['error_alreadyvoted'] = "You have already voted in this poll."; -$l['error_notvoted'] = "You haven't voted in this poll."; -$l['error_invalidpoll'] = "The specified poll is invalid or does not exist."; -$l['error_pollclosed'] = "You cannot vote in a poll that has been closed."; -$l['poll_time_limit'] = "Sorry but you cannot add a poll to your thread. The Administrator has set it so that polls can only be added within {1} hours of posting."; - -$l['poll_deleted'] = "Deleted Poll"; -$l['poll_edited'] = "Edited Poll"; diff --git a/html/forums/inc/languages/english/portal.lang.php b/html/forums/inc/languages/english/portal.lang.php deleted file mode 100644 index 477ed39..0000000 --- a/html/forums/inc/languages/english/portal.lang.php +++ /dev/null @@ -1,52 +0,0 @@ -{2} unread message(s)."; -$l['pms_unread'] = "Unread Messages"; -$l['pms_total'] = "Total Messages"; -$l['search_forums'] = "Search Forums"; -$l['advanced_search'] = "Advanced Search"; -$l['forum_stats'] = "Forum Statistics"; -$l['num_members'] = "Members:"; -$l['latest_member'] = "Latest member:"; -$l['num_threads'] = "Forum threads:"; -$l['num_posts'] = "Forum posts:"; -$l['full_stats'] = "Full Statistics"; -$l['welcome'] = "Welcome, {1}"; -$l['guest'] = "Guest"; -$l['guest_welcome_registration'] = "You have to register before you can post on our site."; -$l['username'] = "Username"; -$l['password'] = "Password"; -$l['login'] = "Login!"; -$l['member_welcome_lastvisit'] = "Last visit:"; -$l['since_then'] = "Since then, there have been:"; -$l['new_announcements'] = "{1} new announcements"; -$l['new_announcement'] = "1 new announcement"; -$l['new_threads'] = "{1} new threads"; -$l['new_thread'] = "1 new thread"; -$l['new_posts'] = "{1} new posts"; -$l['new_post'] = "1 new post"; -$l['view_new'] = "View New Posts"; -$l['view_todays'] = "View Today's Posts"; -$l['online'] = "Online Users"; -$l['online_user'] = "There is currently 1 user online"; -$l['online_users'] = "There are currently {1} online users."; -$l['online_counts'] = "{1} Member(s) | {2} Guest(s)"; -$l['print_this_item'] = "Print this item"; -$l['send_to_friend'] = "Send this item to a friend"; -$l['latest_announcements'] = "Latest Announcements"; -$l['portal_disabled'] = "You cannot use the portal functionality as it has been disabled by the Administrator."; diff --git a/html/forums/inc/languages/english/printthread.lang.php b/html/forums/inc/languages/english/printthread.lang.php deleted file mode 100644 index d6a9017..0000000 --- a/html/forums/inc/languages/english/printthread.lang.php +++ /dev/null @@ -1,11 +0,0 @@ -Note: Once these messages are deleted there is no way to recover them."; -$l['num_messages'] = "Message Count"; -$l['empty_q'] = "Empty Folder?"; -$l['keep_unread'] = "Keep Unread Messages"; -$l['pm_folders'] = "Private Messaging Folders"; -$l['existing_folders'] = "Existing Folders"; -$l['edit_folder_note'] = "You can change the names of your current private messaging folders here. To delete a folder, delete the name of the folder. Some folders cannot be removed.
    Note: Deleting a folder will also delete any messages in it."; -$l['new_folders'] = "Add New Folders"; -$l['add_folders_note'] = "Here you can create additional message folders. You do not have to fill in all of the text boxes."; -$l['update_folders'] = "Update Folders"; -$l['cannot_be_removed'] = "Cannot be removed"; -$l['reached_warning'] = "Warning. You have reached your message limit."; -$l['reached_warning2'] = "To be able to receive messages you will need to delete old messages."; -$l['deny_receipt'] = "[Deny Receipt]"; -$l['viewing_pm'] = "Viewing PM:"; -$l['reply'] = "Reply"; -$l['reply_to_all'] = "Reply to All"; -$l['forward'] = "Forward"; -$l['compose_pm'] = "Compose a Private Message"; -$l['compose_to'] = "Recipients:"; -$l['compose_bcc'] = "BCC:"; -$l['compose_bcc_show'] = "BCC"; -$l['compose_bcc_show_title'] = "Show the BCC input box allowing you to blind carbon copy messages to other users."; -$l['separate_names'] = "Separate multiple user names with a comma."; -$l['max_recipients'] = "
    You may send this message to a maximum of {1} people."; -$l['compose_subject'] = "Subject:"; -$l['compose_message'] = "Message:"; -$l['compose_options'] = "Options:"; -$l['message_icon'] = "Message Icon:"; -$l['options_sig'] = "Signature: include your signature in this message."; -$l['options_disable_smilies'] = "Disable Smilies: disable smilies from showing in this message."; -$l['options_save_copy'] = "Save a Copy: save a copy of this message in your Sent Items folder."; -$l['options_read_receipt'] = "Request Read Receipt: receive a message when this message is read."; -$l['send_message'] = "Send Message"; -$l['save_draft'] = "Save as Draft"; -$l['preview'] = "Preview"; -$l['select_buddy'] = "Or Select a Buddy:"; -$l['pm_tracking'] = "Private Message Tracking"; -$l['read_messages'] = "Read Messages"; -$l['unread_messages'] = "Unread Messages"; -$l['q'] = "?"; -$l['dateread'] = "Date Read"; -$l['stop_tracking'] = "Stop Tracking"; -$l['datesent'] = "Date Sent"; -$l['cancel'] = "Cancel"; -$l['export_date_sent'] = "Date"; -$l['export_folder'] = "Folder"; -$l['export_subject'] = "Subject"; -$l['export_to'] = "To"; -$l['export_from'] ="From"; -$l['export_message'] = "Message"; -$l['not_sent'] = "N/A (not sent)"; -$l['at'] = "at"; -$l['nomessages'] = "There are no private messages in this folder."; -$l['details'] = "Details"; -$l['message'] = "Message"; -$l['buddy_list'] = "Buddy List"; -$l['multiple_recipients'] = "Multiple recipients"; -$l['bcc'] = "BCC:"; -$l['reply_title'] = "Reply to this private message"; -$l['forward_title'] = "Forward this private message to another user"; -$l['delete_title'] = "Delete this private message"; -$l['you_replied_on'] = "You replied to this message on {1}"; -$l['you_forwarded_on'] = "You forwarded this message on {1}"; -$l['you_replied'] = "You replied to this message {1}"; -$l['you_forwarded'] = "You forwarded this message {1}"; -$l['select_from_buddies'] = "Select from Buddies"; -$l['no_readmessages'] = "You currently do not have any read messages being tracked."; -$l['no_unreadmessages'] = "You currently do not have any unread messages being tracked."; -$l['stop_tracking_all'] = "Stop Tracking all messages"; - -$l['enter_keywords'] = "Enter Keywords"; -$l['advanced_search'] = "Advanced Search"; -$l['search_pms'] = "Search PMs"; -$l['advanced_private_message_search'] = "Advanced Private Message Search"; -$l['search_criteria'] = "Search Criteria"; -$l['keywords'] = "Keywords"; -$l['search_in_subject'] = "Search in Subject"; -$l['search_in_message'] = "Search in Message"; -$l['message_status'] = "Message Status"; -$l['message_status_new'] = "New"; -$l['message_status_replied_to'] = "Replied to"; -$l['message_status_forwarded'] = "Forwarded"; -$l['message_status_read'] = "Read"; -$l['folder'] = "Folder"; -$l['search_options'] = "Search Options"; -$l['sort_by'] = "Sort By"; -$l['sort_by_subject'] = "Sort By: Subject"; -$l['sort_by_sender'] = "Sort By: Sender"; -$l['sort_by_date'] = "Sort By: Date"; -$l['ascending_order'] = "Ascending Order"; -$l['descending_order'] = "Descending Order"; -$l['search_private_messages'] = "Search Private Messages"; -$l['check_all'] = "Check All"; - -$l['error_nopmsarchive'] = "Sorry, but there are no private messages matching the criteria you specified."; -$l['error_invalidpmfoldername'] = "Sorry, but a folder name you have entered contains characters which are not allowed."; -$l['error_emptypmfoldername'] = "Sorry, but a folder name you have entered does not contain any text. Please enter a name for the folder, or completely blank the name to delete the folder."; -$l['error_invalidpmrecipient'] = "The recipient you entered is either invalid or doesn't exist. Please go back and enter a correct one."; -$l['error_invalidpm'] = "Invalid PM"; -$l['error_pmrecipientreachedquota'] = "You cannot send a private message to {1} because he/she has reached their private messaging quota. They cannot be sent any message until their messages have been cleared out. An email has been sent to the user about this. Please try sending your message at a later stage."; -$l['error_recipientpmturnedoff'] = "{1} has chosen not to receive private messages or may not be allowed to do so. Therefore you may not send your private message to this user."; -$l['error_pmsturnedoff'] = "You currently have private messages disabled in your profile.
    To be able to use the private messaging system this setting must be enabled."; -$l['error_recipientignoring'] = "We are sorry but we cannot process your private message to {1}. You do not have permission to perform this action."; -$l['error_pm_already_submitted'] = "You have already submitted the same private message to the same recipient within the last 5 hours."; -$l['error_nopms'] = "You must have one or more private messages in order to access this function."; - -$l['error_minsearchlength'] = "One or more of your search terms were shorter than the minimum length. The minimum search term length is {1} characters.

    If you're trying to search for an entire phrase, enclose it within double quotes. For example \"The quick brown fox jumps over the lazy dog\"."; -$l['error_nosearchresults'] = "Sorry, but no results were returned using the query information you provided. Please redefine your search terms and try again."; -$l['error_no_search_support'] = "This database engine does not support searching."; -$l['error_nosearchterms'] = "You did not enter any search terms. At a minimum, you must enter either some search terms or a username to search by."; -$l['error_searchflooding_1'] = "Sorry, but you can only perform one search every {1} seconds. Please wait another 1 second before attempting to search again."; -$l['error_searchflooding'] = "Sorry, but you can only perform one search every {1} seconds. Please wait another {2} seconds before attempting to search again."; -$l['error_invalidsearch'] = "An invalid search was specified. Please go back and try again."; - -$l['redirect_pmsaved'] = "The private message has been saved in your Drafts folder."; -$l['redirect_pmstrackingstopped'] = "Tracking of the selected PMs has been stopped."; -$l['redirect_pmstrackingcanceled'] = "The selected unread PMs have been deleted from the recipient's inbox."; -$l['redirect_allpmstrackingstopped'] = "Tracking of all read PMs has been stopped."; -$l['redirect_pmsmoved'] = "The selected private messages have been moved."; -$l['redirect_pmsdeleted'] = "The selected private messages have been deleted."; -$l['redirect_pmsent'] = "Thank you, your private message has successfully been sent.
    You will now be returned to your private message inbox."; -$l['redirect_pmfoldersupdated'] = "Thank you, your private messaging folders have successfully been updated.
    You will now be returned to your private message Inbox."; -$l['redirect_pmfoldersemptied'] = "The selected private messaging folders have successfully been emptied.
    You will now be taken back to your Private Messaging Inbox."; -$l['redirect_searchresults'] = "Thank you, your search has been submitted and you will now be taken to the results list."; - -$l['quick_reply'] = "Quick Reply"; -$l['message_note'] = "Type your reply to this message here."; -$l['send_reply'] = "Send Reply"; -$l['quickreply_signature'] = "Signature"; -$l['quickreply_disable_smilies'] = "Disable Smilies"; -$l['quickreply_save_copy'] = "Save a Copy"; -$l['quickreply_read_receipt'] = "Request Read Receipt"; - diff --git a/html/forums/inc/languages/english/ratethread.lang.php b/html/forums/inc/languages/english/ratethread.lang.php deleted file mode 100644 index 275d261..0000000 --- a/html/forums/inc/languages/english/ratethread.lang.php +++ /dev/null @@ -1,20 +0,0 @@ -A member of the forum team will check your report soon."; - -$l['error_report_length'] = "Please provide a detailed reason for your report."; -$l['error_invalid_report'] = "This content either does not exist or is not able to be reported."; -$l['error_invalid_report_reason'] = "The selected reason is invalid."; -$l['error_comment_required'] = "An additional comment is required for the selected reason."; -$l['error_report_duplicate'] = "This content has already been reported by another member.
    You may also report this content below."; -$l['report_reason_other_description'] = "Please provide more information about why you are reporting this content."; diff --git a/html/forums/inc/languages/english/reputation.lang.php b/html/forums/inc/languages/english/reputation.lang.php deleted file mode 100644 index a85e8d7..0000000 --- a/html/forums/inc/languages/english/reputation.lang.php +++ /dev/null @@ -1,82 +0,0 @@ -"; -$l['neg_rep_disabled'] = "* - Negative reputation is currently disabled"; -$l['pos_rep_disabled'] = "* - Positive reputation is currently disabled"; -$l['neu_rep_disabled'] = "* - Neutral reputation is currently disabled"; -$l['no_comment_needed'] = "You're adding reputation because of this user's post, which is linked in their profile. A comment isn't needed, but if you want to leave one, please enter it below.
    "; -$l['no_comment'] = "[No comment]"; -$l['vote_added'] = "Rating Added"; -$l['vote_updated'] = "Rating Updated"; -$l['vote_deleted'] = "Rating Deleted"; -$l['vote_added_message'] = "Your reputation rating has successfully been added for this user."; -$l['vote_updated_message'] = "Your reputation rating has successfully been updated for this user."; -$l['vote_deleted_message'] = "The reputation rating has been deleted from this user."; -$l['update_reputation_vote'] = "Update your reputation rating for {1}"; -$l['positive'] = "Positive"; -$l['negative'] = "Negative"; -$l['neutral'] = "Neutral"; -$l['user_comments'] = "Your comments on {1}:"; -$l['add_vote'] = "Add Rating"; -$l['update_vote'] = "Update Rating"; -$l['delete_vote'] = "Delete"; -$l['report_vote'] = "Report"; -$l['power_positive'] = "Positive ({1})"; -$l['power_neutral'] = "Neutral"; -$l['power_negative'] = "Negative ({1})"; -$l['show_all'] = "Show: All Votes"; -$l['show_positive'] = "Show: Positive Ratings"; -$l['show_neutral'] = "Show: Neutral Ratings"; -$l['show_negative'] = "Show: Negative Ratings"; -$l['sort_updated'] = "Sort by: Last Updated"; -$l['sort_username'] = "Sort by: Username"; -$l['last_updated'] = "Last updated {1}"; -$l['postrep_given'] = "Rating given for {2}'s post {3}
    "; -$l['postrep_given_nolink'] = "Rating given for {1}'s post
    "; -$l['postrep_given_thread'] = "in {2}"; -$l['no_reputation_votes'] = "This user currently does not have any reputation ratings with the specified criteria below."; -$l['delete_reputation_confirm'] = "Are you sure you wish to delete this reputation Rating?"; -$l['delete_reputation_log'] = "Deleted reputation rating by {1} (UID: {2})"; -$l['reputations_disabled_group'] = "The reputation system is disabled for users of this user group."; -$l['rate_user'] = "Rate User"; diff --git a/html/forums/inc/languages/english/search.lang.php b/html/forums/inc/languages/english/search.lang.php deleted file mode 100644 index e060e2f..0000000 --- a/html/forums/inc/languages/english/search.lang.php +++ /dev/null @@ -1,112 +0,0 @@ -{1} results on this page are selected."; -$l['all_selected'] = "All {1} results in this search are selected."; -$l['select_all'] = "Select all {1} results in this search."; -$l['clear_selection'] = "Clear Selection."; - -$l['results'] = "results"; -$l['mod_options'] = "Moderator Options"; -$l['display_all'] = "Display all"; -$l['display_only_approved'] = "Display only approved"; -$l['display_only_unapproved'] = "Display only unapproved"; -$l['display_only_softdeleted'] = "Display only soft deleted"; - -$l['redirect_searchresults'] = "Thank you, your search has been submitted and you will now be taken to the results list."; - -$l['error_minsearchlength'] = "One or more of your search terms were shorter than the minimum length. The minimum search term length is {1} characters.

    If you're trying to search for an entire phrase, enclose it within double quotes. For example \"The quick brown fox jumps over the lazy dog\"."; -$l['error_nosearchresults'] = "Sorry, but no results were returned using the query information you provided. Please redefine your search terms and try again."; -$l['error_no_search_support'] = "This database engine does not support searching."; -$l['error_nosearchterms'] = "You did not enter any search terms. At a minimum, you must enter either some search terms or a username to search by."; -$l['error_searchflooding_1'] = "Sorry, but you can only perform one search every {1} seconds. Please wait another 1 second before attempting to search again."; -$l['error_searchflooding'] = "Sorry, but you can only perform one search every {1} seconds. Please wait another {2} seconds before attempting to search again."; -$l['error_invalidsearch'] = "An invalid search was specified. Please go back and try again."; diff --git a/html/forums/inc/languages/english/sendthread.lang.php b/html/forums/inc/languages/english/sendthread.lang.php deleted file mode 100644 index 6846518..0000000 --- a/html/forums/inc/languages/english/sendthread.lang.php +++ /dev/null @@ -1,17 +0,0 @@ -Note: This is a public poll, other users will be able to see what you voted for."; -$l['total'] = "Total"; -$l['vote'] = "Vote!"; -$l['total_votes'] = "{1} vote(s)"; -$l['you_voted'] = "* You voted for this item."; -$l['poll_closed'] = "This poll is closed."; -$l['poll_closes'] = "This poll will close on: {1}"; -$l['already_voted'] = "You have already voted in this poll."; -$l['undo_vote'] = "Undo vote"; -$l['quick_reply'] = "Quick Reply"; -$l['message_note'] = "Type your reply to this message here."; -$l['signature'] = "Signature"; -$l['email_notify'] = "Email Notification"; -$l['disable_smilies'] = "Disable Smilies"; -$l['post_reply'] = "Post Reply"; -$l['post_reply_img'] = "Post Reply"; -$l['new_reply'] = "New Reply"; -$l['search_button'] = 'Search'; -$l['post_thread'] = "Post Thread"; -$l['preview_post'] = "Preview Post"; -$l['rating_average'] = "{1} Vote(s) - {2} Average"; -$l['rate_thread'] = "Rate This Thread:"; -$l['thread_rating'] = "Thread Rating:"; -$l['similar_threads'] = "Possibly Related Threads..."; -$l['thread'] = "Thread"; -$l['replies'] = "Replies"; -$l['views'] = "Views"; -$l['lastpost'] = "Last Post"; -$l['messages_in_thread'] = "Messages In This Thread"; -$l['users_browsing_thread'] = "Users browsing this thread:"; -$l['users_browsing_thread_guests'] = "{1} Guest(s)"; -$l['users_browsing_thread_invis'] = "{1} Invisible User(s)"; -$l['users_browsing_thread_reading'] = "Reading..."; -$l['inline_soft_delete_posts'] = "Soft Delete Posts"; -$l['inline_restore_posts'] = "Restore Posts"; -$l['inline_delete_posts'] = "Delete Posts Permanently"; -$l['inline_merge_posts'] = "Merge Posts"; -$l['inline_split_posts'] = "Split Posts"; -$l['inline_move_posts'] = "Move Posts"; -$l['inline_approve_posts'] = "Approve Posts"; -$l['inline_unapprove_posts'] = "Unapprove Posts"; -$l['inline_post_moderation'] = "Inline Post Moderation:"; -$l['inline_go'] = "Go"; -$l['clear'] = "Clear"; -$l['thread_closed'] = "Thread Closed"; -$l['no_subject'] = "No subject"; -$l['error_nonextnewest'] = "There are no threads that are newer than the one you were previously viewing."; -$l['error_nonextoldest'] = "There are no threads that are older than the one you were previously viewing."; -$l['quickreply_multiquote_selected'] = "You have selected one or more posts to quote."; -$l['quickreply_multiquote_now'] = "Quote these posts now"; -$l['or'] ="or"; -$l['quickreply_multiquote_deselect'] = "deselect them"; -$l['search_thread'] = "Search Thread"; -$l['enter_keywords'] = "Enter Keywords"; -$l['view_thread_notes'] = "Thread Notes"; -$l['view_all_notes'] = "View All Notes"; - -$l['save_changes'] = 'Save Changes'; -$l['cancel_edit'] = 'Cancel Edit'; -$l['quick_edit_update_error'] = 'There was an error editing your reply:'; -$l['quick_reply_post_error'] = 'There was an error posting your reply:'; -$l['quick_delete_error'] = 'There was an error deleting your reply:'; -$l['quick_delete_success'] = 'The post was deleted successfully.'; -$l['quick_delete_thread_success'] = 'The thread was deleted successfully.'; -$l['quick_restore_error'] = 'There was an error restoring your reply:'; -$l['quick_restore_success'] = 'The post was restored successfully.'; - diff --git a/html/forums/inc/languages/english/stats.lang.php b/html/forums/inc/languages/english/stats.lang.php deleted file mode 100644 index 4a27064..0000000 --- a/html/forums/inc/languages/english/stats.lang.php +++ /dev/null @@ -1,37 +0,0 @@ -{1} ({2} posts)"; -$l['popular_forum'] = "Most popular forum: {1} ({2} posts, {3} threads)"; -$l['most_popular'] = "Most Popular..."; -$l['most_replied_threads'] = "Most Replied To Threads"; -$l['most_viewed_threads'] = "Most Viewed Threads"; -$l['not_enough_info_stats'] = "Sorry, but there is not enough information on this board to generate statistics. Before statistics can be generated this board needs to contain at least 1 member and 1 thread."; -$l['replies'] = "replies"; -$l['views'] = "views"; -$l['top_referrer'] = "Top referrer: {1} ({2} referrals)"; - diff --git a/html/forums/inc/languages/english/syndication.lang.php b/html/forums/inc/languages/english/syndication.lang.php deleted file mode 100644 index dc78f8a..0000000 --- a/html/forums/inc/languages/english/syndication.lang.php +++ /dev/null @@ -1,13 +0,0 @@ -The main page has information on your account."; -$l['account_summary'] = "Your Account Summary"; -$l['username'] = "Username:"; -$l['user_id'] = "User ID:"; -$l['title'] = "User Title:"; -$l['postnum'] = "Posts:"; -$l['posts_day'] = "({1} per day | {2} percent of total posts)"; -$l['additional_contact_details'] = "Additional Contact Information"; -$l['email'] = "Email:"; -$l['reputation'] = "Reputation:"; -$l['website'] = "Website:"; -$l['usergroup'] = "User Group:"; -$l['birthday'] = "Date of Birth:"; -$l['birthdayprivacy'] = "Date of Birth Privacy:"; -$l['birthdayprivacyall'] = "Display Age and Date of Birth"; -$l['birthdayprivacynone'] = "Hide Age and Date of Birth"; -$l['birthdayprivacyage'] = "Display Only Age"; -$l['avatar'] = "Avatar:"; -$l['avatar_mine'] = "This is your Avatar"; -$l['change_avatar'] = "Change Avatar"; -$l['avatar_url'] = "Avatar URL:"; -$l['avatar_url_note'] = "Enter the URL of an avatar on the internet."; -$l['avatar_url_gravatar'] = "To use a Gravatar enter your Gravatar email."; -$l['avatar_upload'] = "Upload Avatar:"; -$l['avatar_upload_note'] = "Choose an avatar on your local computer to upload."; -$l['no_avatar'] = "No Avatar"; -$l['no_avatar_note'] = "Select this option if you don't want an avatar."; -$l['change_username'] = "Change Username"; -$l['new_username'] = "New Username:"; -$l['update_username'] = "Update Username"; -$l['edit_lists'] = "Edit Buddy and Ignore Lists"; -$l['edit_buddy_list'] = "Edit Buddy List"; -$l['edit_ignore_list'] = "Edit Ignore List"; -$l['users_added_to_ignore_list'] = "The selected user(s) have been added to your ignore list"; -$l['users_added_to_buddy_list'] = "The selected user(s) have been added to your buddy list"; -$l['removed_from_ignore_list'] = "{1} has been removed from your ignore list"; -$l['removed_from_buddy_list'] = "{1} has been removed from your buddy list"; -$l['cant_add_self_to_ignore_list'] = "You cannot add yourself to your ignore list."; -$l['cant_add_self_to_buddy_list'] = "You cannot add yourself to your buddy list."; -$l['users_already_on_ignore_list'] = "One or more users you added are already on your ignore list."; -$l['users_already_on_ignore_list_alt'] = "One or more users you added is on your buddy list. Please remove them as a buddy before ignoring them."; -$l['users_already_on_buddy_list'] = "One or more users you added are already on your buddy list."; -$l['users_already_on_buddy_list_alt'] = "One or more users you added is on your ignore list. Please remove them from the list before adding them as a buddy."; -$l['invalid_user_selected'] = "One or more of the selected users were not found."; -$l['ignore_list_empty'] = "Your ignore list is currently empty. To add one or more users to your ignore list, please use the field above."; -$l['buddy_list_empty'] = "Your buddy list is currently empty. To add one or more users to your buddy list, please use the field above."; -$l['confirm_remove_buddy'] = "Remove this user from your buddy list?"; -$l['confirm_remove_ignored'] = "Remove this user from your ignore list?"; -$l['adding_buddy'] = "Adding Buddy.."; -$l['adding_ignored'] = "Adding to Ignored.."; -$l['add_buddies'] = "Add Users to your Buddy List"; -$l['add_buddies_desc'] = "To add one or more users to your buddy list, enter their usernames below. Separate multiple usernames with a comma."; -$l['username_or_usernames'] = "Username(s):"; -$l['add_to_buddies'] = "Add to Buddies"; -$l['current_buddies'] = "You currently have {1} user(s) on your buddy list"; -$l['add_ignored_users'] = "Add Users to your Ignore List"; -$l['add_ignored_users_desc'] = "To ignore posts and private messages from specific users, enter their username below. You can separate multiple names with a comma."; -$l['ignore_users'] = "Ignore User(s)"; -$l['current_ignored_users'] = "You currently have {1} user(s) on ignore"; -$l['online'] = "Online"; -$l['offline'] = "Offline"; -$l['remove_from_list'] = "Remove from list"; -$l['edit_sig'] = "Edit Signature"; -$l['edit_sig_note'] = "Here you can enter a short message which will be automatically appended to the bottom of your posts."; -$l['edit_sig_note2'] = "Smilies are {1}.
    MyCode is {2}.
    [img] tags are {3}.
    HTML is {4}.
    Max. length is {5} characters."; -$l['edit_sig_error_title'] = "An error has occurred:"; -$l['edit_sig_no_permission'] = "You do not have permission to edit your signature."; -$l['characters_remaining'] = "characters remaining"; -$l['enable_sig_posts'] = "Enable my signature in all of my existing posts."; -$l['disable_sig_posts'] = "Disable my signature in all of my existing posts."; -$l['leave_sig_settings'] = "No action."; -$l['update_sig'] = "Update Signature"; -$l['preview'] = "Preview Signature"; -$l['current_sig'] = "Your Current Signature"; -$l['sig_preview'] = "Signature Preview"; - -$l['sig_suspended'] = "Your ability to add a signature has been suspended."; -$l['sig_suspended_posts'] = "You must have at least {1} posts before adding a signature."; - -$l['change_email'] = "Change Email Address"; -$l['please_enter_confirm_new_email'] = "Please Enter and Confirm Your New Email Address"; -$l['new_email'] = "New Email Address:"; -$l['confirm_email'] = "Confirm Email Address:"; -$l['update_email'] = "Update Email Address"; -$l['thread'] = "Thread"; -$l['author'] = "Author"; -$l['replies'] = "Replies"; -$l['views'] = "Views"; -$l['lastpost'] = "Last Post"; -$l['post_reply'] = "Post Reply"; -$l['forum_subscriptions'] = "Forum Subscriptions"; -$l['posts'] = "Posts"; -$l['forum'] = "Forum"; -$l['threads'] = "Threads"; -$l['unsubscribe'] = "Unsubscribe"; -$l['new_thread'] = "New Thread"; -$l['personal_notepad'] = "Personal Notepad"; -$l['update_notepad'] = "Update Notepad"; -$l['edit_options'] = "Edit Options"; -$l['login_cookies_privacy'] = "Privacy"; -$l['invisible_mode'] = "Hide me from the Who's Online list."; -$l['invisible_mode_desc'] = "Selecting yes will hide you from the online users list."; -$l['messaging_notification'] = "Messaging and Notification"; -$l['allow_notices'] = "Receive emails from the Administrators."; -$l['allow_notices_desc'] = "Selecting yes will allow Administrators to send you notices and board newsletters."; -$l['allow_emails'] = "Hide your email from other members."; -$l['allow_emails_desc'] = "Selecting yes will allow other members to send you emails through this board."; -$l['email_notify'] = "Automatically subscribe to threads you post in."; -$l['email_notify_desc'] = "Selecting yes will automatically subscribe you to threads when you make a post in them."; -$l['receive_pms'] = "Receive private messages from other users."; -$l['receive_pms_desc'] = "Enables you to send and receive Private Messages."; -$l['receive_from_buddy'] = "Only receive private messages from users on my Buddy List. This setting has no effect unless there is at least one buddy on the list."; -$l['pm_notice'] = "Alert me with a notice when I receive a Private Message."; -$l['pm_notify'] = "Notify me by email when I receive a new Private Message."; -$l['show_codebuttons'] = "Show the MyCode formatting options on the posting pages."; -$l['source_editor'] = "Put the editor in source mode by default"; -$l['show_redirect'] = "Show friendly redirect pages."; -$l['thread_view_options'] = "Thread View Options"; -$l['thread_mode'] = "Thread View Mode:"; -$l['thread_mode_desc'] = "The style of threads shown to you. Selecting 'Use Default' will use the boards default mode."; -$l['use_default'] = "Use Default"; -$l['threaded'] = "Threaded"; -$l['linear'] = "Linear"; -$l['show_classic_postbit'] = "Display posts in classic mode."; -$l['show_images'] = "Display images in posts."; -$l['show_videos'] = "Display videos in posts."; -$l['show_sigs'] = "Display users' signatures in their posts."; -$l['show_sigs_desc'] = "Do you want to view user's signatures in their posts?"; -$l['show_avatars'] = "Display users' avatars in their posts."; -$l['show_avatars_desc'] = "Do you want to view user's avatars in their posts?"; -$l['show_quick_reply'] = "Show the quick reply box on the view thread page."; -$l['show_quick_reply_desc'] = "The quick reply box enables you to make a 'quick reply' to threads using the reply box provided at the end of a thread"; -$l['forum_display_options'] = "Forum Display Options"; -$l['thread_view'] = "Default Thread View:"; -$l['thread_view_lastday'] = "Show threads from last day"; -$l['thread_view_5days'] = "Show threads from last 5 days"; -$l['thread_view_10days'] = "Show threads from last 10 days"; -$l['thread_view_20days'] = "Show threads from last 20 days"; -$l['thread_view_50days'] = "Show threads from last 50 days"; -$l['thread_view_75days'] = "Show threads from last 75 days"; -$l['thread_view_100days'] = "Show threads from last 100 days"; -$l['thread_view_year'] = "Show threads from the last year"; -$l['thread_view_all'] = "Show all threads"; -$l['date_time_options'] = "Date and Time Options"; -$l['date_format'] = "Date Format:"; -$l['date_format_desc'] = "The format that dates will be shown in."; -$l['time_format'] = "Time Format:"; -$l['time_format_desc'] = "The format that times will be shown in."; -$l['time_offset'] = "Time Zone (DST correction excluded):"; -$l['time_offset_desc'] = "If you live in a time zone which differs to what this board is set at, you can select it from the list below."; -$l['gmt'] = "GMT"; -$l['dst_correction'] = "Daylight Saving Time correction:"; -$l['dst_correction_auto'] = "Automatically detect DST settings"; -$l['dst_correction_enabled'] = "Always use DST correction"; -$l['dst_correction_disabled'] = "Never use DST correction"; -$l['board_language'] = "Board Language"; -$l['other_options'] = "Other Options"; -$l['style'] = "Board Style:"; -$l['style_desc'] = "If you don't like the default style of this board you can change how you view it here."; -$l['update_options'] = "Update Options"; -$l['tpp_option'] = "Show {1} threads per page"; -$l['ppp_option'] = "Show {1} posts per page"; -$l['ppp'] = "Posts Per Page:"; -$l['ppp_desc'] = "Allows you to select the amount of posts to be shown per page in a thread."; -$l['tpp'] = "Threads Per Page:"; -$l['tpp_desc'] = "Allows you to select the amount of threads to be shown per page in the thread listing."; -$l['change_password'] = "Change Password"; -$l['current_password'] = "Current Password:"; -$l['password_confirmation'] = "Password Confirmation"; -$l['please_enter_confirm_new_password'] = "Please Enter and Confirm Your New Password"; -$l['new_password'] = "New Password:"; -$l['confirm_password'] = "Confirm Password:"; -$l['update_password'] = "Update Password"; -$l['edit_profile'] = "Edit Profile"; -$l['profile_required'] = "Required Fields"; -$l['change_email_notice'] = "To change your email address please click here"; -$l['profile_optional'] = "Optional Fields"; -$l['website_url'] = "Your Website URL:"; -$l['birthdate'] = "Birthdate:"; -$l['contact_field_icq'] = "ICQ Number:"; -$l['contact_field_aim'] = "AIM Screen Name:"; -$l['contact_field_yahoo'] = "Yahoo ID:"; -$l['contact_field_skype'] = "Skype ID:"; -$l['contact_field_google'] = "Google Hangouts ID:"; -$l['additional_information'] = "Additional Information"; -$l['update_profile'] = "Update Profile"; -$l['away_information'] = "Away Information"; -$l['away_status'] = "Away Status:"; -$l['away_status_desc'] = "Allows you to leave an away message if you are going away for a while."; -$l['im_away'] = "I'm Away"; -$l['im_here'] = "I'm Here"; -$l['away_reason'] = "Away Reason:"; -$l['away_reason_desc'] = "Allows you to enter a small description of why you are away (max 200 characters)."; -$l['return_date'] = "Return Date:"; -$l['return_date_desc'] = "If you know when you will be back, you can enter your return date here."; -$l['subscriptions'] = "Thread Subscriptions"; -$l['remove_all_subscriptions'] = "Remove All Subscriptions"; -$l['no_thread_subscriptions'] = "You're currently not subscribed to any threads.

    To subscribe to a thread:

    1. Navigate to the thread you wish to subscribe to.
    2. Click the 'Subscribe to this thread' link towards the bottom of the page.
    "; -$l['no_forum_subscriptions'] = "You're currently not subscribed to any forums.

    To subscribe to a forum:

    1. Navigate to the forum you wish to subscribe to.
    2. Click the 'Subscribe to this forum' link just above, towards the right side of, the list of threads in that forum.
    "; -$l['no_drafts'] = "You do not currently have any draft threads or posts.

    To save a draft thread or post:

    1. Proceed to the normal posting pages for the action you wish to perform (post a new thread or reply to an existing one).
    2. Fill in as much or as little as you want on the posting page.
    3. Click the 'Save as Draft' button below the posting area.
    "; -$l['drafts'] = "Saved Drafts"; -$l['drafts_count'] = "Saved Drafts ({1})"; -$l['draft_saved'] = "Saved"; -$l['edit_draft'] = "Edit Draft"; -$l['draft_title'] = "Draft Title"; -$l['delete_drafts'] = "Delete Selected Drafts"; -$l['draft_options'] = "Draft Options"; -$l['selected_drafts_deleted'] = "The selected drafts have been deleted.
    You will be now taken back to the drafts listing."; -$l['no_drafts_selected'] = "You did not select any drafts to delete"; -$l['group_memberships'] = "Group Memberships"; -$l['not_member_of_group'] = "Sorry, you cannot perform that action because you are currently not a member of that group."; -$l['cannot_set_displaygroup'] = "This group cannot be set as a display group."; -$l['display_group_changed'] = "Your display group has been updated.
    You will be now taken back to the group memberships page."; -$l['usergroups_memberof'] = "Groups You're a Member Of"; -$l['usertitle'] = "User Title"; -$l['usergroup_leave'] = "Leave Group"; -$l['usergroup_leave_primary'] = "(You cannot leave your primary group)"; -$l['usergroup_leave_leader'] = "(You are a leader of this group)"; -$l['usergroup_joins_moderated'] = "A group leader is required to moderate joins to this group."; -$l['usergroup_joins_invite'] = "A group leader must invite you to join this group."; -$l['usergroup_cannot_leave'] = "(You cannot leave this user group)"; -$l['usergroup_joins_anyone'] = "Anyone is free to join this group."; -$l['usergroup_leaders'] = "Group led by:"; -$l['usergroups_joinable'] = "Groups You Can Join"; -$l['join_conditions'] = "Join Conditions"; -$l['join_group'] = "Join Group"; -$l['join_group_applied'] = "You applied to join this group: {1}"; -$l['pending_invitation'] = "You have been invited to this group: Accept Invite"; -$l['usergroups_leader'] = "Groups You Lead"; -$l['usergroup_members'] = "Group Members"; -$l['join_requests'] = "Pending Join Requests"; -$l['request_join_usergroup'] = "Request Group Membership"; -$l['join_group_moderate_note'] = "All joins to this group must first be approved by a moderator."; -$l['user_group'] = "Group:"; -$l['usergroups_usergroup'] = "User Group"; -$l['join_reason'] = "Reason:"; -$l['send_join_request'] = "Send Join Request"; -$l['cannot_join_group'] = "Sorry, but you cannot join this group as it is not a publicly join-able group."; -$l['cannot_join_invite_group'] = "In order to join this group, you must be invited by a group leader."; -$l['no_pending_invitation'] = "You do not have any pending invitation to this group."; -$l['already_accepted_invite'] = "You have already accepted an invite to join this group."; -$l['already_member_of_group'] = "You cannot join a group of which you are already a member of."; -$l['already_sent_join_request'] = "You have already sent a request to join this group and it is yet to be moderated."; -$l['group_join_requestsent'] = "Your join request has been successfully sent. Once your membership is approved you will be automatically joined to this user group.
    You will be now taken to the group memberships page."; -$l['joined_group'] = "You have successfully joined the specified group.
    You will be now taken back to the group management page."; -$l['cannot_leave_primary_group'] = "Sorry, but you cannot leave your primary group."; -$l['left_group'] = "You have successfully left the specified group.
    You will be now taken back to the group management page."; -$l['avatar_note'] = "An avatar is a small identifying image shown under the author's name whenever they make a post."; -$l['avatar_note_dimensions'] = "The maximum dimensions for avatars are: {1}x{2} pixels."; -$l['avatar_note_size'] = "The maximum file size for avatars is {1}."; -$l['custom_avatar'] = "Custom Avatar"; -$l['remove_avatar'] = "Remove Avatar"; -$l['attachments_manager'] ="Attachments Manager"; -$l['attachments_attachment'] ="Attachment"; -$l['attachments_post'] = "Post"; -$l['delete_attachments'] = "Delete Selected Attachments"; -$l['attachment_size_downloads'] = "({1}, {2} Downloads)"; -$l['attachment_thread'] = "Thread:"; -$l['no_attachments'] = "You currently do not have any files attached to your posts."; -$l['date_uploaded'] ="Posted"; -$l['no_attachments_selected'] = "You did not select any attachments to delete."; -$l['attachments_deleted'] = "The selected attachments have been successfully deleted.
    You will be now redirected to the attachments manager."; -$l['attachments_usage_quota'] = "- Using {1} of {2} ({3}) in {4} Attachments"; -$l['attachments_usage'] = "- {1} in {2} Attachments"; -$l['attachments_stats'] = "Your Attachment Statistics"; -$l['attachstats_attachs'] = "Number of Attachments"; -$l['attachstats_spaceused'] = "Space Used"; -$l['attachstats_quota'] = "Attachment Quota"; -$l['attachstats_totaldl'] = "Total Downloads"; -$l['attachstats_bandwidth'] = "Approximate Bandwidth Usage"; -$l['error_avatartoobig'] = "Sorry, but we cannot change your avatar as the new avatar you specified is too big. The maximum dimensions are {1}x{2} (width x height)"; -$l['error_invalidavatarurl'] = "The URL you entered for your avatar does not appear to be valid. Please ensure you enter a valid URL."; -$l['error_remote_avatar_not_allowed'] = "Remote avatar URLs have been disabled by the forum administrator."; -$l['custom_usertitle'] = "Custom User Title"; -$l['new_custom_usertitle'] = "New Custom User Title: (leave blank to use existing)"; -$l['custom_usertitle_note'] = "Here you can assign yourself a custom user title which will overwrite the one based on your display group."; -$l['default_usertitle'] = "Default User Title:"; -$l['current_custom_usertitle'] = "Current Custom User Title:"; -$l['revert_usertitle'] = "Revert to group default"; -$l['primary_usergroup'] = "Primary User Group:"; -$l['display_group'] = "Display Group"; -$l['set_as_display_group'] = "Set as Display Group"; -$l['registration_date'] ="Registration Date:"; -$l['view_members'] = "View Members"; -$l['view_requests'] = "Join Requests"; -$l['cannot_leave_group'] = "You cannot leave this group because it is not a publicly join-able group."; -$l['details'] = "Details"; -$l['members_referred'] = "Members Referred:"; -$l['referral_link'] = "
    To refer a member to this board, direct them to {1}/member.php?action=register&referrer={2}"; -$l['redirect_subscriptionsremoved'] = "Your thread subscriptions list has been cleared.
    You will be now returned to the thread subscriptions list."; -$l['redirect_forumsubscriptionsremoved'] = "Your forum subscriptions list has now been cleared.
    You will be now returned to where you came from."; -$l['redirect_subscriptionadded'] = "The selected thread has been added to your subscriptions list.
    You will be now returned to the location you came from."; -$l['redirect_optionsupdated'] = "You have successfully updated your options.
    You will be now returned to the edit options page."; -$l['redirect_subscriptionremoved'] = "The selected thread has been removed from your subscriptions list.
    You will be now returned to the thread subscriptions list."; -$l['redirect_sigupdated'] = "Your signature has been successfully updated.
    You will be now returned to the signature settings."; -$l['redirect_notepadupdated'] = "Your personal notepad has been updated.
    You will be now returned to the User CP."; -$l['redirect_profileupdated'] = "Your profile has been successfully updated.
    You will be now returned to the profile settings."; -$l['redirect_forumsubscriptionadded'] = "The selected forum has been added to your forum subscriptions list.
    You will be now returned to where you came from."; -$l['redirect_forumsubscriptionremoved'] = "The selected forum has been removed from your forum subscriptions list.
    You will be now returned to where you came from."; -$l['redirect_namechanged'] = "Your name has been successfully changed.
    You will be now returned to the username settings."; -$l['redirect_emailupdated'] = "Your email address has been successfully updated.
    You will be now returned to the email settings."; -$l['redirect_passwordupdated'] = "Your password has been successfully updated.
    You will be now returned to the password settings."; -$l['redirect_changeemail_activation'] = "Your email address has been successfully updated. For your new email address to become active, we require that you complete a validation process.

    Please check the new email address you specified for further instructions on how to complete the account activation process.

    "; -$l['redirect_avatarupdated'] = "Your avatar has been successfully changed.
    You will be now returned to the avatar settings."; -$l['error_noavatar'] = "You did not choose an avatar. Please go back and do so now. If you don't want an avatar, select the \"No avatar\" option."; -$l['error_avatartype'] = "Invalid file type. An uploaded avatar must be in GIF, JPEG, BMP or PNG format."; -$l['error_alreadyingroup'] = "The user specified is already a part of the user group."; -$l['error_usercp_return_date_past'] = "You cannot return in the past!"; -$l['error_avatarresizefailed'] = "Your avatar was unable to be resized so that it is within the required dimensions."; -$l['error_avataruserresize'] = "You can also try checking the 'attempt to resize my avatar' check box and uploading the same image again."; -$l['avatar_auto_resize_note'] = "If your avatar is too large, it will automatically be resized."; -$l['avatar_auto_resize_option'] = "Try to resize my avatar if it is too large."; -$l['subscribe_to_thread'] = "Subscribe to Thread: {1}"; -$l['notification_method'] = "Notification Method:"; -$l['no_notification'] = "No Notification"; -$l['no_notification_desc'] = "You will not receive any automatic notifications of replies to this thread."; -$l['email_notification'] = "Instant Email Notification"; -$l['email_notification_desc'] = "You will receive instant notification via email of any replies made to this thread."; -$l['pm_notification'] = "Instant PM Notification"; -$l['pm_notification_desc'] = "You will receive instant notification via PM of any replies made to this thread."; -$l['do_subscribe'] = "Subscribe to Thread"; -$l['subscription_method'] = "Default Thread Subscription Mode:"; -$l['no_auto_subscribe'] = "Do not subscribe"; -$l['no_subscribe'] = "No notification"; -$l['instant_email_subscribe'] = "Instant email notification"; -$l['instant_pm_subscribe'] = "Instant PM notification"; -$l['with_selected'] = "With Selected:"; -$l['delete_subscriptions'] = "Delete subscriptions"; -$l['update_no_notification'] = "Change to no notification"; -$l['update_email_notification'] = "Change to email notification"; -$l['update_pm_notification'] = "Change to PM notification"; -$l['no_subscriptions_selected'] = "You did not select any subscriptions to perform the selected action on."; -$l['redirect_subscriptions_updated'] = "The selected subscriptions have been updated.
    You will be now returned to the thread subscriptions list."; -$l['latest_threads'] = "Your Latest Threads"; -$l['find_all_threads'] = "Find All of Your Threads"; -$l['new_thread_subscriptions'] = "Thread Subscriptions With New Posts"; -$l['view_all_subscriptions'] = "View All Subscriptions"; -$l['latest_warnings'] = "Latest Warnings Received"; -$l['current_warning_level'] = "Current warning level: {1}% ({2}/{3})"; -$l['warning'] = "Warning"; -$l['date_issued'] = "Date Issued"; -$l['expiry_date'] = "Expiry Date"; -$l['issued_by'] = "Issued By"; -$l['warning_for_post'] = "for post: "; -$l['warning_revoked'] = "Revoked"; -$l['already_expired'] = "Expired"; -$l['warning_points'] = "({1} points)"; -$l['new_posts_thread'] = "New Posts"; -$l['new_hot_thread'] = "Hot Thread (New)"; -$l['posts_by_you'] = "Contains Posts by You"; -$l['no_new_thread'] = "No New Posts"; -$l['hot_thread'] = "Hot Thread (No New)"; -$l['locked_thread'] = "Locked Thread"; -$l['icon_dot'] = "Contains posts by you. "; // The spaces for the icon labels are strategically placed so that there should be no extra space at the beginning or end of the resulting label and that spaces separate each 'status' ;) -$l['icon_no_new'] = "No new posts."; -$l['icon_new'] = "New posts."; -$l['icon_hot'] = " Hot thread."; -$l['icon_lock'] = " Locked thread."; - -$l['buddylist_error'] = 'There was an error fetching the buddy list. '; - -$l['buddyrequests_sent'] = 'Buddy Requests Sent'; -$l['buddyrequests_received'] = 'Buddy Requests Received'; -$l['from'] = 'From'; -$l['to'] = 'To'; -$l['date'] = 'Date'; -$l['options'] = 'Options'; -$l['accept'] = 'Accept'; -$l['decline'] = 'Decline'; -$l['cancel'] = 'Cancel'; -$l['no_requests'] = 'No requests found.'; -$l['buddyrequests_pm'] = 'Receive PM notifications for new buddy requests.'; -$l['buddyrequests_auto'] = 'Automatically accept buddy requests (if the above checkbox is ticked, a PM is sent informing of the new buddy connection)'; -$l['buddyrequest_received'] = 'Buddy request received'; -$l['buddyrequest_new_buddy'] = 'You have a new buddy'; -$l['buddyrequest_new_buddy_message'] = "Hi,\n\nI have been automatically added to your buddy list."; -$l['buddyrequest_accepted_request'] = 'I have accepted your buddy request'; -$l['buddyrequest_accepted_request_message'] = "Hi,\n\nI have accepted your buddy request."; -$l['buddyrequest_received_message'] = "I have just sent you a buddy request.\nYou can view your pending requests from User Control Panel -> Buddy/Ignore List."; -$l['users_already_sent_request'] = "You have already sent a buddy request to one of the users you added."; -$l['users_already_rec_request'] = "You have a pending buddy request from one of the users you added."; -$l['users_already_sent_request_alt'] = "You have sent a buddy request to one of the users you added. Please cancel the buddy request before adding the user to the ignore list."; -$l['users_already_rec_request_alt'] = "You have a pending buddy request from one of the users you added. Please decline the buddy request before adding the user to the ignore list."; -$l['invalid_request'] = 'You have selected an invalid buddy request.'; -$l['buddyrequest_cancelled'] = 'The selected buddy request has been cancelled.'; -$l['buddyrequest_accepted'] = 'The selected buddy request has been accepted.'; -$l['buddyrequest_declined'] = 'The selected buddy request has been declined.'; -$l['user_doesnt_exist'] = 'The end user no longer exists.'; -$l['buddyrequests_sent_success'] = 'Buddy requests sent successfully.'; diff --git a/html/forums/inc/languages/english/usercpnav.lang.php b/html/forums/inc/languages/english/usercpnav.lang.php deleted file mode 100644 index f7b61d0..0000000 --- a/html/forums/inc/languages/english/usercpnav.lang.php +++ /dev/null @@ -1,33 +0,0 @@ -Saved Drafts ({1})"; -$l['ucp_nav_notepad'] = "Personal Pad"; -$l['ucp_nav_view_profile'] = "View Profile"; -$l['ucp_nav_home'] = "User CP Home"; -$l['ucp_nav_usergroups'] = "Group Memberships"; -$l['ucp_nav_attachments'] = "Manage Attachments"; diff --git a/html/forums/inc/languages/english/warnings.lang.php b/html/forums/inc/languages/english/warnings.lang.php deleted file mode 100644 index a638a01..0000000 --- a/html/forums/inc/languages/english/warnings.lang.php +++ /dev/null @@ -1,88 +0,0 @@ -Anonymous PM: send this private message as an anonymous user."; -$l['expiration_never'] = "permanently"; -$l['expiration_hours'] = "hours"; -$l['expiration_days'] = "days"; -$l['expiration_weeks'] = "weeks"; -$l['expiration_months'] = "months"; -$l['redirect_warned_banned'] = "

    The user has also been moved to the {1} group {2}."; -$l['redirect_warned_suspended'] = "

    This users posting privileges have been suspended {1}."; -$l['redirect_warned_moderate'] = "

    All posts by this user will now be moderated {1}."; -$l['redirect_warned_pmerror'] = "

    Please note that the PM was not sent."; -$l['redirect_warned'] = "The warning level of {1} has been increased to {2}%.{3}

    You will now be taken back to where you came from."; -$l['error_warning_system_disabled'] = "You cannot use the warning system as it has been disabled by the board administrator."; -$l['error_cant_warn_group'] = "You do not have permission to warn users of this group."; -$l['error_invalid_user'] = "Selected user doesn't exist."; -$l['details'] = "Details"; -$l['view'] = "View"; -$l['current_warning_level'] = "Current warning level: {1}% ({2}/{3})"; -$l['warning_details'] = "Warning Details"; -$l['revoke_warning'] = "Revoke this Warning"; -$l['revoke_warning_desc'] = "To revoke this warning please enter a reason below. This will not remove any bans or suspensions imposed by this warning."; -$l['warning_is_revoked'] = "This Warning has been revoked"; -$l['revoked_by'] = "Revoked By"; -$l['date_revoked'] = "Date Revoked"; -$l['warning_already_revoked'] = "This warning has already been revoked."; -$l['no_revoke_reason'] = "You did not enter a reason as to why you want to revoke this warning."; -$l['redirect_warning_revoked'] = "This warning has successfully been revoked and the users warning points decreased.

    You will now be taken back to the warning."; -$l['result'] = "Result:"; -$l['result_banned'] = "User will be moved to banned group ({1}) {2}"; -$l['result_suspended'] = "Posting privileges will be suspended {1}"; -$l['result_moderated'] = "Posts will be moderated {1}"; -$l['result_period'] = "for {1} {2}"; -$l['result_period_perm'] = "permanently"; -$l['hour_or_hours'] = "Hour(s)"; -$l['day_or_days'] = "Day(s)"; -$l['week_or_weeks'] = "Week(s)"; -$l['month_or_months'] = "Month(s)"; -$l['expires'] = "Expires:"; -$l['new_warning_level'] = "New warning level:"; -$l['error_cant_warn_user'] = "You do not have permission to warn this user."; -$l['existing_post_warnings'] = "Existing Warnings for this Post"; diff --git a/html/forums/inc/languages/english/xmlhttp.lang.php b/html/forums/inc/languages/english/xmlhttp.lang.php deleted file mode 100644 index 278895a..0000000 --- a/html/forums/inc/languages/english/xmlhttp.lang.php +++ /dev/null @@ -1,45 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/mailhandlers/index.html b/html/forums/inc/mailhandlers/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/mailhandlers/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/mailhandlers/php.php b/html/forums/inc/mailhandlers/php.php deleted file mode 100644 index 43dccc0..0000000 --- a/html/forums/inc/mailhandlers/php.php +++ /dev/null @@ -1,86 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/** - * PHP mail handler class. - */ -class PhpMail extends MailHandler -{ - /** - * Additional parameters to pass to PHPs mail() function. - * - * @var string - */ - public $additional_parameters = ''; - - /** - * Sends the email. - * - * @return bool whether or not the email got sent or not. - */ - function send() - { - global $lang, $mybb; - - // For some reason sendmail/qmail doesn't like \r\n - $this->sendmail = @ini_get('sendmail_path'); - if($this->sendmail) - { - $this->headers = str_replace("\r\n", "\n", $this->headers); - $this->message = str_replace("\r\n", "\n", $this->message); - $this->delimiter = "\n"; - } - - // Some mail providers ignore email's with incorrect return-to path's so try and fix that here - $this->sendmail_from = @ini_get('sendmail_from'); - if($this->sendmail_from != $mybb->settings['adminemail']) - { - @ini_set("sendmail_from", $mybb->settings['adminemail']); - } - - $dir = "/{$mybb->config['admin_dir']}/"; - $pos = strrpos($_SERVER['PHP_SELF'], $dir); - if(defined('IN_ADMINCP') && $pos !== false) - { - $temp_script_path = $_SERVER['PHP_SELF']; - $_SERVER['PHP_SELF'] = substr($_SERVER['PHP_SELF'], $pos + strlen($dir) - 1); - } - - // If safe mode is on, don't send the additional parameters as we're not allowed to - if($mybb->safemode) - { - $sent = @mail($this->to, $this->subject, $this->message, trim($this->headers)); - } - else - { - $sent = @mail($this->to, $this->subject, $this->message, trim($this->headers), $this->additional_parameters); - } - $function_used = 'mail()'; - - if(defined('IN_ADMINCP') && $pos !== false) - { - $_SERVER['PHP_SELF'] = $temp_script_path; - } - - if(!$sent) - { - $this->fatal_error("MyBB was unable to send the email using the PHP {$function_used} function."); - return false; - } - - return true; - } -} diff --git a/html/forums/inc/mailhandlers/smtp.php b/html/forums/inc/mailhandlers/smtp.php deleted file mode 100644 index 9afe44c..0000000 --- a/html/forums/inc/mailhandlers/smtp.php +++ /dev/null @@ -1,538 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -/** - * SMTP mail handler class. - */ - -if(!defined('MYBB_SSL')) -{ - define('MYBB_SSL', 1); -} - -if(!defined('MYBB_TLS')) -{ - define('MYBB_TLS', 2); -} - -class SmtpMail extends MailHandler -{ - /** - * The SMTP connection. - * - * @var resource - */ - public $connection; - - /** - * SMTP username. - * - * @var string - */ - public $username = ''; - - /** - * SMTP password. - * - * @var string - */ - public $password = ''; - - /** - * Hello string sent to the smtp server with either HELO or EHLO. - * - * @var string - */ - public $helo = 'localhost'; - - /** - * User authenticated or not. - * - * @var boolean - */ - public $authenticated = false; - - /** - * How long before timeout. - * - * @var integer - */ - public $timeout = 5; - - /** - * SMTP status. - * - * @var integer - */ - public $status = 0; - - /** - * SMTP default port. - * - * @var integer - */ - public $port = 25; - - /** - * SMTP default secure port. - * - * @var integer - */ - public $secure_port = 465; - - /** - * SMTP host. - * - * @var string - */ - public $host = ''; - - /** - * The last received error message from the SMTP server. - * - * @var string - */ - public $last_error = ''; - - /** - * Are we keeping the connection to the SMTP server alive? - * - * @var boolean - */ - public $keep_alive = false; - - /** - * Whether to use TLS encryption. - * - * @var boolean - */ - public $use_tls = false; - - function __construct() - { - global $mybb; - - $protocol = ''; - switch($mybb->settings['secure_smtp']) - { - case MYBB_SSL: - $protocol = 'ssl://'; - break; - case MYBB_TLS: - $this->use_tls = true; - break; - } - - if(empty($mybb->settings['smtp_host'])) - { - $this->host = @ini_get('SMTP'); - } - else - { - $this->host = $mybb->settings['smtp_host']; - } - - $local = array('127.0.0.1', '::1', 'localhost'); - if(!in_array($this->host, $local)) - { - if(function_exists('gethostname') && gethostname() !== false) - { - $this->helo = gethostname(); - } - elseif(function_exists('php_uname')) - { - $helo = php_uname('n'); - if(!empty($helo)) - { - $this->helo = $helo; - } - } - elseif(!empty($_SERVER['SERVER_NAME'])) - { - $this->helo = $_SERVER['SERVER_NAME']; - } - } - - $this->host = $protocol . $this->host; - - if(empty($mybb->settings['smtp_port']) && !empty($protocol) && !@ini_get('smtp_port')) - { - $this->port = $this->secure_port; - } - else if(empty($mybb->settings['smtp_port']) && @ini_get('smtp_port')) - { - $this->port = @ini_get('smtp_port'); - } - else if(!empty($mybb->settings['smtp_port'])) - { - $this->port = $mybb->settings['smtp_port']; - } - - $this->password = $mybb->settings['smtp_pass']; - $this->username = $mybb->settings['smtp_user']; - } - - /** - * Sends the email. - * - * @return bool whether or not the email got sent or not. - */ - function send() - { - global $lang, $mybb; - - if(!$this->connected()) - { - if(!$this->connect()) - { - $this->close(); - } - } - - if($this->connected()) - { - if(!$this->send_data('MAIL FROM:<'.$this->from.'>', '250')) - { - $this->fatal_error("The mail server does not understand the MAIL FROM command. Reason: ".$this->get_error()); - return false; - } - - // Loop through recipients - $emails = explode(',', $this->to); - foreach($emails as $to) - { - $to = trim($to); - if(!$this->send_data('RCPT TO:<'.$to.'>', '250')) - { - $this->fatal_error("The mail server does not understand the RCPT TO command. Reason: ".$this->get_error()); - return false; - } - } - - if($this->send_data('DATA', '354')) - { - $this->send_data('Date: ' . gmdate('r')); - $this->send_data('To: ' . $this->to); - - $this->send_data('Subject: ' . $this->subject); - - // Only send additional headers if we've got any - if(trim($this->headers)) - { - $this->send_data(trim($this->headers)); - } - - $this->send_data(""); - - // Queue the actual message - $this->message = str_replace("\n.", "\n..", $this->message); - $this->send_data($this->message); - } - else - { - $this->fatal_error("The mail server did not understand the DATA command"); - return false; - } - - $this->send_data('.', '250'); - - if(!$this->keep_alive) - { - $this->close(); - } - return true; - } - else - { - return false; - } - } - - /** - * Connect to the SMTP server. - * - * @return boolean True if connection was successful - */ - function connect() - { - global $lang, $mybb; - - $this->connection = @fsockopen($this->host, $this->port, $error_number, $error_string, $this->timeout); - - // DIRECTORY_SEPARATOR checks if running windows - if(function_exists('stream_set_timeout') && DIRECTORY_SEPARATOR != '\\') - { - @stream_set_timeout($this->connection, $this->timeout, 0); - } - - if(is_resource($this->connection)) - { - $this->status = 1; - $this->get_data(); - if(!$this->check_status('220')) - { - $this->fatal_error("The mail server is not ready, it did not respond with a 220 status message."); - return false; - } - - if($this->use_tls || (!empty($this->username) && !empty($this->password))) - { - $helo = 'EHLO'; - } - else - { - $helo = 'HELO'; - } - - $data = $this->send_data("{$helo} {$this->helo}", '250'); - if(!$data) - { - $this->fatal_error("The server did not understand the {$helo} command"); - return false; - } - - if($this->use_tls && preg_match("#250( |-)STARTTLS#mi", $data)) - { - if(!$this->send_data('STARTTLS', '220')) - { - $this->fatal_error("The server did not understand the STARTTLS command. Reason: ".$this->get_error()); - return false; - } - if(!@stream_socket_enable_crypto($this->connection, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) - { - $this->fatal_error("Failed to start TLS encryption"); - return false; - } - // Resend EHLO to get updated service list - $data = $this->send_data("{$helo} {$this->helo}", '250'); - if(!$data) - { - $this->fatal_error("The server did not understand the EHLO command"); - return false; - } - } - - if(!empty($this->username) && !empty($this->password)) - { - preg_match("#250( |-)AUTH( |=)(.+)$#mi", $data, $matches); - if(!$this->auth($matches[3])) - { - return false; - } - } - return true; - } - else - { - $this->fatal_error("Unable to connect to the mail server with the given details. Reason: {$error_number}: {$error_string}"); - return false; - } - } - - /** - * Authenticate against the SMTP server. - * - * @param string $auth_methods A list of authentication methods supported by the server - * @return boolean True on success - */ - function auth($auth_methods) - { - global $lang, $mybb; - - $auth_methods = explode(" ", trim($auth_methods)); - - if(in_array("LOGIN", $auth_methods)) - { - if(!$this->send_data("AUTH LOGIN", 334)) - { - if($this->code == 503) - { - return true; - } - $this->fatal_error("The SMTP server did not respond correctly to the AUTH LOGIN command"); - return false; - } - - if(!$this->send_data(base64_encode($this->username), '334')) - { - $this->fatal_error("The SMTP server rejected the supplied SMTP username. Reason: ".$this->get_error()); - return false; - } - - if(!$this->send_data(base64_encode($this->password), '235')) - { - $this->fatal_error("The SMTP server rejected the supplied SMTP password. Reason: ".$this->get_error()); - return false; - } - } - else if(in_array("PLAIN", $auth_methods)) - { - if(!$this->send_data("AUTH PLAIN", '334')) - { - if($this->code == 503) - { - return true; - } - $this->fatal_error("The SMTP server did not respond correctly to the AUTH PLAIN command"); - return false; - } - $auth = base64_encode(chr(0).$this->username.chr(0).$this->password); - if(!$this->send_data($auth, 235)) - { - $this->fatal_error("The SMTP server rejected the supplied login username and password. Reason: ".$this->get_error()); - return false; - } - } - else - { - $this->fatal_error("The SMTP server does not support any of the AUTH methods that MyBB supports"); - return false; - } - - // Still here, we're authenticated - return true; - } - - /** - * Fetch data from the SMTP server. - * - * @return string The data from the SMTP server - */ - function get_data() - { - $string = ''; - - while((($line = fgets($this->connection, 515)) !== false)) - { - $string .= $line; - if(substr($line, 3, 1) == ' ') - { - break; - } - } - $string = trim($string); - $this->data = $string; - $this->code = substr($this->data, 0, 3); - return $string; - } - - /** - * Check if we're currently connected to an SMTP server - * - * @return boolean true if connected - */ - function connected() - { - if($this->status == 1) - { - return true; - } - return false; - } - - /** - * Send data through to the SMTP server. - * - * @param string $data The data to be sent - * @param int|bool $status_num The response code expected back from the server (if we have one) - * @return boolean True on success - */ - function send_data($data, $status_num = false) - { - if($this->connected()) - { - if(fwrite($this->connection, $data."\r\n")) - { - if($status_num != false) - { - $rec = $this->get_data(); - if($this->check_status($status_num)) - { - return $rec; - } - else - { - $this->set_error($rec); - return false; - } - } - return true; - } - else - { - $this->fatal_error("Unable to send the data to the SMTP server"); - return false; - } - } - return false; - } - - /** - * Checks if the received status code matches the one we expect. - * - * @param int $status_num The status code we expected back from the server - * @return string|bool - */ - function check_status($status_num) - { - if($this->code == $status_num) - { - return $this->data; - } - else - { - return false; - } - } - - /** - * Close the connection to the SMTP server. - */ - function close() - { - if($this->status == 1) - { - $this->send_data('QUIT'); - fclose($this->connection); - $this->status = 0; - } - } - - /** - * Get the last error message response from the SMTP server - * - * @return string The error message response from the SMTP server - */ - function get_error() - { - if(!$this->last_error) - { - $this->last_error = "N/A"; - } - - return $this->last_error; - } - - /** - * Set the last error message response from the SMTP server - * - * @param string $error The error message response - */ - function set_error($error) - { - $this->last_error = $error; - } -} diff --git a/html/forums/inc/mybb_group.php b/html/forums/inc/mybb_group.php deleted file mode 100644 index 41f6c9f..0000000 --- a/html/forums/inc/mybb_group.php +++ /dev/null @@ -1,17 +0,0 @@ -add_hook('admin_config_settings_manage', 'hello_settings'); - $plugins->add_hook('admin_config_settings_change', 'hello_settings'); - $plugins->add_hook('admin_config_settings_start', 'hello_settings'); - // We could hook at 'admin_config_settings_begin' only for simplicity sake. -} -else -{ - // Add our hello_index() function to the index_start hook so when that hook is run our function is executed - $plugins->add_hook('index_start', 'hello_index'); - - // Add our hello_post() function to the postbit hook so it gets executed on every post - $plugins->add_hook('postbit', 'hello_post'); - - // Add our hello_new() function to the misc_start hook so our misc.php?action=hello inserts a new message into the created DB table. - $plugins->add_hook('misc_start', 'hello_new'); -} - -function hello_info() -{ - global $lang; - $lang->load('hello'); - - /** - * Array of information about the plugin. - * name: The name of the plugin - * description: Description of what the plugin does - * website: The website the plugin is maintained at (Optional) - * author: The name of the author of the plugin - * authorsite: The URL to the website of the author (Optional) - * version: The version number of the plugin - * compatibility: A CSV list of MyBB versions supported. Ex, '121,123', '12*'. Wildcards supported. - * codename: An unique code name to be used by updated from the official MyBB Mods community. - */ - return array( - 'name' => 'Hello World!', - 'description' => $lang->hello_desc, - 'website' => 'https://mybb.com', - 'author' => 'MyBB Group', - 'authorsite' => 'https://mybb.com', - 'version' => '2.0', - 'compatibility' => '18*', - 'codename' => 'hello' - ); -} - -/* - * _activate(): - * Called whenever a plugin is activated via the Admin CP. This should essentially make a plugin - * 'visible' by adding templates/template changes, language changes etc. -*/ -function hello_activate() -{ - global $db, $lang; - $lang->load('hello'); - - // Add a new template (hello_index) to our global templates (sid = -1) - $templatearray = array( - 'index' => '
    - - - - - - - - - - - - - - -
    - {$lang->hello} -
    -
    - - - {$lang->hello_add_message}: -
    -
    - {$messages} -
    -
    ', - 'post' => '

    {$lang->hello}:
    {$messages}', - 'message' => '
    - {$message}' - ); - - $group = array( - 'prefix' => $db->escape_string('hello'), - 'title' => $db->escape_string('Hello World!') - ); - - // Update or create template group: - $query = $db->simple_select('templategroups', 'prefix', "prefix='{$group['prefix']}'"); - - if($db->fetch_field($query, 'prefix')) - { - $db->update_query('templategroups', $group, "prefix='{$group['prefix']}'"); - } - else - { - $db->insert_query('templategroups', $group); - } - - // Query already existing templates. - $query = $db->simple_select('templates', 'tid,title,template', "sid=-2 AND (title='{$group['prefix']}' OR title LIKE '{$group['prefix']}=_%' ESCAPE '=')"); - - $templates = $duplicates = array(); - - while($row = $db->fetch_array($query)) - { - $title = $row['title']; - $row['tid'] = (int)$row['tid']; - - if(isset($templates[$title])) - { - // PluginLibrary had a bug that caused duplicated templates. - $duplicates[] = $row['tid']; - $templates[$title]['template'] = false; // force update later - } - else - { - $templates[$title] = $row; - } - } - - // Delete duplicated master templates, if they exist. - if($duplicates) - { - $db->delete_query('templates', 'tid IN ('.implode(",", $duplicates).')'); - } - - // Update or create templates. - foreach($templatearray as $name => $code) - { - if(strlen($name)) - { - $name = "hello_{$name}"; - } - else - { - $name = "hello"; - } - - $template = array( - 'title' => $db->escape_string($name), - 'template' => $db->escape_string($code), - 'version' => 1, - 'sid' => -2, - 'dateline' => TIME_NOW - ); - - // Update - if(isset($templates[$name])) - { - if($templates[$name]['template'] !== $code) - { - // Update version for custom templates if present - $db->update_query('templates', array('version' => 0), "title='{$template['title']}'"); - - // Update master template - $db->update_query('templates', $template, "tid={$templates[$name]['tid']}"); - } - } - // Create - else - { - $db->insert_query('templates', $template); - } - - // Remove this template from the earlier queried list. - unset($templates[$name]); - } - - // Remove no longer used templates. - foreach($templates as $name => $row) - { - $db->delete_query('templates', "title='{$db->escape_string($name)}'"); - } - - // Settings group array details - $group = array( - 'name' => 'hello', - 'title' => $db->escape_string($lang->setting_group_hello), - 'description' => $db->escape_string($lang->setting_group_hello_desc), - 'isdefault' => 0 - ); - - // Check if the group already exists. - $query = $db->simple_select('settinggroups', 'gid', "name='hello'"); - - if($gid = (int)$db->fetch_field($query, 'gid')) - { - // We already have a group. Update title and description. - $db->update_query('settinggroups', $group, "gid='{$gid}'"); - } - else - { - // We don't have a group. Create one with proper disporder. - $query = $db->simple_select('settinggroups', 'MAX(disporder) AS disporder'); - $disporder = (int)$db->fetch_field($query, 'disporder'); - - $group['disporder'] = ++$disporder; - - $gid = (int)$db->insert_query('settinggroups', $group); - } - - // Deprecate all the old entries. - $db->update_query('settings', array('description' => 'HELLODELETEMARKER'), "gid='{$gid}'"); - - // add settings - $settings = array( - 'display1' => array( - 'optionscode' => 'yesno', - 'value' => 1 - ), - 'display2' => array( - 'optionscode' => 'yesno', - 'value' => 1 - )); - - $disporder = 0; - - // Create and/or update settings. - foreach($settings as $key => $setting) - { - // Prefix all keys with group name. - $key = "hello_{$key}"; - - $lang_var_title = "setting_{$key}"; - $lang_var_description = "setting_{$key}_desc"; - - $setting['title'] = $lang->{$lang_var_title}; - $setting['description'] = $lang->{$lang_var_description}; - - // Filter valid entries. - $setting = array_intersect_key($setting, - array( - 'title' => 0, - 'description' => 0, - 'optionscode' => 0, - 'value' => 0, - )); - - // Escape input values. - $setting = array_map(array($db, 'escape_string'), $setting); - - // Add missing default values. - ++$disporder; - - $setting = array_merge( - array('description' => '', - 'optionscode' => 'yesno', - 'value' => 0, - 'disporder' => $disporder), - $setting); - - $setting['name'] = $db->escape_string($key); - $setting['gid'] = $gid; - - // Check if the setting already exists. - $query = $db->simple_select('settings', 'sid', "gid='{$gid}' AND name='{$setting['name']}'"); - - if($sid = $db->fetch_field($query, 'sid')) - { - // It exists, update it, but keep value intact. - unset($setting['value']); - $db->update_query('settings', $setting, "sid='{$sid}'"); - } - else - { - // It doesn't exist, create it. - $db->insert_query('settings', $setting); - // Maybe use $db->insert_query_multiple somehow - } - } - - // Delete deprecated entries. - $db->delete_query('settings', "gid='{$gid}' AND description='HELLODELETEMARKER'"); - - // This is required so it updates the settings.php file as well and not only the database - they must be synchronized! - rebuild_settings(); - - // Include this file because it is where find_replace_templatesets is defined - require_once MYBB_ROOT.'inc/adminfunctions_templates.php'; - - // Edit the index template and add our variable to above {$forums} - find_replace_templatesets('index', '#'.preg_quote('{$forums}').'#', "{\$hello}\n{\$forums}"); -} - -/* - * _deactivate(): - * Called whenever a plugin is deactivated. This should essentially 'hide' the plugin from view - * by removing templates/template changes etc. It should not, however, remove any information - * such as tables, fields etc - that should be handled by an _uninstall routine. When a plugin is - * uninstalled, this routine will also be called before _uninstall() if the plugin is active. -*/ -function hello_deactivate() -{ - require_once MYBB_ROOT.'inc/adminfunctions_templates.php'; - - // remove template edits - find_replace_templatesets('index', '#'.preg_quote('{$hello}').'#', ''); -} - -/* - * _install(): - * Called whenever a plugin is installed by clicking the 'Install' button in the plugin manager. - * If no install routine exists, the install button is not shown and it assumed any work will be - * performed in the _activate() routine. -*/ -function hello_install() -{ - global $db; - - // Create our table collation - $collation = $db->build_create_table_collation(); - - // Create table if it doesn't exist already - if(!$db->table_exists('hello_messages')) - { - switch($db->type) - { - case "pgsql": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."hello_messages ( - mid serial, - message varchar(100) NOT NULL default '', - PRIMARY KEY (mid) - );"); - break; - case "sqlite": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."hello_messages ( - mid INTEGER PRIMARY KEY, - message varchar(100) NOT NULL default '' - );"); - break; - default: - $db->write_query("CREATE TABLE ".TABLE_PREFIX."hello_messages ( - mid int unsigned NOT NULL auto_increment, - message varchar(100) NOT NULL default '', - PRIMARY KEY (mid) - ) ENGINE=MyISAM{$collation};"); - break; - } - } -} - -/* - * _is_installed(): - * Called on the plugin management page to establish if a plugin is already installed or not. - * This should return TRUE if the plugin is installed (by checking tables, fields etc) or FALSE - * if the plugin is not installed. -*/ -function hello_is_installed() -{ - global $db; - - // If the table exists then it means the plugin is installed because we only drop it on uninstallation - return $db->table_exists('hello_messages'); -} - -/* - * _uninstall(): - * Called whenever a plugin is to be uninstalled. This should remove ALL traces of the plugin - * from the installation (tables etc). If it does not exist, uninstall button is not shown. -*/ -function hello_uninstall() -{ - global $db, $mybb; - - if($mybb->request_method != 'post') - { - global $page, $lang; - $lang->load('hello'); - - $page->output_confirm_action('index.php?module=config-plugins&action=deactivate&uninstall=1&plugin=hello', $lang->hello_uninstall_message, $lang->hello_uninstall); - } - - // Delete template groups. - $db->delete_query('templategroups', "prefix='hello'"); - - // Delete templates belonging to template groups. - $db->delete_query('templates', "title='hello' OR title LIKE 'hello_%'"); - - // Delete settings group - $db->delete_query('settinggroups', "name='hello'"); - - // Remove the settings - $db->delete_query('settings', "name IN ('hello_display1','hello_display2')"); - - // This is required so it updates the settings.php file as well and not only the database - they must be synchronized! - rebuild_settings(); - - // Drop tables if desired - if(!isset($mybb->input['no'])) - { - $db->drop_table('hello_messages'); - } -} - -/* - * Loads the settings language strings. -*/ -function hello_settings() -{ - global $lang; - - // Load our language file - $lang->load('hello'); -} - -/* - * Displays the list of messages on index and a form to submit new messages - depending on the setting of course. -*/ -function hello_index() -{ - global $mybb; - - // Only run this function is the setting is set to yes - if($mybb->settings['hello_display1'] == 0) - { - return; - } - - global $db, $lang, $templates, $hello, $theme; - - // Load our language file - $lang->load('hello'); - - // Retreive all messages from the database - $messages = ''; - $query = $db->simple_select('hello_messages', 'message', '', array('order_by' => 'mid', 'order_dir' => 'DESC')); - while($message = $db->fetch_field($query, 'message')) - { - // htmlspecialchars_uni is similar to PHP's htmlspecialchars but allows unicode - $message = htmlspecialchars_uni($message); - $messages .= eval($templates->render('hello_message')); - } - - // If no messages were found, display that notice. - if(empty($messages)) - { - $message = $lang->hello_empty; - $messages = eval($templates->render('hello_message')); - } - - // Set $hello as our template and use eval() to do it so we can have our variables parsed - #eval('$hello = "'.$templates->get('hello_index').'";'); - $hello = eval($templates->render('hello_index')); -} - -/* - * Displays the list of messages under every post - depending on the setting. - * @param $post Array containing information about the current post. Note: must be received by reference otherwise our changes are not preserved. -*/ -function hello_post(&$post) -{ - global $settings; - - // Only run this function is the setting is set to yes - if($settings['hello_display2'] == 0) - { - return; - } - - global $lang, $templates; - - // Load our language file - if(!isset($lang->hello)) - { - $lang->load('hello'); - } - - static $messages; - - // Only retreive messages from the database if they were not retreived already - if(!isset($messages)) - { - global $db; - - // Retreive all messages from the database - $messages = ''; - $query = $db->simple_select('hello_messages', 'message', '', array('order_by' => 'mid', 'order_dir' => 'DESC')); - while($message = $db->fetch_field($query, 'message')) - { - // htmlspecialchars_uni is similar to PHP's htmlspecialchars but allows unicode - $message = htmlspecialchars_uni($message); - $messages .= eval($templates->render('hello_message')); - } - - // If no messages were found, display that notice. - if(empty($messages)) - { - $message = $lang->hello_empty; - $messages = eval($templates->render('hello_message')); - } - } - - // Alter the current post's message - $post['message'] .= eval($templates->render('hello_post')); -} - -/* -* This is where new messages get submitted. -*/ -function hello_new() -{ - global $mybb; - - // If we're not running the 'hello' action as specified in our form, get out of there. - if($mybb->get_input('action') != 'hello') - { - return; - } - - // Only accept POST - if($mybb->request_method != 'post') - { - error_no_permission(); - } - - global $lang; - - // Correct post key? This is important to prevent CSRF - verify_post_check($mybb->get_input('my_post_key')); - - // Load our language file - $lang->load('hello'); - - $message = trim($mybb->get_input('message')); - - // Message cannot be empty - if(!$message || my_strlen($message) > 100) - { - error($lang->hello_message_empty); - } - - global $db; - - // Escape input data - $message = $db->escape_string($message); - - // Insert into database - $db->insert_query('hello_messages', array('message' => $message)); - - // Redirect to index.php with a message - redirect('index.php', $lang->hello_done); -} diff --git a/html/forums/inc/plugins/index.html b/html/forums/inc/plugins/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/plugins/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/settings.php b/html/forums/inc/settings.php deleted file mode 100644 index e69de29..0000000 diff --git a/html/forums/inc/tasks/backupdb.php b/html/forums/inc/tasks/backupdb.php deleted file mode 100644 index bd1aabc..0000000 --- a/html/forums/inc/tasks/backupdb.php +++ /dev/null @@ -1,147 +0,0 @@ -task_backup_cannot_write_backup); - } - else - { - $db->set_table_prefix(''); - - $file = MYBB_ADMIN_DIR.'backups/backup_'.date("_Ymd_His_").random_str(16); - - if(function_exists('gzopen')) - { - $fp = gzopen($file.'.incomplete.sql.gz', 'w9'); - } - else - { - $fp = fopen($file.'.incomplete.sql', 'w'); - } - - $tables = $db->list_tables($config['database']['database'], $config['database']['table_prefix']); - - $time = date('dS F Y \a\t H:i', TIME_NOW); - $contents = "-- MyBB Database Backup\n-- Generated: {$time}\n-- -------------------------------------\n\n"; - - if(is_object($plugins)) - { - $args = array( - 'task' => &$task, - 'tables' => &$tables, - ); - $plugins->run_hooks('task_backupdb', $args); - } - - foreach($tables as $table) - { - $field_list = array(); - $fields_array = $db->show_fields_from($table); - foreach($fields_array as $field) - { - $field_list[] = $field['Field']; - } - - $fields = "`".implode("`,`", $field_list)."`"; - - $structure = $db->show_create_table($table).";\n"; - $contents .= $structure; - clear_overflow($fp, $contents); - - if($db->engine == 'mysqli') - { - $query = mysqli_query($db->read_link, "SELECT * FROM {$db->table_prefix}{$table}", MYSQLI_USE_RESULT); - } - else - { - $query = $db->simple_select($table); - } - - while($row = $db->fetch_array($query)) - { - $insert = "INSERT INTO {$table} ($fields) VALUES ("; - $comma = ''; - foreach($field_list as $field) - { - if(!isset($row[$field]) || is_null($row[$field])) - { - $insert .= $comma."NULL"; - } - else if($db->engine == 'mysqli') - { - $insert .= $comma."'".mysqli_real_escape_string($db->read_link, $row[$field])."'"; - } - else - { - $insert .= $comma."'".$db->escape_string($row[$field])."'"; - } - $comma = ','; - } - $insert .= ");\n"; - $contents .= $insert; - clear_overflow($fp, $contents); - } - $db->free_result($query); - } - - $db->set_table_prefix(TABLE_PREFIX); - - if(function_exists('gzopen')) - { - gzwrite($fp, $contents); - gzclose($fp); - rename($file.'.incomplete.sql.gz', $file.'.sql.gz'); - } - else - { - fwrite($fp, $contents); - fclose($fp); - rename($file.'.incomplete.sql', $file.'.sql'); - } - - add_task_log($task, $lang->task_backup_ran); - } -} - -// Allows us to refresh cache to prevent over flowing -function clear_overflow($fp, &$contents) -{ - global $mybb; - - if(function_exists('gzopen')) - { - gzwrite($fp, $contents); - } - else - { - fwrite($fp, $contents); - } - - $contents = ''; -} diff --git a/html/forums/inc/tasks/checktables.php b/html/forums/inc/tasks/checktables.php deleted file mode 100644 index 5f683ce..0000000 --- a/html/forums/inc/tasks/checktables.php +++ /dev/null @@ -1,88 +0,0 @@ -type == "sqlite") - { - return; - } - - @set_time_limit(0); - - $ok = array( - "The storage engine for the table doesn't support check", - "Table is already up to date", - "OK" - ); - - $comma = ""; - $tables_list = ""; - $repaired = ""; - $setting_done = false; - - $tables = $db->list_tables($mybb->config['database']['database'], $mybb->config['database']['table_prefix']); - foreach($tables as $key => $table) - { - $tables_list .= "{$comma}{$table} "; - $comma = ","; - } - - if($tables_list) - { - $query = $db->query("CHECK TABLE {$tables_list}CHANGED;"); - while($table = $db->fetch_array($query)) - { - if(!in_array($table['Msg_text'], $ok)) - { - if($table['Table'] != $mybb->config['database']['database'].".".TABLE_PREFIX."settings" && $setting_done != true) - { - $boardclosed = $mybb->settings['boardclosed']; - $boardclosed_reason = $mybb->settings['boardclosed_reason']; - - $db->update_query("settings", array('value' => 1), "name='boardclosed'", 1); - $db->update_query("settings", array('value' => $db->escape_string($lang->error_database_repair)), "name='boardclosed_reason'", 1); - rebuild_settings(); - - $setting_done = true; - } - - $db->query("REPAIR TABLE {$table['Table']}"); - $repaired[] = $table['Table']; - } - } - - if($setting_done == true) - { - $db->update_query("settings", array('value' => (int)$boardclosed), "name='boardclosed'", 1); - $db->update_query("settings", array('value' => $db->escape_string($boardclosed_reason)), "name='boardclosed_reason'", 1); - - rebuild_settings(); - } - - } - - if(is_object($plugins)) - { - $plugins->run_hooks('task_checktables', $task); - } - - if(!empty($repaired)) - { - add_task_log($task, $lang->sprintf($lang->task_checktables_ran_found, implode(', ', $repaired))); - } - else - { - add_task_log($task, $lang->task_checktables_ran); - } -} diff --git a/html/forums/inc/tasks/dailycleanup.php b/html/forums/inc/tasks/dailycleanup.php deleted file mode 100644 index 5a7a89b..0000000 --- a/html/forums/inc/tasks/dailycleanup.php +++ /dev/null @@ -1,92 +0,0 @@ - TIME_NOW-60*60*24, - 'threadreadcut' => TIME_NOW-(((int)$mybb->settings['threadreadcut'])*60*60*24), - 'privatemessages' => TIME_NOW-(60*60*24*7), - 'deleteinvite' => TIME_NOW-(((int)$mybb->settings['deleteinvites'])*60*60*24), - 'stoppmtracking' => TIME_NOW-(60*60*24*180) - ); - - if(is_object($plugins)) - { - $args = array( - 'task' => &$task, - 'time' => &$time - ); - $plugins->run_hooks('task_dailycleanup_start', $args); - } - - // Clear out sessions older than 24h - $db->delete_query("sessions", "time < '".(int)$time['sessionstime']."'"); - - // Delete old read topics - if($mybb->settings['threadreadcut'] > 0) - { - $db->delete_query("threadsread", "dateline < '".(int)$time['threadreadcut']."'"); - $db->delete_query("forumsread", "dateline < '".(int)$time['threadreadcut']."'"); - } - - // Check PMs moved to trash over a week ago & delete them - $query = $db->simple_select("privatemessages", "pmid, uid, folder", "deletetime<='".(int)$time['privatemessages']."' AND folder='4'"); - while($pm = $db->fetch_array($query)) - { - $user_update[$pm['uid']] = 1; - $pm_update[] = $pm['pmid']; - } - - // Delete old group invites - if($mybb->settings['deleteinvites'] > 0) - { - $db->delete_query("joinrequests", "dateline < '".(int)$time['deleteinvite']."' AND invite='1'"); - } - - // Stop tracking read PMs after 6 months - $sql_array = array( - "receipt" => 0 - ); - $db->update_query("privatemessages", $sql_array, "receipt='2' AND folder!='3' AND status!='0' AND readtime < '".(int)$time['stoppmtracking']."'"); - - if(is_object($plugins)) - { - $args = array( - 'user_update' => &$user_update, - 'pm_update' => &$pm_update - ); - $plugins->run_hooks('task_dailycleanup_end', $args); - } - - if(!empty($pm_update)) - { - $db->delete_query("privatemessages", "pmid IN(".implode(',', $pm_update).")"); - } - - if(!empty($user_update)) - { - foreach($user_update as $uid => $data) - { - update_pm_count($uid); - } - } - - $cache->update_most_replied_threads(); - $cache->update_most_viewed_threads(); - $cache->update_birthdays(); - $cache->update_forumsdisplay(); - - add_task_log($task, $lang->task_dailycleanup_ran); -} diff --git a/html/forums/inc/tasks/delayedmoderation.php b/html/forums/inc/tasks/delayedmoderation.php deleted file mode 100644 index 2d30652..0000000 --- a/html/forums/inc/tasks/delayedmoderation.php +++ /dev/null @@ -1,259 +0,0 @@ -simple_select("delayedmoderation", "*", "delaydateline <= '".TIME_NOW."'"); - while($delayedmoderation = $db->fetch_array($query)) - { - if(is_object($plugins)) - { - $args = array( - 'task' => &$task, - 'delayedmoderation' => &$delayedmoderation, - ); - $plugins->run_hooks('task_delayedmoderation', $args); - } - - $tids = explode(',', $delayedmoderation['tids']); - $input = my_unserialize($delayedmoderation['inputs']); - - if(my_strpos($delayedmoderation['type'], "modtool") !== false) - { - list(, $custom_id) = explode('_', $delayedmoderation['type'], 2); - $custommod->execute($custom_id, $tids); - } - else - { - switch($delayedmoderation['type']) - { - case "openclosethread": - $closed_tids = $open_tids = array(); - $query2 = $db->simple_select("threads", "tid,closed", "tid IN({$delayedmoderation['tids']})"); - while($thread = $db->fetch_array($query2)) - { - if($thread['closed'] == 1) - { - $closed_tids[] = $thread['tid']; - } - else - { - $open_tids[] = $thread['tid']; - } - } - - if(!empty($closed_tids)) - { - $moderation->open_threads($closed_tids); - } - - if(!empty($open_tids)) - { - $moderation->close_threads($open_tids); - } - break; - case "deletethread": - foreach($tids as $tid) - { - $moderation->delete_thread($tid); - } - break; - case "move": - foreach($tids as $tid) - { - $moderation->move_thread($tid, $input['new_forum']); - } - break; - case "stick": - $unstuck_tids = $stuck_tids = array(); - $query2 = $db->simple_select("threads", "tid,sticky", "tid IN({$delayedmoderation['tids']})"); - while($thread = $db->fetch_array($query2)) - { - if($thread['sticky'] == 1) - { - $stuck_tids[] = $thread['tid']; - } - else - { - $unstuck_tids[] = $thread['tid']; - } - } - - if(!empty($stuck_tids)) - { - $moderation->unstick_threads($stuck_tids); - } - - if(!empty($unstuck_tids)) - { - $moderation->stick_threads($unstuck_tids); - } - break; - case "merge": - // $delayedmoderation['tids'] should be a single tid - if(count($tids) != 1) - { - continue; - } - - // explode at # sign in a url (indicates a name reference) and reassign to the url - $realurl = explode("#", $input['threadurl']); - $input['threadurl'] = $realurl[0]; - - // Are we using an SEO URL? - if(substr($input['threadurl'], -4) == "html") - { - // Get thread to merge's tid the SEO way - preg_match("#thread-([0-9]+)?#i", $input['threadurl'], $threadmatch); - preg_match("#post-([0-9]+)?#i", $input['threadurl'], $postmatch); - - if($threadmatch[1]) - { - $parameters['tid'] = $threadmatch[1]; - } - - if($postmatch[1]) - { - $parameters['pid'] = $postmatch[1]; - } - } - else - { - // Get thread to merge's tid the normal way - $splitloc = explode(".php", $input['threadurl']); - $temp = explode("&", my_substr($splitloc[1], 1)); - - if(!empty($temp)) - { - for($i = 0; $i < count($temp); $i++) - { - $temp2 = explode("=", $temp[$i], 2); - $parameters[$temp2[0]] = $temp2[1]; - } - } - else - { - $temp2 = explode("=", $splitloc[1], 2); - $parameters[$temp2[0]] = $temp2[1]; - } - } - - if($parameters['pid'] && !$parameters['tid']) - { - $post = get_post($parameters['pid']); - $mergetid = $post['tid']; - } - else if($parameters['tid']) - { - $mergetid = $parameters['tid']; - } - - $mergetid = (int)$mergetid; - $mergethread = get_thread($mergetid); - - if(!$mergethread['tid']) - { - continue; - } - - if($mergetid == $delayedmoderation['tids']) - { - // sanity check - continue; - } - - if($input['subject']) - { - $subject = $input['subject']; - } - else - { - $query = $db->simple_select("threads", "subject", "tid='{$delayedmoderation['tids']}'"); - $subject = $db->fetch_field($query, "subject"); - } - - $moderation->merge_threads($mergetid, $delayedmoderation['tids'], $subject); - break; - case "removeredirects": - foreach($tids as $tid) - { - $moderation->remove_redirects($tid); - } - break; - case "removesubscriptions": - $moderation->remove_thread_subscriptions($tids, true); - break; - case "approveunapprovethread": - $approved_tids = $unapproved_tids = array(); - $query2 = $db->simple_select("threads", "tid,visible", "tid IN({$delayedmoderation['tids']})"); - while($thread = $db->fetch_array($query2)) - { - if($thread['visible'] == 1) - { - $approved_tids[] = $thread['tid']; - } - else - { - $unapproved_tids[] = $thread['tid']; - } - } - - if(!empty($approved_tids)) - { - $moderation->unapprove_threads($approved_tids); - } - - if(!empty($unapproved_tids)) - { - $moderation->approve_threads($unapproved_tids); - } - break; - case "softdeleterestorethread": - $delete_tids = $restore_tids = array(); - $query2 = $db->simple_select("threads", "tid,visible", "tid IN({$delayedmoderation['tids']})"); - while($thread = $db->fetch_array($query2)) - { - if($thread['visible'] == -1) - { - $restore_tids[] = $thread['tid']; - } - else - { - $delete_tids[] = $thread['tid']; - } - } - - if(!empty($restore_tids)) - { - $moderation->restore_threads($restore_tids); - } - - if(!empty($delete_tids)) - { - $moderation->soft_delete_threads($delete_tids); - } - break; - } - } - - $db->delete_query("delayedmoderation", "did='{$delayedmoderation['did']}'"); - } - - add_task_log($task, $lang->task_delayedmoderation_ran); -} diff --git a/html/forums/inc/tasks/hourlycleanup.php b/html/forums/inc/tasks/hourlycleanup.php deleted file mode 100644 index 464d236..0000000 --- a/html/forums/inc/tasks/hourlycleanup.php +++ /dev/null @@ -1,53 +0,0 @@ - TIME_NOW, - 'searchlog' => TIME_NOW-(60*60*24), - 'captcha' => TIME_NOW-(60*60*24), - 'question' => TIME_NOW-(60*60*24) - ); - - if(is_object($plugins)) - { - $args = array( - 'task' => &$task, - 'time' => &$time - ); - $plugins->run_hooks('task_hourlycleanup', $args); - } - - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation; - - // Delete moved threads with time limits - $query = $db->simple_select('threads', 'tid', "deletetime != '0' AND deletetime < '".(int)$time['threads']."'"); - while($tid = $db->fetch_field($query, 'tid')) - { - $moderation->delete_thread($tid); - } - - // Delete old searches - $db->delete_query("searchlog", "dateline < '".(int)$time['searchlog']."'"); - - // Delete old captcha images - $cut = TIME_NOW-(60*60*24*7); - $db->delete_query("captcha", "dateline < '".(int)$time['captcha']."'"); - - // Delete old registration questions - $cut = TIME_NOW-(60*60*24*7); - $db->delete_query("questionsessions", "dateline < '".(int)$time['question']."'"); - - add_task_log($task, $lang->task_hourlycleanup_ran); -} diff --git a/html/forums/inc/tasks/index.html b/html/forums/inc/tasks/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/inc/tasks/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/inc/tasks/logcleanup.php b/html/forums/inc/tasks/logcleanup.php deleted file mode 100644 index b7f0944..0000000 --- a/html/forums/inc/tasks/logcleanup.php +++ /dev/null @@ -1,63 +0,0 @@ -config['log_pruning']['admin_logs'] > 0) - { - $cut = TIME_NOW-60*60*24*$mybb->config['log_pruning']['admin_logs']; - $db->delete_query("adminlog", "dateline<'{$cut}'"); - } - - // Clear out old moderator logs - if($mybb->config['log_pruning']['mod_logs'] > 0) - { - $cut = TIME_NOW-60*60*24*$mybb->config['log_pruning']['mod_logs']; - $db->delete_query("moderatorlog", "dateline<'{$cut}'"); - } - - // Clear out old task logs - if($mybb->config['log_pruning']['task_logs'] > 0) - { - $cut = TIME_NOW-60*60*24*$mybb->config['log_pruning']['task_logs']; - $db->delete_query("tasklog", "dateline<'{$cut}'"); - } - - // Clear out old mail error logs - if($mybb->config['log_pruning']['mail_logs'] > 0) - { - $cut = TIME_NOW-60*60*24*$mybb->config['log_pruning']['mail_logs']; - $db->delete_query("mailerrors", "dateline<'{$cut}'"); - } - - // Clear out old user mail logs - if($mybb->config['log_pruning']['user_mail_logs'] > 0) - { - $cut = TIME_NOW-60*60*24*$mybb->config['log_pruning']['user_mail_logs']; - $db->delete_query("maillogs", "dateline<'{$cut}'"); - } - - // Clear out old promotion logs - if($mybb->config['log_pruning']['promotion_logs'] > 0) - { - $cut = TIME_NOW-60*60*24*$mybb->config['log_pruning']['promotion_logs']; - $db->delete_query("promotionlogs", "dateline<'{$cut}'"); - } - - if(is_object($plugins)) - { - $plugins->run_hooks('task_logcleanup', $task); - } - - add_task_log($task, $lang->task_logcleanup_ran); -} diff --git a/html/forums/inc/tasks/massmail.php b/html/forums/inc/tasks/massmail.php deleted file mode 100644 index 33e8f23..0000000 --- a/html/forums/inc/tasks/massmail.php +++ /dev/null @@ -1,150 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -require_once MYBB_ROOT."/inc/functions_massmail.php"; -require_once MYBB_ROOT."inc/datahandlers/pm.php"; - -function task_massmail($task) -{ - global $db, $mybb, $lang, $plugins; - - $query = $db->simple_select("massemails", "*", "senddate <= '".TIME_NOW."' AND status IN (1,2)"); - while($mass_email = $db->fetch_array($query)) - { - if(is_object($plugins)) - { - $args = array( - 'task' => &$task, - 'mass_email' => &$mass_email - ); - $plugins->run_hooks('task_massmail', $args); - } - - if($mass_email['status'] == 1) - { - $db->update_query("massemails", array('status' => 2), "mid='{$mass_email['mid']}'"); - } - - $sentcount = 0; - - if(!$mass_email['perpage']) - { - $mass_email['perpage'] = 50; - } - - if(strpos($mass_email['htmlmessage'], '
    ') === false && strpos($mass_email['htmlmessage'], '
    ') === false) - { - $mass_email['htmlmessage'] = nl2br($mass_email['htmlmessage']); - } - - $mass_email['orig_message'] = $mass_email['message']; - $mass_email['orig_htmlmessage'] = $mass_email['htmlmessage']; - - // Need to perform the search to fetch the number of users we're emailing - $member_query = build_mass_mail_query(my_unserialize($mass_email['conditions'])); - - $count_query = $db->simple_select("users u", "COUNT(uid) AS num", $member_query); - $mass_email['totalcount'] = $db->fetch_field($count_query, "num"); - - $query2 = $db->simple_select("users u", "u.uid, u.language, u.pmnotify, u.lastactive, u.username, u.email", $member_query, array('limit_start' => $mass_email['sentcount'], 'limit' => $mass_email['perpage'], 'order_by' => 'u.uid', 'order_dir' => 'asc')); - while($user = $db->fetch_array($query2)) - { - $replacement_fields = array( - "{uid}" => $user['uid'], - "{username}" => $user['username'], - "{email}" => $user['email'], - "{bbname}" => $mybb->settings['bbname'], - "{bburl}" => $mybb->settings['bburl'], - "[".$lang->massmail_username."]" => $user['username'], - "[".$lang->email_addr."]" => $user['email'], - "[".$lang->board_name."]" => $mybb->settings['bbname'], - "[".$lang->board_url."]" => $mybb->settings['bburl'] - ); - - foreach($replacement_fields as $find => $replace) - { - $mass_email['message'] = str_replace($find, $replace, $mass_email['message']); - $mass_email['htmlmessage'] = str_replace($find, $replace, $mass_email['htmlmessage']); - } - - // Private Message - if($mass_email['type'] == 1) - { - $pm_handler = new PMDataHandler(); - $pm_handler->admin_override = true; - - $pm = array( - "subject" => $mass_email['subject'], - "message" => $mass_email['message'], - "fromid" => $mass_email['uid'], - "options" => array("savecopy" => 0), - ); - - $pm['to'] = explode(",", $user['username']); - $pm_handler->set_data($pm); - if(!$pm_handler->validate_pm()) - { - $friendly_errors = implode('\n', $pm_handler->get_friendly_errors()); - add_task_log($task, $lang->sprintf($lang->task_massmail_ran_errors, htmlspecialchars_uni($user['username']), $friendly_errors)); - $friendly_errors = ""; - } - else - { - $pm_handler->insert_pm(); - } - } - // Normal Email - else - { - switch($mass_email['format']) - { - case 2: - $format = "both"; - $text_message = $mass_email['message']; - $mass_email['message'] = $mass_email['htmlmessage']; - break; - case 1: - $format = "html"; - $text_message = ""; - $mass_email['message'] = $mass_email['htmlmessage']; - break; - default: - $format = "text"; - $text_message = ""; - } - my_mail($user['email'], $mass_email['subject'], $mass_email['message'], "", "", "", false, $format, $text_message); - } - ++$sentcount; - - $mass_email['message'] = $mass_email['orig_message']; - $mass_email['htmlmessage'] = $mass_email['orig_htmlmessage']; - } - - $update_array = array(); - - $update_array['sentcount'] = $mass_email['sentcount'] + $sentcount; - $update_array['totalcount'] = $mass_email['totalcount']; - - if($update_array['sentcount'] >= $mass_email['totalcount']) - { - $update_array['status'] = 3; - } - - $db->update_query("massemails", $update_array, "mid='{$mass_email['mid']}'"); - } - - add_task_log($task, $lang->task_massmail_ran); -} diff --git a/html/forums/inc/tasks/promotions.php b/html/forums/inc/tasks/promotions.php deleted file mode 100644 index 6210e13..0000000 --- a/html/forums/inc/tasks/promotions.php +++ /dev/null @@ -1,255 +0,0 @@ -read("usergroups"); - // Iterate through all our promotions - $query = $db->simple_select("promotions", "*", "enabled = '1'"); - while($promotion = $db->fetch_array($query)) - { - // Does the destination usergroup even exist?? If it doesn't and it moves a user to it, the user will get PHP errors. - if(!array_key_exists($promotion['newusergroup'], $usergroups)) - { - // Instead of just skipping this promotion, disable it to stop it even being selected when this task is run. - $update = array( - "enabled" => 0 - ); - $db->update_query("promotions", $update, "pid = '" . (int)$promotion['pid'] . "'"); - continue; - } - - $and = ""; - $sql_where = ""; - - // Based on the promotion generate criteria for user selection - $requirements = explode(',', $promotion['requirements']); - if(in_array('postcount', $requirements) && (int)$promotion['posts'] >= 0 && !empty($promotion['posttype'])) - { - $sql_where .= "{$and}postnum {$promotion['posttype']} '{$promotion['posts']}'"; - - $and = " AND "; - } - - if(in_array('threadcount', $requirements) && (int)$promotion['threads'] >= 0 && !empty($promotion['threadtype'])) - { - $sql_where .= "{$and}threadnum {$promotion['threadtype']} '{$promotion['threads']}'"; - - $and = " AND "; - } - - if(in_array('reputation', $requirements) && !empty($promotion['reputationtype'])) - { - $sql_where .= "{$and}reputation {$promotion['reputationtype']} '{$promotion['reputations']}'"; - - $and = " AND "; - } - - if(in_array('referrals', $requirements) && (int)$promotion['referrals'] >= 0 && !empty($promotion['referralstype'])) - { - $sql_where .= "{$and}referrals {$promotion['referralstype']} '{$promotion['referrals']}'"; - - $and = " AND "; - } - - if(in_array('warnings', $requirements) && (int)$promotion['warnings'] >= 0 && !empty($promotion['warningstype'])) - { - $sql_where .= "{$and}warningpoints {$promotion['warningstype']} '{$promotion['warnings']}'"; - - $and = " AND "; - } - - if(in_array('timeregistered', $requirements) && (int)$promotion['registered'] > 0 && !empty($promotion['registeredtype'])) - { - switch($promotion['registeredtype']) - { - case "hours": - $regdate = $promotion['registered']*60*60; - break; - case "days": - $regdate = $promotion['registered']*60*60*24; - break; - case "weeks": - $regdate = $promotion['registered']*60*60*24*7; - break; - case "months": - $regdate = $promotion['registered']*60*60*24*30; - break; - case "years": - $regdate = $promotion['registered']*60*60*24*365; - break; - default: - $regdate = $promotion['registered']*60*60*24; - } - $sql_where .= "{$and}regdate <= '".(TIME_NOW-$regdate)."'"; - $and = " AND "; - } - - if(in_array('timeonline', $requirements) && (int)$promotion['online'] > 0 && !empty($promotion['onlinetype'])) - { - switch($promotion['onlinetype']) - { - case "hours": - $timeonline = $promotion['online']*60*60; - break; - case "days": - $timeonline = $promotion['online']*60*60*24; - break; - case "weeks": - $timeonline = $promotion['online']*60*60*24*7; - break; - case "months": - $timeonline = $promotion['online']*60*60*24*30; - break; - case "years": - $timeonline = $promotion['online']*60*60*24*365; - break; - default: - $timeonline = $promotion['online']*60*60*24; - } - $sql_where .= "{$and}timeonline <= '".(TIME_NOW-$timeonline)."'"; - $and = " AND "; - } - - if(!empty($promotion['originalusergroup']) && $promotion['originalusergroup'] != '*') - { - $sql_where .= "{$and}usergroup IN ({$promotion['originalusergroup']})"; - - $and = " AND "; - } - - if(!empty($promotion['newusergroup'])) - { - // Skip users that are already in the new group - switch($db->type) - { - case "pgsql": - case "sqlite": - $sql_where .= "{$and}usergroup != '{$promotion['newusergroup']}' AND ','||additionalgroups||',' NOT LIKE '%,{$promotion['newusergroup']},%'"; - break; - default: - $sql_where .= "{$and}usergroup != '{$promotion['newusergroup']}' AND CONCAT(',', additionalgroups, ',') NOT LIKE '%,{$promotion['newusergroup']},%'"; - } - - $and = " AND "; - } - - $uid = array(); - $log_inserts = array(); - - if($promotion['usergrouptype'] == "secondary") - { - $usergroup_select = "additionalgroups"; - } - else - { - $usergroup_select = "usergroup"; - } - - if(is_object($plugins)) - { - $args = array( - 'task' => &$task, - 'promotion' => &$promotion, - 'sql_where' => &$sql_where, - 'and' => &$and, - 'usergroup_select' => &$usergroup_select - ); - $plugins->run_hooks('task_promotions', $args); - } - - $query2 = $db->simple_select("users", "uid,{$usergroup_select}", $sql_where); - - $uids = array(); - while($user = $db->fetch_array($query2)) - { - if(is_super_admin($user['uid'])) - { - // Skip super admins - continue; - } - - // super admin check? - if($usergroup_select == "additionalgroups") - { - $log_inserts[] = array( - 'pid' => $promotion['pid'], - 'uid' => $user['uid'], - 'oldusergroup' => $user['additionalgroups'], - 'newusergroup' => $promotion['newusergroup'], - 'dateline' => TIME_NOW, - 'type' => "secondary", - ); - } - else - { - $log_inserts[] = array( - 'pid' => $promotion['pid'], - 'uid' => $user['uid'], - 'oldusergroup' => $user['usergroup'], - 'newusergroup' => $promotion['newusergroup'], - 'dateline' => TIME_NOW, - 'type' => "primary", - ); - } - - $uids[] = $user['uid']; - - - if($usergroup_select == "additionalgroups") - { - if(join_usergroup($user['uid'], $promotion['newusergroup']) === false) - { - // Did the user already have the additional usergroup? - array_pop($log_inserts); - array_pop($uids); - } - } - - if((count($uids) % 20) == 0) - { - if($usergroup_select == "usergroup") - { - $db->update_query("users", array('usergroup' => $promotion['newusergroup']), "uid IN(".implode(",", $uids).")"); - } - - if(!empty($log_inserts)) - { - $db->insert_query_multiple("promotionlogs", $log_inserts); - } - - $uids = array(); - $log_inserts = array(); - } - } - - if(count($uids) > 0) - { - if($usergroup_select == "usergroup") - { - $db->update_query("users", array('usergroup' => $promotion['newusergroup']), "uid IN(".implode(",", $uids).")"); - } - - if(!empty($log_inserts)) - { - $db->insert_query_multiple("promotionlogs", $log_inserts); - } - - $uids = array(); - $log_inserts = array(); - } - } - - $cache->update_moderators(); - - add_task_log($task, $lang->task_promotions_ran); -} diff --git a/html/forums/inc/tasks/recachestylesheets.php b/html/forums/inc/tasks/recachestylesheets.php deleted file mode 100644 index 8ef1cda..0000000 --- a/html/forums/inc/tasks/recachestylesheets.php +++ /dev/null @@ -1,39 +0,0 @@ -config['admin_dir']."/inc/functions_themes.php")) - { - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php"; - } - else if(file_exists(MYBB_ROOT."admin/inc/functions_themes.php")) - { - require_once MYBB_ROOT."admin/inc/functions_themes.php"; - } - - $query = $db->simple_select('themestylesheets', '*'); - - $num_recached = 0; - - while($stylesheet = $db->fetch_array($query)) - { - if(cache_stylesheet($stylesheet['tid'], $stylesheet['name'], $stylesheet['stylesheet'])) - { - $db->update_query("themestylesheets", array('cachefile' => $db->escape_string($stylesheet['name'])), "sid='{$stylesheet['sid']}'", 1); - ++$num_recached; - } - } - - add_task_log($task, $lang->sprintf($lang->task_recachestylesheets_ran, $num_recached)); -} - diff --git a/html/forums/inc/tasks/threadviews.php b/html/forums/inc/tasks/threadviews.php deleted file mode 100644 index 53ee881..0000000 --- a/html/forums/inc/tasks/threadviews.php +++ /dev/null @@ -1,35 +0,0 @@ -settings['delayedthreadviews'] != 1) - { - return; - } - - // Update thread views - $query = $db->simple_select("threadviews", "tid, COUNT(tid) AS views", "", array('group_by' => 'tid')); - while($threadview = $db->fetch_array($query)) - { - $db->update_query("threads", array('views' => "views+{$threadview['views']}"), "tid='{$threadview['tid']}'", 1, true); - } - - $db->write_query("TRUNCATE TABLE ".TABLE_PREFIX."threadviews"); - - if(is_object($plugins)) - { - $plugins->run_hooks('task_threadviews', $task); - } - - add_task_log($task, $lang->task_threadviews_ran); -} diff --git a/html/forums/inc/tasks/usercleanup.php b/html/forums/inc/tasks/usercleanup.php deleted file mode 100644 index fc32330..0000000 --- a/html/forums/inc/tasks/usercleanup.php +++ /dev/null @@ -1,74 +0,0 @@ -expire_warnings(); - - // Expire any post moderation or suspension limits - $query = $db->simple_select("users", "uid, moderationtime, suspensiontime", "(moderationtime!=0 AND moderationtime<".TIME_NOW.") OR (suspensiontime!=0 AND suspensiontime<".TIME_NOW.")"); - while($user = $db->fetch_array($query)) - { - $updated_user = array(); - if($user['moderationtime'] != 0 && $user['moderationtime'] < TIME_NOW) - { - $updated_user['moderateposts'] = 0; - $updated_user['moderationtime'] = 0; - } - if($user['suspensiontime'] != 0 && $user['suspensiontime'] < TIME_NOW) - { - $updated_user['suspendposting'] = 0; - $updated_user['suspensiontime'] = 0; - } - $db->update_query("users", $updated_user, "uid='{$user['uid']}'"); - } - - // Expire any suspended signatures - $query = $db->simple_select("users", "uid, suspendsigtime", "suspendsignature != 0 AND suspendsigtime < '".TIME_NOW."'"); - while($user = $db->fetch_array($query)) - { - if($user['suspendsigtime'] != 0 && $user['suspendsigtime'] < TIME_NOW) - { - $updated_user = array( - "suspendsignature" => 0, - "suspendsigtime" => 0, - ); - $db->update_query("users", $updated_user, "uid='".$user['uid']."'"); - } - } - - // Expire bans - $query = $db->simple_select("banned", "*", "lifted!=0 AND lifted<".TIME_NOW); - while($ban = $db->fetch_array($query)) - { - $updated_user = array( - "usergroup" => $ban['oldgroup'], - "additionalgroups" => $ban['oldadditionalgroups'], - "displaygroup" => $ban['olddisplaygroup'] - ); - $db->update_query("users", $updated_user, "uid='{$ban['uid']}'"); - $db->delete_query("banned", "uid='{$ban['uid']}'"); - } - - $cache->update_moderators(); - - if(is_object($plugins)) - { - $plugins->run_hooks('task_usercleanup', $task); - } - - add_task_log($task, $lang->task_usercleanup_ran); -} diff --git a/html/forums/inc/tasks/userpruning.php b/html/forums/inc/tasks/userpruning.php deleted file mode 100644 index b3871ba..0000000 --- a/html/forums/inc/tasks/userpruning.php +++ /dev/null @@ -1,101 +0,0 @@ -settings['enablepruning'] != 1) - { - return; - } - - // Are we pruning by posts? - if($mybb->settings['enableprunebyposts'] == 1) - { - $in_usergroups = array(); - $users = array(); - - $usergroups = $cache->read('usergroups'); - foreach($usergroups as $gid => $usergroup) - { - // Exclude admin, moderators, super moderators, banned - if($usergroup['canmodcp'] == 1 || $usergroup['cancp'] == 1 || $usergroup['issupermod'] == 1 || $usergroup['isbannedgroup'] == 1) - { - continue; - } - $in_usergroups[] = $gid; - } - - // If we're not pruning unactivated users, then remove them from the criteria - if($mybb->settings['pruneunactived'] == 0) - { - $key = array_search('5', $in_usergroups); - unset($in_usergroups[$key]); - } - - $prunepostcount = (int)$mybb->settings['prunepostcount']; - - $regdate = TIME_NOW-((int)$mybb->settings['dayspruneregistered']*24*60*60); - - $usergroups = $db->escape_string(implode(',', $in_usergroups)); - - $query = $db->simple_select('users', 'uid', "regdate<={$regdate} AND postnum<={$prunepostcount} AND usergroup IN({$usergroups})"); - while($uid = $db->fetch_field($query, 'uid')) - { - $users[$uid] = $uid; - } - - if($users && $mybb->settings['prunepostcountall']) - { - $query = $db->simple_select('posts', 'uid, COUNT(pid) as posts', "uid IN ('".implode("','", $users)."') AND visible>0", array('group_by' => 'uid')); - while($user = $db->fetch_array($query)) - { - if($user['posts'] >= $prunepostcount) - { - unset($users[$user['uid']]); - } - } - } - } - - // Are we pruning unactivated users? - if($mybb->settings['pruneunactived'] == 1) - { - $regdate = TIME_NOW-((int)$mybb->settings['dayspruneunactivated']*24*60*60); - $query = $db->simple_select("users", "uid", "regdate<={$regdate} AND usergroup='5'"); - while($user = $db->fetch_array($query)) - { - $users[$user['uid']] = $user['uid']; - } - } - - if(is_object($plugins)) - { - $args = array( - 'task' => &$task, - 'in_usergroups' => &$in_usergroups, - 'users' => &$users, - ); - $plugins->run_hooks('task_userpruning', $args); - } - - if(!empty($users)) - { - // Set up user handler. - require_once MYBB_ROOT.'inc/datahandlers/user.php'; - $userhandler = new UserDataHandler('delete'); - - // Delete the prunned users - $userhandler->delete_user($users, $mybb->settings['prunethreads']); - } - - add_task_log($task, $lang->task_userpruning_ran); -} diff --git a/html/forums/inc/tasks/versioncheck.php b/html/forums/inc/tasks/versioncheck.php deleted file mode 100644 index 3dfd76f..0000000 --- a/html/forums/inc/tasks/versioncheck.php +++ /dev/null @@ -1,101 +0,0 @@ -version_code); - - $updated_cache = array( - 'last_check' => TIME_NOW - ); - - // Check for the latest version - require_once MYBB_ROOT.'inc/class_xml.php'; - $contents = fetch_remote_file("https://mybb.com/version_check.php"); - - if(!$contents) - { - add_task_log($task, $lang->task_versioncheck_ran_errors); - return false; - } - - $pos = strpos($contents, "<"); - if($pos > 1) - { - $contents = substr($contents, $pos); - } - - $pos = strpos(strrev($contents), ">"); - if($pos > 1) - { - $contents = substr($contents, 0, (-1) * ($pos-1)); - } - - $parser = new XMLParser($contents); - $tree = $parser->get_tree(); - - $latest_code = (int)$tree['mybb']['version_code']['value']; - $latest_version = "".htmlspecialchars_uni($tree['mybb']['latest_version']['value'])." (".$latest_code.")"; - if($latest_code > $mybb->version_code) - { - $latest_version = "".$latest_version.""; - $version_warn = 1; - $updated_cache['latest_version'] = $latest_version; - $updated_cache['latest_version_code'] = $latest_code; - } - else - { - $latest_version = "".$latest_version.""; - } - - // Check for the latest news - require_once MYBB_ROOT."inc/class_feedparser.php"; - - $feed_parser = new FeedParser(); - $feed_parser->parse_feed("http://feeds.feedburner.com/MyBBDevelopmentBlog"); - - $updated_cache['news'] = array(); - - require_once MYBB_ROOT . '/inc/class_parser.php'; - $post_parser = new postParser(); - - if($feed_parser->error == '') - { - foreach($feed_parser->items as $item) - { - if (isset($updated_cache['news'][2])) - { - break; - } - - $description = $item['description']; - - $description = $post_parser->parse_message($description, array( - 'allow_html' => true, - ) - ); - - $description = preg_replace('##', '', $description); - - $updated_cache['news'][] = array( - 'title' => htmlspecialchars_uni($item['title']), - 'description' => $description, - 'link' => htmlspecialchars_uni($item['link']), - 'author' => htmlspecialchars_uni($item['author']), - 'dateline' => $item['date_timestamp'] - ); - } - } - - $cache->update("update_check", $updated_cache); - add_task_log($task, $lang->task_versioncheck_ran); -} diff --git a/html/forums/index.php b/html/forums/index.php deleted file mode 100644 index 8b16449..0000000 --- a/html/forums/index.php +++ /dev/null @@ -1,384 +0,0 @@ -run_hooks('index_start'); - -// Load global language phrases -$lang->load('index'); - -$logoutlink = ''; -if($mybb->user['uid'] != 0) -{ - eval('$logoutlink = "'.$templates->get('index_logoutlink').'";'); -} - -$statspage = ''; -if($mybb->settings['statsenabled'] != 0) -{ - eval('$statspage = "'.$templates->get('index_statspage').'";'); -} - -$whosonline = ''; -if($mybb->settings['showwol'] != 0 && $mybb->usergroup['canviewonline'] != 0) -{ - // Get the online users. - if($mybb->settings['wolorder'] == 'username') - { - $order_by = 'u.username ASC'; - $order_by2 = 's.time DESC'; - } - else - { - $order_by = 's.time DESC'; - $order_by2 = 'u.username ASC'; - } - - $timesearch = TIME_NOW - (int)$mybb->settings['wolcutoff']; - $comma = ''; - $query = $db->query(" - SELECT s.sid, s.ip, s.uid, s.time, s.location, s.location1, u.username, u.invisible, u.usergroup, u.displaygroup - FROM ".TABLE_PREFIX."sessions s - LEFT JOIN ".TABLE_PREFIX."users u ON (s.uid=u.uid) - WHERE s.time > '".$timesearch."' - ORDER BY {$order_by}, {$order_by2} - "); - - $forum_viewers = $doneusers = array(); - $membercount = $guestcount = $anoncount = $botcount = 0; - $onlinemembers = $comma = ''; - - // Fetch spiders - $spiders = $cache->read('spiders'); - - // Loop through all users. - while($user = $db->fetch_array($query)) - { - // Create a key to test if this user is a search bot. - $botkey = my_strtolower(str_replace('bot=', '', $user['sid'])); - - // Decide what type of user we are dealing with. - if($user['uid'] > 0) - { - // The user is registered. - if(empty($doneusers[$user['uid']]) || $doneusers[$user['uid']] < $user['time']) - { - // If the user is logged in anonymously, update the count for that. - if($user['invisible'] == 1) - { - ++$anoncount; - } - ++$membercount; - if($user['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid']) - { - // If this usergroup can see anonymously logged-in users, mark them. - if($user['invisible'] == 1) - { - $invisiblemark = '*'; - } - else - { - $invisiblemark = ''; - } - - // Properly format the username and assign the template. - $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); - $user['profilelink'] = build_profile_link($user['username'], $user['uid']); - eval('$onlinemembers .= "'.$templates->get('index_whosonline_memberbit', 1, 0).'";'); - $comma = $lang->comma; - } - // This user has been handled. - $doneusers[$user['uid']] = $user['time']; - } - } - elseif(my_strpos($user['sid'], 'bot=') !== false && $spiders[$botkey]) - { - // The user is a search bot. - $onlinemembers .= $comma.format_name($spiders[$botkey]['name'], $spiders[$botkey]['usergroup']); - $comma = $lang->comma; - ++$botcount; - } - else - { - // The user is a guest. - ++$guestcount; - } - - if($user['location1']) - { - ++$forum_viewers[$user['location1']]; - } - } - - // Build the who's online bit on the index page. - $onlinecount = $membercount + $guestcount + $botcount; - - if($onlinecount != 1) - { - $onlinebit = $lang->online_online_plural; - } - else - { - $onlinebit = $lang->online_online_singular; - } - if($membercount != 1) - { - $memberbit = $lang->online_member_plural; - } - else - { - $memberbit = $lang->online_member_singular; - } - if($anoncount != 1) - { - $anonbit = $lang->online_anon_plural; - } - else - { - $anonbit = $lang->online_anon_singular; - } - if($guestcount != 1) - { - $guestbit = $lang->online_guest_plural; - } - else - { - $guestbit = $lang->online_guest_singular; - } - $lang->online_note = $lang->sprintf($lang->online_note, my_number_format($onlinecount), $onlinebit, $mybb->settings['wolcutoffmins'], my_number_format($membercount), $memberbit, my_number_format($anoncount), $anonbit, my_number_format($guestcount), $guestbit); - eval('$whosonline = "'.$templates->get('index_whosonline').'";'); -} - -// Build the birthdays for to show on the index page. -$bdays = $birthdays = ''; -if($mybb->settings['showbirthdays'] != 0) -{ - // First, see what day this is. - $bdaycount = $bdayhidden = 0; - $bdaydate = my_date('j-n', TIME_NOW, '', 0); - $year = my_date('Y', TIME_NOW, '', 0); - - $bdaycache = $cache->read('birthdays'); - - if(!is_array($bdaycache)) - { - $cache->update_birthdays(); - $bdaycache = $cache->read('birthdays'); - } - - $hiddencount = $today_bdays = 0; - if(isset($bdaycache[$bdaydate])) - { - $hiddencount = $bdaycache[$bdaydate]['hiddencount']; - $today_bdays = $bdaycache[$bdaydate]['users']; - } - - $comma = ''; - if(!empty($today_bdays)) - { - if((int)$mybb->settings['showbirthdayspostlimit'] > 0) - { - $bdayusers = array(); - foreach($today_bdays as $key => $bdayuser_pc) - { - $bdayusers[$bdayuser_pc['uid']] = $key; - } - - if(!empty($bdayusers)) - { - // Find out if our users have enough posts to be seen on our birthday list - $bday_sql = implode(',', array_keys($bdayusers)); - $query = $db->simple_select('users', 'uid, postnum', "uid IN ({$bday_sql})"); - - while($bdayuser = $db->fetch_array($query)) - { - if($bdayuser['postnum'] < $mybb->settings['showbirthdayspostlimit']) - { - unset($today_bdays[$bdayusers[$bdayuser['uid']]]); - } - } - } - } - - // We still have birthdays - display them in our list! - if(!empty($today_bdays)) - { - foreach($today_bdays as $bdayuser) - { - if($bdayuser['displaygroup'] == 0) - { - $bdayuser['displaygroup'] = $bdayuser['usergroup']; - } - - // If this user's display group can't be seen in the birthday list, skip it - if($groupscache[$bdayuser['displaygroup']] && $groupscache[$bdayuser['displaygroup']]['showinbirthdaylist'] != 1) - { - continue; - } - - $age = ''; - $bday = explode('-', $bdayuser['birthday']); - if($year > $bday['2'] && $bday['2'] != '') - { - $age = ' ('.($year - $bday['2']).')'; - } - - $bdayuser['username'] = format_name(htmlspecialchars_uni($bdayuser['username']), $bdayuser['usergroup'], $bdayuser['displaygroup']); - $bdayuser['profilelink'] = build_profile_link($bdayuser['username'], $bdayuser['uid']); - eval('$bdays .= "'.$templates->get('index_birthdays_birthday', 1, 0).'";'); - ++$bdaycount; - $comma = $lang->comma; - } - } - } - - if($hiddencount > 0) - { - if($bdaycount > 0) - { - $bdays .= ' - '; - } - - $bdays .= "{$hiddencount} {$lang->birthdayhidden}"; - } - - // If there are one or more birthdays, show them. - if($bdaycount > 0 || $hiddencount > 0) - { - eval('$birthdays = "'.$templates->get('index_birthdays').'";'); - } -} - -// Build the forum statistics to show on the index page. -$forumstats = ''; -if($mybb->settings['showindexstats'] != 0) -{ - // First, load the stats cache. - $stats = $cache->read('stats'); - - // Check who's the newest member. - if(!$stats['lastusername']) - { - $newestmember = $lang->nobody;; - } - else - { - $newestmember = build_profile_link($stats['lastusername'], $stats['lastuid']); - } - - // Format the stats language. - $lang->stats_posts_threads = $lang->sprintf($lang->stats_posts_threads, my_number_format($stats['numposts']), my_number_format($stats['numthreads'])); - $lang->stats_numusers = $lang->sprintf($lang->stats_numusers, my_number_format($stats['numusers'])); - $lang->stats_newestuser = $lang->sprintf($lang->stats_newestuser, $newestmember); - - // Find out what the highest users online count is. - $mostonline = $cache->read('mostonline'); - if($onlinecount > $mostonline['numusers']) - { - $time = TIME_NOW; - $mostonline['numusers'] = $onlinecount; - $mostonline['time'] = $time; - $cache->update('mostonline', $mostonline); - } - $recordcount = $mostonline['numusers']; - $recorddate = my_date($mybb->settings['dateformat'], $mostonline['time']); - $recordtime = my_date($mybb->settings['timeformat'], $mostonline['time']); - - // Then format that language string. - $lang->stats_mostonline = $lang->sprintf($lang->stats_mostonline, my_number_format($recordcount), $recorddate, $recordtime); - - eval('$forumstats = "'.$templates->get('index_stats').'";'); -} - -// Show the board statistics table only if one or more index statistics are enabled. -$boardstats = ''; -if(($mybb->settings['showwol'] != 0 && $mybb->usergroup['canviewonline'] != 0) || $mybb->settings['showindexstats'] != 0 || ($mybb->settings['showbirthdays'] != 0 && $bdaycount > 0)) -{ - if(!isset($stats) || isset($stats) && !is_array($stats)) - { - // Load the stats cache. - $stats = $cache->read('stats'); - } - - eval('$boardstats = "'.$templates->get('index_boardstats').'";'); -} - -if($mybb->user['uid'] == 0) -{ - // Build a forum cache. - $query = $db->simple_select('forums', '*', 'active!=0', array('order_by' => 'pid, disporder')); - - $forumsread = array(); - if(isset($mybb->cookies['mybb']['forumread'])) - { - $forumsread = my_unserialize($mybb->cookies['mybb']['forumread']); - } -} -else -{ - // Build a forum cache. - $query = $db->query(" - SELECT f.*, fr.dateline AS lastread - FROM ".TABLE_PREFIX."forums f - LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid = f.fid AND fr.uid = '{$mybb->user['uid']}') - WHERE f.active != 0 - ORDER BY pid, disporder - "); -} - -while($forum = $db->fetch_array($query)) -{ - if($mybb->user['uid'] == 0) - { - if(!empty($forumsread[$forum['fid']])) - { - $forum['lastread'] = $forumsread[$forum['fid']]; - } - } - $fcache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; -} -$forumpermissions = forum_permissions(); - -// Get the forum moderators if the setting is enabled. -$moderatorcache = array(); -if($mybb->settings['modlist'] != 0 && $mybb->settings['modlist'] != 'off') -{ - $moderatorcache = $cache->read('moderators'); -} - -$excols = 'index'; -$permissioncache['-1'] = '1'; -$bgcolor = 'trow1'; - -// Decide if we're showing first-level subforums on the index page. -$showdepth = 2; -if($mybb->settings['subforumsindex'] != 0) -{ - $showdepth = 3; -} - -$forum_list = build_forumbits(); -$forums = $forum_list['forum_list']; - -$plugins->run_hooks('index_end'); - -eval('$index = "'.$templates->get('index').'";'); -output_page($index); diff --git a/html/forums/install/images/active.png b/html/forums/install/images/active.png deleted file mode 100644 index 8870723..0000000 Binary files a/html/forums/install/images/active.png and /dev/null differ diff --git a/html/forums/install/images/inactive.png b/html/forums/install/images/inactive.png deleted file mode 100644 index 2cf48fc..0000000 Binary files a/html/forums/install/images/inactive.png and /dev/null differ diff --git a/html/forums/install/images/index.html b/html/forums/install/images/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/install/images/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/install/images/logo.png b/html/forums/install/images/logo.png deleted file mode 100644 index 531dc80..0000000 Binary files a/html/forums/install/images/logo.png and /dev/null differ diff --git a/html/forums/install/images/submit_bg.png b/html/forums/install/images/submit_bg.png deleted file mode 100644 index 688062e..0000000 Binary files a/html/forums/install/images/submit_bg.png and /dev/null differ diff --git a/html/forums/install/images/tcat.png b/html/forums/install/images/tcat.png deleted file mode 100644 index 1d07e08..0000000 Binary files a/html/forums/install/images/tcat.png and /dev/null differ diff --git a/html/forums/install/images/thead.png b/html/forums/install/images/thead.png deleted file mode 100644 index 7a56d81..0000000 Binary files a/html/forums/install/images/thead.png and /dev/null differ diff --git a/html/forums/install/index.php b/html/forums/install/index.php deleted file mode 100644 index 8dc05a2..0000000 --- a/html/forums/install/index.php +++ /dev/null @@ -1,2530 +0,0 @@ -set_path(MYBB_ROOT.'install/resources'); -$lang->load('language'); - -// Load DB interface -require_once MYBB_ROOT."inc/db_base.php"; - -// Prevent any shut down functions from running -$done_shutdown = 1; - -// Include the necessary constants for installation -$grouppermignore = array('gid', 'type', 'title', 'description', 'namestyle', 'usertitle', 'stars', 'starimage', 'image'); -$groupzerogreater = array('pmquota', 'maxpmrecipients', 'maxreputationsday', 'attachquota', 'maxemails', 'maxwarningsday', 'maxposts', 'edittimelimit', 'canusesigxposts', 'maxreputationsperuser', 'maxreputationsperthread', 'emailfloodtime'); -$displaygroupfields = array('title', 'description', 'namestyle', 'usertitle', 'stars', 'starimage', 'image'); -$fpermfields = array('canview', 'canviewthreads', 'candlattachments', 'canpostthreads', 'canpostreplys', 'canpostattachments', 'canratethreads', 'caneditposts', 'candeleteposts', 'candeletethreads', 'caneditattachments', 'canpostpolls', 'canvotepolls', 'cansearch', 'modposts', 'modthreads', 'modattachments', 'mod_edit_posts'); - -// Include the installation resources -require_once INSTALL_ROOT.'resources/output.php'; -$output = new installerOutput; - -$dboptions = array(); - -if(function_exists('mysqli_connect')) -{ - $dboptions['mysqli'] = array( - 'class' => 'DB_MySQLi', - 'title' => 'MySQL Improved', - 'short_title' => 'MySQLi', - 'structure_file' => 'mysql_db_tables.php', - 'population_file' => 'mysql_db_inserts.php' - ); -} - -if(function_exists('mysql_connect')) -{ - $dboptions['mysql'] = array( - 'class' => 'DB_MySQL', - 'title' => 'MySQL', - 'short_title' => 'MySQL', - 'structure_file' => 'mysql_db_tables.php', - 'population_file' => 'mysql_db_inserts.php' - ); -} - -if(function_exists('pg_connect')) -{ - $dboptions['pgsql'] = array( - 'class' => 'DB_PgSQL', - 'title' => 'PostgreSQL', - 'short_title' => 'PostgreSQL', - 'structure_file' => 'pgsql_db_tables.php', - 'population_file' => 'mysql_db_inserts.php' - ); -} - -if(class_exists('PDO')) -{ - $supported_dbs = PDO::getAvailableDrivers(); - if(in_array('sqlite', $supported_dbs)) - { - $dboptions['sqlite'] = array( - 'class' => 'DB_SQLite', - 'title' => 'SQLite 3', - 'short_title' => 'SQLite', - 'structure_file' => 'sqlite_db_tables.php', - 'population_file' => 'mysql_db_inserts.php' - ); - } -} - -if(file_exists('lock') && $mybb->dev_mode != true) -{ - $output->print_error($lang->locked); -} -else if($installed == true && empty($mybb->input['action'])) -{ - $output->print_header($lang->already_installed, "errormsg", 0); - echo $lang->sprintf($lang->mybb_already_installed, $mybb->version); - $output->print_footer(); -} -else -{ - $output->steps = array( - 'intro' => $lang->welcome, - 'license' => $lang->license_agreement, - 'requirements_check' => $lang->req_check, - 'database_info' => $lang->db_config, - 'create_tables' => $lang->table_creation, - 'populate_tables' => $lang->data_insertion, - 'templates' => $lang->theme_install, - 'configuration' => $lang->board_config, - 'adminuser' => $lang->admin_user, - 'final' => $lang->finish_setup, - ); - - switch($mybb->get_input('action')) - { - case 'license': - license_agreement(); - break; - case 'requirements_check': - requirements_check(); - break; - case 'database_info': - database_info(); - break; - case 'create_tables': - create_tables(); - break; - case 'populate_tables': - populate_tables(); - break; - case 'templates': - insert_templates(); - break; - case 'configuration': - configure(); - break; - case 'adminuser': - create_admin_user(); - break; - case 'final': - install_done(); - break; - default: - $mybb->input['action'] = 'intro'; - intro(); - break; - } -} - -/** - * Welcome page - */ -function intro() -{ - global $output, $mybb, $lang; - - $output->print_header(); - if(strpos(strtolower(get_current_location('', '', true)), '/upload/') !== false) - { - echo $lang->sprintf($lang->mybb_incorrect_folder); - } - echo $lang->sprintf($lang->welcome_step, $mybb->version); - $output->print_footer('license'); -} - -/** - * Show the license agreement - */ -function license_agreement() -{ - global $output, $lang, $mybb; - - ob_start(); - $output->print_header($lang->license_agreement, 'license'); - - if($mybb->get_input('allow_anonymous_info', MyBB::INPUT_INT) == 1) - { - require_once MYBB_ROOT."inc/functions_serverstats.php"; - $build_server_stats = build_server_stats(1, '', $mybb->version_code); - - if($build_server_stats['info_sent_success'] == false) - { - echo $build_server_stats['info_image']; - } - } - ob_end_flush(); - - $license = << - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser 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 -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. 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 -them 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 prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. 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. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey 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; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If 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 convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU 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 that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - 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. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -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. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - -EOF; - echo $lang->sprintf($lang->license_step, $license); - $output->print_footer('requirements_check'); -} - -/** - * Check our requirements - */ -function requirements_check() -{ - global $output, $mybb, $dboptions, $lang; - - $mybb->input['action'] = "requirements_check"; - $output->print_header($lang->req_check, 'requirements'); - echo $lang->req_step_top; - $errors = array(); - $showerror = 0; - - if(!file_exists(MYBB_ROOT."/inc/config.php")) - { - if(!@rename(MYBB_ROOT."/inc/config.default.php", MYBB_ROOT."/inc/config.php")) - { - if(!$configwritable) - { - $errors[] = $lang->sprintf($lang->req_step_error_box, $lang->req_step_error_configdefaultfile); - $configstatus = $lang->sprintf($lang->req_step_span_fail, $lang->not_writable); - $showerror = 1; - } - } - } - - // Check PHP Version - if(version_compare(PHP_VERSION, '5.2.0', "<")) - { - $errors[] = $lang->sprintf($lang->req_step_error_box, $lang->sprintf($lang->req_step_error_phpversion, PHP_VERSION)); - $phpversion = $lang->sprintf($lang->req_step_span_fail, PHP_VERSION); - $showerror = 1; - } - else - { - $phpversion = $lang->sprintf($lang->req_step_span_pass, PHP_VERSION); - } - - $mboptions = array(); - - if(function_exists('mb_detect_encoding')) - { - $mboptions[] = $lang->multi_byte; - } - - if(function_exists('iconv')) - { - $mboptions[] = 'iconv'; - } - - // Check Multibyte extensions - if(count($mboptions) < 1) - { - $mbstatus = $lang->sprintf($lang->req_step_span_fail, $lang->none); - } - else - { - $mbstatus = implode(', ', $mboptions); - } - - // Check database engines - if(count($dboptions) < 1) - { - $errors[] = $lang->sprintf($lang->req_step_error_box, $lang->req_step_error_dboptions); - $dbsupportlist = $lang->sprintf($lang->req_step_span_fail, $lang->none); - $showerror = 1; - } - else - { - foreach($dboptions as $dboption) - { - $dbsupportlist[] = $dboption['title']; - } - $dbsupportlist = implode(', ', $dbsupportlist); - } - - // Check XML parser is installed - if(!function_exists('xml_parser_create')) - { - $errors[] = $lang->sprintf($lang->req_step_error_box, $lang->req_step_error_xmlsupport); - $xmlstatus = $lang->sprintf($lang->req_step_span_fail, $lang->not_installed); - $showerror = 1; - } - else - { - $xmlstatus = $lang->sprintf($lang->req_step_span_pass, $lang->installed); - } - - // Check config file is writable - $configwritable = @fopen(MYBB_ROOT.'inc/config.php', 'w'); - if(!$configwritable) - { - $errors[] = $lang->sprintf($lang->req_step_error_box, $lang->req_step_error_configfile); - $configstatus = $lang->sprintf($lang->req_step_span_fail, $lang->not_writable); - $showerror = 1; - } - else - { - $configstatus = $lang->sprintf($lang->req_step_span_pass, $lang->writable); - } - @fclose($configwritable); - - // Check settings file is writable - $settingswritable = @fopen(MYBB_ROOT.'inc/settings.php', 'w'); - if(!$settingswritable) - { - $errors[] = $lang->sprintf($lang->req_step_error_box, $lang->req_step_error_settingsfile); - $settingsstatus = $lang->sprintf($lang->req_step_span_fail, $lang->not_writable); - $showerror = 1; - } - else - { - $settingsstatus = $lang->sprintf($lang->req_step_span_pass, $lang->writable); - } - @fclose($settingswritable); - - // Check cache directory is writable - $cachewritable = @fopen(MYBB_ROOT.'cache/test.write', 'w'); - if(!$cachewritable) - { - $errors[] = $lang->sprintf($lang->req_step_error_box, $lang->req_step_error_cachedir); - $cachestatus = $lang->sprintf($lang->req_step_span_fail, $lang->not_writable); - $showerror = 1; - @fclose($cachewritable); - } - else - { - $cachestatus = $lang->sprintf($lang->req_step_span_pass, $lang->writable); - @fclose($cachewritable); - @my_chmod(MYBB_ROOT.'cache', '0777'); - @my_chmod(MYBB_ROOT.'cache/test.write', '0777'); - @unlink(MYBB_ROOT.'cache/test.write'); - } - - // Check upload directory is writable - $uploadswritable = @fopen(MYBB_ROOT.'uploads/test.write', 'w'); - if(!$uploadswritable) - { - $errors[] = $lang->sprintf($lang->req_step_error_box, $lang->req_step_error_uploaddir); - $uploadsstatus = $lang->sprintf($lang->req_step_span_fail, $lang->not_writable); - $showerror = 1; - @fclose($uploadswritable); - } - else - { - $uploadsstatus = $lang->sprintf($lang->req_step_span_pass, $lang->writable); - @fclose($uploadswritable); - @my_chmod(MYBB_ROOT.'uploads', '0777'); - @my_chmod(MYBB_ROOT.'uploads/test.write', '0777'); - @unlink(MYBB_ROOT.'uploads/test.write'); - } - - // Check avatar directory is writable - $avatarswritable = @fopen(MYBB_ROOT.'uploads/avatars/test.write', 'w'); - if(!$avatarswritable) - { - $errors[] = $lang->sprintf($lang->req_step_error_box, $lang->req_step_error_avatardir); - $avatarsstatus = $lang->sprintf($lang->req_step_span_fail, $lang->not_writable); - $showerror = 1; - @fclose($avatarswritable); - } - else - { - $avatarsstatus = $lang->sprintf($lang->req_step_span_pass, $lang->writable); - @fclose($avatarswritable); - @my_chmod(MYBB_ROOT.'uploads/avatars', '0777'); - @my_chmod(MYBB_ROOT.'uploads/avatars/test.write', '0777'); - @unlink(MYBB_ROOT.'uploads/avatars/test.write'); - } - - // Output requirements page - echo $lang->sprintf($lang->req_step_reqtable, $phpversion, $dbsupportlist, $mbstatus, $xmlstatus, $configstatus, $settingsstatus, $cachestatus, $uploadsstatus, $avatarsstatus); - - if($showerror == 1) - { - $error_list = error_list($errors); - echo $lang->sprintf($lang->req_step_error_tablelist, $error_list); - echo "\n input['action']}\" />"; - echo "\n
    recheck} »\" />

    \n"; - $output->print_footer(); - } - else - { - echo $lang->req_step_reqcomplete; - $output->print_footer('database_info'); - } -} - -/** - * Which database do we use? - */ -function database_info() -{ - global $output, $dbinfo, $errors, $mybb, $dboptions, $lang; - - $mybb->input['action'] = 'database_info'; - $output->print_header($lang->db_config, 'dbconfig'); - - echo ""; - - // Check for errors from this stage - if(is_array($errors)) - { - $error_list = error_list($errors); - echo $lang->sprintf($lang->db_step_error_config, $error_list); - } - else - { - echo $lang->db_step_config_db; - } - - $dbengines = ''; - - // Loop through database engines - foreach($dboptions as $dbfile => $dbtype) - { - if($mybb->get_input('dbengine') == $dbfile) - { - $dbengines .= ""; - } - else - { - $dbengines .= ""; - } - } - - $db_info = array(); - foreach($dboptions as $dbfile => $dbtype) - { - require_once MYBB_ROOT."inc/db_{$dbfile}.php"; - $db = new $dbtype['class']; - $encodings = $db->fetch_db_charsets(); - $encoding_select = ''; - $mybb->input['config'] = $mybb->get_input('config', MyBB::INPUT_ARRAY); - if(empty($mybb->input['config'][$dbfile]['dbhost'])) - { - $mybb->input['config'][$dbfile]['dbhost'] = "localhost"; - } - if(empty($mybb->input['config'][$dbfile]['tableprefix'])) - { - $mybb->input['config'][$dbfile]['tableprefix'] = "mybb_"; - } - if(empty($mybb->input['config'][$dbfile]['dbname'])) - { - $mybb->input['config'][$dbfile]['dbname'] = ''; - } - if(empty($mybb->input['config'][$dbfile]['dbuser'])) - { - $mybb->input['config'][$dbfile]['dbuser'] = ''; - } - if(empty($mybb->input['config'][$dbfile]['dbpass'])) - { - $mybb->input['config'][$dbfile]['dbpass'] = ''; - } - if(empty($mybb->input['config'][$dbfile]['encoding'])) - { - $mybb->input['config'][$dbfile]['encoding'] = "utf8"; - } - - $class = ''; - if(empty($first) && !$mybb->get_input('dbengine')) - { - $mybb->input['dbengine'] = $dbfile; - $first = true; - } - if($dbfile == $mybb->input['dbengine']) - { - $class = "_selected"; - } - - $db_info[$dbfile] = " - - - {$dbtype['title']} {$lang->database_settings} - "; - - // SQLite gets some special settings - if($dbfile == 'sqlite') - { - $db_info[$dbfile] .= " - - - input['config'][$dbfile]['dbname'])."\" /> - "; - } - // Others get db host, username, password etc - else - { - $db_info[$dbfile] .= " - - - input['config'][$dbfile]['dbhost'])."\" /> - - - - input['config'][$dbfile]['dbuser'])."\" /> - - - - input['config'][$dbfile]['dbpass'])."\" /> - - - - input['config'][$dbfile]['dbname'])."\" /> - "; - } - - // Now we're up to table settings - $db_info[$dbfile] .= " - - {$dbtype['title']} {$lang->table_settings} - - - - input['config'][$dbfile]['tableprefix'])."\" /> - - "; - - // Encoding selection only if supported - if(is_array($encodings)) - { - $select_options = ""; - foreach($encodings as $encoding => $title) - { - if($mybb->input['config'][$dbfile]['encoding'] == $encoding) - { - $select_options .= ""; - } - else - { - $select_options .= ""; - } - } - $db_info[$dbfile] .= " - - - - - "; - } - } - $dbconfig = implode("", $db_info); - - echo $lang->sprintf($lang->db_step_config_table, $dbengines, $dbconfig); - $output->print_footer('create_tables'); -} - -/** - * Create our tables - */ -function create_tables() -{ - global $output, $dbinfo, $errors, $mybb, $dboptions, $lang; - - $mybb->input['dbengine'] = $mybb->get_input('dbengine'); - if(!file_exists(MYBB_ROOT."inc/db_{$mybb->input['dbengine']}.php")) - { - $errors[] = $lang->db_step_error_invalidengine; - database_info(); - } - - $mybb->input['config'] = $mybb->get_input('config', MyBB::INPUT_ARRAY); - $config = $mybb->input['config'][$mybb->input['dbengine']]; - - if(strstr($mybb->input['dbengine'], "sqlite") !== false) - { - if(strstr($config['dbname'], "./") !== false || strstr($config['dbname'], "../") !== false || empty($config['dbname'])) - { - $errors[] = $lang->db_step_error_sqlite_invalid_dbname; - database_info(); - } - } - - // Attempt to connect to the db - require_once MYBB_ROOT."inc/db_{$mybb->input['dbengine']}.php"; - switch($mybb->input['dbengine']) - { - case "sqlite": - $db = new DB_SQLite; - break; - case "pgsql": - $db = new DB_PgSQL; - break; - case "mysqli": - $db = new DB_MySQLi; - break; - default: - $db = new DB_MySQL; - } - $db->error_reporting = 0; - - $connect_array = array( - "hostname" => $config['dbhost'], - "username" => $config['dbuser'], - "password" => $config['dbpass'], - "database" => $config['dbname'], - "encoding" => $config['encoding'] - ); - - $connection = $db->connect($connect_array); - if($connection === false) - { - $errors[] = $lang->sprintf($lang->db_step_error_noconnect, $config['dbhost']); - } - // double check if the DB exists for MySQL - elseif(method_exists($db, 'select_db') && !$db->select_db($config['dbname'])) - { - $errors[] = $lang->sprintf($lang->db_step_error_nodbname, $config['dbname']); - } - - // Most DB engines only allow certain characters in the table name. Oracle requires an alphabetic character first. - if((!preg_match("#^[A-Za-z][A-Za-z0-9_]*$#", $config['tableprefix'])) && $config['tableprefix'] != '') - { - $errors[] = $lang->db_step_error_invalid_tableprefix; - } - - // Needs to be smaller then 64 characters total (MySQL Limit). - // This allows 24 characters for the actual table name, which should be sufficient. - if(strlen($config['tableprefix']) > 40) - { - $errors[] = $lang->db_step_error_tableprefix_too_long; - } - - if(($db->engine == 'mysql' || $db->engine == 'mysqli') && $config['encoding'] == 'utf8mb4' && version_compare($db->get_version(), '5.5.3', '<')) - { - $errors[] = $lang->db_step_error_utf8mb4_error; - } - - if(is_array($errors)) - { - database_info(); - } - - // Decide if we can use a database encoding or not - if($db->fetch_db_charsets() != false) - { - $db_encoding = "\$config['database']['encoding'] = '{$config['encoding']}';"; - } - else - { - $db_encoding = "// \$config['database']['encoding'] = '{$config['encoding']}';"; - } - - $config['dbpass'] = addslashes($config['dbpass']); - - // Write the configuration file - $configdata = "input['dbengine']}'; -\$config['database']['database'] = '{$config['dbname']}'; -\$config['database']['table_prefix'] = '{$config['tableprefix']}'; - -\$config['database']['hostname'] = '{$config['dbhost']}'; -\$config['database']['username'] = '{$config['dbuser']}'; -\$config['database']['password'] = '{$config['dbpass']}'; - -/** - * Admin CP directory - * For security reasons, it is recommended you - * rename your Admin CP directory. You then need - * to adjust the value below to point to the - * new directory. - */ - -\$config['admin_dir'] = 'admin'; - -/** - * Hide all Admin CP links - * If you wish to hide all Admin CP links - * on the front end of the board after - * renaming your Admin CP directory, set this - * to 1. - */ - -\$config['hide_admin_links'] = 0; - -/** - * Data-cache configuration - * The data cache is a temporary cache - * of the most commonly accessed data in MyBB. - * By default, the database is used to store this data. - * - * If you wish to use the file system (cache/ directory), MemCache (or MemCached), xcache, APC, or eAccelerator - * you can change the value below to 'files', 'memcache', 'memcached', 'xcache', 'apc' or 'eaccelerator' from 'db'. - */ - -\$config['cache_store'] = 'db'; - -/** - * Memcache configuration - * If you are using memcache or memcached as your - * data-cache, you need to configure the hostname - * and port of your memcache server below. - * - * If not using memcache, ignore this section. - */ - -\$config['memcache']['host'] = 'localhost'; -\$config['memcache']['port'] = 11211; - -/** - * Super Administrators - * A comma separated list of user IDs who cannot - * be edited, deleted or banned in the Admin CP. - * The administrator permissions for these users - * cannot be altered either. - */ - -\$config['super_admins'] = '1'; - -/** - * Database Encoding - * If you wish to set an encoding for MyBB uncomment - * the line below (if it isn't already) and change - * the current value to the mysql charset: - * http://dev.mysql.com/doc/refman/5.1/en/charset-mysql.html - */ - -{$db_encoding} - -/** - * Automatic Log Pruning - * The MyBB task system can automatically prune - * various log files created by MyBB. - * To enable this functionality for the logs below, set the - * the number of days before each log should be pruned. - * If you set the value to 0, the logs will not be pruned. - */ - -\$config['log_pruning'] = array( - 'admin_logs' => 365, // Administrator logs - 'mod_logs' => 365, // Moderator logs - 'task_logs' => 30, // Scheduled task logs - 'mail_logs' => 180, // Mail error logs - 'user_mail_logs' => 180, // User mail logs - 'promotion_logs' => 180 // Promotion logs -); - -/** - * Disallowed Remote Hosts - * List of hosts the fetch_remote_file() function will not - * perform requests to. - * It is recommended that you enter hosts resolving to the - * forum server here to prevent Server Side Request - * Forgery attacks. - */ - -\$config['disallowed_remote_hosts'] = array( - 'localhost', -); - -/** - * Disallowed Remote Addresses - * List of IPv4 addresses the fetch_remote_file() function - * will not perform requests to. - * It is recommended that you enter addresses resolving to - * the forum server here to prevent Server Side Request - * Forgery attacks. - * Removing all values disables resolving hosts in that - * function. - */ - -\$config['disallowed_remote_addresses'] = array( - '127.0.0.1', - '10.0.0.0/8', - '172.16.0.0/12', - '192.168.0.0/16', -); - -"; - - $file = fopen(MYBB_ROOT.'inc/config.php', 'w'); - fwrite($file, $configdata); - fclose($file); - - if(function_exists('opcache_invalidate')) - { - opcache_invalidate(MYBB_ROOT."inc/config.php"); - } - - // Error reporting back on - $db->error_reporting = 1; - - $output->print_header($lang->table_creation, 'createtables'); - echo $lang->sprintf($lang->tablecreate_step_connected, $dboptions[$mybb->input['dbengine']]['short_title'], $db->get_version()); - - if($dboptions[$mybb->input['dbengine']]['structure_file']) - { - $structure_file = $dboptions[$mybb->input['dbengine']]['structure_file']; - } - else - { - $structure_file = 'mysql_db_tables.php'; - } - - require_once INSTALL_ROOT."resources/{$structure_file}"; - foreach($tables as $val) - { - $val = preg_replace('#mybb_(\S+?)([\s\.,\(]|$)#', $config['tableprefix'].'\\1\\2', $val); - $val = preg_replace('#;$#', $db->build_create_table_collation().";", $val); - preg_match('#CREATE TABLE (\S+)(\s?|\(?)\(#i', $val, $match); - if($match[1]) - { - $db->drop_table($match[1], false, false); - echo $lang->sprintf($lang->tablecreate_step_created, $match[1]); - } - $db->query($val); - if($match[1]) - { - echo $lang->done . "
    \n"; - } - } - echo $lang->tablecreate_step_done; - $output->print_footer('populate_tables'); -} - -/** - * Insert our default data - */ -function populate_tables() -{ - global $output, $lang; - - require MYBB_ROOT.'inc/config.php'; - $db = db_connection($config); - - $output->print_header($lang->table_population, 'tablepopulate'); - echo $lang->sprintf($lang->populate_step_insert); - - if(!empty($dboptions[$db->type]['population_file'])) - { - $population_file = $dboptions[$db->type]['population_file']; - } - else - { - $population_file = 'mysql_db_inserts.php'; - } - - require_once INSTALL_ROOT."resources/{$population_file}"; - foreach($inserts as $val) - { - $val = preg_replace('#mybb_(\S+?)([\s\.,]|$)#', $config['database']['table_prefix'].'\\1\\2', $val); - $db->query($val); - } - - // Update the sequences for PgSQL - if($config['database']['type'] == "pgsql") - { - $db->query("SELECT setval('{$config['database']['table_prefix']}attachtypes_atid_seq', (SELECT max(atid) FROM {$config['database']['table_prefix']}attachtypes));"); - $db->query("SELECT setval('{$config['database']['table_prefix']}forums_fid_seq', (SELECT max(fid) FROM {$config['database']['table_prefix']}forums));"); - $db->query("SELECT setval('{$config['database']['table_prefix']}helpdocs_hid_seq', (SELECT max(hid) FROM {$config['database']['table_prefix']}helpdocs));"); - $db->query("SELECT setval('{$config['database']['table_prefix']}helpsections_sid_seq', (SELECT max(sid) FROM {$config['database']['table_prefix']}helpsections));"); - $db->query("SELECT setval('{$config['database']['table_prefix']}icons_iid_seq', (SELECT max(iid) FROM {$config['database']['table_prefix']}icons));"); - $db->query("SELECT setval('{$config['database']['table_prefix']}profilefields_fid_seq', (SELECT max(fid) FROM {$config['database']['table_prefix']}profilefields));"); - $db->query("SELECT setval('{$config['database']['table_prefix']}smilies_sid_seq', (SELECT max(sid) FROM {$config['database']['table_prefix']}smilies));"); - $db->query("SELECT setval('{$config['database']['table_prefix']}spiders_sid_seq', (SELECT max(sid) FROM {$config['database']['table_prefix']}spiders));"); - $db->query("SELECT setval('{$config['database']['table_prefix']}templategroups_gid_seq', (SELECT max(gid) FROM {$config['database']['table_prefix']}templategroups));"); - } - - echo $lang->populate_step_inserted; - $output->print_footer('templates'); -} - -/** - * Install our theme - */ -function insert_templates() -{ - global $mybb, $output, $cache, $db, $lang; - - require MYBB_ROOT.'inc/config.php'; - $db = db_connection($config); - - require_once MYBB_ROOT.'inc/class_datacache.php'; - $cache = new datacache; - - $output->print_header($lang->theme_installation, 'theme'); - - echo $lang->theme_step_importing; - - $db->delete_query("themes"); - $db->delete_query("templates"); - $db->delete_query("themestylesheets"); - my_rmdir_recursive(MYBB_ROOT."cache/themes", array(MYBB_ROOT."cache/themes/index.html")); - - $insert_array = array( - 'title' => 'Default Templates' - ); - $templateset = $db->insert_query("templatesets", $insert_array); - - $contents = @file_get_contents(INSTALL_ROOT.'resources/mybb_theme.xml'); - if(!empty($mybb->config['admin_dir']) && file_exists(MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php")) - { - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions.php"; - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php"; - } - elseif(file_exists(MYBB_ROOT."admin/inc/functions_themes.php")) - { - require_once MYBB_ROOT."admin/inc/functions.php"; - require_once MYBB_ROOT."admin/inc/functions_themes.php"; - } - else - { - $output->print_error("Please make sure your admin directory is uploaded correctly."); - } - $theme_id = import_theme_xml($contents, array("templateset" => -2, "version_compat" => 1)); - $tid = build_new_theme("Default", null, $theme_id); - - // Update our properties template set to the correct one - $query = $db->simple_select("themes", "stylesheets, properties", "tid='{$tid}'", array('limit' => 1)); - - $theme = $db->fetch_array($query); - $properties = my_unserialize($theme['properties']); - $stylesheets = my_unserialize($theme['stylesheets']); - - $properties['templateset'] = $templateset; - unset($properties['inherited']['templateset']); - - // 1.8: Stylesheet Colors - $contents = @file_get_contents(INSTALL_ROOT.'resources/mybb_theme_colors.xml'); - - require_once MYBB_ROOT."inc/class_xml.php"; - $parser = new XMLParser($contents); - $tree = $parser->get_tree(); - - if(is_array($tree) && is_array($tree['colors'])) - { - if(is_array($tree['colors']['scheme'])) - { - foreach($tree['colors']['scheme'] as $tag => $value) - { - $exp = explode("=", $value['value']); - - $properties['colors'][$exp[0]] = $exp[1]; - } - } - - if(is_array($tree['colors']['stylesheets'])) - { - $count = count($properties['disporder']) + 1; - foreach($tree['colors']['stylesheets']['stylesheet'] as $stylesheet) - { - $new_stylesheet = array( - "name" => $db->escape_string($stylesheet['attributes']['name']), - "tid" => $tid, - "attachedto" => $db->escape_string($stylesheet['attributes']['attachedto']), - "stylesheet" => $db->escape_string($stylesheet['value']), - "lastmodified" => TIME_NOW, - "cachefile" => $db->escape_string($stylesheet['attributes']['name']) - ); - - $sid = $db->insert_query("themestylesheets", $new_stylesheet); - $css_url = "css.php?stylesheet={$sid}"; - - $cached = cache_stylesheet($tid, $stylesheet['attributes']['name'], $stylesheet['value']); - - if($cached) - { - $css_url = $cached; - } - - // Add to display and stylesheet list - $properties['disporder'][$stylesheet['attributes']['name']] = $count; - $stylesheets[$stylesheet['attributes']['attachedto']]['global'][] = $css_url; - - ++$count; - } - } - } - - $db->update_query("themes", array("def" => 1, "properties" => $db->escape_string(my_serialize($properties)), "stylesheets" => $db->escape_string(my_serialize($stylesheets))), "tid = '{$tid}'"); - - echo $lang->theme_step_imported; - $output->print_footer('configuration'); -} - -/** - * Default configuration - */ -function configure() -{ - global $output, $mybb, $errors, $lang; - - $output->print_header($lang->board_config, 'config'); - - echo << - function warnUser(inp, warn) - { - var parenttr = $('#'+inp.id).closest('tr'); - if(inp.value != inp.defaultValue) - { - if(!parenttr.next('.setting_peeker').length) - { - var revertlink = ' {$lang->config_step_revert}'; - parenttr.removeClass('last').after(''+warn+revertlink+''); - } - } else { - parenttr.next('.setting_peeker').remove(); - if(parenttr.is(':last-child')) - { - parenttr.addClass('last'); - } - } - } - - function revertSetting(defval, inpid) - { - $(inpid).val(defval); - var parenttr = $(inpid).closest('tr'); - parenttr.next('.setting_peeker').remove(); - if(parenttr.is(':last-child')) - { - parenttr.addClass('last'); - } - } - - -EOF; - - // If board configuration errors - if(is_array($errors)) - { - $error_list = error_list($errors); - echo $lang->sprintf($lang->config_step_error_config, $error_list); - - $bbname = htmlspecialchars_uni($mybb->get_input('bbname')); - $bburl = htmlspecialchars_uni($mybb->get_input('bburl')); - $websitename = htmlspecialchars_uni($mybb->get_input('websitename')); - $websiteurl = htmlspecialchars_uni($mybb->get_input('websiteurl')); - $cookiedomain = htmlspecialchars_uni($mybb->get_input('cookiedomain')); - $cookiepath = htmlspecialchars_uni($mybb->get_input('cookiepath')); - $contactemail = htmlspecialchars_uni($mybb->get_input('contactemail')); - } - else - { - $bbname = 'Forums'; - $cookiedomain = ''; - $websitename = 'Your Website'; - - $protocol = "http://"; - if((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != "off")) - { - $protocol = "https://"; - } - - // Attempt auto-detection - if(!empty($_SERVER['HTTP_HOST'])) - { - $hostname = $protocol.$_SERVER['HTTP_HOST']; - $cookiedomain = $_SERVER['HTTP_HOST']; - } - elseif(!empty($_SERVER['SERVER_NAME'])) - { - $hostname = $protocol.$_SERVER['SERVER_NAME']; - $cookiedomain = $_SERVER['SERVER_NAME']; - } - - if(my_substr($cookiedomain, 0, 4) == "www.") - { - $cookiedomain = substr($cookiedomain, 4); - } - - // IP addresses and hostnames are not valid - if(my_inet_pton($cookiedomain) !== false || strpos($cookiedomain, '.') === false) - { - $cookiedomain = ''; - } - else - { - $cookiedomain = ".{$cookiedomain}"; - } - - if(!empty($_SERVER['SERVER_PORT'])) - { - $port = ":{$_SERVER['SERVER_PORT']}"; - $pos = strrpos($cookiedomain, $port); - - if($pos !== false) - { - $cookiedomain = substr($cookiedomain, 0, $pos); - } - - if($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443 && !preg_match("#:[0-9]#i", $hostname)) - { - $hostname .= $port; - } - } - - $currentlocation = get_current_location('', '', true); - $noinstall = substr($currentlocation, 0, strrpos($currentlocation, '/install/')); - - $cookiepath = $noinstall.'/'; - $bburl = $hostname.$noinstall; - $websiteurl = $hostname.'/'; - - if(isset($_SERVER['SERVER_ADMIN']) && filter_var($_SERVER['SERVER_ADMIN'], FILTER_VALIDATE_EMAIL)) - { - $contactemail = $_SERVER['SERVER_ADMIN']; - } - } - - echo $lang->sprintf($lang->config_step_table, $bbname, $bburl, $websitename, $websiteurl, $cookiedomain, $cookiepath, $contactemail); - $output->print_footer('adminuser'); -} - -/** - * How do we want to name the admin user? - */ -function create_admin_user() -{ - global $output, $mybb, $errors, $db, $lang; - - $mybb->input['action'] = "adminuser"; - // If no errors then check for errors from last step - if(!is_array($errors)) - { - if(empty($mybb->input['bburl'])) - { - $errors[] = $lang->config_step_error_url; - } - if(empty($mybb->input['bbname'])) - { - $errors[] = $lang->config_step_error_name; - } - if(is_array($errors)) - { - configure(); - } - } - $output->print_header($lang->create_admin, 'admin'); - - echo << - function comparePass() - { - var parenttr = $('#adminpass2').closest('tr'); - var passval = $('#adminpass2').val(); - if(passval && passval != $('#adminpass').val()) - { - if(!parenttr.next('.pass_peeker').length) - { - parenttr.removeClass('last').after('{$lang->admin_step_nomatch}'); - } - } else { - parenttr.addClass('last').next('.pass_peeker').remove(); - } - } - - -EOF; - - if(is_array($errors)) - { - $error_list = error_list($errors); - echo $lang->sprintf($lang->admin_step_error_config, $error_list); - $adminuser = $mybb->get_input('adminuser'); - $adminemail = $mybb->get_input('adminemail'); - } - else - { - require MYBB_ROOT.'inc/config.php'; - $db = db_connection($config); - - echo $lang->admin_step_setupsettings; - $adminuser = $adminemail = ''; - - $settings = file_get_contents(INSTALL_ROOT.'resources/settings.xml'); - $parser = new XMLParser($settings); - $parser->collapse_dups = 0; - $tree = $parser->get_tree(); - $groupcount = $settingcount = 0; - - // Insert all the settings - foreach($tree['settings'][0]['settinggroup'] as $settinggroup) - { - $groupdata = array( - 'name' => $db->escape_string($settinggroup['attributes']['name']), - 'title' => $db->escape_string($settinggroup['attributes']['title']), - 'description' => $db->escape_string($settinggroup['attributes']['description']), - 'disporder' => (int)$settinggroup['attributes']['disporder'], - 'isdefault' => $settinggroup['attributes']['isdefault'], - ); - $gid = $db->insert_query('settinggroups', $groupdata); - ++$groupcount; - foreach($settinggroup['setting'] as $setting) - { - $settingdata = array( - 'name' => $db->escape_string($setting['attributes']['name']), - 'title' => $db->escape_string($setting['title'][0]['value']), - 'description' => $db->escape_string($setting['description'][0]['value']), - 'optionscode' => $db->escape_string($setting['optionscode'][0]['value']), - 'value' => $db->escape_string($setting['settingvalue'][0]['value']), - 'disporder' => (int)$setting['disporder'][0]['value'], - 'gid' => $gid, - 'isdefault' => 1 - ); - - $db->insert_query('settings', $settingdata); - $settingcount++; - } - } - - if(my_substr($mybb->get_input('bburl'), -1, 1) == '/') - { - $mybb->input['bburl'] = my_substr($mybb->get_input('bburl'), 0, -1); - } - - $db->update_query("settings", array('value' => $db->escape_string($mybb->get_input('bbname'))), "name='bbname'"); - $db->update_query("settings", array('value' => $db->escape_string($mybb->get_input('bburl'))), "name='bburl'"); - $db->update_query("settings", array('value' => $db->escape_string($mybb->get_input('websitename'))), "name='homename'"); - $db->update_query("settings", array('value' => $db->escape_string($mybb->get_input('websiteurl'))), "name='homeurl'"); - $db->update_query("settings", array('value' => $db->escape_string($mybb->get_input('cookiedomain'))), "name='cookiedomain'"); - $db->update_query("settings", array('value' => $db->escape_string($mybb->get_input('cookiepath'))), "name='cookiepath'"); - $db->update_query("settings", array('value' => $db->escape_string($mybb->get_input('contactemail'))), "name='adminemail'"); - $db->update_query("settings", array('value' => 'contact.php'), "name='contactlink'"); - - write_settings(); - - echo $lang->sprintf($lang->admin_step_insertesettings, $settingcount, $groupcount); - - // Save the acp pin - $pin = addslashes($mybb->get_input('pin')); - - $file = @fopen(MYBB_ROOT."inc/config.php", "a"); - - @fwrite($file, "/** - * Admin CP Secret PIN - * If you wish to request a PIN - * when someone tries to login - * on your Admin CP, enter it below. - */ - -\$config['secret_pin'] = '{$pin}';"); - - @fclose($file); - - include_once MYBB_ROOT."inc/functions_task.php"; - $tasks = file_get_contents(INSTALL_ROOT.'resources/tasks.xml'); - $parser = new XMLParser($tasks); - $parser->collapse_dups = 0; - $tree = $parser->get_tree(); - $taskcount = 0; - - // Insert scheduled tasks - foreach($tree['tasks'][0]['task'] as $task) - { - $new_task = array( - 'title' => $db->escape_string($task['title'][0]['value']), - 'description' => $db->escape_string($task['description'][0]['value']), - 'file' => $db->escape_string($task['file'][0]['value']), - 'minute' => $db->escape_string($task['minute'][0]['value']), - 'hour' => $db->escape_string($task['hour'][0]['value']), - 'day' => $db->escape_string($task['day'][0]['value']), - 'weekday' => $db->escape_string($task['weekday'][0]['value']), - 'month' => $db->escape_string($task['month'][0]['value']), - 'enabled' => $db->escape_string($task['enabled'][0]['value']), - 'logging' => $db->escape_string($task['logging'][0]['value']) - ); - - $new_task['nextrun'] = fetch_next_run($new_task); - - $db->insert_query("tasks", $new_task); - $taskcount++; - } - - // For the version check task, set a random date and hour (so all MyBB installs don't query mybb.com all at the same time) - $update_array = array( - 'hour' => rand(0, 23), - 'weekday' => rand(0, 6) - ); - - $db->update_query("tasks", $update_array, "file = 'versioncheck'"); - - echo $lang->sprintf($lang->admin_step_insertedtasks, $taskcount); - - $views = file_get_contents(INSTALL_ROOT.'resources/adminviews.xml'); - $parser = new XMLParser($views); - $parser->collapse_dups = 0; - $tree = $parser->get_tree(); - $view_count = 0; - - // Insert admin views - foreach($tree['adminviews'][0]['view'] as $view) - { - $fields = array(); - foreach($view['fields'][0]['field'] as $field) - { - $fields[] = $field['attributes']['name']; - } - - $conditions = array(); - if(isset($view['conditions'][0]['condition']) && is_array($view['conditions'][0]['condition'])) - { - foreach($view['conditions'][0]['condition'] as $condition) - { - if(!$condition['value']) continue; - if($condition['attributes']['is_serialized'] == 1) - { - $condition['value'] = my_unserialize($condition['value']); - } - $conditions[$condition['attributes']['name']] = $condition['value']; - } - } - - $custom_profile_fields = array(); - if(isset($view['custom_profile_fields'][0]['field']) && is_array($view['custom_profile_fields'][0]['field'])) - { - foreach($view['custom_profile_fields'][0]['field'] as $field) - { - $custom_profile_fields[] = $field['attributes']['name']; - } - } - - $new_view = array( - "uid" => 0, - "type" => $db->escape_string($view['attributes']['type']), - "visibility" => (int)$view['attributes']['visibility'], - "title" => $db->escape_string($view['title'][0]['value']), - "fields" => $db->escape_string(my_serialize($fields)), - "conditions" => $db->escape_string(my_serialize($conditions)), - "custom_profile_fields" => $db->escape_string(my_serialize($custom_profile_fields)), - "sortby" => $db->escape_string($view['sortby'][0]['value']), - "sortorder" => $db->escape_string($view['sortorder'][0]['value']), - "perpage" => (int)$view['perpage'][0]['value'], - "view_type" => $db->escape_string($view['view_type'][0]['value']) - ); - $db->insert_query("adminviews", $new_view); - $view_count++; - } - - echo $lang->sprintf($lang->admin_step_insertedviews, $view_count); - - echo $lang->admin_step_createadmin; - } - - echo $lang->sprintf($lang->admin_step_admintable, $adminuser, $adminemail); - $output->print_footer('final'); -} - -/** - * Installation is finished - */ -function install_done() -{ - global $output, $db, $mybb, $errors, $cache, $lang; - - if(empty($mybb->input['adminuser'])) - { - $errors[] = $lang->admin_step_error_nouser; - } - if(empty($mybb->input['adminpass'])) - { - $errors[] = $lang->admin_step_error_nopassword; - } - if($mybb->get_input('adminpass') != $mybb->get_input('adminpass2')) - { - $errors[] = $lang->admin_step_error_nomatch; - } - if(empty($mybb->input['adminemail'])) - { - $errors[] = $lang->admin_step_error_noemail; - } - if(is_array($errors)) - { - create_admin_user(); - } - - require MYBB_ROOT.'inc/config.php'; - $db = db_connection($config); - - require MYBB_ROOT.'inc/settings.php'; - $mybb->settings = &$settings; - - ob_start(); - $output->print_header($lang->finish_setup, 'finish'); - - echo $lang->done_step_usergroupsinserted; - - // Insert all of our user groups from the XML file - $usergroup_settings = file_get_contents(INSTALL_ROOT.'resources/usergroups.xml'); - $parser = new XMLParser($usergroup_settings); - $parser->collapse_dups = 0; - $tree = $parser->get_tree(); - - $admin_gid = ''; - $group_count = 0; - foreach($tree['usergroups'][0]['usergroup'] as $usergroup) - { - // usergroup[cancp][0][value] - $new_group = array(); - foreach($usergroup as $key => $value) - { - if(!is_array($value)) - { - continue; - } - - $new_group[$key] = $db->escape_string($value[0]['value']); - } - $db->insert_query("usergroups", $new_group, false); - - // If this group can access the admin CP and we haven't established the admin group - set it (just in case we ever change IDs) - if($new_group['cancp'] == 1 && !$admin_gid) - { - $admin_gid = $usergroup['gid'][0]['value']; - } - $group_count++; - } - - // Restart usergroup sequence with correct # of groups - if($config['database']['type'] == "pgsql") - { - $db->query("SELECT setval('{$config['database']['table_prefix']}usergroups_gid_seq', (SELECT max(gid) FROM {$config['database']['table_prefix']}usergroups));"); - } - - echo $lang->done . '

    '; - - echo $lang->done_step_admincreated; - $now = TIME_NOW; - $salt = random_str(); - $loginkey = generate_loginkey(); - $saltedpw = md5(md5($salt).md5($mybb->get_input('adminpass'))); - - $newuser = array( - 'username' => $db->escape_string($mybb->get_input('adminuser')), - 'password' => $saltedpw, - 'salt' => $salt, - 'loginkey' => $loginkey, - 'email' => $db->escape_string($mybb->get_input('adminemail')), - 'usergroup' => $admin_gid, // assigned above - 'regdate' => $now, - 'lastactive' => $now, - 'lastvisit' => $now, - 'website' => '', - 'icq' => '', - 'aim' => '', - 'yahoo' => '', - 'skype' =>'', - 'google' =>'', - 'birthday' => '', - 'signature' => '', - 'allownotices' => 1, - 'hideemail' => 0, - 'subscriptionmethod' => '0', - 'receivepms' => 1, - 'pmnotice' => 1, - 'pmnotify' => 1, - 'buddyrequestspm' => 1, - 'buddyrequestsauto' => 0, - 'showimages' => 1, - 'showvideos' => 1, - 'showsigs' => 1, - 'showavatars' => 1, - 'showquickreply' => 1, - 'invisible' => 0, - 'style' => '0', - 'timezone' => 0, - 'dst' => 0, - 'threadmode' => '', - 'daysprune' => 0, - 'regip' => $db->escape_binary(my_inet_pton(get_ip())), - 'language' => '', - 'showcodebuttons' => 1, - 'tpp' => 0, - 'ppp' => 0, - 'referrer' => 0, - 'buddylist' => '', - 'ignorelist' => '', - 'pmfolders' => '', - 'notepad' => '', - 'showredirect' => 1, - 'usernotes' => '' - ); - $db->insert_query('users', $newuser); - echo $lang->done . '

    '; - - echo $lang->done_step_adminoptions; - $adminoptions = file_get_contents(INSTALL_ROOT.'resources/adminoptions.xml'); - $parser = new XMLParser($adminoptions); - $parser->collapse_dups = 0; - $tree = $parser->get_tree(); - $insertmodule = array(); - - $db->delete_query("adminoptions"); - - // Insert all the admin permissions - foreach($tree['adminoptions'][0]['user'] as $users) - { - $uid = $users['attributes']['uid']; - - foreach($users['permissions'][0]['module'] as $module) - { - foreach($module['permission'] as $permission) - { - $insertmodule[$module['attributes']['name']][$permission['attributes']['name']] = $permission['value']; - } - } - - $defaultviews = array(); - foreach($users['defaultviews'][0]['view'] as $view) - { - $defaultviews[$view['attributes']['type']] = $view['value']; - } - - $adminoptiondata = array( - 'uid' => (int)$uid, - 'cpstyle' => '', - 'notes' => '', - 'permissions' => $db->escape_string(my_serialize($insertmodule)), - 'defaultviews' => $db->escape_string(my_serialize($defaultviews)) - ); - - $insertmodule = array(); - - $db->insert_query('adminoptions', $adminoptiondata); - } - echo $lang->done . '

    '; - - // Automatic Login - my_unsetcookie("sid"); - my_unsetcookie("mybbuser"); - my_setcookie('mybbuser', $uid.'_'.$loginkey, null, true); - ob_end_flush(); - - // Make fulltext columns if supported - if($db->supports_fulltext('threads')) - { - $db->create_fulltext_index('threads', 'subject'); - } - if($db->supports_fulltext_boolean('posts')) - { - $db->create_fulltext_index('posts', 'message'); - } - - echo $lang->done_step_cachebuilding; - require_once MYBB_ROOT.'inc/class_datacache.php'; - $cache = new datacache; - $cache->update_version(); - $cache->update_attachtypes(); - $cache->update_smilies(); - $cache->update_badwords(); - $cache->update_usergroups(); - $cache->update_forumpermissions(); - $cache->update_stats(); - $cache->update_statistics(); - $cache->update_forums(); - $cache->update_moderators(); - $cache->update_usertitles(); - $cache->update_reportedcontent(); - $cache->update_awaitingactivation(); - $cache->update_mycode(); - $cache->update_profilefields(); - $cache->update_posticons(); - $cache->update_spiders(); - $cache->update_bannedips(); - $cache->update_banned(); - $cache->update_bannedemails(); - $cache->update_birthdays(); - $cache->update_groupleaders(); - $cache->update_threadprefixes(); - $cache->update_forumsdisplay(); - $cache->update("plugins", array()); - $cache->update("internal_settings", array('encryption_key' => random_str(32))); - $cache->update_default_theme(); - $cache->update_reportreasons(true); - - $version_history = array(); - $dh = opendir(INSTALL_ROOT."resources"); - while(($file = readdir($dh)) !== false) - { - if(preg_match("#upgrade([0-9]+).php$#i", $file, $match)) - { - $version_history[$match[1]] = $match[1]; - } - } - sort($version_history, SORT_NUMERIC); - $cache->update("version_history", $version_history); - - // Schedule an update check so it occurs an hour ago. Gotta stay up to date! - $update['nextrun'] = TIME_NOW - 3600; - $db->update_query("tasks", $update, "tid='12'"); - - $cache->update_update_check(); - $cache->update_tasks(); - - echo $lang->done . '

    '; - - echo $lang->done_step_success; - - $written = 0; - if(is_writable('./')) - { - $lock = @fopen('./lock', 'w'); - $written = @fwrite($lock, '1'); - @fclose($lock); - if($written) - { - echo $lang->done_step_locked; - } - } - if(!$written) - { - echo $lang->done_step_dirdelete; - } - echo $lang->done_whats_next; - $output->print_footer(''); -} - -/** - * @param array $config - * - * @return DB_MySQL|DB_MySQLi|DB_PgSQL|DB_SQLite - */ -function db_connection($config) -{ - require_once MYBB_ROOT."inc/db_{$config['database']['type']}.php"; - switch($config['database']['type']) - { - case "sqlite": - $db = new DB_SQLite; - break; - case "pgsql": - $db = new DB_PgSQL; - break; - case "mysqli": - $db = new DB_MySQLi; - break; - default: - $db = new DB_MySQL; - } - - // Connect to Database - define('TABLE_PREFIX', $config['database']['table_prefix']); - - $db->connect($config['database']); - $db->set_table_prefix(TABLE_PREFIX); - $db->type = $config['database']['type']; - - return $db; -} - -/** - * @param array $array - * - * @return string - */ -function error_list($array) -{ - $string = "
      \n"; - foreach($array as $error) - { - $string .= "
    • {$error}
    • \n"; - } - $string .= "
    \n"; - return $string; -} - -/** - * Write our settings to the settings file - */ -function write_settings() -{ - global $db; - - $settings = ''; - $query = $db->simple_select('settings', '*', '', array('order_by' => 'title')); - while($setting = $db->fetch_array($query)) - { - $setting['value'] = str_replace("\"", "\\\"", $setting['value']); - $settings .= "\$settings['{$setting['name']}'] = \"{$setting['value']}\";\n"; - } - if(!empty($settings)) - { - $settings = " - - - - 1 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - 1 - - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 1 - 1 - 1 - 1 - 1 - - - 1 - 1 - 1 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 1 - 1 - 1 - 1 - 1 - - - 1 - 1 - 1 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - - \ No newline at end of file diff --git a/html/forums/install/resources/adminviews.xml b/html/forums/install/resources/adminviews.xml deleted file mode 100644 index b5bf293..0000000 --- a/html/forums/install/resources/adminviews.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - <![CDATA[All Users]]> - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/html/forums/install/resources/index.html b/html/forums/install/resources/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/install/resources/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/install/resources/language.lang.php b/html/forums/install/resources/language.lang.php deleted file mode 100644 index f2d7356..0000000 --- a/html/forums/install/resources/language.lang.php +++ /dev/null @@ -1,374 +0,0 @@ -Welcome to the installation wizard for MyBB {1}. MyBB has detected it is already configured this directory.

    -

    Please choose a suitable action below:

    - -
    -

    Upgrade my existing copy of MyBB to {1} (Recommended)

    -

    This option will upgrade your current version of MyBB to MyBB {1}.

    -

    You should choose this option when you wish to retain your current forum threads, posts, users and other information.

    -
    -
    -
    -
    - -
    -

    Install a new copy of MyBB

    -

    This option will delete any existing forum you may have set up and install a fresh version of MyBB.

    -

    You should choose this option to erase your existing copy of MyBB if you wish to start again.

    -
    - -
    -
    -
    "; - -$l['mybb_incorrect_folder'] = "
    -

    MyBB has detected that it is running from the \"Upload\" directory.

    -

    While there is nothing wrong with this, it is recommended that your upload the contents of the \"Upload\" directory and not the directory itself.

    For more information please see the MyBB Docs.

    -
    "; - -$l['welcome_step'] = '

    Welcome to the installation wizard for MyBB {1}. This wizard will install and configure a copy of MyBB on your server.

    -

    Now that you\'ve uploaded the MyBB files the database and settings need to be created and imported. Below is an outline of what is going to be completed during installation.

    -
      -
    • MyBB requirements checked
    • -
    • Configuration of database engine
    • -
    • Creation of database tables
    • -
    • Default data inserted
    • -
    • Default themes and templates imported
    • -
    • Creation of an administrator account to manage your board
    • -
    • Basic board settings configured
    • -
    -

    After each step has successfully been completed, click Next to move on to the next step.

    -

    Click "Next" to view the MyBB license agreement.

    -

    (What information is sent?)

    '; - -$l['license_step'] = '
    -{1} -
    -

    By clicking Next, you agree to the terms stated in the MyBB License Agreement above.

    '; - - -$l['req_step_top'] = '

    Before you can install MyBB, we must check that you meet the minimum requirements for installation.

    '; -$l['req_step_reqtable'] = '
    -
    Requirements Check
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Requirements
    PHP Version:{1}
    Supported DB Extensions:{2}
    Supported Translation Extensions:{3}
    PHP XML Extensions:{4}
    Configuration File Writable:{5}
    Settings File Writable:{6}
    Cache Directory Writable:{7}
    File Uploads Directory Writable:{8}
    Avatar Uploads Directory Writable:{9}
    -
    '; -$l['req_step_reqcomplete'] = '

    Congratulations, you meet the requirements to run MyBB.

    -

    Click Next to continue with the installation process.

    '; - -$l['req_step_span_fail'] = '{1}'; -$l['req_step_span_pass'] = '{1}'; - -$l['req_step_error_box'] = '

    {1}

    '; -$l['req_step_error_phpversion'] = 'MyBB Requires PHP 5.2.0 or later to run. You currently have {1} installed.'; -$l['req_step_error_dboptions'] = 'MyBB requires one or more suitable database extensions to be installed. Your server reported that none were available.'; -$l['req_step_error_xmlsupport'] = 'MyBB requires PHP to be compiled with support for XML Data Handling. Please see PHP.net for more information.'; -$l['req_step_error_configdefaultfile'] = 'The configuration file (inc/config.default.php) could not be renamed. Please manually rename the config.default.php file to config.php to allow it to be written to or contact MyBB Support.'; -$l['req_step_error_configfile'] = 'The configuration file (inc/config.php) is not writable. Please adjust the chmod permissions to allow it to be written to.'; -$l['req_step_error_settingsfile'] = 'The settings file (inc/settings.php) is not writable. Please adjust the chmod permissions to allow it to be written to.'; -$l['req_step_error_cachedir'] = 'The cache directory (cache/) is not writable. Please adjust the chmod permissions to allow it to be written to.'; -$l['req_step_error_uploaddir'] = 'The uploads directory (uploads/) is not writable. Please adjust the chmod permissions to allow it to be written to.'; -$l['req_step_error_avatardir'] = 'The avatars directory (uploads/avatars/) is not writable. Please adjust the chmod permissions to allow it to be written to.'; -$l['req_step_error_cssddir'] = 'The css directory (css/) is not writable. Please adjust the chmod permissions to allow it to be written to.'; -$l['req_step_error_tablelist'] = '
    -

    Error

    -

    The MyBB Requirements check failed due to the reasons below. MyBB installation cannot continue because you did not meet the MyBB requirements. Please correct the errors below and try again:

    -{1} -
    '; - - -$l['db_step_config_db'] = '

    It is now time to configure the database that MyBB will use as well as your database authentication details. If you do not have this information, it can usually be obtained from your webhost.

    '; -$l['db_step_config_table'] = '
    -
    Database Configuration
    - - - - - - - - -{2} -
    Database Settings
    -
    -

    Once you\'ve checked these details are correct, click next to continue.

    '; - -$l['database_settings'] = "Database Settings"; -$l['database_path'] = "Database Path:"; -$l['database_host'] = "Database Server Hostname:"; -$l['database_user'] = "Database Username:"; -$l['database_pass'] = "Database Password:"; -$l['database_name'] = "Database Name:"; -$l['table_settings'] = "Table Settings"; -$l['table_prefix'] = "Table Prefix:"; -$l['table_encoding'] = "Table Encoding:"; - -$l['db_step_error_config'] = '
    -

    Error

    -

    There seems to be one or more errors with the database configuration information that you supplied:

    -{1} -

    Once the above are corrected, continue with the installation.

    -
    '; -$l['db_step_error_invalidengine'] = 'You have selected an invalid database engine. Please make your selection from the list below.'; -$l['db_step_error_noconnect'] = 'Could not connect to the database server at \'{1}\' with the supplied username and password. Are you sure the hostname and user details are correct?'; -$l['db_step_error_nodbname'] = 'Could not select the database \'{1}\'. Are you sure it exists and the specified username and password have access to it?'; -$l['db_step_error_missingencoding'] = 'You have not selected an encoding yet. Please make sure you selected an encoding before continuing. (Select \'UTF-8 Unicode\' if you are not sure)'; -$l['db_step_error_sqlite_invalid_dbname'] = 'You may not use relative URLs for SQLite databases. Please use a file system path (ex: /home/user/database.db) for your SQLite database.'; -$l['db_step_error_invalid_tableprefix'] = 'You may only use an underscore (_) and alphanumeric characters in a table prefix. Please use a valid table prefix before continuing.'; -$l['db_step_error_tableprefix_too_long'] = 'You may only use a table prefix with a length of 40 characters or less. Please use a shorter table prefix before continuing.'; -$l['db_step_error_utf8mb4_error'] = '\'4-Byte UTF-8 Unicode\' requires MySQL 5.5.3 or above. Please select an encoding which is compatible with your MySQL version.'; - -$l['tablecreate_step_connected'] = '

    Connection to the database server and database you specified was successful.

    -

    Database Engine: {1} {2}

    -

    The MyBB database tables will now be created.

    '; -$l['tablecreate_step_created'] = 'Creating table {1}...'; -$l['tablecreate_step_done'] = '

    All tables have been created, click Next to populate them.

    '; - -$l['populate_step_insert'] = '

    Now that the basic tables have been created, it\'s time to insert the default data.

    '; -$l['populate_step_inserted'] = '

    The default data has successfully been inserted into the database. Click Next to insert the default MyBB template and theme sets.

    '; - - -$l['theme_step_importing'] = '

    Loading and importing theme and template file...

    '; -$l['theme_step_imported'] = '

    The default theme and template sets have been successfully inserted. Click Next to configure the basic options for your board.

    '; - - -$l['config_step_table'] = '

    It is now time for you to configure the basic settings for your forums such as forum name, URL, your website details, along with your "cookie" domain and paths. These settings can easily be changed in the future through the MyBB Admin Control Panel.

    -
    -
    Board Configuration
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Forum Details
    Website Details
    Cookie settings (?)
    Contact Details
    Security Settings

    Leave this empty if you don\'t want to set one
    -
    - -

    Once you\'ve correctly entered the details above and are ready to proceed, click Next.

    '; - -$l['config_step_error_config'] = '
    -

    Error

    -

    There seems to be one or more errors with the board configuration you supplied:

    -{1} -

    Once the above are corrected, continue with the installation.

    -
    '; -$l['config_step_error_url'] = 'You did not enter the URL to your forums.'; -$l['config_step_error_name'] = 'You did not enter a name for your copy of MyBB.'; -$l['config_step_revert'] = 'Click to revert this setting to original value.'; - - -$l['admin_step_setupsettings'] = '

    Setting up basic board settings...

    '; -$l['admin_step_insertesettings'] = '

    Inserted {1} settings into {2} groups.

    -

    Updating settings with user defined values.

    '; -$l['admin_step_insertedtasks'] = '

    Inserted {1} scheduled tasks.

    '; -$l['admin_step_insertedviews'] = '

    Inserted {1} admin views.

    '; -$l['admin_step_createadmin'] ='

    You need to create an initial administrator account for you to login and manage your copy of MyBB. Please fill in the required fields below to create this account.

    '; -$l['admin_step_admintable'] = '
    -
    Administrator Account Details
    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Account Details
    Contact Details
    -
    - -

    Once you\'ve correctly entered the details above and are ready to proceed, click Next.

    '; - -$l['admin_step_error_config'] = '
    -

    Error

    -

    There seems to be one or more errors with the board configuration you supplied:

    -{1} -

    Once the above are corrected, continue with the installation.

    -
    '; -$l['admin_step_error_nouser'] = 'You did not enter a username for your Administrator account.'; -$l['admin_step_error_nopassword'] = 'You did not enter a password for your Administrator account.'; -$l['admin_step_error_nomatch'] = 'The passwords you entered do not match.'; -$l['admin_step_error_noemail'] = 'You did not enter your email address for the Administrator\'s account.'; -$l['admin_step_nomatch'] = 'The retyped password does not match the password from the first input. Please correct it before continuing.'; - -$l['done_step_usergroupsinserted'] = "

    Importing user groups..."; -$l['done_step_admincreated'] = '

    Creating Administrator account...'; -$l['done_step_adminoptions'] = '

    Building Administrator permissions...'; -$l['done_step_cachebuilding'] = '

    Building data caches...'; -$l['done_step_success'] = '

    Your copy of MyBB has successfully been installed and configured correctly.

    -

    The MyBB Group thanks you for your support in installing our software and we hope to see you around the Community Forums if you need help or wish to become a part of the MyBB community.

    '; -$l['done_step_locked'] = '

    Your installer has been locked. To unlock the installer please delete the \'lock\' file in this directory.

    You may now proceed to your new copy of MyBB or its Admin Control Panel.

    '; -$l['done_step_dirdelete'] = '

    Please remove this directory before exploring your copy of MyBB.

    '; -$l['done_whats_next'] = '

    Switching from another forum software?

    MyBB offers a merge system for easy merging of multiple forums from various different popular forum software, allowing an easy conversion process to MyBB. If you\'re looking to switch to MyBB, you\'re heading in the right direction! Check out the Merge System for more information.

    '; - -/* UPGRADE LANGUAGE VARIABLES */ -$l['upgrade'] = "Upgrade Process"; -$l['upgrade_welcome'] = "

    Welcome to the upgrade wizard for MyBB {1}.

    Before you continue, please make sure you know which version of MyBB you were previously running as you will need to select it below.

    We strongly recommend that you also obtain a complete backup of your database and files before attempting to upgrade so if something goes wrong you can easily revert back to the previous version. Also, ensure that your backups are complete before proceeding.

    Make sure you only click Next ONCE on each step of the upgrade process. Pages may take a while to load depending on the size of your forum.

    Once you are ready, please select your old version below and click Next to continue.

    "; -$l['upgrade_templates_reverted'] = 'Templates Reverted'; -$l['upgrade_templates_reverted_success'] = "

    All of the templates have successfully been reverted to the new ones contained in this release. Please press next to continue with the upgrade process.

    "; -$l['upgrade_settings_sync'] = 'Settings Synchronization'; -$l['upgrade_settings_sync_success'] = "

    The board settings have been synchronized with the latest in MyBB.

    {1} new settings inserted along with {2} new setting groups.

    To finalize the upgrade, please click next below to continue.

    "; -$l['upgrade_datacache_building'] = 'Data Cache Building'; -$l['upgrade_building_datacache'] = '

    Building caches...'; -$l['upgrade_continue'] = 'Please press next to continue'; -$l['upgrade_locked'] = "

    Your installer has been locked. To unlock the installer please delete the 'lock' file in this directory.

    You may now proceed to your upgraded copy of MyBB or its Admin Control Panel.

    "; -$l['upgrade_removedir'] = 'Please remove this directory before exploring your upgraded MyBB.'; -$l['upgrade_congrats'] = "

    Congratulations, your copy of MyBB has successfully been updated to {1}.

    {2}

    What's Next?

    • Please use the 'Find Updated Templates' tool in the Admin CP to find customized templates updated during this upgrade process. Edit them to contain the changes or revert them to originals.
    • Ensure that your board is still fully functional.
    "; -$l['upgrade_template_reversion'] = "Template Reversion Warning"; -$l['upgrade_template_reversion_success'] = "

    All necessary database modifications have successfully been made to upgrade your board.

    This upgrade requires all templates to be reverted to the new ones contained in the package so please back up any custom templates you have made before clicking next."; -$l['upgrade_send_stats'] = "

    (What information is sent?)

    "; - -$l['please_login'] = "Please Login"; -$l['login'] = "Login"; -$l['login_desc'] = "Please enter your username and password to begin the upgrade process. You must be a valid forum administrator to perform the upgrade."; -$l['login_username'] = "Username"; -$l['login_password'] = "Password"; -$l['login_password_desc'] = "Please note that passwords are case sensitive."; - -/* Error messages */ -$l['development_preview'] = "

    Warning

    This version of MyBB is a development preview and is to be used for testing purposes only.

    No official support, other than for plugins and theme development, will be provided for this version. By continuing with this install/upgrade you do so at your own risk.

    "; -$l['locked'] = 'The installer is currently locked, please remove \'lock\' from the install directory to continue'; -$l['no_permision'] = "You do not have permissions to run this process. You need administrator permissions to be able to run the upgrade procedure.

    If you need to logout, please click here. From there you will be able to log in again under your administrator account."; -$l['no_theme_functions_file'] = 'No theme functions file has been found. Make sure that all files are uploaded properly.'; - -$l['task_versioncheck_ran'] = "The version check task successfully ran."; diff --git a/html/forums/install/resources/mybb_theme.xml b/html/forums/install/resources/mybb_theme.xml deleted file mode 100644 index 739e0dc..0000000 --- a/html/forums/install/resources/mybb_theme.xml +++ /dev/null @@ -1,14118 +0,0 @@ - - - - - - - - - - - - .expcolimage { - margin-top: 0; -} - -blockquote { - border: 1px solid #ccc; - margin: 0; - background: #fff; - padding: 10px; -} - -blockquote cite { - font-weight: bold; - border-bottom: 1px solid #ccc; - font-style: normal; - display: block; - padding-bottom: 3px; - margin: 0 0 10px 0; -} - -blockquote cite span { - float: right; - font-weight: normal; - font-size: 12px; - color: #666; -} - -blockquote cite span.highlight { - float: none; - font-weight: bold; - padding-bottom: 0; -} - -.codeblock { - background: #fff; - border: 1px solid #ccc; - padding: 10px; -} - -.codeblock .title { - border-bottom: 1px solid #ccc; - font-weight: bold; - padding-bottom: 3px; - margin: 0 0 10px 0; -} - -.codeblock code { - overflow: auto; - height: auto; - max-height: 200px; - display: block; - font-family: Monaco, Consolas, Courier, monospace; - font-size: 13px; -} - -.smilie { - vertical-align: middle; -} - -.smilie_pointer { - cursor: pointer; -} - -.separator { - margin: 5px; - padding: 0; - height: 0px; - font-size: 1px; - list-style-type: none; -} - -.popup_menu .popup_item_container { - margin: 1px; - text-align: left; -} - -.popup_menu .popup_item { - display: block; - padding: 4px; - white-space: nowrap; - text-decoration: none; -} - -.popup_menu a.popup_item:hover { - text-decoration: none; -} - -.subject_new { - font-weight: bold; -} - -.highlight { - background: #FFFFCC; - padding-top: 3px; - padding-bottom: 3px; -} - -.pm_alert { - background: #FFF6BF; - border: 1px solid #FFD324; - text-align: center; - padding: 5px 20px; - margin-bottom: 15px; - font-size: 11px; -} - -.red_alert { - background: #FBE3E4; - border: 1px solid #A5161A; - color: #A5161A; - text-align: center; - padding: 5px 20px; - margin-bottom: 15px; - font-size: 11px; - word-wrap: break-word; -} - -.red_alert a:link, -.red_alert a:visited, -.red_alert a:hover, -.red_alert a:active { - color: #A5161A; -} - -.high_warning { - color: #CC0000; -} - -.moderate_warning { - color: #F3611B; -} - -.low_warning { - color: #AE5700; -} - -.imminent_banned { - color: #880000; -} - -.high_banned { - color: #FF0000; -} - -.moderate_banned { - color: #FF6600; -} - -.low_banned { - color: #008000; -} - -.online { - color: #15A018; -} - -.offline { - color: #C7C7C7; -} - -div.error { - padding: 5px 10px; - border: 2px solid #FFD324; - background: #FFF6BF; - font-size: 12px; -} - -div.error p { - margin: 0; - color: #333; - font-weight: normal; -} - -div.error p em { - font-style: normal; - font-weight: bold; - padding-left: 24px; - display: block; - color: #C00; - background: url(images/error.png) no-repeat 0; -} - -div.error ul { - margin-left: 24px; -} - -.pagination { - font-size: 11px; - padding-top: 10px; - margin-bottom: 5px; -} - -.tfoot .pagination, -.tcat .pagination { - padding-top: 0; -} - -.pagination .pages { - font-weight: bold; -} - -.pagination .pagination_current, -.pagination a { - padding: 3px 6px; - margin-bottom: 3px; -} - -.pagination a { - background: #f5f5f5; - border: 1px solid #ccc; -} - -.pagination .pagination_current { - background: none; - color: #333; - border: none; - font-weight: bold; -} - -.pagination a:hover { - background: #0072BC; - color: #fff; - border-color: #263c30; - text-decoration: none; -} - -.pagination .go_page img { - margin-bottom: -4px; -} - -.drop_go_page { - background: #f5f5f5; - padding: 4px; -} - -.pagination_breadcrumb { - background-color: #efefef; - border: 1px solid #fff; - outline: 1px solid #ccc; - padding: 5px; - margin-top: 5px; - font-weight: normal; -} - -.pagination_breadcrumb_link { - vertical-align: middle; - cursor: pointer; -} - -.thread_legend, -.thread_legend dd { - margin: 0; - padding: 0; -} - -.thread_legend dd { - padding-bottom: 4px; - margin-right: 15px; -} - -.thread_legend img { - margin-right: 4px; - vertical-align: bottom; -} - -.forum_legend, -.forum_legend dt, -.forum_legend dd { - margin: 0; - padding: 0; -} - -.forum_legend dd { - float: left; - margin-right: 10px; - margin-top: 7px; -} - -.forum_legend dt { - margin-right: 10px; - float: left; -} - -.success_message { - color: #00b200; - font-weight: bold; - font-size: 10px; - margin-bottom: 10px; -} - -.error_message { - color: #C00; - font-weight: bold; - font-size: 10px; - margin-bottom: 10px; -} - -#posts_container { - padding: 0; -} - -.ignored_post { - border-top: 3px solid #333; - padding: 15px; -} - -.ignored_post .show_ignored_post { - margin-top: -15px; -} - -.ignored_post .show_ignored_post a.button span { - background-position: 0 -400px; -} - -.deleted_post_hidden { - border-top: 2px solid #ccc; - padding: 15px; -} - -.deleted_post_collapsed { - border-top: 3px solid #333; - padding: 15px; -} - -.deleted_post_collapsed .show_deleted_post { - margin-top: -15px; -} - -.deleted_post_collapsed .show_deleted_post a.button span { - background-position: 0 -400px; -} - -.post { - overflow: hidden; -} - -.post.classic { - padding-top: 15px; -} - -.post .post_author { - border-bottom: 1px solid #ccc; - border-top: 2px solid #ccc; - background: #f5f5f5; - padding: 5px; - overflow: hidden; -} - -.post.classic .post_author { - border: 1px solid #ddd; - float: left; - width: 15%; - margin: 0 1% 15px 0; - border-left: 0; - padding: 5px 1%; -} - -.post .post_author .buddy_status { - vertical-align: middle; - margin-top: -4px; -} - -.post .post_author div.author_avatar { - float: left; - margin-right: 3px; -} - -.post.classic .post_author div.author_avatar { - float: none; - text-align: center; - margin-bottom: 8px; -} - -.post .post_author div.author_avatar img { - padding: 5px; - border: 1px solid #ddd; - background: #fff; -} - -.post .post_author div.author_information { - float: left; - padding: 6px 8px; -} - -.post.classic .post_author div.author_information { - float: none; - padding: 0; - text-align: center; -} - -.post .post_author div.author_statistics { - float: right; - font-size: 11px; - padding: 3px 10px 3px 5px; - color: #666; - line-height: 1.3; -} - -.post.classic .post_author div.author_statistics { - border-top: 1px dotted #ccc; - margin: 6px 0 0 0; - padding: 6px 6px 3px 6px; - float: none; -} - -.post .post_head { - font-size: 11px; - padding-bottom: 4px; - border-bottom: 1px dotted #ddd; - margin-bottom: 4px; -} - -.post .post_head span.post_date { - color: #666; -} - -.post .post_head span.edited_post { - font-size: 10px; - color: #999; -} - -.post .post_head span.edited_post a { - color: #666; -} - -.post_body { - font-size: 14px; - padding: 12px 0; -} - -.post.classic .post_content { - float: left; - width: 79%; - padding: 0 1% 5px 1%; -} - -.post_content { - padding: 9px 10px 5px 10px; -} - -.post_content .signature { - margin-top: 5px; - border-top: 1px dotted #ddd; - padding: 10px 0 4px 0; -} - -.post .post_meta { - margin: 4px 0; - font-size: 11px; - color: #999; -} - -.post .post_meta a:link, -.post .post_meta a:visited { - color: #777; -} - -.post .post_meta a:hover, -.post .post_meta a:active { - color: #777; -} - -.post_controls { - clear: both; - background: #f5f5f5; - border-bottom: 1px solid #ccc; - padding: 5px; - overflow: hidden; -} - -.postbit_buttons > a:link, -.postbit_buttons > a:hover, -.postbit_buttons > a:visited, -.postbit_buttons > a:active { - display: inline-block; - padding: 2px 5px; - margin: 2px; - font-size: 11px; - background: #eee url(images/buttons_bg.png) repeat-x; - border: 1px solid #ccc; - color: #555; -} - -.postbit_buttons > a:hover { - border-color: #bbb; -} - -.postbit_buttons a span { - padding-left: 20px; - display: inline-block; - height: 16px; - background-image: url(images/buttons_sprite.png); - background-repeat: no-repeat; -} - -.postbit_buttons a.postbit_find span { - background-position: 0 0; -} - -.postbit_buttons a.postbit_reputation_add span { - background-position: 0 -20px; -} - -.postbit_buttons a.postbit_email span { - background-position: 0 -40px; -} - -.postbit_buttons a.postbit_website span { - background-position: 0 -60px; -} - -.postbit_buttons a.postbit_pm span { - background-position: 0 -80px; -} - -.postbit_buttons a.postbit_quote span { - background-position: 0 -100px; -} - -.postbit_buttons a.postbit_multiquote span { - background-position: 0 -120px; -} - -.postbit_buttons a.postbit_multiquote_on span { - background-position: 0 -140px; -} - -.postbit_buttons a.postbit_edit span { - background-position: 0 -160px; -} - -.postbit_buttons a.postbit_qdelete span { - background-position: 0 -180px; -} - -.postbit_buttons a.postbit_qrestore span { - background-position: 0 -200px; -} - -.postbit_buttons a.postbit_report span { - background-position: 0 -220px; -} - -.postbit_buttons a.postbit_warn span { - background-position: 0 -240px; -} - -.postbit_buttons a.postbit_purgespammer span { - background-position: 0 -540px; -} - -.postbit_buttons a.postbit_reply_pm span { - background-position: 0 -260px; -} - -.postbit_buttons a.postbit_reply_all span { - background-position: 0 -280px; -} - -.postbit_buttons a.postbit_forward_pm span { - background-position: 0 -300px; -} - -.postbit_buttons a.postbit_delete_pm span { - background-position: 0 -320px; -} - -a.button:link, -a.button:hover, -a.button:visited, -a.button:active { - background: #0f0f0f url(images/tcat.png) repeat-x; - color: #fff; - display: inline-block; - padding: 4px 8px; - margin: 2px 2px 6px 2px; - border: 1px solid #000; - font-size: 14px; -} - -a.button.small_button { - font-size: 13px; - margin: 0; - padding: 3px 6px; -} - -a.button span { - padding-left: 20px; - display: inline-block; - background-image: url(images/buttons_sprite.png); - background-repeat: no-repeat; -} - -a.button.new_thread_button span { - background-position: 0 -340px; -} - -a.button.new_reply_button span { - background-position: 0 -360px; -} - -a.button.closed_button span { - background-position: 0 -380px; -} - -a.button.rate_user_button span { - background-position: 0 -400px; -} - -a.button.add_buddy_button span { - background-position: 0 -440px; -} - -a.button.remove_buddy_button span { - background-position: 0 -480px; -} - -a.button.add_ignore_button span { - background-position: 0 -460px; -} - -a.button.remove_ignore_button span { - background-position: 0 -500px; -} - -a.button.report_user_button span { - background-position: 0 -520px; -} - -.quick_jump { - background: url(images/jump.png) no-repeat 0; - width: 13px; - height: 13px; - padding-left: 13px; /* amount of padding needed for image to fully show */ - margin-top: -3px; - border: none; -} - -.pollbar { - background: url(images/pollbar.png) top left repeat-x; - border: 1px solid #3f3f3f; - height: 10px; -} - -.pollbar .percent { - display: none; -} - -.posticons_label { - white-space: nowrap; -} - -/** jGrowl Start **/ - -/** Special IE6 Style Positioning **/ -.ie6 { - position: absolute; -} - -.ie6.top-right { - right: auto; - bottom: auto; - left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); - top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); -} - -.ie6.top-left { - left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); - top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); -} - -.ie6.bottom-right { - left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); - top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); -} - -.ie6.bottom-left { - left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); - top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); -} - -.ie6.center { - left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); - top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); - width: 100%; -} - -/** jGrowl Styling **/ -.jGrowl { - z-index: 9999; - color: #ffffff; - font-size: 12px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - position: fixed; -} -.jGrowl.top-left { - left: 0px; - top: 0px; -} -.jGrowl.top-right { - right: 0px; - top: 0px; -} -.jGrowl.bottom-left { - left: 0px; - bottom: 0px; -} -.jGrowl.bottom-right { - right: 0px; - bottom: 0px; -} -.jGrowl.center { - top: 0px; - width: 50%; - left: 25%; -} - -/** Cross Browser Styling **/ - -.jGrowl.center .jGrowl-notification, -.jGrowl.center .jGrowl-closer { - margin-left: auto; - margin-right: auto; -} -.jGrowl-notification { - background-color: transparent; - opacity: 0.9; - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=(0.9*100)); - -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=(0.9*100)); - zoom: 1; - width: 250px; - padding: 10px; - margin: 10px; - text-align: left; - display: none; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; - word-break: break-all; -} -.jGrowl .jGrowl-notification { - min-height: 40px; -} -.jGrowl-notification .ui-state-highlight, -.jGrowl-notification .ui-widget-content .ui-state-highlight, -.jGrowl-notification .ui-widget-header .ui-state-highlight { - border: 1px solid #000; - background: #000; - color: #fff; -} -.jGrowl-notification .jGrowl-header { - font-weight: bold; - font-size: .85em; -} -.jGrowl-notification .jGrowl-close { - background-color: transparent; - color: inherit; - border: none; - z-index: 99; - float: right; - font-weight: bold; - font-size: 1em; - cursor: pointer; -} -.jGrowl-closer { - background-color: #000000; - opacity: 0.9; - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=(0.9*100)); - -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=(0.9*100)); - zoom: 1; - width: 250px; - padding: 10px; - margin: 10px; - text-align: left; - display: none; - border-radius: 5px; - word-break: break-all; - padding-top: 4px; - padding-bottom: 4px; - cursor: pointer; - font-size: .9em; - font-weight: bold; - text-align: center; -} -.jGrowl-closer .ui-state-highlight, -.jGrowl-closer .ui-widget-content .ui-state-highlight, -.jGrowl-closer .ui-widget-header .ui-state-highlight { - border: 1px solid #000; - background: #000; - color: #fff; -} - -.jGrowl .jGrowl-notification.jgrowl_success { - background: lightgreen; - border: 1px solid lightgreen; - color: #333; -} - -.jGrowl .jGrowl-notification.jgrowl_error { - background: red; - border: 1px solid red; - color: #333; -} - -.jGrowl .jGrowl-notification.jgrowl_process, .jGrowl .jGrowl-closer { - background: yellow; - border: 1px solid yellow; - color: #333; -} - -/** Hide jGrowl when printing **/ -@media print { - .jGrowl { - display: none; - } -} - -/** jGrowl End **/ - -/** Modal Start **/ - -.modal { - display: none; - width: 400px; - text-align: left; - background: #fff; - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - -o-border-radius: 8px; - -ms-border-radius: 8px; - border-radius: 8px; - -webkit-box-shadow: 0 0 10px #000; - -moz-box-shadow: 0 0 10px #000; - -o-box-shadow: 0 0 10px #000; - -ms-box-shadow: 0 0 10px #000; - box-shadow: 0 0 10px #000; -} - -.modal a.close-modal { - position: absolute; - top: -12.5px; - right: -12.5px; - display: block; - width: 30px; - height: 30px; - text-indent: -9999px; - background: url(images/close.png) no-repeat 0 0; -} - -.modal-spinner { - display: none; - width: 64px; - height: 64px; - position: fixed; - top: 50%; - left: 50%; - margin-right: -32px; - margin-top: -32px; - background: url(images/spinner_big.gif) no-repeat center center; - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - -o-border-radius: 8px; - -ms-border-radius: 8px; - border-radius: 8px; -} - -/** Modal End **/ - -/** Impromptu Start **/ - -/*! jQuery-Impromptu - v6.2.1 - 2015-05-10 -* http://trentrichardson.com/Impromptu -* Copyright (c) 2015 Trent Richardson; Licensed MIT */ - -.jqifade{ - position: absolute; - background-color: #777777; -} -iframe.jqifade{ - display:block; - z-index:-1; -} -div.jqi{ - width: 400px; - max-width:90%; - font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; - position: absolute; - background-color: #ffffff; - font-size: 11px; - text-align: left; - border: solid 1px #eeeeee; - border-radius: 6px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - padding: 7px; -} -div.jqi .jqicontainer{ -} -div.jqi .jqiclose{ - position: absolute; - top: 4px; right: -2px; - width: 18px; - cursor: default; - color: #bbbbbb; - font-weight: bold; -} -div.jqi .jqistate{ - background-color: #fff; -} -div.jqi .jqititle{ - padding: 5px 10px; - font-size: 16px; - line-height: 20px; - border-bottom: solid 1px #eeeeee; -} -div.jqi .jqimessage{ - padding: 10px; - line-height: 20px; - color: #444444; - overflow: auto; -} -div.jqi .jqibuttonshide{ - display: none; -} -div.jqi .jqibuttons{ - text-align: right; - margin: 0 -7px -7px -7px; - border-top: solid 1px #e4e4e4; - background-color: #f4f4f4; - border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - -webkit-border-radius: 0 0 6px 6px; -} -div.jqi .jqibuttons button{ - margin: 0; - padding: 15px 20px; - background-color: transparent; - font-weight: normal; - border: none; - border-left: solid 1px #e4e4e4; - color: #777; - font-weight: bold; - font-size: 12px; -} -div.jqi .jqibuttons button.jqidefaultbutton{ - color: #489afe; -} -div.jqi .jqibuttons button:hover, -div.jqi .jqibuttons button:focus{ - color: #287ade; - outline: none; -} -div.jqi .jqibuttons button[disabled]{ - color: #aaa; -} -.jqiwarning .jqi .jqibuttons{ - background-color: #b95656; -} - -/* sub states */ -div.jqi .jqiparentstate::after{ - background-color: #777; - opacity: 0.6; - filter: alpha(opacity=60); - content: ''; - position: absolute; - top:0;left:0;bottom:0;right:0; - border-radius: 6px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; -} -div.jqi .jqisubstate{ - position: absolute; - top:0; - left: 20%; - width: 60%; - padding: 7px; - border: solid 1px #eeeeee; - border-top: none; - border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - -webkit-border-radius: 0 0 6px 6px; -} -div.jqi .jqisubstate .jqibuttons button{ - padding: 10px 18px; -} - -/* arrows for tooltips/tours */ -.jqi .jqiarrow{ position: absolute; height: 0; width:0; line-height: 0; font-size: 0; border: solid 10px transparent;} - -.jqi .jqiarrowtl{ left: 10px; top: -20px; border-bottom-color: #ffffff; } -.jqi .jqiarrowtc{ left: 50%; top: -20px; border-bottom-color: #ffffff; margin-left: -10px; } -.jqi .jqiarrowtr{ right: 10px; top: -20px; border-bottom-color: #ffffff; } - -.jqi .jqiarrowbl{ left: 10px; bottom: -20px; border-top-color: #ffffff; } -.jqi .jqiarrowbc{ left: 50%; bottom: -20px; border-top-color: #ffffff; margin-left: -10px; } -.jqi .jqiarrowbr{ right: 10px; bottom: -20px; border-top-color: #ffffff; } - -.jqi .jqiarrowlt{ left: -20px; top: 10px; border-right-color: #ffffff; } -.jqi .jqiarrowlm{ left: -20px; top: 50%; border-right-color: #ffffff; margin-top: -10px; } -.jqi .jqiarrowlb{ left: -20px; bottom: 10px; border-right-color: #ffffff; } - -.jqi .jqiarrowrt{ right: -20px; top: 10px; border-left-color: #ffffff; } -.jqi .jqiarrowrm{ right: -20px; top: 50%; border-left-color: #ffffff; margin-top: -10px; } -.jqi .jqiarrowrb{ right: -20px; bottom: 10px; border-left-color: #ffffff; } - -/** Impromptu End */ -]]> - - - - - - td { - border-bottom: 0; -} - -.tborder tbody tr:last-child > td:first-child { - -moz-border-radius-bottomleft: 6px; - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; -} - -.tborder tbody tr:last-child > td:last-child { - -moz-border-radius-bottomright: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; -} - -.thead { - -moz-border-radius-topleft: 6px; - -moz-border-radius-topright: 6px; - -webkit-border-top-left-radius: 6px; - -webkit-border-top-right-radius: 6px; - border-top-left-radius: 6px; - border-top-right-radius: 6px; -} - -.thead_collapsed { - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-bottomright: 6px; - -webkit-border-bottom-left-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; -} - -.thead_left { - -moz-border-radius-topright: 0; - -webkit-border-top-right-radius: 0; - border-top-right-radius: 0; -} - -.thead_right { - -moz-border-radius-topleft: 0; - -webkit-border-top-left-radius: 0; - border-top-left-radius: 0; -} - -.tcat_menu { - -moz-border-radius: 0 !important; - -webkit-border-radius: 0 !important; - border-radius: 0 !important; -} - -.tborder tbody:nth-last-child(2) .tcat_collapse_collapsed { - -moz-border-radius-bottomleft: 6px !important; - -moz-border-radius-bottomright: 6px !important; - -webkit-border-bottom-left-radius: 6px !important; - -webkit-border-bottom-right-radius: 6px !important; - border-bottom-left-radius: 6px !important; - border-bottom-right-radius: 6px !important; -} - -button, -input.button, -input.textbox, -input.invalid_field, -input.valid_field, -select, -textarea, -.editor_control_bar, -blockquote, -.codeblock, -fieldset, -.pm_alert, -.red_alert, -.popup_menu, -.postbit_buttons > a, -a.button { - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -.post.classic .post_author { - -moz-border-radius: 0 6px 6px 0; - -webkit-border-radius: 0 6px 6px 0; - border-radius: 0 6px 6px 0; -} - -.popup_menu .popup_item_container:first-child .popup_item { - -moz-border-radius-topleft: 6px; - -moz-border-radius-topright: 6px; - -webkit-border-top-left-radius: 6px; - -webkit-border-top-right-radius: 6px; - border-top-left-radius: 6px; - border-top-right-radius: 6px; -} - -.popup_menu .popup_item_container:last-child .popup_item { - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-bottomright: 6px; - -webkit-border-bottom-left-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; -} - -.pagination a { - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -.pollbar { - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; -} - -div.error { - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -}]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/html/forums/install/resources/mybb_theme_colors.xml b/html/forums/install/resources/mybb_theme_colors.xml deleted file mode 100644 index c065020..0000000 --- a/html/forums/install/resources/mybb_theme_colors.xml +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/html/forums/install/resources/mysql_db_inserts.php b/html/forums/install/resources/mysql_db_inserts.php deleted file mode 100644 index b16e3e5..0000000 --- a/html/forums/install/resources/mysql_db_inserts.php +++ /dev/null @@ -1,166 +0,0 @@ -\r\n
    \r\nYou are encouraged to register; once you register you will be able to post messages, set your own preferences, and maintain a profile.
    \r\n
    \r\nSome of the features that generally require registration are subscriptions, changing of styles, accessing of your Personal Pad (simple notepad) and emailing forum members.', 1, 1, 1);"; -$inserts[] = "INSERT INTO mybb_helpdocs (hid, sid, name, description, document, usetranslation, enabled, disporder) VALUES (2, 1, 'Updating Profile', 'Changing your data currently on record.', 'At some point during your stay, you may decide you need to update some information such as your instant messenger information, your password, or perhaps you need to change your email address. You may change any of this information from your user control panel. To access this control panel, simply click on the link in the upper right hand corner of most any page entitled \"user cp\". From there, simply choose \"Edit Profile\" and change or update any desired items, then proceed to click the submit button located at the bottom of the page for changes to take effect.', 1, 1, 2);"; -$inserts[] = "INSERT INTO mybb_helpdocs (hid, sid, name, description, document, usetranslation, enabled, disporder) VALUES (3, 1, 'Use of Cookies on myBB', 'myBB uses cookies to store certain information about your registration.', 'myBulletinBoard makes use of cookies to store your login information if you are registered, and your last visit if you are not.
    \r\n
    \r\nCookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk.
    \r\n
    \r\nCookies on this forum also track the specific topics you have read and when you last read them.
    \r\n
    \r\nTo clear all cookies set by this forum, you can click here.', 1, 1, 3);"; -$inserts[] = "INSERT INTO mybb_helpdocs (hid, sid, name, description, document, usetranslation, enabled, disporder) VALUES (4, 1, 'Logging In and Out', 'How to login and log out.', 'When you login, you set a cookie on your machine so that you can browse the forums without having to enter in your username and password each time. Logging out clears that cookie to ensure nobody else can browse the forum as you.
    \r\n
    \r\nTo login, simply click the login link at the top right hand corner of the forum. To log out, click the log out link in the same place. In the event you cannot log out, clearing cookies on your machine will take the same effect.', 1, 1, 4);"; -$inserts[] = "INSERT INTO mybb_helpdocs (hid, sid, name, description, document, usetranslation, enabled, disporder) VALUES (5, 2, 'Posting a New Topic', 'Starting a new thread in a forum.', 'When you go to a forum you are interested in and you wish to create a new topic (or thread), simply choose the button at the top and bottom of the forums entitled \"New topic\". Please take note that you may not have permission to post a new topic in every forum as your administrator may have restricted posting in that forum to staff or archived the forum entirely.', 1, 1, 1);"; -$inserts[] = "INSERT INTO mybb_helpdocs (hid, sid, name, description, document, usetranslation, enabled, disporder) VALUES (6, 2, 'Posting a Reply', 'Replying to a topic within a forum.', 'During the course of your visit, you may encounter a thread to which you would like to make a reply. To do so, simply click the \"Post reply\" button at the bottom or top of the thread. Please take note that your administrator may have restricted posting to certain individuals in that particular forum.
    \r\n
    \r\nAdditionally, a moderator of a forum may have closed a thread meaning that users cannot reply to it. There is no way for a user to open such a thread without the help of a moderator or administrator.', 1, 1, 2);"; -$inserts[] = "INSERT INTO mybb_helpdocs (hid, sid, name, description, document, usetranslation, enabled, disporder) VALUES (7, 2, 'MyCode', 'Learn how to use MyCode to enhance your posts.', 'You can use MyCode, a simplified version of HTML, in your posts to create certain effects.\r\n


    \r\n[b]This text is bold[/b]
    \r\n   This text is bold\r\n

    \r\n[i]This text is italicized[/i]
    \r\n   This text is italicized\r\n

    \r\n[u]This text is underlined[/u]
    \r\n   This text is underlined\r\n


    \r\n[url]http://www.example.com/[/url]
    \r\n   http://www.example.com/\r\n

    \r\n[url=http://www.example.com/]Example.com[/url]
    \r\n   Example.com\r\n

    \r\n[email]example@example.com[/email]
    \r\n   example@example.com\r\n

    \r\n[email=example@example.com]E-mail Me![/email]
    \r\n   E-mail Me!\r\n

    \r\n[email=example@example.com?subject=spam]E-mail with subject[/email]
    \r\n   E-mail with subject\r\n


    \r\n[quote]Quoted text will be here[/quote]
    \r\n   Quoted text will be here\r\n

    \r\n[code]Text with preserved formatting[/code]
    \r\n   Text with preserved formatting\r\n


    \r\n[img]http://www.php.net/images/php.gif[/img]
    \r\n   \r\n

    \r\n[img=50x50]http://www.php.net/images/php.gif[/img]
    \r\n   \r\n


    \r\n[color=red]This text is red[/color]
    \r\n   This text is red\r\n

    \r\n[size=3]This text is size 3[/size]
    \r\n   This text is size 3\r\n

    \r\n[font=Tahoma]This font is Tahoma[/font]
    \r\n   This font is Tahoma\r\n


    \r\n[align=center]This is centered[/align]

    This is centered
    \r\n

    \r\n[align=right]This is right-aligned[/align]

    This is right-aligned
    \r\n


    \r\n[list]
    \r\n[*]List Item #1
    \r\n[*]List Item #2
    \r\n[*]List Item #3
    \r\n[/list]
    \r\n

      \r\n
    • List item #1
    • \r\n
    • List item #2
    • \r\n
    • List Item #3
    • \r\n

    You can make an ordered list by using [list=1] for a numbered, and [list=a] for an alphabetical list.', 1, 1, 3);"; - -$inserts[] = "INSERT INTO mybb_helpsections (sid, name, description, usetranslation, enabled, disporder) VALUES (1, 'User Maintenance', 'Basic instructions for maintaining a forum account.', 1, 1, 1);"; -$inserts[] = "INSERT INTO mybb_helpsections (sid, name, description, usetranslation, enabled, disporder) VALUES (2, 'Posting', 'Posting, replying, and basic usage of forum.', 1, 1, 2);"; - -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(1, 'Bug', 'images/icons/bug.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(2, 'Exclamation', 'images/icons/exclamation.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(3, 'Question', 'images/icons/question.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(4, 'Smile', 'images/icons/smile.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(5, 'Sad', 'images/icons/sad.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(6, 'Wink', 'images/icons/wink.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(7, 'Big Grin', 'images/icons/biggrin.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(8, 'Tongue', 'images/icons/tongue.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(9, 'Brick', 'images/icons/brick.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(10, 'Heart', 'images/icons/heart.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(11, 'Information', 'images/icons/information.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(12, 'Lightbulb', 'images/icons/lightbulb.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(13, 'Music', 'images/icons/music.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(14, 'Photo', 'images/icons/photo.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(15, 'Rainbow', 'images/icons/rainbow.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(16, 'Shocked', 'images/icons/shocked.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(17, 'Star', 'images/icons/star.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(18, 'Thumbs Down', 'images/icons/thumbsdown.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(19, 'Thumbs Up', 'images/icons/thumbsup.png');"; -$inserts[] = "INSERT INTO mybb_icons (iid, name, path) VALUES(20, 'Video', 'images/icons/video.png');"; - -$inserts[] = "INSERT INTO mybb_profilefields (fid, name, description, disporder, type, regex, length, maxlength, required, registration, profile, postbit, viewableby, editableby, postnum) VALUES (1, 'Location', 'Where in the world do you live?', 1, 'text', '', 0, 255, 0, 0, 1, 0, -1, -1, 0);"; -$inserts[] = "INSERT INTO mybb_profilefields (fid, name, description, disporder, type, regex, length, maxlength, required, registration, profile, postbit, viewableby, editableby, postnum) VALUES (2, 'Bio', 'Enter a few short details about yourself, your life story etc.', 2, 'textarea', '', 0, 0, 0, 0, 1, 0, -1, -1, 0);"; -$inserts[] = "INSERT INTO mybb_profilefields (fid, name, description, disporder, type, regex, length, maxlength, required, registration, profile, postbit, viewableby, editableby, postnum) VALUES (3, 'Sex', 'Please select your sex from the list below.', 3, 'select\nUndisclosed\nMale\nFemale\nOther', '', 0, 0, 0, 0, 1, 0, -1, -1, 0);"; - -$inserts[] = "INSERT INTO mybb_questions (qid, question, answer, shown, correct, incorrect, active) VALUES(1, 'What does 2 + 2 equal?', '4\nFour', 0, 0, 0, 1);"; - -$inserts[] = "INSERT INTO mybb_reportreasons (rid, title, appliesto, extra, disporder) VALUES(1, '', 'all', 1, 99);"; -$inserts[] = "INSERT INTO mybb_reportreasons (rid, title, appliesto, extra, disporder) VALUES(2, '', 'all', 0, 1);"; -$inserts[] = "INSERT INTO mybb_reportreasons (rid, title, appliesto, extra, disporder) VALUES(3, '', 'all', 0, 2);"; -$inserts[] = "INSERT INTO mybb_reportreasons (rid, title, appliesto, extra, disporder) VALUES(4, '', 'all', 0, 3);"; -$inserts[] = "INSERT INTO mybb_reportreasons (rid, title, appliesto, extra, disporder) VALUES(5, '', 'post', 0, 4);"; - -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(1, 'Smile', ':)', 'images/smilies/smile.png', 1, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(2, 'Wink', ';)', 'images/smilies/wink.png', 2, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(3, 'Cool', ':cool:', 'images/smilies/cool.png', 3, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(4, 'Big Grin', ':D', 'images/smilies/biggrin.png', 4, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(5, 'Tongue', ':P', 'images/smilies/tongue.png', 5, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(6, 'Rolleyes', ':rolleyes:', 'images/smilies/rolleyes.png', 6, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(7, 'Shy', ':shy:', 'images/smilies/shy.png', 7, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(8, 'Sad', ':(', 'images/smilies/sad.png', 8, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(9, 'At', ':at:', 'images/smilies/at.png', 9, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(10, 'Angel', ':angel:', 'images/smilies/angel.png', 10, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(11, 'Angry', ':@', 'images/smilies/angry.png', 11, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(12, 'Blush', ':blush:', 'images/smilies/blush.png', 12, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(13, 'Confused', ':s', 'images/smilies/confused.png', 13, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(14, 'Dodgy', ':dodgy:', 'images/smilies/dodgy.png', 14, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(15, 'Exclamation', ':exclamation:', 'images/smilies/exclamation.png', 15, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(16, 'Heart', ':heart:', 'images/smilies/heart.png', 16, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(17, 'Huh', ':huh:', 'images/smilies/huh.png', 17, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(18, 'Idea', ':idea:', 'images/smilies/lightbulb.png', 18, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(19, 'Sleepy', ':sleepy:', 'images/smilies/sleepy.png', 19, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(20, 'Undecided', ':-/', 'images/smilies/undecided.png', 20, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(21, 'Cry', ':cry:', 'images/smilies/cry.png', 21, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(22, 'Sick', ':sick:', 'images/smilies/sick.png', 22, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(23, 'Arrow', ':arrow:', 'images/smilies/arrow.png', 23, 1);"; -$inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(24, 'My', ':my:', 'images/smilies/my.png', 24, 1);"; - -$inserts[] = "INSERT INTO mybb_spiders (name,useragent) VALUES ('Google','Googlebot');"; -$inserts[] = "INSERT INTO mybb_spiders (name,useragent) VALUES ('Bing','bingbot');"; -$inserts[] = "INSERT INTO mybb_spiders (name,useragent) VALUES ('Alexa Internet','ia_archiver');"; -$inserts[] = "INSERT INTO mybb_spiders (name,useragent) VALUES ('Ask.com','Teoma');"; -$inserts[] = "INSERT INTO mybb_spiders (name,useragent) VALUES ('Baidu','Baiduspider');"; -$inserts[] = "INSERT INTO mybb_spiders (name,useragent) VALUES ('Yandex','YandexBot');"; -$inserts[] = "INSERT INTO mybb_spiders (name,useragent) VALUES ('Blekko','Blekkobot');"; -$inserts[] = "INSERT INTO mybb_spiders (name,useragent) VALUES ('Facebook','facebookexternalhit');"; -$inserts[] = "INSERT INTO mybb_spiders (name,useragent) VALUES ('Twitter','Twitterbot');"; -$inserts[] = "INSERT INTO mybb_spiders (name,useragent) VALUES ('Internet Archive','archive.org_bot');"; - -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('1','calendar','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('2','editpost','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('3','forumbit','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('4','forumjump','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('5','forumdisplay','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('6','index','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('7','error','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('8','memberlist','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('9','multipage','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('10','private','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('11','portal','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('12','postbit','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('13','posticons','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('14','showthread','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('15','usercp','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('16','online','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('17','moderation','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('18','nav','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('19','search','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('20','showteam','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('21','reputation','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('22','newthread','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('23','newreply','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('24','member','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('25','warnings','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('26','global','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('27','header','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('28','managegroup','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('29','misc','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('30','modcp','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('31','announcement','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('32','polls','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('33','post','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('34','printthread','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('35','report','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('36','smilieinsert','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('37','stats','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('38','xmlhttp','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('39','footer','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('40','video','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('41','sendthread','','1');"; -$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('42','mycode','','1');"; - -$inserts[] = "INSERT INTO mybb_usertitles (utid, posts, title, stars, starimage) VALUES (1, 0, 'Newbie', 1, '');"; -$inserts[] = "INSERT INTO mybb_usertitles (utid, posts, title, stars, starimage) VALUES (2, 1, 'Junior Member', 2, '');"; -$inserts[] = "INSERT INTO mybb_usertitles (utid, posts, title, stars, starimage) VALUES (3, 50, 'Member', 3, '');"; -$inserts[] = "INSERT INTO mybb_usertitles (utid, posts, title, stars, starimage) VALUES (4, 250, 'Senior Member', 4, '');"; -$inserts[] = "INSERT INTO mybb_usertitles (utid, posts, title, stars, starimage) VALUES (5, 750, 'Posting Freak', 5, '');"; - diff --git a/html/forums/install/resources/mysql_db_tables.php b/html/forums/install/resources/mysql_db_tables.php deleted file mode 100644 index 8dae656..0000000 --- a/html/forums/install/resources/mysql_db_tables.php +++ /dev/null @@ -1,1184 +0,0 @@ -welcome; - } - - if($lang->title) - { - $this->title = $lang->title; - } - - @header("Content-type: text/html; charset=utf-8"); - - $this->doneheader = 1; - $dbconfig_add = ''; - if($image == "dbconfig") - { - $dbconfig_add = ""; - } - echo << - - - {$this->title} > {$title} - - - - {$dbconfig_add} - - -END; - if($form) - { - echo "\n

    script."\">\n"; - $this->openedform = 1; - } - - echo << - -
    - -END; - if($mybb->version_code >= 1700 && $mybb->version_code < 1800) - { - echo $lang->development_preview; - } - if(empty($this->steps)) - { - $this->steps = array(); - } - if(is_array($this->steps)) - { - echo "\n
    "; - echo "\n
      \n"; - foreach($this->steps as $action => $step) - { - if($action == $mybb->input['action']) - { - echo "
    • {$step}
    • \n"; - } - else - { - echo "
    • {$step}
    • \n"; - } - } - echo "
    "; - echo "\n
    "; - echo "\n
    \n"; - } - else - { - echo "\n
    "; - echo "\n
    \n"; - } - if($title != "") - { - echo <<{$title}

    \n -END; - } - } - - /** - * @param string $contents - */ - function print_contents($contents) - { - echo $contents; - } - - /** - * @param string $message - */ - function print_error($message) - { - global $lang; - if(!$this->doneheader) - { - $this->print_header($lang->error, "", 0, 1); - } - echo "
    \n "; - echo "

    ".$lang->error."

    "; - $this->print_contents($message); - echo "\n
    "; - $this->print_footer(); - } - - /** - * @param string $nextact - */ - function print_footer($nextact="") - { - global $lang, $footer_extra; - if($nextact && $this->openedform) - { - echo "\n "; - echo "\n
    next." »\" />

    \n"; - $formend = ""; - } - else - { - $formend = ""; - } - - echo << - -
    -
    -
    - {$formend} - {$footer_extra} - - -END; - exit; - } -} diff --git a/html/forums/install/resources/pgsql_db_tables.php b/html/forums/install/resources/pgsql_db_tables.php deleted file mode 100644 index 47eb54f..0000000 --- a/html/forums/install/resources/pgsql_db_tables.php +++ /dev/null @@ -1,1142 +0,0 @@ -
    Please make sure IN_MYBB is defined."); -} - -$tables[] = "CREATE TABLE mybb_adminlog ( - uid int NOT NULL default '0', - ipaddress bytea NOT NULL default '', - dateline int NOT NULL default '0', - module varchar(50) NOT NULL default '', - action varchar(50) NOT NULL default '', - data text NOT NULL default '' -);"; - -$tables[] = "CREATE TABLE mybb_adminoptions ( - uid int NOT NULL default '0', - cpstyle varchar(50) NOT NULL default '', - cplanguage varchar(50) NOT NULL default '', - codepress smallint NOT NULL default '1', - notes text NOT NULL default '', - permissions text NOT NULL default '', - defaultviews text NOT NULL, - loginattempts smallint NOT NULL default '0', - loginlockoutexpiry int NOT NULL default '0', - authsecret varchar(16) NOT NULL default '', - recovery_codes varchar(177) NOT NULL default '', - UNIQUE (uid) -);"; - -$tables[] = "CREATE TABLE mybb_adminsessions ( - sid varchar(32) NOT NULL default '', - uid int NOT NULL default '0', - loginkey varchar(50) NOT NULL default '', - ip bytea NOT NULL default '', - dateline int NOT NULL default '0', - lastactive int NOT NULL default '0', - data text NOT NULL default '', - useragent varchar(200) NOT NULL default '', - authenticated smallint NOT NULL default '0' -);"; - -$tables[] = "CREATE TABLE mybb_adminviews ( - vid serial, - uid int NOT NULL default '0', - title varchar(100) NOT NULL default '', - type varchar(6) NOT NULL default '', - visibility smallint NOT NULL default '0', - fields text NOT NULL, - conditions text NOT NULL, - custom_profile_fields text NOT NULL, - sortby varchar(20) NOT NULL default '', - sortorder varchar(4) NOT NULL default '', - perpage smallint NOT NULL default '0', - view_type varchar(6) NOT NULL default '', - PRIMARY KEY (vid) -);"; - -$tables[] = "CREATE TABLE mybb_announcements ( - aid serial, - fid int NOT NULL default '0', - uid int NOT NULL default '0', - subject varchar(120) NOT NULL default '', - message text NOT NULL default '', - startdate int NOT NULL default '0', - enddate int NOT NULL default '0', - allowhtml smallint NOT NULL default '0', - allowmycode smallint NOT NULL default '0', - allowsmilies smallint NOT NULL default '0', - PRIMARY KEY (aid) -);"; - -$tables[] = "CREATE TABLE mybb_attachments ( - aid serial, - pid int NOT NULL default '0', - posthash varchar(50) NOT NULL default '', - uid int NOT NULL default '0', - filename varchar(120) NOT NULL default '', - filetype varchar(120) NOT NULL default '', - filesize int NOT NULL default '0', - attachname varchar(120) NOT NULL default '', - downloads int NOT NULL default '0', - dateuploaded int NOT NULL default '0', - visible smallint NOT NULL default '0', - thumbnail varchar(120) NOT NULL default '', - PRIMARY KEY (aid) -);"; - -$tables[] = "CREATE TABLE mybb_attachtypes ( - atid serial, - name varchar(120) NOT NULL default '', - mimetype varchar(120) NOT NULL default '', - extension varchar(10) NOT NULL default '', - maxsize int NOT NULL default '0', - icon varchar(100) NOT NULL default '', - enabled smallint NOT NULL default '1', - groups text NOT NULL default '-1', - forums text NOT NULL default '-1', - avatarfile smallint NOT NULL default '0', - PRIMARY KEY (atid) -);"; - -$tables[] = "CREATE TABLE mybb_awaitingactivation ( - aid serial, - uid int NOT NULL default '0', - dateline int NOT NULL default '0', - code varchar(100) NOT NULL default '', - type char(1) NOT NULL default '', - validated smallint NOT NULL default '0', - misc varchar(255) NOT NULL default '', - PRIMARY KEY (aid) -);"; - -$tables[] = "CREATE TABLE mybb_badwords ( - bid serial, - badword varchar(100) NOT NULL default '', - replacement varchar(100) NOT NULL default '', - PRIMARY KEY (bid) -);"; - -$tables[] = "CREATE TABLE mybb_banfilters ( - fid serial, - filter varchar(200) NOT NULL default '', - type smallint NOT NULL default '0', - lastuse int NOT NULL default '0', - dateline int NOT NULL default '0', - PRIMARY KEY (fid) -);"; - -$tables[] = "CREATE TABLE mybb_banned ( - uid int NOT NULL default '0', - gid int NOT NULL default '0', - oldgroup int NOT NULL default '0', - oldadditionalgroups text NOT NULL default '', - olddisplaygroup int NOT NULL default '0', - admin int NOT NULL default '0', - dateline int NOT NULL default '0', - bantime varchar(50) NOT NULL default '', - lifted int NOT NULL default '0', - reason varchar(255) NOT NULL default '' -);"; - -$tables[] = "CREATE TABLE mybb_buddyrequests ( - id serial, - uid int NOT NULL default '0', - touid int NOT NULL default '0', - date int NOT NULL default '0', - PRIMARY KEY (id) -);"; - -$tables[] = "CREATE TABLE mybb_calendars ( - cid serial, - name varchar(100) NOT NULL default '', - disporder smallint NOT NULL default '0', - startofweek smallint NOT NULL default '0', - showbirthdays smallint NOT NULL default '0', - eventlimit smallint NOT NULL default '0', - moderation smallint NOT NULL default '0', - allowhtml smallint NOT NULL default '0', - allowmycode smallint NOT NULL default '0', - allowimgcode smallint NOT NULL default '0', - allowvideocode smallint NOT NULL default '0', - allowsmilies smallint NOT NULL default '0', - PRIMARY KEY(cid) -);"; - -$tables[] = "CREATE TABLE mybb_calendarpermissions ( - cid serial, - gid int NOT NULL default '0', - canviewcalendar smallint NOT NULL default '0', - canaddevents smallint NOT NULL default '0', - canbypasseventmod smallint NOT NULL default '0', - canmoderateevents smallint NOT NULL default '0' -);"; - -$tables[] = "CREATE TABLE mybb_captcha ( - imagehash varchar(32) NOT NULL default '', - imagestring varchar(8) NOT NULL default '', - dateline int NOT NULL default '0', - used smallint NOT NULL default '0' -);"; - -$tables[] = "CREATE TABLE mybb_datacache ( - title varchar(50) NOT NULL default '', - cache text NOT NULL default '', - PRIMARY KEY (title) -);"; - -$tables[] = "CREATE TABLE mybb_delayedmoderation ( - did serial, - type varchar(30) NOT NULL default '', - delaydateline int NOT NULL default '0', - uid int NOT NULL default '0', - fid smallint NOT NULL default '0', - tids text NOT NULL, - dateline int NOT NULL default '0', - inputs text NOT NULL default '', - PRIMARY KEY (did) -);"; - -$tables[] = "CREATE TABLE mybb_events ( - eid serial, - cid int NOT NULL default '0', - uid int NOT NULL default '0', - name varchar(120) NOT NULL default '', - description text NOT NULL, - visible smallint NOT NULL default '0', - private smallint NOT NULL default '0', - dateline int NOT NULL default '0', - starttime int NOT NULL default '0', - endtime int NOT NULL default '0', - timezone varchar(5) NOT NULL default '', - ignoretimezone smallint NOT NULL default '0', - usingtime smallint NOT NULL default '0', - repeats text NOT NULL, - PRIMARY KEY (eid) -);"; - -$tables[] = "CREATE TABLE mybb_forumpermissions ( - pid serial, - fid int NOT NULL default '0', - gid int NOT NULL default '0', - canview smallint NOT NULL default '0', - canviewthreads smallint NOT NULL default '0', - canonlyviewownthreads smallint NOT NULL default '0', - candlattachments smallint NOT NULL default '0', - canpostthreads smallint NOT NULL default '0', - canpostreplys smallint NOT NULL default '0', - canonlyreplyownthreads smallint NOT NULL default '0', - canpostattachments smallint NOT NULL default '0', - canratethreads smallint NOT NULL default '0', - caneditposts smallint NOT NULL default '0', - candeleteposts smallint NOT NULL default '0', - candeletethreads smallint NOT NULL default '0', - caneditattachments smallint NOT NULL default '0', - canviewdeletionnotice smallint NOT NULL default '0', - modposts smallint NOT NULL default '0', - modthreads smallint NOT NULL default '0', - mod_edit_posts smallint NOT NULL default '0', - modattachments smallint NOT NULL default '0', - canpostpolls smallint NOT NULL default '0', - canvotepolls smallint NOT NULL default '0', - cansearch smallint NOT NULL default '0', - PRIMARY KEY (pid) -);"; - -$tables[] = "CREATE TABLE mybb_forums ( - fid serial, - name varchar(120) NOT NULL default '', - description text NOT NULL default '', - linkto varchar(180) NOT NULL default '', - type char(1) NOT NULL default '', - pid smallint NOT NULL default '0', - parentlist text NOT NULL default '', - disporder smallint NOT NULL default '0', - active smallint NOT NULL default '0', - open smallint NOT NULL default '0', - threads int NOT NULL default '0', - posts int NOT NULL default '0', - lastpost int NOT NULL default '0', - lastposter varchar(120) NOT NULL default '', - lastposteruid int NOT NULL default '0', - lastposttid int NOT NULL default '0', - lastpostsubject varchar(120) NOT NULL default '', - allowhtml smallint NOT NULL default '0', - allowmycode smallint NOT NULL default '0', - allowsmilies smallint NOT NULL default '0', - allowimgcode smallint NOT NULL default '0', - allowvideocode smallint NOT NULL default '0', - allowpicons smallint NOT NULL default '0', - allowtratings smallint NOT NULL default '0', - usepostcounts smallint NOT NULL default '0', - usethreadcounts smallint NOT NULL default '0', - requireprefix smallint NOT NULL default '0', - password varchar(50) NOT NULL default '', - showinjump smallint NOT NULL default '0', - style smallint NOT NULL default '0', - overridestyle smallint NOT NULL default '0', - rulestype smallint NOT NULL default '0', - rulestitle varchar(200) NOT NULL default '', - rules text NOT NULL default '', - unapprovedthreads int NOT NULL default '0', - unapprovedposts int NOT NULL default '0', - deletedthreads int NOT NULL default '0', - deletedposts int NOT NULL default '0', - defaultdatecut smallint NOT NULL default '0', - defaultsortby varchar(10) NOT NULL default '', - defaultsortorder varchar(4) NOT NULL default '', - PRIMARY KEY (fid) -);"; - -$tables[] = "CREATE TABLE mybb_forumsread ( - fid int NOT NULL default '0', - uid int NOT NULL default '0', - dateline int NOT NULL default '0' -);"; - -$tables[] = "CREATE TABLE mybb_forumsubscriptions ( - fsid serial, - fid smallint NOT NULL default '0', - uid int NOT NULL default '0', - PRIMARY KEY (fsid) -);"; - -$tables[] = "CREATE TABLE mybb_groupleaders ( - lid serial, - gid smallint NOT NULL default '0', - uid int NOT NULL default '0', - canmanagemembers smallint NOT NULL default '0', - canmanagerequests smallint NOT NULL default '0', - caninvitemembers smallint NOT NULL default '0', - PRIMARY KEY (lid) -);"; - -$tables[] = "CREATE TABLE mybb_helpdocs ( - hid serial, - sid smallint NOT NULL default '0', - name varchar(120) NOT NULL default '', - description text NOT NULL default '', - document text NOT NULL default '', - usetranslation smallint NOT NULL default '0', - enabled smallint NOT NULL default '0', - disporder smallint NOT NULL default '0', - PRIMARY KEY (hid) -);"; - -$tables[] = "CREATE TABLE mybb_helpsections ( - sid serial, - name varchar(120) NOT NULL default '', - description text NOT NULL default '', - usetranslation smallint NOT NULL default '0', - enabled smallint NOT NULL default '0', - disporder smallint NOT NULL default '0', - PRIMARY KEY (sid) -);"; - -$tables[] = "CREATE TABLE mybb_icons ( - iid serial, - name varchar(120) NOT NULL default '', - path varchar(220) NOT NULL default '', - PRIMARY KEY (iid) -);"; - -$tables[] = "CREATE TABLE mybb_joinrequests ( - rid serial, - uid int NOT NULL default '0', - gid smallint NOT NULL default '0', - reason varchar(250) NOT NULL default '', - dateline int NOT NULL default '0', - invite smallint NOT NULL default '0', - PRIMARY KEY (rid) -);"; - -$tables[] = "CREATE TABLE mybb_massemails ( - mid serial, - uid int NOT NULL default '0', - subject varchar(200) NOT NULL default '', - message text NOT NULL, - htmlmessage text NOT NULL, - type smallint NOT NULL default '0', - format smallint NOT NULL default '0', - dateline numeric(30,0) NOT NULL default '0', - senddate numeric(30,0) NOT NULL default '0', - status smallint NOT NULL default '0', - sentcount int NOT NULL default '0', - totalcount int NOT NULL default '0', - conditions text NOT NULL, - perpage int NOT NULL default '50', - PRIMARY KEY(mid) -);"; - -$tables[] = "CREATE TABLE mybb_mailerrors ( - eid serial, - subject varchar(200) NOT NULL default '', - message text NOT NULL default '', - toaddress varchar(150) NOT NULL default '', - fromaddress varchar(150) NOT NULL default '', - dateline int NOT NULL default '0', - error text NOT NULL default '', - smtperror varchar(200) NOT NULL default '', - smtpcode smallint NOT NULL default '0', - PRIMARY KEY(eid) -);"; - -$tables[] = "CREATE TABLE mybb_maillogs ( - mid serial, - subject varchar(200) not null default '', - message text NOT NULL default '', - dateline int NOT NULL default '0', - fromuid int NOT NULL default '0', - fromemail varchar(200) not null default '', - touid int NOT NULL default '0', - toemail varchar(200) NOT NULL default '', - tid int NOT NULL default '0', - ipaddress bytea NOT NULL default '', - type smallint NOT NULL default '0', - PRIMARY KEY(mid) -);"; - -$tables[] = "CREATE TABLE mybb_mailqueue ( - mid serial, - mailto varchar(200) NOT NULL, - mailfrom varchar(200) NOT NULL, - subject varchar(200) NOT NULL, - message text NOT NULL default '', - headers text NOT NULL default '', - PRIMARY KEY(mid) -);"; - -$tables[] = "CREATE TABLE mybb_moderatorlog ( - uid int NOT NULL default '0', - dateline int NOT NULL default '0', - fid smallint NOT NULL default '0', - tid int NOT NULL default '0', - pid int NOT NULL default '0', - action text NOT NULL default '', - data text NOT NULL, - ipaddress bytea NOT NULL default '' -);"; - -$tables[] = "CREATE TABLE mybb_moderators ( - mid serial, - fid smallint NOT NULL default '0', - id int NOT NULL default '0', - isgroup smallint NOT NULL default '0', - caneditposts smallint NOT NULL default '0', - cansoftdeleteposts smallint NOT NULL default '0', - canrestoreposts smallint NOT NULL default '0', - candeleteposts smallint NOT NULL default '0', - cansoftdeletethreads smallint NOT NULL default '0', - canrestorethreads smallint NOT NULL default '0', - candeletethreads smallint NOT NULL default '0', - canviewips smallint NOT NULL default '0', - canviewunapprove smallint NOT NULL default '0', - canviewdeleted smallint NOT NULL default '0', - canopenclosethreads smallint NOT NULL default '0', - canstickunstickthreads smallint NOT NULL default '0', - canapproveunapprovethreads smallint NOT NULL default '0', - canapproveunapproveposts smallint NOT NULL default '0', - canapproveunapproveattachs smallint NOT NULL default '0', - canmanagethreads smallint NOT NULL default '0', - canmanagepolls smallint NOT NULL default '0', - canpostclosedthreads smallint NOT NULL default '0', - canmovetononmodforum smallint NOT NULL default '0', - canusecustomtools smallint NOT NULL default '0', - canmanageannouncements smallint NOT NULL default '0', - canmanagereportedposts smallint NOT NULL default '0', - canviewmodlog smallint NOT NULL default '0', - PRIMARY KEY (mid) -);"; - -$tables[] = "CREATE TABLE mybb_modtools ( - tid serial, - name varchar(200) NOT NULL, - description text NOT NULL default '', - forums text NOT NULL default '', - groups text NOT NULL default '', - type char(1) NOT NULL default '', - postoptions text NOT NULL default '', - threadoptions text NOT NULL default '', - PRIMARY KEY (tid) -);"; - -$tables[] = "CREATE TABLE mybb_mycode ( - cid serial, - title varchar(100) NOT NULL default '', - description text NOT NULL default '', - regex text NOT NULL default '', - replacement text NOT NULL default '', - active smallint NOT NULL default '0', - parseorder smallint NOT NULL default '0', - PRIMARY KEY(cid) -);"; - -$tables[] = "CREATE TABLE mybb_polls ( - pid serial, - tid int NOT NULL default '0', - question varchar(200) NOT NULL default '', - dateline int NOT NULL default '0', - options text NOT NULL default '', - votes text NOT NULL default '', - numoptions smallint NOT NULL default '0', - numvotes int NOT NULL default '0', - timeout int NOT NULL default '0', - closed smallint NOT NULL default '0', - multiple smallint NOT NULL default '0', - public smallint NOT NULL default '0', - maxoptions smallint NOT NULL default '0', - PRIMARY KEY (pid) -);"; - -$tables[] = "CREATE TABLE mybb_pollvotes ( - vid serial, - pid int NOT NULL default '0', - uid int NOT NULL default '0', - voteoption smallint NOT NULL default '0', - dateline int NOT NULL default '0', - PRIMARY KEY (vid) -);"; - -$tables[] = "CREATE TABLE mybb_posts ( - pid serial, - tid int NOT NULL default '0', - replyto int NOT NULL default '0', - fid smallint NOT NULL default '0', - subject varchar(120) NOT NULL default '', - icon smallint NOT NULL default '0', - uid int NOT NULL default '0', - username varchar(80) NOT NULL default '', - dateline int NOT NULL default '0', - message text NOT NULL default '', - ipaddress bytea NOT NULL default '', - includesig smallint NOT NULL default '0', - smilieoff smallint NOT NULL default '0', - edituid int NOT NULL default '0', - edittime int NOT NULL default '0', - editreason varchar(150) NOT NULL default '', - visible smallint NOT NULL default '0', - PRIMARY KEY (pid) -);"; - -$tables[] = "CREATE TABLE mybb_privatemessages ( - pmid serial, - uid int NOT NULL default '0', - toid int NOT NULL default '0', - fromid int NOT NULL default '0', - recipients text NOT NULL default '', - folder smallint NOT NULL default '1', - subject varchar(120) NOT NULL default '', - icon smallint NOT NULL default '0', - message text NOT NULL default '', - dateline int NOT NULL default '0', - deletetime int NOT NULL default '0', - status smallint NOT NULL default '0', - statustime int NOT NULL default '0', - includesig smallint NOT NULL default '0', - smilieoff smallint NOT NULL default '0', - receipt smallint NOT NULL default '0', - readtime int NOT NULL default '0', - ipaddress bytea NOT NULL default '', - PRIMARY KEY (pmid) -);"; - -$tables[] = "CREATE TABLE mybb_profilefields ( - fid serial, - name varchar(100) NOT NULL default '', - description text NOT NULL default '', - disporder smallint NOT NULL default '0', - type text NOT NULL default '', - regex text NOT NULL default '', - length smallint NOT NULL default '0', - maxlength smallint NOT NULL default '0', - required smallint NOT NULL default '0', - registration smallint NOT NULL default '0', - profile smallint NOT NULL default '0', - postbit smallint NOT NULL default '0', - viewableby text NOT NULL default '-1', - editableby text NOT NULL default '-1', - postnum smallint NOT NULL default '0', - allowhtml smallint NOT NULL default '0', - allowmycode smallint NOT NULL default '0', - allowsmilies smallint NOT NULL default '0', - allowimgcode smallint NOT NULL default '0', - allowvideocode smallint NOT NULL default '0', - PRIMARY KEY (fid) -);"; - -$tables[] = "CREATE TABLE mybb_promotions ( - pid serial, - title varchar(120) NOT NULL default '', - description text NOT NULL default '', - enabled smallint NOT NULL default '1', - logging smallint NOT NULL default '0', - posts int NOT NULL default '0', - posttype varchar(2) NOT NULL default '', - threads int NOT NULL default '0', - threadtype varchar(2) NOT NULL default '', - registered int NOT NULL default '0', - registeredtype varchar(20) NOT NULL default '', - online int NOT NULL default '0', - onlinetype varchar(20) NOT NULL default '', - reputations int NOT NULL default '0', - reputationtype varchar(2) NOT NULL default '', - referrals int NOT NULL default '0', - referralstype varchar(2) NOT NULL default '', - warnings int NOT NULL default '0', - warningstype varchar(2) NOT NULL default '', - requirements varchar(200) NOT NULL default '', - originalusergroup varchar(120) NOT NULL default '0', - newusergroup smallint NOT NULL default '0', - usergrouptype varchar(120) NOT NULL default '0', - PRIMARY KEY(pid) -);"; - -$tables[] = "CREATE TABLE mybb_promotionlogs ( - plid serial, - pid int NOT NULL default '0', - uid int NOT NULL default '0', - oldusergroup varchar(200) NOT NULL default '0', - newusergroup smallint NOT NULL default '0', - dateline int NOT NULL default '0', - type varchar(9) NOT NULL default 'primary', - PRIMARY KEY(plid) -);"; - -$tables[] = "CREATE TABLE mybb_questions ( - qid serial, - question varchar(200) NOT NULL default '', - answer varchar(150) NOT NULL default '', - shown int NOT NULL default 0, - correct int NOT NULL default 0, - incorrect int NOT NULL default 0, - active smallint NOT NULL default '0', - PRIMARY KEY (qid) -);"; - -$tables[] = "CREATE TABLE mybb_questionsessions ( - sid varchar(32) NOT NULL default '', - qid int NOT NULL default '0', - dateline int NOT NULL default '0', - UNIQUE (sid) -);"; - -$tables[] = "CREATE TABLE mybb_reportedcontent ( - rid serial, - id int NOT NULL default '0', - id2 int NOT NULL default '0', - id3 int NOT NULL default '0', - uid int NOT NULL default '0', - reportstatus smallint NOT NULL default '0', - reasonid smallint NOT NULL default '0', - reason varchar(250) NOT NULL default '', - type varchar(50) NOT NULL default '', - reports int NOT NULL default '0', - reporters text NOT NULL default '', - dateline int NOT NULL default '0', - lastreport int NOT NULL default '0', - PRIMARY KEY (rid) -);"; - -$tables[] = "CREATE TABLE mybb_reportreasons ( - rid serial, - title varchar(250) NOT NULL default '', - appliesto varchar(250) NOT NULL default '', - extra smallint NOT NULL default '0', - disporder smallint NOT NULL default '0', - PRIMARY KEY (rid) -);"; - -$tables[] = "CREATE TABLE mybb_reputation ( - rid serial, - uid int NOT NULL default '0', - adduid int NOT NULL default '0', - pid int NOT NULL default '0', - reputation smallint NOT NULL default '0', - dateline int NOT NULL default '0', - comments text NOT NULL default '', - PRIMARY KEY(rid) -);"; - -$tables[] = "CREATE TABLE mybb_searchlog ( - sid varchar(32) NOT NULL default '', - uid int NOT NULL default '0', - dateline int NOT NULL default '0', - ipaddress bytea NOT NULL default '', - threads text NOT NULL default '', - posts text NOT NULL default '', - resulttype varchar(10) NOT NULL default '', - querycache text NOT NULL default '', - keywords text NOT NULL default '', - UNIQUE (sid) -);"; - -$tables[] = "CREATE TABLE mybb_sessions ( - sid varchar(32) NOT NULL default '', - uid int NOT NULL default '0', - ip bytea NOT NULL default '', - time int NOT NULL default '0', - location varchar(150) NOT NULL default '', - useragent varchar(200) NOT NULL default '', - anonymous smallint NOT NULL default '0', - nopermission smallint NOT NULL default '0', - location1 int NOT NULL default '0', - location2 int NOT NULL default '0', - UNIQUE (sid) -);"; - -$tables[] = "CREATE TABLE mybb_settinggroups ( - gid serial, - name varchar(100) NOT NULL default '', - title varchar(220) NOT NULL default '', - description text NOT NULL default '', - disporder smallint NOT NULL default '0', - isdefault smallint NOT NULL default '0', - PRIMARY KEY (gid) -);"; - -$tables[] = "CREATE TABLE mybb_settings ( - sid serial, - name varchar(120) NOT NULL default '', - title varchar(120) NOT NULL default '', - description text NOT NULL default '', - optionscode text NOT NULL default '', - value text NOT NULL default '', - disporder smallint NOT NULL default '0', - gid smallint NOT NULL default '0', - isdefault smallint NOT NULL default '0', - PRIMARY KEY (sid) -);"; - -$tables[] = "CREATE TABLE mybb_smilies ( - sid serial, - name varchar(120) NOT NULL default '', - find text NOT NULL, - image varchar(220) NOT NULL default '', - disporder smallint NOT NULL default '0', - showclickable smallint NOT NULL default '0', - PRIMARY KEY (sid) -);"; - -$tables[] = "CREATE TABLE mybb_spamlog ( - sid serial, - username varchar(120) NOT NULL DEFAULT '', - email varchar(220) NOT NULL DEFAULT '', - ipaddress bytea NOT NULL default '', - dateline numeric(30,0) NOT NULL default '0', - data text NOT NULL default '', - PRIMARY KEY (sid) -);"; - -$tables[] = "CREATE TABLE mybb_spiders ( - sid serial, - name varchar(100) NOT NULL default '', - theme smallint NOT NULL default '0', - language varchar(20) NOT NULL default '', - usergroup smallint NOT NULL default '0', - useragent varchar(200) NOT NULL default '', - lastvisit int NOT NULL default '0', - PRIMARY KEY(sid) -);"; - -$tables[] = "CREATE TABLE mybb_stats ( - dateline numeric(30,0) NOT NULL default '0', - numusers numeric(10,0) NOT NULL default '0', - numthreads numeric(10,0) NOT NULL default '0', - numposts numeric(10,0) NOT NULL default '0', - UNIQUE (dateline) -);"; - -$tables[] = "CREATE TABLE mybb_tasks ( - tid serial, - title varchar(120) NOT NULL default '', - description text NOT NULL default '', - file varchar(30) NOT NULL default '', - minute varchar(200) NOT NULL default '', - hour varchar(200) NOT NULL default '', - day varchar(100) NOT NULL default '', - month varchar(30) NOT NULL default '', - weekday varchar(15) NOT NULL default '', - nextrun int NOT NULL default '0', - lastrun int NOT NULL default '0', - enabled smallint NOT NULL default '1', - logging smallint NOT NULL default '0', - locked int NOT NULL default '0', - PRIMARY KEY(tid) -);"; - -$tables[] = "CREATE TABLE mybb_tasklog ( - lid serial, - tid int NOT NULL default '0', - dateline int NOT NULL default '0', - data text NOT NULL, - PRIMARY KEY(lid) -);"; - -$tables[] = "CREATE TABLE mybb_templategroups ( - gid serial, - prefix varchar(50) NOT NULL default '', - title varchar(100) NOT NULL default '', - isdefault smallint NOT NULL default '0', - PRIMARY KEY (gid) -);"; - -$tables[] = "CREATE TABLE mybb_templates ( - tid serial, - title varchar(120) NOT NULL default '', - template text NOT NULL default '', - sid smallint NOT NULL default '0', - version varchar(20) NOT NULL default '0', - status varchar(10) NOT NULL default '', - dateline int NOT NULL default '0', - PRIMARY KEY (tid) -);"; - -$tables[] = "CREATE TABLE mybb_templatesets ( - sid serial, - title varchar(120) NOT NULL default '', - PRIMARY KEY (sid) -);"; - -$tables[] = "CREATE TABLE mybb_themes ( - tid serial, - name varchar(100) NOT NULL default '', - pid smallint NOT NULL default '0', - def smallint NOT NULL default '0', - properties text NOT NULL default '', - stylesheets text NOT NULL default '', - allowedgroups text NOT NULL default '', - PRIMARY KEY (tid) -);"; - -$tables[] = "CREATE TABLE mybb_themestylesheets( - sid serial, - name varchar(30) NOT NULL default '', - tid numeric(10,0) NOT NULL default '0', - attachedto text NOT NULL, - stylesheet text NOT NULL, - cachefile varchar(100) NOT NULL default '', - lastmodified numeric(30,0) NOT NULL default '0', - PRIMARY KEY(sid) -);"; - -$tables[] = "CREATE TABLE mybb_threadprefixes ( - pid serial, - prefix varchar(120) NOT NULL default '', - displaystyle varchar(200) NOT NULL default '', - forums text NOT NULL, - groups text NOT NULL, - PRIMARY KEY(pid) -);"; - -$tables[] = "CREATE TABLE mybb_threadratings ( - rid serial, - tid int NOT NULL default '0', - uid int NOT NULL default '0', - rating smallint NOT NULL default '0', - ipaddress bytea NOT NULL default '', - PRIMARY KEY (rid) -);"; - -$tables[] = "CREATE TABLE mybb_threadviews ( - tid int NOT NULL default '0' -);"; - -$tables[] = "CREATE TABLE mybb_threads ( - tid serial, - fid smallint NOT NULL default '0', - subject varchar(120) NOT NULL default '', - prefix smallint NOT NULL default '0', - icon smallint NOT NULL default '0', - poll int NOT NULL default '0', - uid int NOT NULL default '0', - username varchar(80) NOT NULL default '', - dateline int NOT NULL default '0', - firstpost int NOT NULL default '0', - lastpost int NOT NULL default '0', - lastposter varchar(120) NOT NULL default '', - lastposteruid int NOT NULL default '0', - views int NOT NULL default '0', - replies int NOT NULL default '0', - closed varchar(30) NOT NULL default '', - sticky smallint NOT NULL default '0', - numratings smallint NOT NULL default '0', - totalratings smallint NOT NULL default '0', - notes text NOT NULL default '', - visible smallint NOT NULL default '0', - unapprovedposts int NOT NULL default '0', - deletedposts int NOT NULL default '0', - attachmentcount int NOT NULL default '0', - deletetime int NOT NULL default '0', - PRIMARY KEY (tid) -);"; - -$tables[] = "CREATE TABLE mybb_threadsread ( - tid int NOT NULL default '0', - uid int NOT NULL default '0', - dateline int NOT NULL default '0' -);"; - -$tables[] = "CREATE TABLE mybb_threadsubscriptions ( - sid serial, - uid int NOT NULL default '0', - tid int NOT NULL default '0', - notification smallint NOT NULL default '0', - dateline int NOT NULL default '0', - PRIMARY KEY (sid) -);"; - -$tables[] = "CREATE TABLE mybb_userfields ( - ufid int NOT NULL default '0', - fid1 text NOT NULL default '', - fid2 text NOT NULL default '', - fid3 text NOT NULL default '', - PRIMARY KEY (ufid) -);"; -$query = $db->write_query("SELECT column_name - FROM information_schema.constraint_column_usage - WHERE table_name = '".$config['tableprefix']."userfields' - AND constraint_name = '".$config['tableprefix']."userfields_pkey' - LIMIT 1"); -$main_field = $db->fetch_field($query, 'column_name'); -if(!empty($main_field)) -{ - $tables[] = "DROP SEQUENCE mybb_userfields_ufid_seq;"; -} -$tables[] = "CREATE SEQUENCE mybb_userfields_ufid_seq;"; - -$tables[] = "CREATE TABLE mybb_usergroups ( - gid serial, - type smallint NOT NULL default '2', - title varchar(120) NOT NULL default '', - description text NOT NULL default '', - namestyle varchar(200) NOT NULL default '{username}', - usertitle varchar(120) NOT NULL default '', - stars smallint NOT NULL default '0', - starimage varchar(120) NOT NULL default '', - image varchar(120) NOT NULL default '', - disporder smallint NOT NULL default '0', - isbannedgroup smallint NOT NULL default '0', - canview smallint NOT NULL default '0', - canviewthreads smallint NOT NULL default '0', - canviewprofiles smallint NOT NULL default '0', - candlattachments smallint NOT NULL default '0', - canviewboardclosed smallint NOT NULL default '0', - canpostthreads smallint NOT NULL default '0', - canpostreplys smallint NOT NULL default '0', - canpostattachments smallint NOT NULL default '0', - canratethreads smallint NOT NULL default '0', - modposts smallint NOT NULL default '0', - modthreads smallint NOT NULL default '0', - mod_edit_posts smallint NOT NULL default '0', - modattachments smallint NOT NULL default '0', - caneditposts smallint NOT NULL default '0', - candeleteposts smallint NOT NULL default '0', - candeletethreads smallint NOT NULL default '0', - caneditattachments smallint NOT NULL default '0', - canviewdeletionnotice smallint NOT NULL default '0', - canpostpolls smallint NOT NULL default '0', - canvotepolls smallint NOT NULL default '0', - canundovotes smallint NOT NULL default '0', - canusepms smallint NOT NULL default '0', - cansendpms smallint NOT NULL default '0', - cantrackpms smallint NOT NULL default '0', - candenypmreceipts smallint NOT NULL default '0', - pmquota int NOT NULL default '0', - maxpmrecipients int NOT NULL default '5', - cansendemail smallint NOT NULL default '0', - cansendemailoverride smallint NOT NULL default '0', - maxemails int NOT NULL default '5', - emailfloodtime int NOT NULL default '5', - canviewmemberlist smallint NOT NULL default '0', - canviewcalendar smallint NOT NULL default '0', - canaddevents smallint NOT NULL default '0', - canbypasseventmod smallint NOT NULL default '0', - canmoderateevents smallint NOT NULL default '0', - canviewonline smallint NOT NULL default '0', - canviewwolinvis smallint NOT NULL default '0', - canviewonlineips smallint NOT NULL default '0', - cancp smallint NOT NULL default '0', - issupermod smallint NOT NULL default '0', - cansearch smallint NOT NULL default '0', - canusercp smallint NOT NULL default '0', - canuploadavatars smallint NOT NULL default '0', - canratemembers smallint NOT NULL default '0', - canchangename smallint NOT NULL default '0', - canbereported smallint NOT NULL default '0', - canchangewebsite smallint NOT NULL default '1', - showforumteam smallint NOT NULL default '0', - usereputationsystem smallint NOT NULL default '0', - cangivereputations smallint NOT NULL default '0', - candeletereputations smallint NOT NULL default '0', - reputationpower int NOT NULL default '0', - maxreputationsday int NOT NULL default '0', - maxreputationsperuser int NOT NULL default '0', - maxreputationsperthread int NOT NULL default '0', - candisplaygroup smallint NOT NULL default '0', - attachquota int NOT NULL default '0', - cancustomtitle smallint NOT NULL default '0', - canwarnusers smallint NOT NULL default '0', - canreceivewarnings smallint NOT NULL default '0', - maxwarningsday int NOT NULL default '3', - canmodcp smallint NOT NULL default '0', - showinbirthdaylist smallint NOT NULL default '0', - canoverridepm smallint NOT NULL default '0', - canusesig smallint NOT NULL default '0', - canusesigxposts smallint NOT NULL default '0', - signofollow smallint NOT NULL default '0', - edittimelimit smallint NOT NULL default '0', - maxposts smallint NOT NULL default '0', - showmemberlist smallint NOT NULL default '1', - canmanageannounce smallint NOT NULL default '0', - canmanagemodqueue smallint NOT NULL default '0', - canmanagereportedcontent smallint NOT NULL default '0', - canviewmodlogs smallint NOT NULL default '0', - caneditprofiles smallint NOT NULL default '0', - canbanusers smallint NOT NULL default '0', - canviewwarnlogs smallint NOT NULL default '0', - canuseipsearch smallint NOT NULL default '0', - PRIMARY KEY (gid) -);"; - -$tables[] = "CREATE TABLE mybb_users ( - uid serial, - username varchar(120) NOT NULL default '', - password varchar(120) NOT NULL default '', - salt varchar(10) NOT NULL default '', - loginkey varchar(50) NOT NULL default '', - email varchar(220) NOT NULL default '', - postnum int NOT NULL default '0', - threadnum int NOT NULL default '0', - avatar varchar(200) NOT NULL default '', - avatardimensions varchar(10) NOT NULL default '', - avatartype varchar(10) NOT NULL default '0', - usergroup smallint NOT NULL default '0', - additionalgroups varchar(200) NOT NULL default '', - displaygroup smallint NOT NULL default '0', - usertitle varchar(250) NOT NULL default '', - regdate int NOT NULL default '0', - lastactive int NOT NULL default '0', - lastvisit int NOT NULL default '0', - lastpost int NOT NULL default '0', - website varchar(200) NOT NULL default '', - icq varchar(10) NOT NULL default '', - aim varchar(50) NOT NULL default '', - yahoo varchar(50) NOT NULL default '', - skype varchar(75) NOT NULL default '', - google varchar(75) NOT NULL default '', - birthday varchar(15) NOT NULL default '', - birthdayprivacy varchar(4) NOT NULL default 'all', - signature text NOT NULL default '', - allownotices smallint NOT NULL default '0', - hideemail smallint NOT NULL default '0', - subscriptionmethod smallint NOT NULL default '0', - invisible smallint NOT NULL default '0', - receivepms smallint NOT NULL default '0', - receivefrombuddy smallint NOT NULL default '0', - pmnotice smallint NOT NULL default '0', - pmnotify smallint NOT NULL default '0', - buddyrequestspm smallint NOT NULL default '1', - buddyrequestsauto smallint NOT NULL default '0', - threadmode varchar(8) NOT NULL default '', - showimages smallint NOT NULL default '0', - showvideos smallint NOT NULL default '0', - showsigs smallint NOT NULL default '0', - showavatars smallint NOT NULL default '0', - showquickreply smallint NOT NULL default '0', - showredirect smallint NOT NULL default '0', - ppp smallint NOT NULL default '0', - tpp smallint NOT NULL default '0', - daysprune smallint NOT NULL default '0', - dateformat varchar(4) NOT NULL default '', - timeformat varchar(4) NOT NULL default '', - timezone varchar(5) NOT NULL default '', - dst smallint NOT NULL default '0', - dstcorrection smallint NOT NULL default '0', - buddylist text NOT NULL default '', - ignorelist text NOT NULL default '', - style smallint NOT NULL default '0', - away smallint NOT NULL default '0', - awaydate int NOT NULL default '0', - returndate varchar(15) NOT NULL default '', - awayreason varchar(200) NOT NULL default '', - pmfolders text NOT NULL default '', - notepad text NOT NULL default '', - referrer int NOT NULL default '0', - referrals int NOT NULL default '0', - reputation int NOT NULL default '0', - regip bytea NOT NULL default '', - lastip bytea NOT NULL default '', - language varchar(50) NOT NULL default '', - timeonline int NOT NULL default '0', - showcodebuttons smallint NOT NULL default '1', - totalpms int NOT NULL default '0', - unreadpms int NOT NULL default '0', - warningpoints int NOT NULL default '0', - moderateposts int NOT NULL default '0', - moderationtime int NOT NULL default '0', - suspendposting smallint NOT NULL default '0', - suspensiontime int NOT NULL default '0', - suspendsignature smallint NOT NULL default '0', - suspendsigtime int NOT NULL default '0', - coppauser smallint NOT NULL default '0', - classicpostbit smallint NOT NULL default '0', - loginattempts smallint NOT NULL default '1', - usernotes text NOT NULL default '', - sourceeditor smallint NOT NULL default '0', - PRIMARY KEY (uid) -);"; - -$tables[] = "CREATE TABLE mybb_usertitles ( - utid serial, - posts int NOT NULL default '0', - title varchar(250) NOT NULL default '', - stars smallint NOT NULL default '0', - starimage varchar(120) NOT NULL default '', - PRIMARY KEY (utid) -);"; - -$tables[] = "CREATE TABLE mybb_warninglevels ( - lid serial, - percentage smallint NOT NULL default '0', - action text NOT NULL, - PRIMARY KEY(lid) -);"; - -$tables[] = "CREATE TABLE mybb_warningtypes ( - tid serial, - title varchar(120) NOT NULL default '', - points smallint NOT NULL default '0', - expirationtime int NOT NULL default '0', - PRIMARY KEY(tid) -);"; - -$tables[] = "CREATE TABLE mybb_warnings ( - wid serial, - uid int NOT NULL default '0', - tid int NOT NULL default '0', - pid int NOT NULL default '0', - title varchar(120) NOT NULL default '', - points smallint NOT NULL default '0', - dateline int NOT NULL default '0', - issuedby int NOT NULL default '0', - expires int NOT NULL default '0', - expired smallint NOT NULL default '0', - daterevoked int NOT NULL default '0', - revokedby int NOT NULL default '0', - revokereason text NOT NULL default '', - notes text NOT NULL default '', - PRIMARY KEY(wid) -);"; - - diff --git a/html/forums/install/resources/settings.xml b/html/forums/install/resources/settings.xml deleted file mode 100644 index fad1d1c..0000000 --- a/html/forums/install/resources/settings.xml +++ /dev/null @@ -1,2522 +0,0 @@ - - - - - Board Closed - - 1 - - - 1 - - - Board Closed Reason - - 2 - - - 1 - - - - - Board Name - - 1 - - - 1 - - - Board URL - Include the http://. Do NOT include a trailing slash.]]> - 2 - - - 1 - - - Homepage Name - - 3 - - - 1 - - - Homepage URL - - 4 - - - 1 - - - Admin Email - - 5 - - - 1 - - - Return Email - - 6 - - - 1 - - - Contact Email - - 7 - - - 1 - - - Contact Us Link - - 8 - - - 1 - - - Cookie Domain - - 9 - - - 1 - - - Cookie Path - - 10 - - - 1 - - - Cookie Prefix - - 11 - - - 1 - - - Secure Cookie Flag - - 12 - - - 1 - - - Show Version Numbers - - 13 - - - 1 - - - Mailing Address - - 14 - - - 1 - - - Contact Fax No - - 15 - - - 1 - - - - - Default Language - - 1 - - - 1 - - - <![CDATA[CAPTCHA Images for Registration & Posting]]> - - 2 - - - 1 - - - <![CDATA[reCAPTCHA Public Key]]> - - 3 - - - 1 - - - <![CDATA[reCAPTCHA Private Key]]> - - 4 - - - 1 - - - Reported Content Notification Method - - 5 - - - 1 - - - Decimal Point - - 6 - - - 1 - - - Thousands Numeric Separator - - 7 - - - 1 - - - Show Language Selector in Footer - - 8 - - - 1 - - - Show Theme Selector in Footer - - 9 - - - 1 - - - Maximum Page Links in Pagination - - 10 - - - 1 - - - Show Jump To Page form in Pagination - - 11 - - - 1 - - - Disable All Plugins - - 12 - - - 1 - - - Expire Old Group Invites - - 13 - - - 1 - - - Friendly Redirection Pages - - 14 - - - 1 - - - Enable Forum Jump Menu? - - 15 - - - 1 - - - - - Enable search engine friendly URLs? - Once this setting is enabled you need to make sure you have the MyBB .htaccess in your MyBB root directory (or the equivalent for your web server). Automatic detection may not work on all servers. Please see the MyBB Docs for assistance.]]> - 1 - - - 1 - - - Enable search engine friendly URLs in Archive? - Once this setting is enabled ensure the archive still works as expected.]]> - 2 - - - 1 - - - Use GZip Page Compression? - - 3 - - - 1 - - - GZip Page Compression Level - - 4 - - - 1 - - - Send No Cache Headers - - 5 - - - 1 - - - *NIX Load Limiting - - 6 - - - 1 - - - Output template start/end comments? - - 7 - - - 1 - - - Enable XMLHttp request features? - - 8 - - - 1 - - - Advanced Stats / Debug information - - 9 - - - 1 - - - Uploads Path - must be chmod 777 (on *nix servers).]]> - 10 - - - 1 - - - Use Error Handling - - 11 - - - 1 - - - Error Logging Medium - - 12 - - - 1 - - - Error Type Medium - - 13 - - - 1 - - - Error Logging Location - - 14 - - - 1 - - - Scrutinize User's IP address? - - 15 - - - 1 - - - Minify Stylesheets? - - 16 - - - 1 - - - - Use a CDN? - - 17 - - - 1 - - - - URL to use for static files - - 18 - - - 1 - - - - Path to store static files - - 19 - - - 1 - - - - - - Date Format - - 1 - - - 1 - - - Time Format - - 2 - - - 1 - - - Date/Time Separator - - 3 - - - 1 - - - Registered Date Format - - 4 - - - 1 - - - Default Timezone Offset - - 5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - 1 - - - Day Light Savings Time - - 6 - - - 1 - - - - - Show Forum Descriptions? - - 1 - - - 1 - - - Subforums to show on Index listing - - 2 - - - 1 - - - Show Subforum Status Icons? - - 3 - - - 1 - - - Hide Private Forums? - - 4 - - - 1 - - - Forums' Moderator Listing - - 5 - - - 1 - - - Show Today's Birthdays? - - 6 - - - 1 - - - Only Show Birthdays with x Posts - - 7 - - - 1 - - - Show Who's Online? - - 8 - - - 1 - - - Show Small Stats Section - - 9 - - - 1 - - - Show x viewing forum - - 10 - - - 1 - - - - - Threads Per Page - - 1 - - - 1 - - - Replies For Hot Topic - - 2 - - - 1 - - - Views For Hot Topic - - 3 - - - 1 - - - User Selectable Threads Per Page - - 4 - - - 1 - - - Use 'dot' Icons - - 5 - - - 1 - - - Use Thread Ratings? - - 6 - - - 1 - - - Users Browsing this Forum - - 7 - - - 1 - - - Announcements Limit - - 8 - - - 1 - - - Attempt to Mark Parent Forums as Read - MyBB Docs for more information regarding this change.]]> - 9 - - - 1 - - - - - Post Layout - - 1 - - - 1 - - - Posts Per Page: - - 2 - - - 1 - - - User Selectable Posts Per Page - - 3 - - - 1 - - - Maximum Avatar Dimensions in Posts - - 4 - - - 1 - - - Read Threads in Database (Days) - - 5 - - - 1 - - - Usenet Style Thread View - - 6 - - - 1 - - - Show Quick Reply Form - - 7 - - - 1 - - - Show Multi-quote Buttons - - 8 - - - 1 - - - Show 'Similar Threads' Table - - 9 - - - 1 - - - Similar Threads Relevancy Rating - - 10 - - - 1 - - - Similar Threads Limit - - 11 - - - 1 - - - Show Forum Multipage Dropdown - - 12 - - - 1 - - - Users Browsing this Thread - - 13 - - - 1 - - - Delayed Thread View Updates - - 14 - - - 1 - - - - - Disable Registrations - - 1 - - - 1 - - - Registration Method - - 2 - - - 1 - - - Awaiting Activation Notification - - 3 - - - 1 - - - Force Users to Login - - 4 - - - 1 - - - Minimum Username Length - - 5 - - - 1 - - - Maximum Username Length - - 6 - - - 1 - - - Minimum Password Length - - 7 - - - 1 - - - Maximum Password Length - - 8 - - - 1 - - - Require a complex password? - - 9 - - - 1 - - - Time Between Registrations - - 10 - - - 1 - - - Maximum Registrations Per IP Address - - 11 - - - 1 - - - <![CDATA[Allow emails to be registered multiple times?]]> - - 12 - - - 1 - - - Users Keep Email - - 13 - - - 1 - - - Display a hidden CAPTCHA - - 14 - - - 1 - - - Hidden CAPTCHA field - - 15 - - - 1 - - - Use Referrals System - - 16 - - - 1 - - - COPPA Compliance - COPPA support on your forums, please select the registration allowance below.]]> - 17 - - - 1 - - - Allowed Login Methods - To allow email as a valid login method, no users are allowed to share email addresses.]]> - 18 - - - 0 - - - Number of failed logins before verification required - - 19 - - - 1 - - - Number of times to allow failed logins - - 20 - - - 1 - - - Time between failed logins - - 21 - - - 1 - - - Display number of failed logins - - 22 - - - 1 - - - Minimum Registration Time - - 23 - - - 1 - - - Show Security Question - - 24 - - - 1 - - - - - Allow MyCode in Signatures - - 1 - - - 1 - - - MyCode affects signature length - - 2 - - - 1 - - - Allow Smilies in Signatures - - 3 - - - 1 - - - Allow HTML in Signatures - - 4 - - - 1 - - - Allow [img] Code in Signatures - - 5 - - - 1 - - - Maximum Number of Images per Signature - - 6 - - - 1 - - - Length limit in Signatures - - 7 - - - 1 - - - Hide Signatures To Groups - - 8 - - - 1 - - - Hide Websites To Groups - - 9 - - - 1 - - - Default User Avatar - {theme} to represent the image directory of each theme.]]> - 10 - - - 1 - - - Default Avatar Dimensions - - 11 - - - 1 - - - Gravatar Rating - -
  • G: suitable for display on all websites with any audience type
  • -
  • PG: may contain rude gestures, provocatively dressed individuals, the lesser swear words or mild violence
  • -
  • R: may contain such things as harsh profanity, intense violence, nudity or hard drug use
  • -
  • X: may contain hardcore sexual imagery or extremely disturbing violence
  • -]]>
    - 12 - - - 1 -
    - - Maximum Avatar Dimensions - xheight. If this is left blank then there will be no dimension restriction.]]> - 13 - - - 1 - - - Max Uploaded Avatar Size - - 14 - - - 1 - - - Avatar Resizing Mode - - 15 - - - 1 - - - Avatar Upload Path - must be chmod 777 (writable) for uploads to work.]]> - 16 - - - 1 - - - Allow Remote Avatars - - 17 - - - 1 - - - Custom User Title Maximum Length - - 18 - - - 1 - - - Allow Away Statuses? - - 19 - - - 1 - - - Allow Buddy-Only Messaging? - - 20 - - - 1 - -
    - - - Minimum Message Length - - 1 - - - 1 - - - Maximum Message Length - This should correlate with the message column type in the posts database table, and adjust accordingly. Below are the maximum lengths for each column type. -
      -
    • TEXT: 65535 (default)
    • -
    • MEDIUMTEXT: 16777215
    • -
    • LONGTEXT: 4294967295
    • -
    ]]>
    - 2 - - - 1 -
    - - MyCode Affects Minimum Message Length? - - 3 - - - 1 - - - Post Flood Checking - - 4 - - - 1 - - - Post Flood Time - - 5 - - - 1 - - - Post Merge Time - - 6 - - - 1 - - - Merge Forums to Ignore - - 7 - - - 1 - - - Merge User Groups to Ignore - - 8 - - - 1 - - - Merge Separator - - 9 - - - 1 - - - Show Posting IP Addresses - - 10 - - - 1 - - - Show 'edited by' Messages - - 11 - - - 1 - - - Show 'edited by' Message for Administrators and Moderators - - 12 - - - 1 - - - Maximum Images per Post - - 13 - - - 1 - - - Maximum Videos per Post - - 14 - - - 1 - - - Amount of Characters for Subscription Previews - - 15 - - - 1 - - - Maximum Nested Quote Tags - - 16 - - - 1 - - - Maximum Poll Option Length - - 17 - - - 1 - - - Maximum Number of Poll Options - - 18 - - - 1 - - - Poll Time Limit - - 19 - - - 1 - - - Show Thread Review - - 20 - - - 1 - - - Allow Edit Reason - - 21 - - - 1 - - - Enable Soft Delete for Users - - 22 - - - 1 - -
    - - - Enable Attachment Functionality - - 1 - - - 1 - - - Maximum Attachments Per Post - - 2 - - - 1 - - - Show Attached Thumbnails in Posts - - 3 - - - 1 - - - Attached Thumbnail Maximum Height - - 4 - - - 1 - - - Attached Thumbnail Maximum Width - - 5 - - - 1 - - - - - Enable Member List Functionality - - 1 - - - 1 - - - Members Per Page - - 2 - - - 1 - - - Default Sort Field - - 3 - - - 1 - - - Default Sort Order - Ascending: A-Z / beginning-end
    Descending: Z-A / end-beginning]]>
    - 4 - - - 1 -
    - - Maximum Display Avatar Dimensions - - 5 - - - 1 - -
    - - - Enable Reputation Functionality - - 1 - - - 1 - - - Allow Positive Reputation - - 2 - - - 1 - - - Allow Negative Reputation - - 3 - - - 1 - - - Allow Neutral Reputation - - 4 - - - 1 - - - Allow Multiple Reputation - Note: Does not effect "Post" reputation]]> - 5 - - - 1 - - - Allow Post Reputations - - 6 - - - 1 - - - Reputation Comments Per Page - - 7 - - - 1 - - - Maximum Reputation Length - - 8 - - - 1 - - - Minimum Reputation Length - - 9 - - - 1 - - - - - Enable Warning System? - - 1 - - - 1 - - - Allow Custom Warning Types? - - 2 - - - 1 - - - Can Users View Own Warnings? - - 3 - - - 1 - - - Allow Anonymous Warning PMs - - 4 - - - 1 - - - Maximum Warning Points - - 5 - - - 1 - - - - - Enable Private Messaging Functionality - - 1 - - - 1 - - - Show Quick Reply Form - - 2 - - - 1 - - - Allow HTML - - 3 - - - 1 - - - Allow MyCode - - 4 - - - 1 - - - Allow Smilies - - 5 - - - 1 - - - Allow [img] Code - - 6 - - - 1 - - - Allow [video] Code - - 7 - - - 1 - - - Private Message Flood Time - - 8 - - - 1 - - - Show Private Message IP Addresses - - 9 - - - 1 - - - Maximum PM Nested Quote Tags - - 10 - - - 1 - - - - - Enable Calendar Functionality - - 1 - - - 1 - - - - - Cut-off Time (mins) - - 1 - - - 1 - - - Refresh Who's online page Time (mins) - - 2 - - - 1 - - - Who's Online Order - - 3 - - - 1 - - - - - Enable user pruning? - - 1 - - - 1 - - - Prune user by post count? - - 2 - - - 1 - - - Post count to prune by - - 3 - - - 1 - - - Count all posts? - - 4 - - - 0 - - - Days registered before pruning by post count - - 5 - - - 1 - - - Prune unactivated users? - - 6 - - - 1 - - - Days registered before pruning unactivated users - - 7 - - - 1 - - - Prune User Posts/Threads - - 8 - - - 1 - - - - - Enable Portal - - 1 - - - 1 - - - Forums to pull announcements from - - 2 - - - 1 - - - Number of announcements to show - - 3 - - - 1 - - - Show the Welcome box - - 4 - - - 1 - - - Show the number of PMs to users - - 5 - - - 1 - - - Show forum statistics - - 6 - - - 1 - - - Show Who's Online - - 7 - - - 1 - - - Show Search Box - - 8 - - - 1 - - - Show Latest Discussions - - 9 - - - 1 - - - Number of latest discussions to show - - 10 - - - 1 - - - Forums to exclude latest discussions from - - 11 - - - 1 - - - - - Search Type - - 1 - ".($db->supports_fulltext("threads") && $db->supports_fulltext_boolean("posts")?"":"")."]]> - - 1 - - - Search Flood Time (seconds) - - 2 - - - 1 - - - Minimum Search Word Length - - 3 - - - 1 - - - Hard Limit for Maximum Search Results - - 4 - - - 1 - - - Enable Help Documents Search - - 5 - - - 1 - - - - - Clickable MyCode Editor - - 1 - - - 1 - - - Clickable MyCode Editor in Partial Mode - - 2 - - - 0 - - - Clickable Smilies Inserter - - 3 - - - 1 - - - No. of Smilies to show - - 4 - - - 1 - - - No. of Smilie Cols to Show - - 5 - - - 1 - - - Allow Basic MyCodes - - 6 - - - 1 - - - Allow Color MyCode - - 7 - - - 1 - - - Allow Size MyCode - - 8 - - - 1 - - - Allow Font MyCode - - 9 - - - 1 - - - Allow Link MyCode - - 10 - - - 1 - - - Allow Email MyCode - - 11 - - - 1 - - - Allow Alignment MyCode - - 12 - - - 1 - - - Allow List MyCode - - 13 - - - 1 - - - Allow Code MyCodes - - 14 - - - 1 - - - Allow Symbol MyCodes - - 15 - - - 1 - - - Allow Me MyCodes - - 16 - - - 1 - - - Parse [img] MyCode To Guests - - 17 - - - 1 - - - Parse [video] MyCode To Guests - - 18 - - - 1 - - - - - Control Panel Language - - 1 - - - 1 - - - Control Panel Style - - 2 - - - 1 - - - Max Number of Login Attempts - - 3 - - - 1 - - - Login Attempts Timeout - - 4 - - - 1 - - - - - Mail handler - - 1 - - - 1 - - - SMTP hostname - Only required if SMTP Mail is selected as the Mail Handler.]]> - 2 - - - 1 - - - SMTP port - Only required if SMTP Mail is selected as the Mail Handler.]]> - 3 - - - 1 - - - SMTP username - Only required if SMTP Mail is selected as the Mail Handler, and the SMTP server requires authentication.]]> - 4 - - - 1 - - - SMTP password - Only required if SMTP Mail is selected as the Mail Handler, and the SMTP server requires authentication.]]> - 5 - - - 1 - - - SMTP Encryption Mode - Only required if SMTP Mail is selected as the Mail Handler.]]> - 6 - - - 1 - - - Additional Parameters for PHP's mail() - More information]]> - 7 - - - 1 - - - Mail Logging - - 8 - - - 1 - - - Add message ID in mail headers - - 9 - - - 1 - - - - - Enable Contact Page - - 1 - - - 1 - - - Disable Contact Page to Guests - - 2 - - - 1 - - - Enable Word Filter on Contact Page - - 3 - - - 1 - - - Maximum Subject Length on Contact Page - - 4 - - - 1 - - - Minimum Message Length on Contact Page - - 5 - - - 1 - - - Maximum Message Length on Contact Page - - 6 - - - 1 - - - - - Allowed Usergroups - - 1 - - - 1 - - - - Post Limit - - 2 - - - 1 - - - - Ban or Delete Spammers - - 3 - - - 1 - - - - Ban Usergroup - - 4 - - - 1 - - - - Ban Reason - - 5 - - - 1 - - - - Stop Forum Spam API Key - here. When you have your key, paste it into the box below.]]> - 6 - - - 1 - - - - - - Check Registrations Against StopForumSpam.com? - - - 1 - - - 1 - - - Check Guest Contact Submissions Against StopForumSpam? - - - 2 - - - 1 - - - Check Guest Replies Against StopForumSpam? - - - 3 - - - 1 - - - Check Guest Threads Against StopForumSpam? - - - 4 - - - 1 - - - Minimum stop forum spam weighting? - - - 5 - - - 1 - - - Check usernames? - - - 6 - - - 1 - - - Check email addresses? - - - 7 - - - 1 - - - Check IP addresses? - - - 8 - - - 1 - - - Block on StopForumSpam error? - - - 9 - - - 1 - - - Log StopForumSpam blocks? - - - 10 - - - 1 - - - - - Allow ICQ Number Field To Usergroups - - 1 - - - 1 - - - - Allow AIM Screen Name To Usergroups - - 2 - - - 1 - - - - Allow Yahoo ID Field To Usergroups - - 3 - - - 1 - - - - Allow Skype ID Field To Usergroups - - 4 - - - 1 - - - - Allow Google Hangouts ID Field To Usergroups - - 5 - - - 1 - - - - - - Enable Statistics Pages - - 1 - - - 1 - - - - Statistics Cache Time - - 2 - - - 1 - - - - Stats Limit - - 3 - - - 1 - - - Show Top Referrer on Statistics Page - - 4 - - - 1 - - -
    diff --git a/html/forums/install/resources/sqlite_db_tables.php b/html/forums/install/resources/sqlite_db_tables.php deleted file mode 100644 index 7d5185b..0000000 --- a/html/forums/install/resources/sqlite_db_tables.php +++ /dev/null @@ -1,1058 +0,0 @@ - - - - Hourly Cleanup - - hourlycleanup - 0 - * - * - * - * - 1 - 1 - - - Daily Cleanup - - dailycleanup - 0 - 0 - * - * - * - 1 - 1 - - - Half-hourly User Cleanup - - usercleanup - 30,59 - * - * - * - * - 1 - 1 - - - Weekly Backup - - backupdb - 0 - 0 - * - 0 - * - 0 - 1 - - - Promotion System - - promotions - 5,25,45 - * - * - * - * - 1 - 1 - - - Thread Views - - threadviews - 10,25,40,55 - * - * - * - * - 0 - 1 - - - Tables Check - - checktables - 0 - * - * - * - * - 0 - 1 - - - Log Pruning - - logcleanup - 21 - 5 - * - * - * - 1 - 1 - - - Mass Mail - - massmail - 10,25,40,55 - * - * - * - * - 1 - 1 - - - User Pruning - - userpruning - 0 - 2 - * - * - * - 1 - 1 - - - Delayed Moderation - - delayedmoderation - 0 - 0 - * - * - * - 1 - 1 - - - Version Check - - versioncheck - 0 - 0 - * - * - * - 1 - 1 - - - Stylesheet Re-Cache - - recachestylesheets - 0 - 0 - 1 - 0 - 0 - 0 - 1 - - \ No newline at end of file diff --git a/html/forums/install/resources/upgrade1.php b/html/forums/install/resources/upgrade1.php deleted file mode 100644 index e425075..0000000 --- a/html/forums/install/resources/upgrade1.php +++ /dev/null @@ -1,408 +0,0 @@ - 1, - "revert_all_themes" => 1, - "revert_all_settings" => 1, - "requires_deactivated_plugins" => 1, -); - -function upgrade1_dbchanges() -{ - global $db, $output; - - $output->print_header("Database Changes since Release Candidate 2"); - - $contents .= "

    Making necessary database modifications..."; - - if($db->field_exists('regip', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP regid;"); - } - $db->write_query("ALTER TABLE users ADD regip varchar(50) NOT NULL;"); - - $db->write_query("ALTER TABLE banned CHANGE lifted lifted varchar(40) NOT NULL;"); - - if($db->field_exists('posthash', "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP posthash;"); - } - $db->write_query("ALTER TABLE attachments ADD posthash varchar(50) NOT NULL AFTER pid;"); - - if($db->field_exists('thumbnail', "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP thumbnail;"); - } - $db->write_query("ALTER TABLE attachments ADD thumbnail blob NOT NULL"); - - if($db->field_exists('thumbnailsm', "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP thumbnailsm;"); - } - $db->write_query("ALTER TABLE attachments ADD thumbnailsm char(3) NOT NULL;"); - - $db->write_query("DELETE FROM attachtypes"); - $db->write_query("INSERT INTO attachtypes VALUES(NULL,'Compressed Archive','','zip gz tar rar ace cab','1024');"); - $db->write_query("INSERT INTO attachtypes VALUES(NULL,'JPEG Image','','jpg jpe jpeg','500');"); - $db->write_query("INSERT INTO attachtypes VALUES(NULL,'Text Document','text/plain','txt','200');"); - $db->write_query("INSERT INTO attachtypes VALUES(NULL,'GIF Image','image/gif','gif','500');"); - $db->write_query("INSERT INTO attachtypes VALUES(NULL,'Bitmap Image','','bmp','500');"); - $db->write_query("INSERT INTO attachtypes VALUES(NULL,'PHP File','','php phps php3 php4','500');"); - $db->write_query("INSERT INTO attachtypes VALUES(NULL,'PNG Image','image/png image/x-png','png','50');"); - $db->write_query("INSERT INTO attachtypes VALUES(NULL,'Microsoft Word Document','','doc rtf','1024');"); - $db->write_query("INSERT INTO attachtypes VALUES(NULL,'Executable','','exe com bat','1024');"); - - if($db->field_exists('small', "themes")) - { - $db->write_query("ALTER TABLE themes DROP small;"); - } - if($db->field_exists('smallend', "themes")) - { - $db->write_query("ALTER TABLE themes DROP smallend;"); - } - if($db->field_exists('font', "themes")) - { - $db->write_query("ALTER TABLE themes DROP font;"); - } - if($db->field_exists('frontend', "themes")) - { - $db->write_query("ALTER TABLE themes DROP fontend;"); - } - if($db->field_exists('large', "themes")) - { - $db->write_query("ALTER TABLE themes DROP large;"); - } - if($db->field_exists('largeend', "themes")) - { - $db->write_query("ALTER TABLE themes DROP largeend;"); - } - - if($db->field_exists('smallfont', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP smallfont;"); - } - $db->write_query("ALTER TABLE themes ADD smallfont varchar(150) NOT NULL;"); - - if($db->field_exists('smallfontsize', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP smallfontsize;"); - } - $db->write_query("ALTER TABLE themes ADD smallfontsize varchar(20) NOT NULL;"); - - if($db->field_exists('normalfont', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP normalfont;"); - } - $db->write_query("ALTER TABLE themes ADD normalfont varchar(150) NOT NULL;"); - - if($db->field_exists('normalfontsize', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP normalfontsize;"); - } - $db->write_query("ALTER TABLE themes ADD normalfontsize varchar(20) NOT NULL;"); - - if($db->field_exists('largefont', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP largefont;"); - } - $db->write_query("ALTER TABLE themes ADD largefont varchar(150) NOT NULL;"); - - if($db->field_exists('largefontsize', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP largefontsize;"); - } - $db->write_query("ALTER TABLE themes ADD largefontsize varchar(20) NOT NULL;"); - - if($db->field_exists('menubgcolor', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP menubgcolor;"); - } - $db->write_query("ALTER TABLE themes ADD menubgcolor varchar(15) NOT NULL;"); - - if($db->field_exists('menubgimage', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP menubgimage;"); - } - $db->write_query("ALTER TABLE themes ADD menubgimage varchar(100) NOT NULL;"); - - if($db->field_exists('menucolor', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP menucolor;"); - } - $db->write_query("ALTER TABLE themes ADD menucolor varchar(15) NOT NULL;"); - - if($db->field_exists('menuhoverbgcolor', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP menuhoverbgcolor;"); - } - $db->write_query("ALTER TABLE themes ADD menuhoverbgcolor varchar(15) NOT NULL;"); - - if($db->field_exists('menuhoverbgimage', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP menuhoverbgimage;"); - } - $db->write_query("ALTER TABLE themes ADD menuhoverbgimage varchar(100) NOT NULL;"); - - if($db->field_exists('menuhovercolor', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP menuhovercolor;"); - } - $db->write_query("ALTER TABLE themes ADD menuhovercolor varchar(15) NOT NULL;"); - - if($db->field_exists('panelbgcolor', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP panelbgcolor;"); - } - $db->write_query("ALTER TABLE themes ADD panelbgcolor varchar(15) NOT NULL;"); - - if($db->field_exists('panelbgimage', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP panelbgimage;"); - } - $db->write_query("ALTER TABLE themes ADD panelbgimage varchar(100) NOT NULL;"); - - if($db->field_exists('linkhover', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP linkhover;"); - } - $db->write_query("ALTER TABLE themes ADD linkhover varchar(15) NOT NULL AFTER link;"); - - if($db->field_exists('extracss', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP extracss;"); - } - $db->write_query("ALTER TABLE themes ADD extracss varchar(10) NOT NULL AFTER linkhover;"); - - - $db->write_query("UPDATE themes SET linkhover='#000000'"); - - $db->write_query("UPDATE themes SET smallfont='Verdana', smallfontsize='11px', normalfont='Verdana', normalfontsize='13px', largefont='Verdana', largefontsize='20px';"); - - $contents .= "done

    "; - - $db->drop_table("settinggroups", false, false); - $db->write_query("CREATE TABLE settinggroups ( - gid smallint(6) NOT NULL auto_increment, - name varchar(220) NOT NULL default '', - description text NOT NULL, - disporder smallint(6) NOT NULL default '0', - isdefault char(3) NOT NULL default '', - PRIMARY KEY (gid) - );"); - - $db->drop_table("settings", false, false); - $db->write_query("CREATE TABLE settings ( - sid smallint(6) NOT NULL auto_increment, - name varchar(120) NOT NULL default '', - title varchar(120) NOT NULL default '', - description text NOT NULL, - optionscode text NOT NULL, - value text NOT NULL, - disporder smallint(6) NOT NULL default '0', - gid smallint(6) NOT NULL default '0', - PRIMARY KEY (sid) - );"); - - $output->print_contents("$contents

    Please click next to continue with the upgrade process.

    "); - $output->print_footer("1_dbchanges2"); -} -function upgrade1_dbchanges2() -{ - global $db, $output; - - $output->print_header("Database Changes since Release Candidate 2"); - - $db->write_query("DELETE FROM themes"); - $arr = @file("./resources/theme.mybb"); - $contents = @implode("", $arr); - - // now we have $contents we can start dealing with the .theme file! - $themee = explode("(_!&!_)", $contents); - $thver = $themee[0]; - $thname = "Light"; - $thcontents = $themee[2]; - $thtemplates = $themee[3]; - - // go through the actual theme part (colours etc) - $themefile = explode("|#*^^&&^^*#|", $thcontents); - $themeq1 = ""; - $themeq2 = ""; - foreach($themefile as $key => $val) - { - list($item, $value) = explode("|#*!!**!!*#|", $val); - if($db->field_exists($item, "themes")) - { - $themebits[$item] = $value; - } - } - - // add the theme set - $tquery1 = ""; - $tquery2 = ""; - unset($themebits['templateset']); - foreach($themebits as $key => $val) - { - if($key && $val) - { - $tquery1 .= ",$key"; - $tquery2 .= ",'$val'"; - } - } - $db->write_query("INSERT INTO themes (tid,name,templateset$tquery1) VALUES ('','((master))','$sid'$tquery2)"); - $thetid = $db->write_query("INSERT INTO themes (tid,name,templateset$tquery1) VALUES ('','$thname','$sid2'$tquery2)"); - $db->write_query("UPDATE themes SET def='1' WHERE tid='$thetid'"); - - $output->print_contents("Theme imported

    Please click next to continue with the upgrade process.

    "); - $output->print_footer("1_dbchanges3"); -} -function upgrade1_dbchanges3() -{ - - global $db, $output; - - $output->print_header("Database Changes since Release Candidate 2"); - - $contents .= "

    Reinserting all board settings..."; - - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (1, 'General Configuration', 'This section contains various settings such as your board name and url, as well as your website name and url.', 2, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (3, 'Date and Time Formats', 'Here you can specify the different date and time formats used to display dates and times on the forums.', 4, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (7, 'Forum Display Options', 'This section allows you to manage the various settings used on the forum fisplay (forumdisplay.php) of your boards such as enabling and disabling different features.', 6, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (8, 'Show Thread Options', 'This section allows you to manage the various settings used on the thread display page (showthread.php) of your boards such as enabling and disabling different features.', 7, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (10, 'MyCode and Formatting Options', '', 16, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (11, 'Private Messaging', 'Various options with relation to the MyBB Private Messaging system (private.php) can be managed and set here.', 11, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (12, 'Member List', 'This section allows you to control various aspects of the board member listing (memberlist.php), such as how many members to show per page, and which features to enable or disable.', 10, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (13, 'Posting', 'These options control the various elements in relation to posting messages on the forums.', 9, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (14, 'Banning Options', '', 15, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (16, 'Forum Home Options', 'This section allows you to manage the various settings used on the forum home (index.php) of your boards such as enabling and disabling different features.', 5, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (17, 'Calendar', 'The board calendar allows the public and private listing of events and members\' birthdays. This section allows you to control and manage the settings for the Calendar.', 12, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (27, 'Server and Optimization Options', 'These options allow you to set various server and optimization preferences allowing you to reduce the load on your server, and gain better performance on your board.', 3, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (19, 'User Registration and Profile Options', 'Here you can control various settings with relation to user account registration and account management.', 8, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (20, 'Clickable Smilies and BB Code', '', 17, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (21, 'Common Language Bits', '', 18, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (23, 'Who\'s Online', '', 13, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (26, 'Board Online / Offline', 'These settings allow you to globally turn your forums online or offline, and allow you to specify a reason for turning them off.', 1, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (28, 'Control Panel Preferences (Global)', '', 19, 'yes');"); - $db->write_query("INSERT INTO `settinggroups` (`gid`, `name`, `description`, `disporder`, `isdefault`) VALUES (30, 'Portal Settings', '', 14, 'yes');"); - - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (1, 'boardclosed', 'Board Closed', 'If you need to close your forums to make some changes or perform an upgrade, this is the global switch. Viewers will not be able to view your forums, however, they will see a message with the reason you specify below.
    \r\n
    \r\nAdministrators will still be able to view the forums.', 'yesno', 'no', 1, 26);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (2, 'boardclosed_reason', 'Board Closed Reason', 'If your forum is closed, you can set a message here that your visitors will be able to see when they visit your forums.', 'textarea', 'These forums are currently closed for maintenance. Please check back later.', 2, 26);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (3, 'bbname', 'Board Name', 'The name of your message boards. We recommend that it is not over 75 characters.', 'text', 'MyBB Community Forums', 1, 1);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (4, 'bburl', 'Board URL', 'The url to your forums.
    Include the http://. Do NOT include a trailing slash.', 'text', 'http://www.mybb.com/community', 2, 1);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (5, 'homename', 'Homepage Name', 'The name of your homepage. This will appear in the footer with a link to it.', 'text', 'MyBB', 3, 1);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (6, 'homeurl', 'Homepage URL', 'The full URL of your homepage. This will be linked to in the footer along with its name.', 'text', 'http://www.mybb.com', 4, 1);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (7, 'reportviapms', 'Send Reported Posts via PMS', 'Do you want to send reported post messages via the private messaging function to moderators?', 'yesno', 'yes', 5, 8);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (8, 'dateformat', 'Date Format', 'The format of the dates used on the forum. This format uses the PHP date() function. We recommend not changing this unless you know what you\'re doing.', 'text', 'm-d-Y', 1, 3);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (9, 'adminemail', 'Admin Email', 'The administrator\'s email address. This will be used for outgoing emails sent via the forums.', 'text', 'contact@mybb.com', 1, 1);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (10, 'timeformat', 'Time Format', 'The format of the times used on the forum. This format uses PHP\'s date() function. We recommend not changing this unless you know what you\'re doing.', 'text', 'h:i A', 2, 3);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (11, 'threadsperpage', 'Threads Per Page', '', 'text', '20', 1, 7);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (12, 'stickyprefix', 'Sticky Threads Prefix', 'The prefix of topics which have been made sticky by a moderator or administrator.', 'text', 'Sticky:', 2, 7);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (13, 'hottopic', 'Replys For Hot Topic', 'The number of replies that is needed for a topic to be considered \'hot\'.', 'text', '20', 3, 7);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (14, 'cookiedomain', 'Cookie Domain', 'The domain which cookies should be set to. This can remain blank. It should also start with a . so it covers all subdomains.', 'text', '', 5, 1);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (15, 'cookiepath', 'Cookie Path', 'The path which cookies are set to, we recommend setting this to the full directory path to your forums with a trailing slash.', 'text', '', 6, 1);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (16, 'pollprefix', 'Poll Prefix', 'The prefix on forum display which contain polls.', 'text', 'Poll:', 4, 7);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (17, 'postsperpage', 'Posts Per Page:', 'The number of posts to display per page. We recommend its not higher than 20 for people with slower connections.', 'text', '10', 1, 8);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (18, 'regdateformat', 'Registered Date Format', 'The format used on showthread where it shows when the user registered.', 'text', 'M Y', 3, 3);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (19, 'sigmycode', 'Allow MyCode in Signatures', 'Do you want to allow MyCode to be used in users\' signatures?', 'yesno', 'yes', 1, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (20, 'sigsmilies', 'Allow Smilies in Signatures', 'Do you want to allow smilies to be used in users\' signatures?', 'yesno', 'yes', 3, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (21, 'sightml', 'Allow HTML in Signatures', 'Do you want to allow HTML to be used in users\' signatures?', 'yesno', 'no', 4, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (22, 'sigimgcode', 'Allow [img] Code in Signatures', 'Do you want to allow [img] code to be used in users\' signatures?', 'yesno', 'yes', 5, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (23, 'quoteboxstyle', 'Fancy Quote Boxes', 'Selecting yes will cause quotes to be in a table and look more professional. Selecting no will show quotes in the traditional way.', 'yesno', 'yes', 1, 10);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (24, 'codeboxstyle', 'Fancy Code Boxes', 'Selecting yes will cause code to be in a table and look more professional. Selecting no will show code in the traditional way.', 'yesno', 'yes', 2, 10);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (25, 'threadusenetstyle', 'Usenet Style Thread View', 'Selecting yes will cause posts to look similar to how posts look in USENET. No will cause posts to look the modern way.', 'yesno', 'no', 3, 8);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (26, 'pmsallowhtml', 'Allow HTML', 'Selecting yes will allow HTML to be used in private messages.', 'yesno', 'no', 1, 11);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (27, 'pmsallowmycode', 'Allow MyCode', 'Selecting yes will allow MyCode to be used in private messages.', 'yesno', 'yes', 2, 11);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (28, 'pmsallowsmilies', 'Allow Smilies', 'Selecting yes will allow Smilies to be used in private messages.', 'yesno', 'yes', 3, 11);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (29, 'pmsallowimgcode', 'Allow [img] Code', 'Selecting yes will allow [img] Code to be used in private messages.', 'yesno', 'yes', 4, 11);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (30, 'siglength', 'Length limit in Signatures', 'The maximum number of characters a user can place in a signature.', 'text', '255', 6, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (31, 'messagelength', 'Maximum Message Length', 'The maximum number of characters to allow in a message. A setting of 0 allows an unlimited length.', 'text', '0', 1, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (32, 'membersperpage', 'Members Per Page', 'The number of members to show per page on the member list.', 'text', '20', 1, 12);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (33, 'load', '*NIX Load Limiting', 'Limit the maximum server load before myBB rejects people. 0 for none. Recommended limit is 5.0.', 'text', '0', 5, 27);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (34, 'emailkeep', 'Users Keep Email', 'If a current user has an email already registered in your banned list, should he be allowed to keep it.', 'yesno', 'no', 4, 14);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (35, 'ipban', 'Ban by IP', 'Here, you may specify IP addresses or a range of IP addresses. You must separate each IP with a space.', 'textarea', '', 2, 14);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (36, 'emailban', 'Ban by Email', 'You may specify specific email addresses to ban, or you may specify a domain. You must separate email addresses and domains with a space.', 'textarea', '', 3, 14);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (37, 'avatarsize', 'Max Uploaded Avatar Size', 'Maximum file size (in kilobytes) of uploaded avatars.', 'text', '10', 8, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (38, 'avatardir', 'Avatar Directory', 'The directory where your avatars are stored. These are used in the avatar list in the User CP.', 'text', 'images/avatars', 7, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (39, 'showeditedby', 'Show \'edited by\' Messages', 'Once a post is edited by a regular user, do you want to show the edited by message?', 'yesno', 'yes', 6, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (40, 'maxposts', 'Maximum Posts Per Day', 'This is the total number of posts allowed per user per day. 0 for unlimited.', 'text', '0', 2, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (41, 'showeditedbyadmin', 'Show \'edited by\' Message for Forum Staff', 'Do you want to show edited by messages for forum staff when they edit their posts?', 'yesno', 'yes', 7, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (42, 'bannedusernames', 'Banned Usernames', 'Ban users from registering certain usernames. Seperate them with a space.', 'textarea', 'drcracker Oops! hmmm', 1, 14);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (43, 'maxpolloptions', 'Maximum Number of Poll Options', 'The maximum number of options for polls that users can post.', 'text', '10', 3, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (44, 'dotfolders', 'Use \'dot\' Icons', 'Do you want to show dots on the thread indicators of threads users have participated in.', 'yesno', 'yes', 8, 7);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (45, 'contactlink', 'Contact Us Link', 'This will be used for the Contact Us link on the bottom of all the forum pages. Can either be an email address (using mailto:email@website.com) or a hyperlink.', 'text', 'mailto:contact@mybb.com', 2, 1);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (46, 'showdescriptions', 'Show Forum Descriptions?', 'This option will allow you to turn off showing the descriptions for forums.', 'yesno', 'yes', 1, 16);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (47, 'showbirthdays', 'Show Today\'s Birthdays?', 'Do you want to show today\'s birthdays on the forum homepage?', 'yesno', 'yes', 2, 16);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (48, 'showwol', 'Show Who\'s Online?', 'Display the currently active users on the forum home page.', 'yesno', 'yes', 4, 16);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (49, 'hideprivateforums', 'Hide Private Forums?', 'You can hide private forums by turning this option on. This option also hides forums on the forum jump and all subforums.', 'yesno', 'yes', 3, 16);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (50, 'showsimilarthreads', 'Show \'Similar Threads\' Table', 'The Similar Threads table shows threads that are relevant to the thread being read. You can set the relevancy below.', 'yesno', 'no', 4, 8);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (51, 'similarityrating', 'Similar Threads Relevancy Rating', 'This allows you to limit similar threads to ones more relevant (0 being not relevant). This number should not be over 10 and should not be set low (<5) for large forums.', 'text', '1', 6, 8);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (52, 'similarlimit', 'Similar Threads Limit', 'Here you can change the total amount of similar threads to be shown in the similar threads table. It is recommended that it is not over 15 for 56k users.', 'text', '10', 7, 8);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (53, 'privateeventcolor', 'Private Events Color', 'The color that private events will be shown in on the main calendar page.', 'text', 'red', 2, 17);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (54, 'publiceventcolor', 'Public Events Color', 'The color that public events will be shown in on the main calendar page.', 'text', 'green', 1, 17);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (55, 'movedprefix', 'Moved Threads Prefix', 'The prefix that threads that have been moved to another forum should have.', 'text', 'Moved:', 5, 7);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (56, 'hottopicviews', 'Views For Hot Topic', 'The number of views a thread can have before it is considered \'hot\'.', 'text', '150', 7, 7);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (59, 'logip', 'Log Posting IP Addresses', 'Do you wish to log ip addresses of users who post, and who you want to show ip addresses to.', 'radio\r\nno=Do not log IP\r\nhide=Show to Admins & Mods\r\nshow=Show to all Users', 'hide', 3, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (60, 'statslimit', 'Stats Limit', 'The number of threads to show on the stats page for most replies and most views.', 'text', '15', 5, 1);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (65, 'modlist', 'Forums\' Moderator Listing', 'Here you can turn on or off the listing of moderators for each forum on index.php and forumdisplay.php', 'onoff', 'on', 5, 16);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (66, 'smilieinserter', 'Clickable Smilies Inserter', 'Clickable smilies will appear on the posting pages if this option is set to \'on\'.', 'onoff', 'on', 1, 20);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (67, 'smilieinsertertot', 'No. of Smilies to show', 'Enter the total number of smilies to show on the clickable smilie inserter.', 'text', '20', 2, 20);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (68, 'smilieinsertercols', 'No. of Smilie Cols to Show', 'Enter the number of columns you wish to show on the clickable smilie inserter.', 'text', '4', 3, 20);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (69, 'cantext', '\'Can\' text', 'The text that will be used in templates when the user has permission to perform an action (eg. post new threads).', 'text', 'can', 1, 21);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (70, 'canttext', '\'Cannot\' text', 'The text that will be used in templates when the user does not have permission to perform an action (eg. post new threads).', 'text', 'cannot', 2, 21);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (71, 'ontext', '\'On\' text', 'The text that will be used when a feature is turned On (eg. BB Code in posts).', 'text', 'On', 3, 21);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (72, 'offtext', '\'Off\' text', 'The text that will be used when a feature is turned Off (eg. BB Code in posts).', 'text', 'Off', 4, 21);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (73, 'showindexstats', 'Show Small Stats Section', 'Do you want to show the total number of threads, posts, members, and the last member on the forum home?', 'yesno', 'yes', 6, 16);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (74, 'regtype', 'Registration Method', 'Please select the method of registration to use when users register.', 'select\r\ninstant=Instant Activation\r\nverify=Send Email Verification\r\nrandompass=Send Random Password', 'verify', 1, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (75, 'userpppoptions', 'User Selectable Posts Per Page', 'If you would like to allow users to select how many posts are shown per page in a thread, enter the options they should be able to select separated with commas. If this is left blank they will not be able to choose how many posts are shown per page.', 'text', '5,10,20,25,30,40,50', 2, 8);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (76, 'usertppoptions', 'User Selectable Threads Per Page', 'If you would like to allow users to select how many threads per page are shown in a forum, enter the options they should be able to select separated with commas. If this is left blank they will not be able to choose how many threads are shown per page.', 'text', '10,20,25,30,40,50', 6, 7);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (77, 'wolcutoffmins', 'Cut-off Time (mins)', 'The number of minutes before a user is marked offline. Recommended: 15.', 'text', '15', 1, 23);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (78, 'postfloodcheck', 'Post Flood Checking', 'Set to on if you want to enable flood checking for posts. Specifiy the time between posts below.', 'onoff', 'on', 4, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (79, 'postfloodsecs', 'Post Flood Time', 'Set the time (in seconds) users have to wait between posting, to be in effect; the option above must be on.', 'text', '60', 5, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (80, 'gzipoutput', 'Use GZip Page Compression?', 'Do you want to compress pages in GZip format when they are sent to the browser? This means quicker downloads for your visitors, and less traffic usage for you. The level of the compression is set by the server\'s load.', 'yesno', 'yes', 1, 27);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (81, 'standardheaders', 'Send Standard Headers', 'With some web servers, this option can cause problems; with others, it is needed. ', 'yesno', 'no', 2, 27);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (82, 'nocacheheaders', 'Send No Cache Headers', 'With this option you can prevent caching of the page by the browser.', 'yesno', 'no', 3, 27);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (83, 'maxpostimages', 'Maximum Images per Post', 'Enter the maximum number of images (including smilies) a user can put in their post. Set to 0 to disable this.', 'text', '10', 8, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (84, 'maxsigimages', 'Maximum Number of Images per Signature', 'Enter the maximum number of images (including smilies) a user can put in their signature. Set to 0 to disable this.', 'text', '2', 2, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (85, 'browsingthisforum', 'Users Browsing this Forum', 'Here you can turn off the \'users browsing this forum\' feature.', 'onoff', 'on', 9, 7);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (86, 'usereferrals', 'Use Referrals System', 'Do you want to use the user referrals system on these forums?', 'yesno', 'yes', 3, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (87, 'subscribeexcerpt', 'Amount of Characters for Subscription Previews', 'How many characters of the post do you want to send with the email notification of a new reply.', 'text', '100', 9, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (93, 'cpstyle', 'Control Panel Style', 'The Default style that the control panel will use. Styles are inside the styles folder. A folder name inside that folder becomes the style title and style.css inside the style title folder is the css style file.', 'cpstyle', 'Axiom', 1, 28);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (121, 'cplanguage', 'Control Plane Language', 'The language of the control panel.', 'language', 'english', 1, 28);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (94, 'minnamelength', 'Minimum Username Length', 'The minimum number of characters a username can be when a user registers.', 'text', '3', 5, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (95, 'maxnamelength', 'Maximum Username Length', 'The maximum number of characters a username can be when a user registers.', 'text', '30', 6, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (96, 'redirects', 'Friendly Redirection Pages', 'This will enable friendly redirection pages instead of bumping the user directly to the page.', 'onoff', 'on', 4, 27);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (97, 'betweenregstime', 'Time Between Registrations', 'The amount of time (in hours) to disallow registrations for users who have already registered an account under the same ip address.', 'text', '24', 2, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (98, 'maxregsbetweentime', 'Maximum Registrations Per IP Address', 'This option allows you to set the maximum amount of times a certain user can register within the timeframe specified above.', 'text', '2', 4, 19);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (111, 'portal_showstats', 'Show forum statistics', 'Do you want to show the total number of posts, threads, members and the last registered member on the portal page?', 'yesno', 'yes', 5, 30);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (110, 'portal_showpms', 'Show the number of PMs to users', 'Do you want to show the number of private messages the current user has in their pm system.', 'yesno', 'yes', 4, 30);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (109, 'portal_showwelcome', 'Show the Welcome box', 'Do you want to show the welcome box to visitors / users.', 'yesno', 'yes', 3, 30);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (108, 'portal_numannouncements', 'Number of announcements to show', 'Please enter the number of announcements to show on the main page.', 'text', '10', 2, 30);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (103, 'portal_showstats', 'Show forum statistics', 'Do you want to show the total number of posts, threads, members and the last registered member on the portal page?', 'yesno', 'yes', 5, 29);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (104, 'portal_showwol', 'Show Whos Online', 'Do you want to show the \'whos online\' information to users when they visit the portal page?', 'yesno', 'yes', 6, 29);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (107, 'portal_announcementsfid', 'Forum ID to pull announcements from', 'Please enter the forum id (fid) of the forum you wish to pull the announcements from', 'text', '2', 1, 30);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (106, 'portal_showdiscussionsnum', 'Number of latest discussions to show', 'Please enter the number of current forum discussions to show on the portal page.', 'text', '10', 8, 29);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (112, 'portal_showwol', 'Show Who\'s Online', 'Do you want to show the \'Who\'s online\' information to users when they visit the portal page?', 'yesno', 'yes', 6, 30);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (113, 'portal_showsearch', 'Show Search Box', 'Do you want to show the search box, allowing users to quickly search the forums on the portal?', 'yesno', 'yes', 7, 30);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (114, 'portal_showdiscussions', 'Show Latest Discussions', 'Do you wish to show the current forum discussions on the portal page?', 'yesno', 'yes', 8, 30);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (115, 'portal_showdiscussionsnum', 'Number of latest discussions to show', 'Please enter the number of current forum discussions to show on the portal page.', 'text', '10', 9, 30);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (116, 'attachthumbh', 'Attached Thumbnail Maximum Height', 'Enter the width that attached thumbnails should be generated at.', 'text', '60', 12, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (117, 'attachthumbw', 'Attached Thumbnail Maximum Width', 'Enter the width that attached thumbnails should be generated at.', 'text', '60', 13, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (118, 'maxattachments', 'Maximum Attachments Per Post', 'THe maximum number of attachments a user is allowed to upload per post.', 'text', '5', 10, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (119, 'attachthumbnails', 'Show Attached Thumbnails in Posts', 'Do you want to show the generated thumbnails for attached images inside the posts?', 'yesno', 'yes', 11, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (120, 'polloptionlimit', 'Maximum Poll Option Length', 'The maximum length that each poll option can be. (Set to 0 to disable).', 'text', '250', 1, 13);"); - $db->write_query("INSERT INTO `settings` (`sid`, `name`, `title`, `description`, `optionscode`, `value`, `disporder`, `gid`) VALUES (122, 'timezoneoffset', 'Default Timezone Offset', 'Here you can set the default timezone offset for guests and members using the default offset.', 'text', '+10', 5, 3);"); - - $output->print_contents("$contents

    Please click next to continue with the upgrade process.

    "); - $output->print_footer("1_done"); -} diff --git a/html/forums/install/resources/upgrade10.php b/html/forums/install/resources/upgrade10.php deleted file mode 100644 index 43ade94..0000000 --- a/html/forums/install/resources/upgrade10.php +++ /dev/null @@ -1,39 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade10_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - - $db->write_query("UPDATE ".TABLE_PREFIX."templates SET version='0' WHERE version=''"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."templates CHANGE version version int unsigned NOT NULL default '0'"); - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("10_done"); -} - diff --git a/html/forums/install/resources/upgrade11.php b/html/forums/install/resources/upgrade11.php deleted file mode 100644 index b10f7f6..0000000 --- a/html/forums/install/resources/upgrade11.php +++ /dev/null @@ -1,73 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade11_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - - $query = $db->simple_select("templates", "*", "title IN ('showthread_inlinemoderation','showthread_ratethread','editpost','newreply','usercp_drafts','newthread','usercp_options','forumdisplay_inlinemoderation','report','private_empty','usercp_profile','usercp_attachments','usercp_usergroups_joingroup','usercp_avatar','usercp_avatar_gallery','usercp_usergroups_memberof','managegroup','managegroup_adduser','managegroup_joinrequests','private_send','polls_editpoll','private_archive','calendar_addevent','moderation_inline_deleteposts','private_tracking','moderation_threadnotes','showthread_quickreply','member_emailuser','moderation_reports','member_login','index_loginform','moderation_deletethread','moderation_mergeposts','polls_newpoll','member_register_agreement','usercp_password','usercp_email','reputation_add','moderation_deletepoll','usercp_changeavatar','usercp_notepad','member_resetpassword','member_lostpw','usercp_changename','moderation_deleteposts','moderation_split','sendthread','usercp_editsig','private_read','error_nopermission','private_folders','moderation_move','moderation_merge','member_activate','usercp_editlists','calendar_editevent','member_resendactivation','moderation_inline_deletethreads','moderation_inline_movethreads','moderation_inline_mergeposts','moderation_inline_splitposts','member_register','showthread_moderationoptions','headerinclude','private','forumdisplay_threadlist_inlineedit_js')"); - while($template = $db->fetch_array($query)) - { - if($template['title'] == "private_read") - { - $template['template'] = str_replace("private.php?action=delete&pmid={\$pm['pmid']}", "private.php?action=delete&pmid={\$pm['pmid']}&my_post_key={\$mybb->post_code}", $template['template']); - } - elseif($template['title'] == "showthread_moderationoptions") - { - $template['template'] = str_replace('', ' -', $template['template']); - - $template['template'] = str_replace('moderation.php?action=\'+this.options[this.selectedIndex].value+\'&tid={$tid}&modtype=thread', 'moderation.php?action=\'+this.options[this.selectedIndex].value+\'&tid={$tid}&modtype=thread&my_post_key={$mybb->post_code}', $template['template']); - } - elseif($template['title'] == "headerinclude") - { - $template['template'] = str_replace('var cookieDomain = "{$mybb->settings[\'cookiedomain\']}";', 'var my_post_key = \'{$mybb->post_code}\'; -var cookieDomain = "{$mybb->settings[\'cookiedomain\']}";', $template['template']); - } - elseif($template['title'] == "forumdisplay_threadlist_inlineedit_js") - { - $template['template'] = str_replace('"xmlhttp.php?action=edit_subject"', '"xmlhttp.php?action=edit_subject&my_post_key="+my_post_key', $template['template']); - } - else - { - // Remove any duplicates - $template['template'] = str_replace("post_code}\" />", "", $template['template']); - - $template['template'] = preg_replace("##i", "\npost_code}\" />", $template['template']); - } - - // Update MyBB Javascript versions (to clear cache) - $template['template'] = str_replace("?ver=121", "?ver=1212", $template['template']); - - $db->update_query("templates", array('template' => $db->escape_string($template['template']), 'version' => '1212'), "tid='{$template['tid']}'", 1); - } - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("11_done"); -} - diff --git a/html/forums/install/resources/upgrade12.php b/html/forums/install/resources/upgrade12.php deleted file mode 100644 index fef15fe..0000000 --- a/html/forums/install/resources/upgrade12.php +++ /dev/null @@ -1,1997 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0, - "requires_deactivated_plugins" => 1, -); - -@set_time_limit(0); - -// We need to globalize $db here because when this script is called -// during load_module $db is not globalized in the function -global $db; - -// FIRST STEP IS FOR INTEGER CONVERSION PROJECT - -function upgrade12_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Integer Conversion Project"); - - $perpage = 10000; - - $to_int = array( - "announcements" => array("aid", "allowhtml", "allowmycode", "allowsmilies"), - "forumpermissions" => array("pid", "canview","canviewthreads","candlattachments","canpostthreads","canpostreplys","canpostattachments","canratethreads","caneditposts","candeleteposts","candeletethreads","caneditattachments","canpostpolls","canvotepolls","cansearch"), - "forums" => array("fid", "active","open","allowhtml","allowmycode","allowsmilies","allowimgcode","allowpicons","allowtratings","usepostcounts","showinjump","modposts","modthreads","modattachments","overridestyle"), - "groupleaders" => array("lid", "canmanagemembers","canmanagerequests"), - "helpdocs" => array("hid", "usetranslation","enabled"), - "helpsections" => array("sid", "usetranslation","enabled"), - "moderators" => array("mid", "caneditposts","candeleteposts","canviewips","canopenclosethreads","canmanagethreads","canmovetononmodforum"), - "mycode" => array("cid", "active"), - "polls" => array("pid", "closed","multiple","public"), - "posts" => array("pid", "includesig","smilieoff"), - "privatemessages" => array("pmid", "includesig","smilieoff"), - "profilefields" => array("fid", "required","editable","hidden"), - "smilies" => array("sid", "showclickable"), - "usergroups" => array("gid","isbannedgroup","canview","canviewthreads","canviewprofiles","candlattachments","canpostthreads","canpostreplys","canpostattachments","canratethreads","caneditposts","candeleteposts","candeletethreads","caneditattachments","canpostpolls","canvotepolls","canusepms","cansendpms","cantrackpms","candenypmreceipts","cansendemail","canviewmemberlist","canviewcalendar","canviewonline","canviewwolinvis","canviewonlineips","cancp","issupermod","cansearch","canusercp","canuploadavatars","canratemembers","canchangename","showforumteam","usereputationsystem","cangivereputations","candisplaygroup","cancustomtitle"), - "users" => array("uid","allownotices","hideemail","invisible","receivepms","pmpopup","pmnotify","remember","showsigs","showavatars","showquickreply","showredirect","away"), - "threads" => array("tid", "closed") - ); - - if(!$db->field_exists('pmpopup', "users")) - { - $pmpopup_key = array_search('pmpopup', $to_int['users']); - if($pmpopup_key) - { - unset($to_int['users'][$pmpopup_key]); - } - } - - // Continuing? - if($mybb->input['last_table']) - { - $current_table = $mybb->input['last_table']; - } - else - { - $current_table = array_keys($to_int); - $current_table = $current_table[0]; - echo "

    MyBB 1.4 represents a huge leap forward for the MyBB project.

    Due to this, lots of information in the database needs to be converted to a new format.

    "; - } - - echo "

    MyBB is now currently converting a section of data to the new format, this may take a while.

    "; - - $remaining = $perpage; - - $final_table = array_keys($to_int); - $final_table = $final_table[count($final_table)-1]; - - $next_act = "12_dbchanges"; - - $start = $mybb->get_input('start', MyBB::INPUT_INT); - $count = $mybb->input['count']; - - foreach($to_int as $table => $columns) - { - if($table == $current_table) - { - $form_fields['last_table'] = $current_table; - if($remaining <= 0) - { - break; - } - $columns_sql = implode(",", $columns); - $primary_key = $columns[0]; - if(!$mybb->input['count']) - { - $query = $db->simple_select($table, "COUNT({$primary_key}) AS count"); - $count = $form_fields['count'] = $db->fetch_field($query, "count"); - } - if($start <= $count) - { - $end = $start+$perpage; - if($end > $count) $end = $count; - echo "

    {$table}: Converting {$start} to {$end} of {$count}

    "; - flush(); - $form_fields['start'] = $perpage+$start; - - $query = $db->simple_select($table, $columns_sql, "", array('order_by' => $primary_key, 'limit_start' => $start, 'limit' => $remaining)); - while($row = $db->fetch_array($query)) - { - $updated_row = array(); - foreach($columns as $column) - { - if($column == $primary_key || is_int($row[$column])) continue; - if($row[$column] == "yes" || $row[$column] == "on") - { - $updated_row[$column] = 1; - } - else if($row[$column] == "off" || $row[$column] == "no" || $row[$column] == 'new' || $row[$column] == "") - { - $updated_row[$column] = 0; - } - } - if(count($updated_row) > 0) - { - $db->update_query($table, $updated_row, "{$primary_key}={$row[$primary_key]}"); - } - --$remaining; - } - } - else - { - echo "

    {$table}: Converting column type

    "; - flush(); - $change_column = array(); - foreach($columns as $column) - { - // Closed does not get converted to an int - if($column == $primary_key || ($table == "threads" && $column == "closed")) - { - continue; - } - $change_column[] = "MODIFY {$column} int(1) NOT NULL default '0'"; - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."{$table} ".implode(", ", $change_column)); - - if($table == $final_table) - { - // Finished, after all this! - $next_act = "12_dbchanges1"; - } - else - { - $tbl_keys = array_keys($to_int); - $current = array_search($current_table, $tbl_keys); - $form_fields['last_table'] = $current_table = $tbl_keys[$current+1]; - $form_fields['start'] = $start = 0; - $form_fields['count'] = $count = $mybb->input['count'] = 0; - } - } - } - } - - // Still converting - if($next_act == "12_dbchanges") - { - echo "

    Done

    "; - echo "

    Click next to continue with the integer conversion process.

    "; - foreach($form_fields as $key => $val) - { - echo ""; - } - global $footer_extra; - $footer_extra = ""; - $output->print_footer($next_act); - } - else - { - // Convert settings table - $query = $db->write_query("UPDATE ".TABLE_PREFIX."settings SET value=1 WHERE value='yes' OR value='on'"); - $query = $db->write_query("UPDATE ".TABLE_PREFIX."settings SET value=0 WHERE value='no' OR value='off'"); - echo "

    Done

    "; - echo "

    The integrer conversion process is now complete.

    "; - echo "

    Click next to continue with the upgrade process.

    "; - global $footer_extra; - $footer_extra = ""; - - $output->print_footer($next_act); - } -} - -function upgrade12_dbchanges1() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - echo "

    Adding index to private messages table ... "; - flush(); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages ADD INDEX ( `uid` )"); - - echo "done.

    "; - - $contents = "

    Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("12_dbchanges_post1"); -} - -function upgrade12_dbchanges_post1() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - echo "

    Adding index to posts table ... "; - flush(); - - // This will take a LONG time on huge post databases, so we only run it isolted from most of the other queries - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts ADD INDEX ( `visible` )"); - - echo "done.

    "; - flush(); - - $contents = "

    Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("12_dbchanges_post2"); -} - -function upgrade12_dbchanges_post2() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - - if($db->field_exists('longipaddress', "posts")) - { - echo "

    Dropping longipaddress column in posts table ... "; - flush(); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts DROP longipaddress;"); - - echo "done.

    "; - flush(); - } - - echo "

    Adding longipaddress column to posts table ... "; - flush(); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts ADD longipaddress int(11) NOT NULL default '0' AFTER ipaddress"); - - echo "done.

    "; - flush(); - - $contents = "

    Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("12_dbchanges_user"); -} - -function upgrade12_dbchanges_user() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - echo "

    Adding index to users table ... "; - flush(); - - // This will take a LONG time on huge user databases, so we only run it isolted from most of the other queries - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD INDEX ( `lastvisit` )"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD INDEX ( `regdate` )"); - - echo "done.

    "; - flush(); - - $contents = "

    Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("12_dbchanges2"); -} - -function upgrade12_dbchanges2() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - if($db->field_exists('recipients', "privatemessages")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages DROP recipients;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages ADD recipients text NOT NULL AFTER fromid"); - - if($db->field_exists('deletetime', "privatemessages")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages DROP deletetime;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages ADD deletetime bigint(30) NOT NULL default '0' AFTER dateline"); - - if($db->field_exists('maxpmrecipients', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP maxpmrecipients;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD maxpmrecipients int(4) NOT NULL default '5' AFTER pmquota"); - - if($db->field_exists('canwarnusers', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP canwarnusers;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD canwarnusers int(1) NOT NULL default '0' AFTER cancustomtitle"); - - if($db->field_exists('lastip', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP lastip;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD lastip varchar(50) NOT NULL default '' AFTER regip"); - - - - if($db->field_exists('coppauser', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP coppauser;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD coppauser int(1) NOT NULL default '0'"); - - if($db->field_exists('classicpostbit', 'users')) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP classicpostbit;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD classicpostbit int(1) NOT NULL default '0'"); - - if($db->field_exists('canreceivewarnings', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP canreceivewarnings;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD canreceivewarnings int(1) NOT NULL default '0' AFTER canwarnusers"); - - if($db->field_exists('maxwarningsday', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP maxwarningsday;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD maxwarningsday int(3) NOT NULL default '3' AFTER canreceivewarnings"); - - $db->update_query("usergroups", array('canreceivewarnings' => 1), "cancp != 1"); - $db->update_query("usergroups", array('maxwarningsday' => 3, 'canwarnusers' => 1), "cancp=1 OR issupermod=1 OR gid=6"); // Admins, Super Mods and Mods - - if($db->field_exists('canmodcp', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP canmodcp;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD canmodcp int(1) NOT NULL default '0' AFTER maxwarningsday"); - $db->update_query("usergroups", array('canmodcp' => 1), "cancp=1 OR issupermod=1 OR gid='6'"); // Admins, Super Mods and Mods - - if($db->field_exists('newpms', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP newpms;"); - } - - if($db->field_exists('keywords', "searchlog")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."searchlog DROP keywords;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."searchlog ADD keywords text NOT NULL AFTER querycache"); - - if($db->field_exists('canaddpublicevents', "usergroups") && !$db->field_exists('canaddevents', "usergroups")) - { - $db->update_query("usergroups", array('canaddpublicevents' => 0), "canaddpublicevents='no'"); - $db->update_query("usergroups", array('canaddpublicevents' => 1), "canaddpublicevents='yes'"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups CHANGE canaddpublicevents canaddevents int(1) NOT NULL default '0';"); - } - - if($db->field_exists('canaddprivateevents', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP canaddprivateevents;"); - } - - if($db->field_exists('canbypasseventmod', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP canbypasseventmod;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD canbypasseventmod int(1) NOT NULL default '0' AFTER canaddevents;"); - - if($db->field_exists('canmoderateevents', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP canmoderateevents;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD canmoderateevents int(1) NOT NULL default '0' AFTER canbypasseventmod;"); - $db->update_query("usergroups", array('canbypasseventmod' => 1, 'canmoderateevents' => 1), "cancp=1 OR issupermod=1"); - $db->update_query("usergroups", array('canbypasseventmod' => 0, 'canmoderateevents' => 0), "cancp=0 AND issupermod=0"); - $db->update_query("usergroups", array('canaddevents' => 0), "gid='1'"); - - $db->drop_table("maillogs"); - $db->drop_table("mailerrors"); - $db->drop_table("promotions"); - $db->drop_table("promotionlogs"); - $db->drop_table("massemails"); - - $collation = $db->build_create_table_collation(); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."massemails ( - mid int unsigned NOT NULL auto_increment, - uid int unsigned NOT NULL default '0', - subject varchar(200) NOT NULL default '', - message text NOT NULL, - htmlmessage text NOT NULL, - type tinyint(1) NOT NULL default '0', - format tinyint(1) NOT NULL default '0', - dateline bigint(30) NOT NULL default '0', - senddate bigint(30) NOT NULL default '0', - status tinyint(1) NOT NULL default '0', - sentcount int unsigned NOT NULL default '0', - totalcount int unsigned NOT NULL default '0', - conditions text NOT NULL, - perpage smallint(4) NOT NULL default '50', - PRIMARY KEY(mid) - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."maillogs ( - mid int unsigned NOT NULL auto_increment, - subject varchar(200) not null default '', - message TEXT NOT NULL, - dateline bigint(30) NOT NULL default '0', - fromuid int unsigned NOT NULL default '0', - fromemail varchar(200) not null default '', - touid bigint(30) NOT NULL default '0', - toemail varchar(200) NOT NULL default '', - tid int unsigned NOT NULL default '0', - ipaddress varchar(20) NOT NULL default '', - PRIMARY KEY(mid) - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."mailerrors( - eid int unsigned NOT NULL auto_increment, - subject varchar(200) NOT NULL default '', - message TEXT NOT NULL, - toaddress varchar(150) NOT NULL default '', - fromaddress varchar(150) NOT NULL default '', - dateline bigint(30) NOT NULL default '0', - error text NOT NULL, - smtperror varchar(200) NOT NULL default '', - smtpcode int(5) NOT NULL default '0', - PRIMARY KEY(eid) - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."promotions ( - pid int unsigned NOT NULL auto_increment, - title varchar(120) NOT NULL default '', - description text NOT NULL, - enabled tinyint(1) NOT NULL default '1', - logging tinyint(1) NOT NULL default '0', - posts int NOT NULL default '0', - posttype char(2) NOT NULL default '', - registered int NOT NULL default '0', - registeredtype varchar(20) NOT NULL default '', - reputations int NOT NULL default '0', - reputationtype char(2) NOT NULL default '', - requirements varchar(200) NOT NULL default '', - originalusergroup varchar(120) NOT NULL default '0', - newusergroup smallint unsigned NOT NULL default '0', - usergrouptype varchar(120) NOT NULL default '0', - PRIMARY KEY (pid) - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."promotionlogs( - plid int unsigned NOT NULL auto_increment, - pid int unsigned NOT NULL default '0', - uid int unsigned NOT NULL default '0', - oldusergroup varchar(200) NOT NULL default '0', - newusergroup smallint unsigned NOT NULL default '0', - dateline bigint(30) NOT NULL default '0', - type varchar(9) NOT NULL default 'primary', - PRIMARY KEY(plid) - ) ENGINE=MyISAM{$collation};"); - - if($db->field_exists('maxemails', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP maxemails;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD maxemails int(3) NOT NULL default '5' AFTER cansendemail"); - - if($db->field_exists('parseorder', "mycode")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."mycode DROP parseorder;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."mycode ADD parseorder smallint unsigned NOT NULL default '0' AFTER active"); - - if($db->field_exists('mod_edit_posts', "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP mod_edit_posts;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD mod_edit_posts int(1) NOT NULL default '0' AFTER modthreads"); - - if($db->field_exists('pmpopup', "users") && !$db->field_exists('pmnotice', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE pmpopup pmnotice int(1) NOT NULL default '0'"); - } - - $db->drop_table("tasks"); - $db->drop_table("tasklog"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."tasks ( - tid int unsigned NOT NULL auto_increment, - title varchar(120) NOT NULL default '', - description text NOT NULL, - file varchar(30) NOT NULL default '', - minute varchar(200) NOT NULL default '', - hour varchar(200) NOT NULL default '', - day varchar(100) NOT NULL default '', - month varchar(30) NOT NULL default '', - weekday varchar(15) NOT NULL default '', - nextrun bigint(30) NOT NULL default '0', - lastrun bigint(30) NOT NULL default '0', - enabled int(1) NOT NULL default '1', - logging int(1) NOT NULL default '0', - locked bigint(30) NOT NULL default '0', - PRIMARY KEY(tid) - ) ENGINE=MyISAM{$collation};"); - - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."tasklog ( - lid int unsigned NOT NULL auto_increment, - tid int unsigned NOT NULL default '0', - dateline bigint(30) NOT NULL default '0', - data text NOT NULL, - PRIMARY KEY(lid) - ) ENGINE=MyISAM{$collation};"); - - - include_once MYBB_ROOT."inc/functions_task.php"; - $tasks = file_get_contents(INSTALL_ROOT.'resources/tasks.xml'); - $parser = new XMLParser($tasks); - $parser->collapse_dups = 0; - $tree = $parser->get_tree(); - - // Insert scheduled tasks - foreach($tree['tasks'][0]['task'] as $task) - { - $new_task = array( - 'title' => $db->escape_string($task['title'][0]['value']), - 'description' => $db->escape_string($task['description'][0]['value']), - 'file' => $db->escape_string($task['file'][0]['value']), - 'minute' => $db->escape_string($task['minute'][0]['value']), - 'hour' => $db->escape_string($task['hour'][0]['value']), - 'day' => $db->escape_string($task['day'][0]['value']), - 'weekday' => $db->escape_string($task['weekday'][0]['value']), - 'month' => $db->escape_string($task['month'][0]['value']), - 'enabled' => $db->escape_string($task['enabled'][0]['value']), - 'logging' => $db->escape_string($task['logging'][0]['value']) - ); - - $new_task['nextrun'] = fetch_next_run($new_task); - - $db->insert_query("tasks", $new_task); - $taskcount++; - } - - if($db->table_exists("favorites") && !$db->table_exists("threadsubscriptions")) - { - $db->write_query("RENAME TABLE ".TABLE_PREFIX."favorites TO ".TABLE_PREFIX."threadsubscriptions"); - } - - if($db->field_exists('fid', "threadsubscriptions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadsubscriptions CHANGE fid sid int unsigned NOT NULL auto_increment"); - } - - if($db->field_exists('type', "threadsubscriptions")) - { - $db->update_query("threadsubscriptions", array('type' => 0), "type='f'"); - $db->update_query("threadsubscriptions", array('type' => 1), "type='s'"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadsubscriptions CHANGE type notification int(1) NOT NULL default '0'"); - } - - if($db->field_exists('dateline', "threadsubscriptions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadsubscriptions DROP dateline;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadsubscriptions ADD dateline bigint(30) NOT NULL default '0'"); - - if($db->field_exists('subscriptionkey', "threadsubscriptions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadsubscriptions DROP subscriptionkey;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadsubscriptions ADD subscriptionkey varchar(32) NOT NULL default ''"); - - if($db->field_exists('emailnotify', "users")) - { - $db->update_query("users", array('emailnotify' => 0), "emailnotify='no' OR emailnotify='0'"); - $db->update_query("users", array('emailnotify' => 2), "emailnotify='yes' OR emailnotify='1'"); - $db->update_query("users", array('emailnotify' => 0), "emailnotify != 1 AND emailnotify != 2"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE emailnotify subscriptionmethod int(1) NOT NULL default '0'"); - } - - $db->drop_table("warninglevels"); - $db->drop_table("warningtypes"); - $db->drop_table("warnings"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."warninglevels ( - lid int unsigned NOT NULL auto_increment, - percentage int(3) NOT NULL default '0', - action text NOT NULL, - PRIMARY KEY(lid) - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."warningtypes ( - tid int unsigned NOT NULL auto_increment, - title varchar(120) NOT NULL default '', - points int unsigned NOT NULL default '0', - expirationtime bigint(30) NOT NULL default '0', - PRIMARY KEY(tid) - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."warnings ( - wid int unsigned NOT NULL auto_increment, - uid int unsigned NOT NULL default '0', - tid int unsigned NOT NULL default '0', - pid int unsigned NOT NULL default '0', - title varchar(120) NOT NULL default '', - points int unsigned NOT NULL default '0', - dateline bigint(30) NOT NULL default '0', - issuedby int unsigned NOT NULL default '0', - expires bigint(30) NOT NULL default '0', - expired int(1) NOT NULL default '0', - daterevoked bigint(30) NOT NULL default '0', - revokedby int unsigned NOT NULL default '0', - revokereason text NOT NULL, - notes text NOT NULL, - PRIMARY KEY(wid) - ) ENGINE=MyISAM{$collation};"); - - if($db->field_exists('warningpoints', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP warningpoints;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD warningpoints int(3) NOT NULL default '0' AFTER unreadpms"); - - if($db->field_exists('moderateposts', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP moderateposts;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD moderateposts int(1) NOT NULL default '0' AFTER warningpoints"); - - if($db->field_exists('moderationtime', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP moderationtime;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD moderationtime bigint(30) NOT NULL default '0' AFTER moderateposts"); - - if($db->field_exists('suspendposting', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP suspendposting;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD suspendposting int(1) NOT NULL default '0' AFTER moderationtime"); - - if($db->field_exists('suspensiontime', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP suspensiontime;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD suspensiontime bigint(30) NOT NULL default '0' AFTER suspendposting"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned CHANGE oldadditionalgroups oldadditionalgroups TEXT NOT NULL"); - - if($db->field_exists('birthdayprivacy', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP birthdayprivacy;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD birthdayprivacy varchar(4) NOT NULL default 'all' AFTER birthday"); - - if($db->field_exists('birthdayprivacy', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP birthdayprivacy;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD birthdayprivacy varchar(4) NOT NULL default 'all' AFTER birthday"); - - if($db->field_exists('longregip', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP longregip;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD longregip int(11) NOT NULL default '0' AFTER lastip"); - - if($db->field_exists('longlastip', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP longlastip;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD longlastip int(11) NOT NULL default '0' AFTER lastip"); - - // Unused column - if($db->field_exists('titles', "searchlog")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."searchlog DROP titles;"); - } - - $db->drop_table("adminlog"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."adminlog ( - uid int unsigned NOT NULL default '0', - ipaddress varchar(50) NOT NULL default '', - dateline bigint(30) NOT NULL default '0', - module varchar(50) NOT NULL default '', - action varchar(50) NOT NULL default '', - data text NOT NULL, - KEY module (module, action) - ) ENGINE=MyISAM{$collation};"); - - if($db->field_exists('data', "adminsessions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminsessions DROP data;"); - } - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminsessions ADD data TEXT NOT NULL AFTER lastactive;"); - - if($db->field_exists('isdefault', "settings")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."settings DROP isdefault;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."settings ADD isdefault int(1) NOT NULL default '0' AFTER gid;"); - - $setting_group_cache = array(); - $query = $db->simple_select("settinggroups", "gid, isdefault"); - while($settinggroup = $db->fetch_array($query)) - { - $setting_group_cache[$settinggroup['gid']] = $settinggroup['isdefault']; - } - - $query = $db->simple_select("settings", "gid, sid"); - while($setting = $db->fetch_array($query)) - { - if($setting_group_cache[$setting['gid']] == 1) - { - $db->update_query("settings", array('isdefault' => 1), "sid = '{$setting['sid']}'", 1); - } - } - - $db->update_query("settings", array('value' => 'classic'), "name='postlayout' AND value != 'horizontal'"); - - $db->update_query("settings", array('optionscode' => $db->escape_string('php -')), "name='searchtype'", 1); - - $contents = "Done

    "; - $contents .= "

    Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("12_dbchanges3"); -} - -function upgrade12_dbchanges3() -{ - global $db, $output, $mybb; - - $output->print_header("Converting Ban Filters"); - - echo "

    Converting existing banned IP addresses, email addresses and usernames..

    "; - flush(); - - $db->drop_table("banfilters"); - - $collation = $db->build_create_table_collation(); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."banfilters ( - fid int unsigned NOT NULL auto_increment, - filter varchar(200) NOT NULL default '', - type int(1) NOT NULL default '0', - lastuse bigint(30) NOT NULL default '0', - dateline bigint(30) NOT NULL default '0', - PRIMARY KEY (fid) - ) ENGINE=MyISAM{$collation};"); - - // Now we convert all of the old bans in to the new system! - $ban_types = array('bannedips', 'bannedemails', 'bannedusernames'); - foreach($ban_types as $type) - { - // Some people put spaces or breaks (\r\n) instead, so we should take that into account. - $mybb->settings[$type] = str_replace(array("\n", "\r\n", "\r"), ",", $mybb->settings[$type]); - - // Usernames can have spaces so don't replace those with commas. - if($type != 'bannedusernames') - { - $mybb->settings[$type] = str_replace(" ", ",", $mybb->settings[$type]); - } - - $bans = explode(",", $mybb->settings[$type]); - $bans = array_unique($bans); - $bans = array_map("trim", $bans); - foreach($bans as $ban) - { - if(!$ban) - { - continue; - } - - if($type == "bannedips") - { - $ban_type = 1; - } - else if($type == "bannedusernames") - { - $ban_type = 2; - } - else if($type == "bannedemails") - { - $ban_type = 3; - } - $new_ban = array( - "filter" => $db->escape_string($ban), - "type" => $ban_type, - "dateline" => TIME_NOW - ); - $db->insert_query("banfilters", $new_ban); - } - } - - $contents = "Done

    "; - $contents .= "

    Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("12_dbchanges4"); -} - -function upgrade12_dbchanges4() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - $db->drop_table("spiders"); - $db->drop_table("stats"); - - $collation = $db->build_create_table_collation(); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."spiders ( - sid int unsigned NOT NULL auto_increment, - name varchar(100) NOT NULL default '', - theme int unsigned NOT NULL default '0', - language varchar(20) NOT NULL default '', - usergroup int unsigned NOT NULL default '0', - useragent varchar(200) NOT NULL default '', - lastvisit bigint(30) NOT NULL default '0', - PRIMARY KEY(sid) - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."stats ( - dateline bigint(30) NOT NULL default '0', - numusers int unsigned NOT NULL default '0', - numthreads int unsigned NOT NULL default '0', - numposts int unsigned NOT NULL default '0', - PRIMARY KEY(dateline) - ) ENGINE=MyISAM{$collation};"); - - $db->insert_query("spiders", array('name' => 'GoogleBot', 'useragent' => 'google')); - $db->insert_query("spiders", array('name' => 'Lycos', 'useragent' => 'lycos')); - $db->insert_query("spiders", array('name' => 'Ask Jeeves', 'useragent' => 'ask jeeves')); - $db->insert_query("spiders", array('name' => 'Hot Bot', 'useragent' => 'slurp@inktomi')); - $db->insert_query("spiders", array('name' => 'What You Seek', 'useragent' => 'whatuseek')); - $db->insert_query("spiders", array('name' => 'Archive.org', 'useragent' => 'is_archiver')); - $db->insert_query("spiders", array('name' => 'Altavista', 'useragent' => 'scooter')); - $db->insert_query("spiders", array('name' => 'Alexa', 'useragent' => 'ia_archiver')); - $db->insert_query("spiders", array('name' => 'MSN Search', 'useragent' => 'msnbot')); - $db->insert_query("spiders", array('name' => 'Yahoo!', 'useragent' => 'yahoo! slurp')); - - // DST correction changes - $db->update_query("users", array('dst' => 1), "dst=1"); - $db->update_query("users", array('dst' => 0), "dst=0"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE dst dst INT(1) NOT NULL default '0'"); - if($db->field_exists('dstcorrection', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP dstcorrection;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD dstcorrection INT(1) NOT NULL default '0' AFTER dst"); - - $db->update_query("users", array('dstcorrection' => 2)); - - $db->update_query("adminoptions", array('cpstyle' => '')); - - if($db->field_exists('permsset', "adminoptions") && !$db->field_exists('permissions', "adminoptions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions CHANGE permsset permissions TEXT NOT NULL "); - } - - $adminoptions = file_get_contents(INSTALL_ROOT.'resources/adminoptions.xml'); - $parser = new XMLParser($adminoptions); - $parser->collapse_dups = 0; - $tree = $parser->get_tree(); - - // Fetch default permissions list - $default_permissions = array(); - foreach($tree['adminoptions'][0]['user'] as $users) - { - $uid = $users['attributes']['uid']; - if($uid == -4) - { - foreach($users['permissions'][0]['module'] as $module) - { - foreach($module['permission'] as $permission) - { - $default_permissions[$module['attributes']['name']][$permission['attributes']['name']] = $permission['value']; - } - } - break; - } - } - - $convert_permissions = array( - "caneditsettings" => array( - "module" => "config", - "permission" => "settings" - ), - "caneditann" => array( - "module" => "forum", - "permission" => "announcements", - ), - "caneditforums" => array( - "module" => "forum", - "permission" => "management", - ), - "canmodposts" => array( - "module" => "forum", - "permission" => "moderation_queue", - ), - "caneditsmilies" => array( - "module" => "config", - "permission" => "smilies", - ), - "caneditpicons" => array( - "module" => "config", - "permission" => "post_icons", - ), - "caneditthemes" => array( - "module" => "style", - "permission" => "themes", - ), - "canedittemps" => array( - "module" => "style", - "permission" => "templates", - ), - "caneditusers" => array( - "module" => "user", - "permission" => "view", - ), - "caneditpfields" => array( - "module" => "config", - "permission" => "profile_fields", - ), - "caneditmodactions" => array( - "module" => "config", - "permission" => "mod_tools", - ), - "caneditugroups" => array( - "module" => "user", - "permission" => "groups", - ), - "caneditaperms" => array( - "module" => "user", - "permission" => "admin_permissions", - ), - "caneditutitles" => array( - "module" => "user", - "permission" => "titles", - ), - "caneditattach" => array( - "module" => "forum", - "permission" => "attachments", - ), - "canedithelp" => array( - "module" => "config", - "permission" => "help_documents", - ), - "caneditlangs" => array( - "module" => "config", - "permission" => "languages", - ), - "canrunmaint" => array( - "module" => "tools", - "permission" => "recount_rebuild", - ), - "canrundbtools" => array( - "module" => "tools", - "permission" => "backupdb", - ), - ); - - $new_permissions = $default_permissions; - - $query = $db->simple_select("adminoptions"); - while($adminoption = $db->fetch_array($query)) - { - foreach($adminoption as $field => $value) - { - if(strtolower(substr($field, 0, 3)) != "can") - { - continue; - } - - if(array_key_exists($field, $convert_permissions)) - { - // Note: old adminoptions table is still yes/no - do not change me - if($value == "yes") - { - $value = 1; - } - else - { - $value = $default_permissions[$convert_permissions[$field]['module']][$convert_permissions[$field]['permission']]; - } - $new_permissions[$convert_permissions[$field]['module']][$convert_permissions[$field]['permission']] = $value; - } - } - - $db->update_query("adminoptions", array('permissions' => my_serialize($new_permissions)), "uid = '{$adminoption['uid']}'"); - - $new_permissions = $default_permissions; - } - - foreach($convert_permissions as $field => $value) - { - if($db->field_exists($field, "adminoptions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions DROP {$field}"); - } - } - - // Set default views - if($db->field_exists('defaultviews', "adminoptions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions DROP defaultviews"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions ADD defaultviews TEXT NOT NULL"); - $db->update_query("adminoptions", array('defaultviews' => my_serialize(array('user' => 1)))); - - $query = $db->simple_select("forums", "SUM(threads) AS numthreads, SUM(posts) AS numposts, SUM(unapprovedthreads) AS numunapprovedthreads, SUM(unapprovedposts) AS numunapprovedposts"); - $stats = $db->fetch_array($query); - - $query = $db->simple_select("users", "COUNT(uid) AS users"); - $stats['numusers'] = $db->fetch_field($query, 'users'); - - update_stats($stats, true); - - $contents = "Done

    "; - $contents .= "

    Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("12_dbchanges5"); -} - -function upgrade12_dbchanges5() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - $db->drop_table("templategroups"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."templategroups ( - gid int unsigned NOT NULL auto_increment, - prefix varchar(50) NOT NULL default '', - title varchar(100) NOT NULL default '', - PRIMARY KEY (gid) - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('1','calendar','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('2','editpost','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('3','forumbit','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('4','forumjump','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('5','forumdisplay','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('6','index','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('7','error','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('8','memberlist','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('9','multipage','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('10','private','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('11','portal','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('12','postbit','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('13','redirect','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('14','showthread','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('15','usercp','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('16','online','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('17','moderation','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('18','nav','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('19','search','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('20','showteam','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('21','reputation','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('22','newthread','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('23','newreply','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('24','member','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('25','warnings','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('26','global','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('27','header','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('28','managegroup','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('29','misc','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('30','modcp','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('31','php','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('32','polls','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('33','post','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('34','printthread','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('35','report','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('36','smilieinsert','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('37','stats','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('38','xmlhttp','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('39','footer','');"); - - $query = $db->query("SHOW INDEX FROM ".TABLE_PREFIX."users"); - while($ukey = $db->fetch_array($query)) - { - if($ukey['Key_name'] == "username") - { - $index = $ukey; - break; - } - } - if($index) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP KEY username"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD UNIQUE KEY username (username)"); - - if($db->field_exists('statustime', "privatemessages")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages DROP statustime;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages ADD statustime bigint(30) NOT NULL default '0' AFTER status"); - - $collation = $db->build_create_table_collation(); - - $db->drop_table("calendars"); - $db->drop_table("calendarpermissions"); - $db->drop_table("forumsread"); - $db->drop_table("adminviews"); - $db->drop_table("threadviews"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."threadviews ( - tid int unsigned NOT NULL default '0' - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."calendars ( - cid int unsigned NOT NULL auto_increment, - name varchar(100) NOT NULL default '', - disporder int unsigned NOT NULL default '0', - startofweek int(1) NOT NULL default '0', - showbirthdays int(1) NOT NULL default '0', - eventlimit int(3) NOT NULL default '0', - moderation int(1) NOT NULL default '0', - allowhtml int(1) NOT NULL default '0', - allowmycode int(1) NOT NULL default '0', - allowimgcode int(1) NOT NULL default '0', - allowsmilies int(1) NOT NULL default '0', - PRIMARY KEY(cid) - ) ENGINE=MyISAM{$collation};"); - - $calendar_array = array( - 'name' => 'Default Calendar', - 'disporder' => 1, - 'startofweek' => 0, - 'showbirthdays' => 1, - 'eventlimit' => 4, - 'moderation' => 0, - 'allowhtml' => 0, - 'allowmycode' => 1, - 'allowimgcode' => 1, - 'allowsmilies' => 1 - ); - $db->insert_query("calendars", $calendar_array); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."calendarpermissions ( - cid int unsigned NOT NULL default '0', - gid int unsigned NOT NULL default '0', - canviewcalendar int(1) NOT NULL default '0', - canaddevents int(1) NOT NULL default '0', - canbypasseventmod int(1) NOT NULL default '0', - canmoderateevents int(1) NOT NULL default '0' - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."forumsread ( - fid int unsigned NOT NULL default '0', - uid int unsigned NOT NULL default '0', - dateline int(10) NOT NULL default '0', - KEY dateline (dateline), - UNIQUE KEY fid (fid,uid) - ) ENGINE=MyISAM{$collation};"); - - if($db->field_exists('dateuploaded', "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP dateuploaded;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments ADD dateuploaded bigint(30) NOT NULL default '0' AFTER downloads"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."adminviews ( - vid int unsigned NOT NULL auto_increment, - uid int unsigned NOT NULL default '0', - title varchar(100) NOT NULL default '', - type varchar(6) NOT NULL default '', - visibility int(1) NOT NULL default '0', - `fields` text NOT NULL, - conditions text NOT NULL, - sortby varchar(20) NOT NULL default '', - sortorder varchar(4) NOT NULL default '', - perpage int(4) NOT NULL default '0', - view_type varchar(6) NOT NULL default '', - PRIMARY KEY(vid) - ) ENGINE=MyISAM{$collation};"); - - $views = file_get_contents(INSTALL_ROOT.'resources/adminviews.xml'); - $parser = new XMLParser($views); - $parser->collapse_dups = 0; - $tree = $parser->get_tree(); - - // Insert admin views - foreach($tree['adminviews'][0]['view'] as $view) - { - $fields = array(); - foreach($view['fields'][0]['field'] as $field) - { - $fields[] = $field['attributes']['name']; - } - $conditions = array(); - if($view['conditions'][0]['condition']) - { - foreach($view['conditions'][0]['condition'] as $condition) - { - if(!$condition['value']) continue; - if($condition['attributes']['is_serialized'] == 1) - { - $condition['value'] = my_unserialize($condition['value']); - } - $conditions[$condition['attributes']['name']] = $condition['value']; - } - } - $new_view = array( - "uid" => 0, - "type" => $db->escape_string($view['attributes']['type']), - "visibility" => (int)$view['attributes']['visibility'], - "title" => $db->escape_string($view['title'][0]['value']), - "fields" => $db->escape_string(my_serialize($fields)), - "conditions" => $db->escape_string(my_serialize($conditions)), - "sortby" => $db->escape_string($view['sortby'][0]['value']), - "sortorder" => $db->escape_string($view['sortorder'][0]['value']), - "perpage" => (int)$view['perpage'][0]['value'], - "view_type" => $db->escape_string($view['view_type'][0]['value']) - ); - $db->insert_query("adminviews", $new_view); - $view_count++; - } - - $avatardimensions = str_replace('x', '|', my_strtolower($mybb->settings['postmaxavatarsize'])); - - $db->simple_select("users", "uid", "avatar != '' AND avatardimensions = ''"); - while($user = $db->fetch_array($query)) - { - $db->update_query("users", array('avatardimensions' => $avatardimensions), "uid='{$user['uid']}'", 1); - } - - $contents = "Done

    "; - $contents .= "

    Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("12_redoconfig"); -} - -function upgrade12_redoconfig() -{ - global $db, $output, $orig_config, $mybb; - - $config = $orig_config; - - $output->print_header("Rewriting config.php"); - - if(!is_array($config['database'])) - { - // Backup our old Config file - @copy(MYBB_ROOT."inc/config.php", MYBB_ROOT."inc/config.backup.php"); - - $fh = @fopen(MYBB_ROOT."inc/config.php", "w"); - if(!$fh) - { - echo "

    Unable to open inc/config.php
    Before the upgrade process can continue, you need to changes the permissions of inc/config.php so it is writable.

    "; - $output->print_footer("12_redoconfig"); - exit; - } - - if(!$config['memcache_host']) - { - $config['memcache_host'] = "localhost"; - } - - if(!$config['memcache_port']) - { - $config['memcache_port'] = 11211; - } - - $comment = ""; - - if(!$db->db_encoding || !$config['db_encoding']) - { - $comment = " // "; - } - - if(!$config['db_encoding']) - { - $config['db_encoding'] = "utf8"; - } - - $configdata = " 365, // Administrator logs - 'mod_logs' => 0, // Moderator logs - 'task_logs' => 30, // Scheduled task logs - 'mail_logs' => 180, // Mail error logs - 'user_mail_logs' => 180, // User mail logs - 'promotion_logs' => 180 // Promotion logs -); - -?".">"; - fwrite($fh, $configdata); - fclose($fh); - } - echo "

    The configuration file has successfully been rewritten.

    "; - echo "

    Click next to continue with the upgrade process.

    "; - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("12_dbchanges6"); -} - -function upgrade12_dbchanges6() -{ - global $db, $output; - - $output->print_header("Post IP Conversion"); - - if(!$_POST['ipspage']) - { - $ipp = 5000; - } - else - { - $ipp = (int)$_POST['ipspage']; - } - - if($_POST['ipstart']) - { - $startat = (int)$_POST['ipstart']; - $upper = $startat+$ipp; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $ipp; - $lower = 1; - } - - $query = $db->simple_select("posts", "COUNT(pid) AS ipcount"); - $cnt = $db->fetch_array($query); - - if($upper > $cnt['ipcount']) - { - $upper = $cnt['ipcount']; - } - - echo "

    Converting ip {$lower} to {$upper} ({$cnt['ipcount']} Total)

    "; - flush(); - - $ipaddress = false; - - $query = $db->simple_select("posts", "ipaddress, longipaddress, pid", "", array('limit_start' => $lower, 'limit' => $ipp)); - while($post = $db->fetch_array($query)) - { - // Have we already converted this ip? - if(!$post['longipaddress']) - { - $db->update_query("posts", array('longipaddress' => my_ip2long($post['ipaddress'])), "pid = '{$post['pid']}'"); - } - $ipaddress = true; - } - - $remaining = $upper-$cnt['ipcount']; - if($remaining && $ipaddress) - { - $nextact = "12_dbchanges6"; - $startat = $startat+$ipp; - $contents = "

    Done. Click Next to move on to the next set of post ips.

    "; - } - else - { - $nextact = "12_dbchanges7"; - $contents = "

    Done

    All post ips have been converted to the new ip format. Click next to continue.

    "; - } - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer($nextact); -} - -function upgrade12_dbchanges7() -{ - global $db, $output; - - $output->print_header("User IP Conversion"); - - if(!$_POST['ipspage']) - { - $ipp = 5000; - } - else - { - $ipp = (int)$_POST['ipspage']; - } - - if($_POST['ipstart']) - { - $startat = (int)$_POST['ipstart']; - $upper = $startat+$ipp; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $ipp; - $lower = 1; - } - - $query = $db->simple_select("users", "COUNT(uid) AS ipcount"); - $cnt = $db->fetch_array($query); - - if($upper > $cnt['ipcount']) - { - $upper = $cnt['ipcount']; - } - - $contents .= "

    Converting ip {$lower} to {$upper} ({$cnt['ipcount']} Total)

    "; - - $ipaddress = false; - $update_array = array(); - - $query = $db->simple_select("users", "regip, lastip, longlastip, longregip, uid", "", array('limit_start' => $lower, 'limit' => $ipp)); - while($user = $db->fetch_array($query)) - { - // Have we already converted this ip? - if(!$user['longregip']) - { - $update_array['longregip'] = (int)my_ip2long($user['regip']); - } - - if(!$user['longlastip']) - { - $update_array['longlastip'] = (int)my_ip2long($user['lastip']); - } - - if(!empty($update_array)) - { - $db->update_query("users", $update_array, "uid = '{$user['uid']}'"); - } - - $update_array = array(); - $ipaddress = true; - } - - $remaining = $upper-$cnt['ipcount']; - if($remaining && $ipaddress) - { - $nextact = "12_dbchanges7"; - $startat = $startat+$ipp; - $contents .= "

    Done. Click Next to move on to the next set of user ips.

    "; - } - else - { - $nextact = "12_dbchanges8"; - $contents .= "

    Done

    All user ips have been converted to the new ip format. Click next to continue.

    "; - } - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer($nextact); -} - -function upgrade12_dbchanges8() -{ - global $db, $output; - - $output->print_header("Event Conversion"); - - if(!$_POST['eventspage']) - { - $epp = 50; - } - else - { - $epp = (int)$_POST['eventspage']; - } - - if($_POST['eventstart']) - { - $startat = (int)$_POST['eventstart']; - $upper = $startat+$epp; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $epp; - $lower = 1; - } - - $query = $db->simple_select("events", "COUNT(eid) AS eventcount"); - $cnt = $db->fetch_array($query); - - if($upper > $cnt['eventcount']) - { - $upper = $cnt['eventcount']; - } - - $contents .= "

    Converting events {$lower} to {$upper} ({$cnt['eventcount']} Total)

    "; - - // Just started - add fields - if(!$db->field_exists("donecon", "events")) - { - // Add temporary column - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events ADD donecon smallint(1) NOT NULL;"); - - if($db->field_exists('cid', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP cid;"); - } - - if($db->field_exists('visible', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP visible;"); - } - - if($db->field_exists('dateline', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP dateline;"); - } - - if($db->field_exists('starttime', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP starttime;"); - } - - if($db->field_exists('endtime', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP endtime;"); - } - - if($db->field_exists('timezone', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP timezone;"); - } - - if($db->field_exists('ignoretimezone', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP ignoretimezone;"); - } - - if($db->field_exists('usingtime', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP usingtime;"); - } - - if($db->field_exists('repeats', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP repeats;"); - } - - // Got structural changes? - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events ADD cid int unsigned NOT NULL default '0' AFTER eid"); - - if($db->field_exists('author', "events") && !$db->field_exists('uid', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events CHANGE author uid int unsigned NOT NULL default '0'"); - } - - if($db->field_exists('subject', "events") && !$db->field_exists('name', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events CHANGE subject name varchar(120) NOT NULL default ''"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events ADD visible int(1) NOT NULL default '0' AFTER description"); - $db->update_query("events", array('private' => 1), "private='yes' OR private='1'"); - $db->update_query("events", array('private' => 0), "private='no' OR private='0'"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events CHANGE private private int(1) NOT NULL default '0'"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events ADD dateline int(10) unsigned NOT NULL default '0' AFTER private"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events ADD starttime int(10) unsigned NOT NULL default '0' AFTER dateline"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events ADD endtime int(10) unsigned NOT NULL default '0' AFTER starttime"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events ADD timezone int(3) NOT NULL default '0' AFTER endtime"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events ADD ignoretimezone int(1) NOT NULL default '0' AFTER timezone"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events ADD usingtime int(1) NOT NULL default '0' AFTER ignoretimezone"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events ADD repeats text NOT NULL AFTER usingtime"); - } - - if($db->field_exists('date', "events")) - { - $query = $db->simple_select("events", "*", "donecon!=1", array("order_by" => "eid", "limit" => $epp)); - while($event = $db->fetch_array($query)) - { - $e_date = explode("-", $event['date']); - if(!$e_date[2]) $e_date[2] = 2005; - $starttime = gmmktime(0, 0, 0, $e_date[1], $e_date[0], $e_date[2]); - $updated_event = array( - "cid" => 1, - "visible" => 1, - "donecon" => 1, - "starttime" => $starttime, - "dateline" => $starttime - ); - $db->update_query("events", $updated_event, "eid='{$event['eid']}'", 1); - } - - $date = true; - } - else - { - $date = false; - } - - $query = $db->simple_select("events", "COUNT(eid) AS remaining", "donecon!=1"); - $remaining = $db->fetch_field($query, "remaining"); - if($remaining && $date) - { - $nextact = "12_dbchanges8"; - $startat = $startat+$epp; - $contents .= "

    Done. Click Next to move on to the next set of events.

    "; - } - else - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP donecon"); - if($db->field_exists('date', "events")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events DROP date"); - } - $nextact = "12_redothemes"; - $contents .= "

    Done

    All events have been converted to the new calendar system. Click next to continue.

    "; - } - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer($nextact); -} - -function upgrade12_redothemes() -{ - global $db, $output, $config, $mybb; - - $output->print_header("Converting themes"); - - if(!@is_dir(MYBB_ROOT.'cache/')) - { - @mkdir(MYBB_ROOT.'cache/', 077); - - // Add in empty index.html! - $fp = @fopen(MYBB_ROOT."cache/index.html", "w"); - @fwrite($fp, ""); - @fclose($fp); - } - $cachewritable = @fopen(MYBB_ROOT.'cache/test.write', 'w'); - if(!$cachewritable) - { - $not_writable = true; - @fclose($cachewritable); - } - else - { - @fclose($cachewritable); - @my_chmod(MYBB_ROOT.'cache', '0777'); - @my_chmod(MYBB_ROOT.'cache/test.write', '0777'); - @unlink(MYBB_ROOT.'cache/test.write'); - } - - if($not_writable) - { - echo "

    Unable to write to the cache/ directory.
    Before the upgrade process can continue you need to make sure this directory exists and is writable (chmod 777)

    "; - $output->print_footer("12_redothemes"); - exit; - } - - $not_writable = false; - if(!@is_dir(MYBB_ROOT.'cache/themes/')) - { - @mkdir(MYBB_ROOT.'cache/themes/', 077); - - // Add in empty index.html! - $fp = @fopen(MYBB_ROOT."cache/themes/index.html", "w"); - @fwrite($fp, ""); - @fclose($fp); - } - $themewritable = @fopen(MYBB_ROOT.'cache/themes/test.write', 'w'); - if(!$themewritable) - { - $not_writable = true; - @fclose($themewritable); - } - else - { - @fclose($themewritable); - @my_chmod(MYBB_ROOT.'cache/themes', '0777'); - @my_chmod(MYBB_ROOT.'cache/themes/test.write', '0777'); - @unlink(MYBB_ROOT.'cache/themes/test.write'); - } - - if($not_writable) - { - echo "

    Unable to write to the cache/themes/ directory.
    Before the upgrade process can continue you need to make sure this directory exists and is writable (chmod 777)

    "; - $output->print_footer("12_redothemes"); - exit; - } - - if($db->field_exists('themebits', "themes") && !$db->field_exists('properties', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes CHANGE themebits properties text NOT NULL"); - } - - if($db->field_exists('cssbits', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP cssbits"); - } - - if($db->field_exists('csscached', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP csscached"); - } - - if($db->field_exists('stylesheets', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP stylesheets"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes ADD stylesheets text NOT NULL AFTER properties"); - - if($db->table_exists("themestylesheets")) - { - $db->drop_table("themestylesheets"); - } - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."themestylesheets( - sid int unsigned NOT NULL auto_increment, - name varchar(30) NOT NULL default '', - tid int unsigned NOT NULL default '0', - attachedto text NOT NULL, - stylesheet text NOT NULL, - cachefile varchar(100) NOT NULL default '', - lastmodified bigint(30) NOT NULL default '0', - PRIMARY KEY(sid) - ) ENGINE=MyISAM{$collation};"); - - // Define our default stylesheets - MyBB 1.4 contains additional stylesheets that our converted themes will also need - $contents = @file_get_contents(INSTALL_ROOT.'resources/mybb_theme.xml'); - if(file_exists(MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php")) - { - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php"; - } - else if(file_exists(MYBB_ROOT."admin/inc/functions_themes.php")) - { - require_once MYBB_ROOT."admin/inc/functions_themes.php"; - } - else - { - $output->print_error("Please make sure your admin directory is uploaded correctly."); - } - - // Import master theme - if(import_theme_xml($contents, array("tid" => 1, "no_templates" => 1, "version_compat" => 1)) === -1) - { - $output->print_error("Please make sure your install/resources/mybb_theme.xml file is uploaded correctly."); - } - - // Fetch out default stylesheets from master - $query = $db->simple_select("themes", "*", "tid=1"); - $master_theme = $db->fetch_array($query); - - $master_stylesheets = my_unserialize($master_theme['stylesheets']); - - if(is_array($master_stylesheets)) - { - // Note: 1.4 only ships with one global|global stylesheet - foreach($master_stylesheets as $location => $sheets) - { - foreach($sheets as $action => $sheets) - { - foreach($sheets as $stylesheet) - { - if($location == "global" && $action == "global") - { - continue; // Skip global - } - - $default_stylesheets[$location][$action][] = $stylesheet; - $default_stylesheets['inherited']["{$location}_{$action}"][$stylesheet] = 1; // This stylesheet is inherited from the master - } - } - } - } - - $query = $db->simple_select("themes"); - while($theme = $db->fetch_array($query)) - { - if(!$theme['css']) - { - continue; - } - - $theme['css'] .= "\n\n".$theme['extracss']; - - $theme['css'] = upgrade_css_120_to_140($theme['css']); - - - // Create stylesheets - $cache_file = cache_stylesheet($theme['tid'], "global.css", $theme['css']); - - $new_stylesheet = array( - "tid" => $theme['tid'], - "name" => "global.css", - "attachedto" => "", - "stylesheet" => $db->escape_string($theme['css']), - "cachefile" => "global.css", - "lastmodified" => TIME_NOW - ); - $sid = $db->insert_query("themestylesheets", $new_stylesheet); - $css_url = "css.php?stylesheet={$sid}"; - if($cache_file) - { - $css_url = $cache_file; - } - - // Now we go and update the stylesheets column for this theme - $stylesheets = $default_stylesheets; - - // Add in our local for this theme - $stylesheets['global']['global'][] = $css_url; - - // Update the theme - $db->update_query("themes", array("stylesheets" => $db->escape_string(my_serialize($stylesheets))), "tid='{$theme['tid']}'"); - } - - if($db->field_exists('css', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP css"); - } - - if($db->field_exists('extracss', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP extracss"); - } - - // We need to replace this for our themes css to show up - // must be present in the old template (it usually is) - $query = $db->simple_select("templates", "tid,template", "title='headerinclude'"); - while($template = $db->fetch_array($query)) - { - $template['template'] = str_replace('', '{$stylesheets}', $template['template']); - - $db->update_query("templates", array('template' => $db->escape_string($template['template'])), "tid='{$template['tid']}'"); - } - - echo "

    Your themes have successfully been converted to the new theme system.

    "; - echo "

    Click next to continue with the upgrade process.

    "; - - global $footer_extra; - //$footer_extra = ""; - - $output->print_footer("12_done"); -} diff --git a/html/forums/install/resources/upgrade13.php b/html/forums/install/resources/upgrade13.php deleted file mode 100644 index 725516b..0000000 --- a/html/forums/install/resources/upgrade13.php +++ /dev/null @@ -1,237 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade13_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - if($db->type == "mysql" || $db->type == "mysqli") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminsessions ADD INDEX ( `uid` )"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminsessions ADD INDEX ( `dateline` )"); - } - - if($db->type != "sqlite") - { - if($db->index_exists("users", "username")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP KEY username"); - } - - $query = $db->simple_select("users", "username, uid", "1=1 GROUP BY uid, username HAVING count(*) > 1"); - while($user = $db->fetch_array($query)) - { - $db->update_query("users", array('username' => $user['username']."_dup".$user['uid']), "uid='{$user['uid']}'", 1); - } - - if($db->type == "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD UNIQUE(username)"); - } - else - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD UNIQUE KEY username (username)"); - } - } - - if($db->type == "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE longregip longregip int NOT NULL default '0'"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE longlastip longlastip int NOT NULL default '0'"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts CHANGE longipaddress longipaddress int NOT NULL default '0'"); - } - else - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE longregip longregip int(11) NOT NULL default '0'"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE longlastip longlastip int(11) NOT NULL default '0'"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts CHANGE longipaddress longipaddress int(11) NOT NULL default '0'"); - } - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("13_dbchanges1"); -} - -function upgrade13_dbchanges1() -{ - global $db, $output; - - $output->print_header("Post IP Repair Conversion"); - - if(!$_POST['ipspage']) - { - $ipp = 5000; - } - else - { - $ipp = (int)$_POST['ipspage']; - } - - if($_POST['ipstart']) - { - $startat = (int)$_POST['ipstart']; - $upper = $startat+$ipp; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $ipp; - $lower = 1; - } - - $query = $db->simple_select("posts", "COUNT(pid) AS ipcount"); - $cnt = $db->fetch_array($query); - - if($upper > $cnt['ipcount']) - { - $upper = $cnt['ipcount']; - } - - echo "

    Repairing ip {$lower} to {$upper} ({$cnt['ipcount']} Total)

    "; - flush(); - - $ipaddress = false; - - $query = $db->simple_select("posts", "ipaddress, longipaddress, pid", "", array('limit_start' => $lower, 'limit' => $ipp)); - while($post = $db->fetch_array($query)) - { - // Have we already converted this ip? - if(my_ip2long($post['ipaddress']) < 0) - { - $db->update_query("posts", array('longipaddress' => my_ip2long($post['ipaddress'])), "pid = '{$post['pid']}'"); - } - $ipaddress = true; - } - - $remaining = $upper-$cnt['ipcount']; - if($remaining && $ipaddress) - { - $nextact = "13_dbchanges1"; - $startat = $startat+$ipp; - $contents = "

    Done. Click Next to move on to the next set of post ips.

    "; - } - else - { - $nextact = "13_dbchanges2"; - $contents = "

    Done

    All post ips have been converted to the new ip format. Click next to continue.

    "; - } - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer($nextact); -} - -function upgrade13_dbchanges2() -{ - global $db, $output; - - $output->print_header("User IP Repair Conversion"); - - if(!$_POST['ipspage']) - { - $ipp = 5000; - } - else - { - $ipp = (int)$_POST['ipspage']; - } - - if($_POST['ipstart']) - { - $startat = (int)$_POST['ipstart']; - $upper = $startat+$ipp; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $ipp; - $lower = 1; - } - - $query = $db->simple_select("users", "COUNT(uid) AS ipcount"); - $cnt = $db->fetch_array($query); - - if($upper > $cnt['ipcount']) - { - $upper = $cnt['ipcount']; - } - - $contents .= "

    Repairing ip {$lower} to {$upper} ({$cnt['ipcount']} Total)

    "; - - $ipaddress = false; - $update_array = array(); - - $query = $db->simple_select("users", "regip, lastip, longlastip, longregip, uid", "", array('limit_start' => $lower, 'limit' => $ipp)); - while($user = $db->fetch_array($query)) - { - // Have we already converted this ip? - if(my_ip2long($user['regip']) < 0) - { - $update_array['longregip'] = (int)my_ip2long($user['regip']); - } - - if(my_ip2long($user['lastip']) < 0) - { - $update_array['longlastip'] = (int)my_ip2long($user['lastip']); - } - - if(!empty($update_array)) - { - $db->update_query("users", $update_array, "uid = '{$user['uid']}'"); - } - - $update_array = array(); - $ipaddress = true; - } - - $remaining = $upper-$cnt['ipcount']; - if($remaining && $ipaddress) - { - $nextact = "13_dbchanges2"; - $startat = $startat+$ipp; - $contents .= "

    Done. Click Next to move on to the next set of user ips.

    "; - } - else - { - $nextact = "13_done"; - $contents .= "

    Done

    All user ips have been converted to the new ip format. Click next to continue.

    "; - } - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer($nextact); -} - diff --git a/html/forums/install/resources/upgrade14.php b/html/forums/install/resources/upgrade14.php deleted file mode 100644 index cacd80d..0000000 --- a/html/forums/install/resources/upgrade14.php +++ /dev/null @@ -1,216 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade14_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - // TODO: Need to check for PostgreSQL / SQLite support - - if($db->field_exists('codepress', "adminoptions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions DROP codepress;"); - } - - if($db->type == "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions ADD codepress int NOT NULL default '1' AFTER cpstyle"); - } - else - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions ADD codepress int(1) NOT NULL default '1' AFTER cpstyle"); - } - - if($db->type != "sqlite") - { - $longregip_index = $db->index_exists("users", "longregip"); - $longlastip_index = $db->index_exists("users", "longlastip"); - - if($longlastip_index == true) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP KEY longlastip"); - } - - if($longregip_index == true) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP KEY longregip"); - } - - $longipaddress_index = $db->index_exists("posts", "longipaddress"); - if($longipaddress_index == true) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts DROP KEY longipaddress"); - } - } - - if($db->field_exists('loginattempts', "sessions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."sessions DROP loginattempts;"); - } - - if($db->field_exists('loginattempts', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP loginattempts;"); - } - - if($db->type == "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD loginattempts smallint NOT NULL default '1';"); - } - else - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD loginattempts tinyint(2) NOT NULL default '1';"); - } - - if($db->field_exists('failedlogin', "sessions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."sessions DROP failedlogin;"); - } - - if($db->field_exists('failedlogin', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP failedlogin;"); - } - - if($db->type == "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD failedlogin bigint NOT NULL default '0';"); - } - else - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD failedlogin bigint(30) NOT NULL default '0';"); - } - - if($db->type == "mysql" || $db->type == "mysqli") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD INDEX longregip (longregip)"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD INDEX longlastip (longlastip)"); - } - - if($db->type == "sqlite") - { - // Because SQLite 2 nor 3 allows changing a column with a primary key constraint we have to completely rebuild the entire table - // *sigh* This is the 21st century, right? - $query = $db->simple_select("datacache"); - while($datacache = $db->fetch_array($query)) - { - $temp_datacache[$datacache['title']] = array('title' => $db->escape_string($datacache['title']), 'cache' => $db->escape_string($datacache['cache'])); - } - - $db->write_query("DROP TABLE ".TABLE_PREFIX."datacache"); - - $db->write_query("CREATE TABLE ".TABLE_PREFIX."datacache ( - title varchar(50) NOT NULL default '' PRIMARY KEY, - cache mediumTEXT NOT NULL -);"); - - reset($temp_datacache); - foreach($temp_datacache as $data) - { - $db->insert_query("datacache", $data); - } - } - else if($db->type == "pgsql") - { - if(!$db->index_exists("datacache", "title")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."datacache ADD PRIMARY KEY (title)"); - } - } - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("14_dbchanges1"); -} - -function upgrade14_dbchanges1() -{ - global $db, $output; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - if($db->type == "mysql" || $db->type == "mysqli") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts ADD INDEX longipaddress (longipaddress)"); - } - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("14_dbchanges2"); -} - -function upgrade14_dbchanges2() -{ - global $db, $output; - - $output->print_header("Cleaning up old Settings & Groups"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - $db->delete_query("settinggroups", "name='banning' AND isdefault='0'", 1); - - $db->delete_query("settings", "name='bannedusernames'", 1); - $db->delete_query("settings", "name='bannedips'", 1); - $db->delete_query("settings", "name='bannedemails'", 1); - $db->delete_query("settings", "name='publiceventcolor'", 1); - $db->delete_query("settings", "name='privateeventcolor'", 1); - $db->delete_query("settings", "name='cssmedium'", 1); - - $db->delete_query("templates", "title='usercp_options_timezoneselect' AND sid != '-1'"); - $db->delete_query("templates", "title='moderation_reports' AND sid != '-1'"); - $db->delete_query("templates", "title='moderation_reports_report' AND sid != '-1'"); - $db->delete_query("templates", "title='moderation_reports_multipage' AND sid != '-1'"); - $db->delete_query("templates", "title='moderation_allreports' AND sid != '-1'"); - $db->delete_query("templates", "title='showthread_ratingdisplay' AND sid != '-1'"); - $db->delete_query("templates", "title='moderation_getip_adminoptions' AND sid != '-1'"); - $db->delete_query("templates", "title='calendar_eventbit_public' AND sid != '-1'"); - $db->delete_query("templates", "title='calendar_daybit_today' AND sid != '-1'"); - $db->delete_query("templates", "title='calendar_daybit' AND sid != '-1'"); - $db->delete_query("templates", "title='online_iplookup' AND sid != '-1'"); - $db->delete_query("templates", "title='online_iplookup_adminoptions' AND sid != '-1'"); - $db->delete_query("templates", "title='online_row_ip' AND sid != '-1'"); - $db->delete_query("templates", "title='calendar_eventbit_dates' AND sid != '-1'"); - $db->delete_query("templates", "title='calendar_eventbit_dates_recurring' AND sid != '-1'"); - $db->delete_query("templates", "title='calendar_eventbit_times' AND sid != '-1'"); - $db->delete_query("templates", "title='calendar_editevent_normal' AND sid != '-1'"); - $db->delete_query("templates", "title='calendar_editevent_recurring' AND sid != '-1'"); - - $db->update_query("helpdocs", array('document' => $db->escape_string("MyBB makes use of cookies to store your login information if you are registered, and your last visit if you are not. -

    Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. -

    Cookies on this forum also track the specific topics you have read and when you last read them. -

    To clear all cookies set by this forum, you can click here.")), "hid='3'", 1); - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("14_done"); -} - diff --git a/html/forums/install/resources/upgrade15.php b/html/forums/install/resources/upgrade15.php deleted file mode 100644 index dc37f2a..0000000 --- a/html/forums/install/resources/upgrade15.php +++ /dev/null @@ -1,153 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade15_dbchanges() -{ - global $db, $output, $mybb, $cache; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - if($db->type != "pgsql") - { - $db->update_query("settinggroups", array('isdefault' => '1'), "isdefault='yes'"); - $db->update_query("settinggroups", array('isdefault' => '0'), "isdefault='no'"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events CHANGE timezone timezone varchar(4) NOT NULL default '0'"); - } - - if($db->type == "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."warnings ALTER COLUMN revokereason SET default ''"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."warnings ALTER COLUMN notes SET default ''"); - } - - $cache->update("internal_settings", array('encryption_key' => random_str(32))); - - if($db->type != "sqlite") - { - $ip_index = $db->index_exists("sessions", "ip"); - - if($ip_index == false) - { - if($db->type == "pgsql") - { - $db->write_query("CREATE INDEX ip ON ".TABLE_PREFIX."sessions (ip)"); - } - else - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."sessions ADD INDEX (`ip`)"); - } - } - } - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("15_usernameverify"); -} - -function upgrade15_usernameverify() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    WARNING - PLEASE READ THE FOLLOWING: The next step of this process will remove ALL commas (,) from the usernames of your forum whom contain them. The reason for this change is commas in usernames can make the private messages in MyBB return errors when sending to these users.

    "; - flush(); - - $contents .= "Click next to continue with the upgrade process once you have read the warning.

    "; - $output->print_contents($contents); - $output->print_footer("15_usernameupdate"); -} - -function upgrade15_usernameupdate() -{ - global $db, $output, $mybb, $plugins; - - $output->print_header("Performing Queries"); - - echo "

    Performing username updates..

    "; - flush(); - - require_once MYBB_ROOT."inc/datahandler.php"; - require_once MYBB_ROOT."inc/datahandlers/user.php"; - // Load plugin system for datahandler - require_once MYBB_ROOT."inc/class_plugins.php"; - $plugins = new pluginSystem; - - $not_renameable = array(); - - // Because commas can cause some problems with private message sending in usernames we have to remove them - $query = $db->simple_select("users", "uid, username", "username LIKE '%,%'"); - while($user = $db->fetch_array($query)) - { - $prefix = ''; - $userhandler = new UserDataHandler('update'); - - do - { - $username = str_replace(',', '', $user['username']).'_'.$prefix; - - $updated_user = array( - "uid" => $user['uid'], - "username" => $username - ); - $userhandler->set_data($updated_user); - - ++$prefix; - } - while(!$userhandler->verify_username() || $userhandler->verify_username_exists()); - - if(!$userhandler->validate_user()) - { - $not_renameable[] = htmlspecialchars_uni($user['username']); - } - else - { - $db->update_query("users", array('username' => $db->escape_string($username)), "uid='{$user['uid']}'"); - $db->update_query("posts", array('username' => $db->escape_string($username)), "uid='{$user['uid']}'"); - $db->update_query("threads", array('username' => $db->escape_string($username)), "uid='{$user['uid']}'"); - $db->update_query("threads", array('lastposter' => $db->escape_string($username)), "lastposteruid='{$user['uid']}'"); - $db->update_query("forums", array('lastposter' => $db->escape_string($username)), "lastposteruid='{$user['uid']}'"); - - update_stats(array("numusers" => "+0")); - } - } - - if(!empty($not_renameable)) - { - echo "NOTICE: The following users could not be renamed automatically. Please rename these users in the Admin CP manually after the upgrade process has finished completing:
    -
      -
    • "; - echo implode('
    • \n
    • ', $not_renameable); - echo "
    • -
    "; - } - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("15_done"); -} - diff --git a/html/forums/install/resources/upgrade16.php b/html/forums/install/resources/upgrade16.php deleted file mode 100644 index 584b320..0000000 --- a/html/forums/install/resources/upgrade16.php +++ /dev/null @@ -1,25 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do from 1.4.5 to 1.4.13 */ - diff --git a/html/forums/install/resources/upgrade17.php b/html/forums/install/resources/upgrade17.php deleted file mode 100644 index 49e7ea3..0000000 --- a/html/forums/install/resources/upgrade17.php +++ /dev/null @@ -1,961 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade17_dbchanges() -{ - global $db, $output, $mybb, $cache; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - echo "

    Adding index to private messages table ... "; - flush(); - - if($db->type == "mysql" || $db->type == "mysqli") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages ADD INDEX ( `toid` )"); - } - - global $footer_extra; - $footer_extra = ""; - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("17_dbchanges2"); -} - -function upgrade17_dbchanges2() -{ - global $db, $output, $mybb, $cache; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - // Update our version history first - $version_history = array(); - $dh = opendir(INSTALL_ROOT."resources"); - while(($file = readdir($dh)) !== false) - { - if(preg_match("#upgrade([0-9]+).php$#i", $file, $match)) - { - $version_history[$match[1]] = $match[1]; - } - } - sort($version_history, SORT_NUMERIC); - - // This script isn't done yet! - unset($version_history['17']); - - $cache->update("version_history", $version_history); - - if($db->field_exists('prefix', 'threads')) - { - $db->drop_column("threads", "prefix"); - } - - if($db->field_exists('loginattempts', "adminoptions")) - { - $db->drop_column("adminoptions", "loginattempts"); - } - - if($db->field_exists('loginlockoutexpiry', "adminoptions")) - { - $db->drop_column("adminoptions", "loginlockoutexpiry"); - } - - if($db->field_exists('canonlyviewownthreads', "forumpermissions")) - { - $db->drop_column("forumpermissions", "canonlyviewownthreads"); - } - - if($db->field_exists('isgroup', 'moderators')) - { - $db->drop_column("moderators", "isgroup"); - } - - if($db->field_exists('referrals', 'promotions')) - { - $db->drop_column("promotions", "referrals"); - } - - if($db->field_exists('referralstype', 'promotions')) - { - $db->drop_column("promotions", "referralstype"); - } - - if($db->field_exists('pid', 'reputation')) - { - $db->drop_column("reputation", "pid"); - } - - if($db->field_exists('allowvideocode', 'calendars')) - { - $db->drop_column("calendars", "allowvideocode"); - } - - if($db->field_exists('allowvideocode', 'forums')) - { - $db->drop_column("forums", "allowvideocode"); - } - - switch($db->type) - { - case "pgsql": - $db->add_column("threads", "prefix", "smallint NOT NULL default '0' AFTER subject"); - $db->add_column("adminoptions", "loginattempts", "int NOT NULL default '0'"); - $db->add_column("adminoptions", "loginlockoutexpiry", "int NOT NULL default '0'"); - $db->add_column("forumpermissions", "canonlyviewownthreads", "int NOT NULL default '0' AFTER canviewthreads"); - $db->add_column("moderators", "isgroup", "int NOT NULL default '0'"); - $db->add_column("promotions", "referrals", "int NOT NULL default '0' AFTER reputationtype"); - $db->add_column("promotions", "referralstype", "char(2) NOT NULL default '' AFTER referrals"); - $db->add_column("reputation", "pid", "int NOT NULL default '0'"); - $db->add_column("calendars", "allowvideocode", "int NOT NULL default '0' AFTER allowimgcode"); - $db->add_column("forums", "allowvideocode", "int NOT NULL default '0' AFTER allowimgcode"); - break; - case "sqlite": - $db->add_column("threads", "prefix", "smallint NOT NULL default '0' AFTER subject"); - $db->add_column("adminoptions", "loginattempts", "int NOT NULL default '0'"); - $db->add_column("adminoptions", "loginlockoutexpiry", "int NOT NULL default '0'"); - $db->add_column("forumpermissions", "canonlyviewownthreads", "int NOT NULL default '0' AFTER canviewthreads"); - $db->add_column("moderators", "isgroup", "int NOT NULL default '0'"); - $db->add_column("promotions", "referrals", "int NOT NULL default '0' AFTER reputationtype"); - $db->add_column("promotions", "referralstype", "varchar(2) NOT NULL default '' AFTER referrals"); - $db->add_column("reputation", "pid", "int NOT NULL default '0'"); - $db->add_column("calendars", "allowvideocode", "int(1) NOT NULL default '0' AFTER allowimgcode"); - $db->add_column("forums", "allowvideocode", "int(1) NOT NULL default '0' AFTER allowimgcode"); - break; - default: - $db->add_column("threads", "prefix", "smallint unsigned NOT NULL default '0' AFTER subject"); - $db->add_column("adminoptions", "loginattempts", "int unsigned NOT NULL default '0'"); - $db->add_column("adminoptions", "loginlockoutexpiry", "int unsigned NOT NULL default '0'"); - $db->add_column("forumpermissions", "canonlyviewownthreads", "int(1) NOT NULL default '0' AFTER canviewthreads"); - $db->add_column("moderators", "isgroup", "int(1) unsigned NOT NULL default '0'"); - $db->add_column("promotions", "referrals", "int NOT NULL default '0' AFTER reputationtype"); - $db->add_column("promotions", "referralstype", "varchar(2) NOT NULL default '' AFTER referrals"); - $db->add_column("reputation", "pid", "int unsigned NOT NULL default '0'"); - $db->add_column("calendars", "allowvideocode", "int(1) NOT NULL default '0' AFTER allowimgcode"); - $db->add_column("forums", "allowvideocode", "int(1) NOT NULL default '0' AFTER allowimgcode"); - } - - $db->update_query("forums", array('allowvideocode' => '1')); - $db->update_query("calendars", array('allowvideocode' => '1')); - - global $footer_extra; - $footer_extra = ""; - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("17_dbchanges3"); -} - -function upgrade17_dbchanges3() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - if($db->field_exists('canundovotes', 'usergroups')) - { - $db->drop_column("usergroups", "canundovotes"); - } - - if($db->field_exists('maxreputationsperuser', 'usergroups')) - { - $db->drop_column("usergroups", "maxreputationsperuser"); - } - - if($db->field_exists('maxreputationsperthread', 'usergroups')) - { - $db->drop_column("usergroups", "maxreputationsperthread"); - } - - if($db->field_exists('receivefrombuddy', 'users')) - { - $db->drop_column("users", "receivefrombuddy"); - } - - if($db->field_exists('suspendsignature', 'users')) - { - $db->drop_column("users", "suspendsignature"); - } - - if($db->field_exists('suspendsigtime', 'users')) - { - $db->drop_column("users", "suspendsigtime"); - } - - if($db->field_exists('loginattempts', 'users')) - { - $db->drop_column("users", "loginattempts"); - } - - if($db->field_exists('failedlogin', 'users')) - { - $db->drop_column("users", "failedlogin"); - } - - if($db->field_exists('usernotes', "users")) - { - $db->drop_column("users", "usernotes"); - } - - if($db->field_exists('referrals', 'users')) - { - $db->drop_column("users", "referrals"); - } - - switch($db->type) - { - case "pgsql": - $db->add_column("usergroups", "canundovotes", "int NOT NULL default '0' AFTER canvotepolls"); - $db->add_column("usergroups", "maxreputationsperuser", "bigint NOT NULL default '0' AFTER maxreputationsday"); - $db->add_column("usergroups", "maxreputationsperthread", "bigint NOT NULL default '0' AFTER maxreputationsperuser"); - $db->add_column("users", "receivefrombuddy", "int NOT NULL default '0'"); - $db->add_column("users", "suspendsignature", "int NOT NULL default '0'"); - $db->add_column("users", "suspendsigtime", "bigint NOT NULL default '0'"); - $db->add_column("users", "loginattempts", "smallint NOT NULL default '1'"); - $db->add_column("users", "failedlogin", "bigint NOT NULL default '0'"); - $db->add_column("users", "usernotes", "text NOT NULL default ''"); - $db->add_column("users", "referrals", "int NOT NULL default '0' AFTER referrer"); - break; - case "sqlite": - $db->add_column("usergroups", "canundovotes", "int NOT NULL default '0' AFTER canvotepolls"); - $db->add_column("usergroups", "maxreputationsperuser", "bigint NOT NULL default '0' AFTER maxreputationsday"); - $db->add_column("usergroups", "maxreputationsperthread", "bigint NOT NULL default '0' AFTER maxreputationsperuser"); - $db->add_column("users", "receivefrombuddy", "int NOT NULL default '0'"); - $db->add_column("users", "suspendsignature", "int NOT NULL default '0'"); - $db->add_column("users", "suspendsigtime", "bigint NOT NULL default '0'"); - $db->add_column("users", "loginattempts", "tinyint NOT NULL default '1'"); - $db->add_column("users", "failedlogin", "bigint NOT NULL default '0'"); - $db->add_column("users", "usernotes", "text NOT NULL default ''"); - $db->add_column("users", "referrals", "int NOT NULL default '0' AFTER referrer"); - break; - default: - $db->add_column("usergroups", "canundovotes", "int(1) NOT NULL default '0' AFTER canvotepolls"); - $db->add_column("usergroups", "maxreputationsperuser", "bigint(30) NOT NULL default '0' AFTER maxreputationsday"); - $db->add_column("usergroups", "maxreputationsperthread", "bigint(30) NOT NULL default '0' AFTER maxreputationsperuser"); - $db->add_column("users", "receivefrombuddy", "int(1) NOT NULL default '0'"); - $db->add_column("users", "suspendsignature", "int(1) NOT NULL default '0'"); - $db->add_column("users", "suspendsigtime", "bigint(30) NOT NULL default '0'"); - $db->add_column("users", "loginattempts", "tinyint(2) NOT NULL default '1'"); - $db->add_column("users", "failedlogin", "bigint(30) NOT NULL default '0'"); - $db->add_column("users", "usernotes", "text NOT NULL"); - $db->add_column("users", "referrals", "int unsigned NOT NULL default '0' AFTER referrer"); - } - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("17_dbchanges4"); -} - -function upgrade17_dbchanges4() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - if($db->field_exists('remember', 'users')) - { - $db->drop_column("users", "remember"); - } - - if($db->type != "pgsql") - { - // PgSQL doesn't support longtext - $db->modify_column("searchlog", "threads", "longtext NOT NULL"); - $db->modify_column("searchlog", "posts", "longtext NOT NULL"); - } - - if($db->field_exists("uid", "moderators") && !$db->field_exists("id", "moderators")) - { - switch($db->type) - { - case "pgsql": - $db->rename_column("moderators", "uid", "id", "int", true, "'0'"); - break; - default: - $db->rename_column("moderators", "uid", "id", "int unsigned NOT NULL default '0'"); - } - } - - if($db->table_exists("threadprefixes")) - { - $db->drop_table("threadprefixes"); - } - - if($db->table_exists("delayedmoderation")) - { - $db->drop_table("delayedmoderation"); - } - - switch($db->type) - { - case "sqlite": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."threadprefixes ( - rid INTEGER PRIMARY KEY, - tid int NOT NULL default '0', - uid int NOT NULL default '0', - rating smallint NOT NULL default '0', - ipaddress varchar(30) NOT NULL default '' - );"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."delayedmoderation ( - did integer PRIMARY KEY, - type varchar(30) NOT NULL default '', - delaydateline bigint(30) NOT NULL default '0', - uid int(10) NOT NULL default '0', - fid smallint(5) NOT NULL default '0', - tids text NOT NULL, - dateline bigint(30) NOT NULL default '0', - inputs text NOT NULL - );"); - break; - case "pgsql": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."threadprefixes ( - pid serial, - prefix varchar(120) NOT NULL default '', - displaystyle varchar(200) NOT NULL default '', - forums text NOT NULL, - groups text NOT NULL, - PRIMARY KEY(pid) - );"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."delayedmoderation ( - did serial, - type varchar(30) NOT NULL default '', - delaydateline bigint NOT NULL default '0', - uid int NOT NULL default '0', - fid smallint NOT NULL default '0', - tids text NOT NULL, - dateline bigint NOT NULL default '0', - inputs text NOT NULL default '', - PRIMARY KEY (did) - );"); - break; - default: - $db->write_query("CREATE TABLE ".TABLE_PREFIX."threadprefixes ( - pid int unsigned NOT NULL auto_increment, - prefix varchar(120) NOT NULL default '', - displaystyle varchar(200) NOT NULL default '', - forums text NOT NULL, - groups text NOT NULL, - PRIMARY KEY(pid) - ) ENGINE=MyISAM;"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."delayedmoderation ( - did int unsigned NOT NULL auto_increment, - type varchar(30) NOT NULL default '', - delaydateline bigint(30) unsigned NOT NULL default '0', - uid int(10) unsigned NOT NULL default '0', - fid smallint(5) unsigned NOT NULL default '0', - tids text NOT NULL, - dateline bigint(30) NOT NULL default '0', - inputs text NOT NULL, - PRIMARY KEY (did) - ) ENGINE=MyISAM;"); - } - - $added_tasks = sync_tasks(); - - echo "

    Added {$added_tasks} new tasks.

    "; - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("17_dbchanges5"); -} - -function upgrade17_dbchanges5() -{ - global $db, $output, $mybb, $cache; - - if(file_exists(MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions.php")) - { - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions.php"; - } - else if(file_exists(MYBB_ROOT."admin/inc/functions.php")) - { - require_once MYBB_ROOT."admin/inc/functions.php"; - } - else - { - $output->print_error("Please make sure your admin directory is uploaded correctly."); - } - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - flush(); - - $db->update_query("spiders", array('name' => 'Bing'), "name='MSN Search'"); - $db->update_query("spiders", array('useragent' => 'Googlebot', 'name' => 'Google'), "useragent='google'"); - $db->update_query("spiders", array('useragent' => 'Teoma', 'name' => 'Ask.com'), "useragent='ask jeeves'"); - $db->delete_query("spiders", "name='Hot Bot'"); - $db->update_query("spiders", array('useragent' => 'archive_crawler', 'name' => 'Internet Archive'), "name='Archive.org'"); - $db->update_query("spiders", array('name' => 'Alexa Internet'), "useragent='ia_archiver'"); - $db->delete_query("spiders", "useragent='scooter'"); - $db->update_query("spiders", array('useragent' => 'Slurp'), "name='Yahoo!'"); - - $query = $db->simple_select("spiders", "COUNT(*) as numexists", "useragent='twiceler'"); - if($db->fetch_field($query, "numexists") == 0) - { - $db->insert_query("spiders", array('name' => "Cuil", 'useragent' => 'twiceler')); - } - - $query = $db->simple_select("spiders", "COUNT(*) as numexists", "useragent='Baiduspider'"); - if($db->fetch_field($query, "numexists") == 0) - { - $db->insert_query("spiders", array('name' => "Baidu", 'useragent' => 'Baiduspider')); - } - - $db->update_query("attachtypes", array('mimetype' => 'application/x-httpd-php'), "extension='php'"); - $db->update_query("attachtypes", array('mimetype' => 'text/html'), "extension='htm'"); - $db->update_query("attachtypes", array('mimetype' => 'text/html'), "extension='html'"); - $db->update_query("attachtypes", array('mimetype' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'), "extension='docx'"); - $db->update_query("attachtypes", array('mimetype' => 'application/vnd.ms-excel'), "extension='xls'"); - $db->update_query("attachtypes", array('mimetype' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'), "extension='xlsx'"); - $db->update_query("attachtypes", array('mimetype' => 'application/vnd.ms-powerpoint'), "extension='ppt'"); - $db->update_query("attachtypes", array('mimetype' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation'), "extension='pptx'"); - - $cache->update_moderators(); - - $db->update_query("themes", array('allowedgroups' => 'all'), "allowedgroups='' OR allowedgroups IS NULL"); - - // Add permissions for all of our new ACP pages - change_admin_permission('config', 'thread_prefixes'); - change_admin_permission('tools', 'file_verification'); - change_admin_permission('tools', 'statistics'); - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("17_dbchanges6"); -} - -function upgrade17_dbchanges6() -{ - global $db, $output; - - $output->print_header("Post IP Repair Conversion"); - - if(!$_POST['ipspage']) - { - $ipp = 5000; - } - else - { - $ipp = (int)$_POST['ipspage']; - } - - if($_POST['ipstart']) - { - $startat = (int)$_POST['ipstart']; - $upper = $startat+$ipp; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $ipp; - $lower = 1; - } - - $query = $db->simple_select("posts", "COUNT(pid) AS ipcount"); - $cnt = $db->fetch_array($query); - - if($upper > $cnt['ipcount']) - { - $upper = $cnt['ipcount']; - } - - echo "

    Repairing ip {$lower} to {$upper} ({$cnt['ipcount']} Total)

    "; - flush(); - - $ipaddress = false; - - $query = $db->simple_select("posts", "ipaddress, pid", "", array('limit_start' => $lower, 'limit' => $ipp)); - while($post = $db->fetch_array($query)) - { - $db->update_query("posts", array('longipaddress' => (int)my_ip2long($post['ipaddress'])), "pid = '{$post['pid']}'"); - $ipaddress = true; - } - - $remaining = $upper-$cnt['ipcount']; - if($remaining && $ipaddress) - { - $nextact = "17_dbchanges6"; - $startat = $startat+$ipp; - $contents = "

    Done. Click Next to move on to the next set of post ips.

    "; - } - else - { - $nextact = "17_dbchanges7"; - $contents = "

    Done

    All post ips have been successfully repaired. Click next to continue.

    "; - } - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer($nextact); -} - -function upgrade17_dbchanges7() -{ - global $db, $output; - - $output->print_header("User IP Repair Conversion"); - - if(!$_POST['ipspage']) - { - $ipp = 5000; - } - else - { - $ipp = (int)$_POST['ipspage']; - } - - if($_POST['ipstart']) - { - $startat = (int)$_POST['ipstart']; - $upper = $startat+$ipp; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $ipp; - $lower = 1; - } - - $query = $db->simple_select("users", "COUNT(uid) AS ipcount"); - $cnt = $db->fetch_array($query); - - if($upper > $cnt['ipcount']) - { - $upper = $cnt['ipcount']; - } - - $contents .= "

    Repairing ip {$lower} to {$upper} ({$cnt['ipcount']} Total)

    "; - - $ipaddress = false; - $update_array = array(); - - $query = $db->simple_select("users", "regip, lastip, uid", "", array('limit_start' => $lower, 'limit' => $ipp)); - while($user = $db->fetch_array($query)) - { - $update_array = array( - 'longregip' => (int)my_ip2long($user['regip']), - 'longlastip' => (int)my_ip2long($user['lastip']) - ); - - $db->update_query("users", $update_array, "uid = '{$user['uid']}'"); - - $update_array = array(); - $ipaddress = true; - } - - $remaining = $upper-$cnt['ipcount']; - if($remaining && $ipaddress) - { - $nextact = "17_dbchanges7"; - $startat = $startat+$ipp; - $contents .= "

    Done. Click Next to move on to the next set of user ips.

    "; - } - else - { - $nextact = "17_redoconfig"; - $contents .= "

    Done

    All user ips have been successfully repaired. Click next to continue.

    "; - } - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer($nextact); -} - -function upgrade17_redoconfig() -{ - global $db, $output, $orig_config, $mybb; - - $config = $orig_config; - - $output->print_header("Rewriting config.php"); - - if(!is_array($config['memcache'])) - { - // Backup our old Config file - @copy(MYBB_ROOT."inc/config.php", MYBB_ROOT."inc/config.backup.php"); - - $fh = @fopen(MYBB_ROOT."inc/config.php", "w"); - if(!$fh) - { - echo "

    Unable to open inc/config.php
    Before the upgrade process can continue, you need to changes the permissions of inc/config.php so it is writable.

    "; - $output->print_footer("17_redoconfig"); - exit; - } - - if(!$config['memcache_host']) - { - $config['memcache_host'] = "localhost"; - } - - if(!$config['memcache_port']) - { - $config['memcache_port'] = 11211; - } - - $comment = ""; - - if(!$db->db_encoding || !$config['database']['encoding']) - { - $comment = " // "; - } - - if(!$config['database']['encoding']) - { - $config['database']['encoding'] = "utf8"; - } - - // Update SQLite selection. SQLite 2 is depreciated. - if($config['database']['type'] == 'sqlite2' || $config['database']['type'] == 'sqlite3') - { - $config['database']['type'] = 'sqlite'; - } - - // Do we have a read or a write database? - if($config['database']['read']) - { - $database_config = "\$config['database']['type'] = '{$config['database']['type']}';"; - foreach(array('read', 'write') as $type) - { - // Multiple read/write databases? - if($config['database'][$type][0]['database']) - { - $i = 0; - foreach($config['database'][$type] as $database_connection) - { - $database_config .= " -\$config['database']['{$type}'][{$i}]['database'] = '{$database_connection['database']}'; -\$config['database']['{$type}'][{$i}]['table_prefix'] = '{$database_connection['table_prefix']}'; -\$config['database']['{$type}'][{$i}]['hostname'] = '{$database_connection['hostname']}'; -\$config['database']['{$type}'][{$i}]['username'] = '{$database_connection['username']}'; -\$config['database']['{$type}'][{$i}]['password'] = '{$database_connection['password']}';"; - ++$i; - } - } - // Just a single database read/write connection - else - { - $database_config .= " -\$config['database']['{$type}']['database'] = '{$config['database'][$type]['database']}'; -\$config['database']['{$type}']['table_prefix'] = '{$config['database'][$type]['table_prefix']}'; - -\$config['database']['{$type}']['hostname'] = '{$config['database'][$type]['hostname']}'; -\$config['database']['{$type}']['username'] = '{$config['database'][$type]['username']}'; -\$config['database']['{$type}']['password'] = '{$config['database'][$type]['password']}';"; - } - } - } - // Standard database connection stuff - else - { - $database_config = "\$config['database']['type'] = '{$config['database']['type']}'; -\$config['database']['database'] = '{$config['database']['database']}'; -\$config['database']['table_prefix'] = '{$config['database']['table_prefix']}'; - -\$config['database']['hostname'] = '{$config['database']['hostname']}'; -\$config['database']['username'] = '{$config['database']['username']}'; -\$config['database']['password'] = '{$config['database']['password']}'; -"; - } - - $configdata = " {$config['log_pruning']['admin_logs']}, // Administrator logs - 'mod_logs' => {$config['log_pruning']['mod_logs']}, // Moderator logs - 'task_logs' => {$config['log_pruning']['task_logs']}, // Scheduled task logs - 'mail_logs' => {$config['log_pruning']['mail_logs']}, // Mail error logs - 'user_mail_logs' => {$config['log_pruning']['user_mail_logs']}, // User mail logs - 'promotion_logs' => {$config['log_pruning']['promotion_logs']} // Promotion logs -); - -?".">"; - fwrite($fh, $configdata); - fclose($fh); - } - echo "

    The configuration file has been successfully rewritten.

    "; - echo "

    Click next to continue with the upgrade process.

    "; - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer("17_updatecss"); -} -function upgrade17_updatecss() -{ - global $db, $output, $orig_config, $mybb; - - if(file_exists(MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php")) - { - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php"; - } - else if(file_exists(MYBB_ROOT."admin/inc/functions_themes.php")) - { - require_once MYBB_ROOT."admin/inc/functions_themes.php"; - } - else - { - $output->print_error("Please make sure your admin directory is uploaded correctly."); - } - - $output->print_header("Updating CSS"); - - $query = $db->simple_select("themestylesheets", "*", "name='global.css' OR name='usercp.css'"); - while($theme = $db->fetch_array($query)) - { - resync_stylesheet($theme); - } - - $query = $db->simple_select("themestylesheets", "*", "name='global.css' OR name='usercp.css'"); - while($theme = $db->fetch_array($query)) - { - $theme['stylesheet'] = upgrade_css_140_to_160($theme['name'], $theme['stylesheet']); - - // Create stylesheets - cache_stylesheet($theme['tid'], $theme['cachefile'], $theme['stylesheet']); - - $update_stylesheet = array( - "stylesheet" => $db->escape_string($theme['stylesheet']), - "lastmodified" => TIME_NOW - ); - $db->update_query("themestylesheets", $update_stylesheet, "sid='{$theme['sid']}'"); - } - - echo "

    The CSS has been successfully updated.

    "; - echo "

    Click next to continue with the upgrade process.

    "; - - global $footer_extra; - //$footer_extra = ""; - - $output->print_footer("17_done"); -} - -function upgrade_css_140_to_160($name, $css) -{ - // Update our CSS to the new stuff in 1.6 - $parsed_css = css_to_array($css); - - if($name == "global.css") - { - if(is_array($parsed_css)) - { - foreach($parsed_css as $class_id => $array) - { - switch($array['class_name']) - { - case '.navigation .active': - $parsed_css[$class_id]['values'] = str_replace('font-size: small;', 'font-size: 13px;', $array['values']); - break; - case '.highlight': - $parsed_css[$class_id]['values'] = str_replace('padding: 3px;', "padding-top: 3px;\n\tpadding-bottom: 3px;", $array['values']); - break; - case '.pm_alert': - case '.red_alert': - $parsed_css[$class_id]['values'] .= "\n\tmargin-bottom: 15px;"; - break; - case '.pagination .pagination_current': - $parsed_css[$class_id]['values'] .= "\n\tcolor: #000;"; - break; - default: - } - } - } - - $to_add = array( - md5('#panel .remember_me input') => array("class_name" => '#panel .remember_me input', "values" => "vertical-align: middle;\n\tmargin-top: -1px;"), - md5('.hiddenrow') => array("class_name" => '.hiddenrow', "values" => 'display: none;'), - md5('.selectall') => array("class_name" => '.selectall', "values" => "background-color: #FFFBD9;\n\tfont-weight: bold;\n\ttext-align: center;"), - md5('.repbox') => array("class_name" => '.repbox', "values" => "font-size:16px;\n\tfont-weight: bold;\n\tpadding:5px 7px 5px 7px;"), - md5('._neutral') => array("class_name" => '._neutral', "values" => "background-color:#FAFAFA;\n\tcolor: #999999;\n\tborder:1px solid #CCCCCC;"), - md5('._minus') => array("class_name" => '._minus', "values" => "background-color: #FDD2D1;\n\tcolor: #CB0200;\n\tborder:1px solid #980201;"), - md5('._plus') => array("class_name" => '._plus', "values" => "background-color:#E8FCDC;\n\tcolor: #008800;\n\tborder:1px solid #008800;"), - md5('.pagination_breadcrumb') => array("class_name" => '.pagination_breadcrumb', "values" => "background-color: #f5f5f5;\n\tborder: 1px solid #fff;\n\toutline: 1px solid #ccc;\n\tpadding: 5px;\n\tmargin-top: 5px;\n\tfont-weight: normal;"), - md5('.pagination_breadcrumb_link') => array("class_name" => '.pagination_breadcrumb_link', "values" => "vertical-align: middle;\n\tcursor: pointer;"), - ); - } - else if($name == "usercp.css") - { - $to_add = array( - md5('.usercp_notepad') => array("class_name" => '.usercp_notepad', "values" => "width: 99%;"), - md5('.usercp_container') => array("class_name" => '.usercp_container', "values" => "margin: 5px;\n\tpadding: 8px;\n\tborder:1px solid #CCCCCC;"), - ); - } - - foreach($to_add as $class_id => $array) - { - if($already_parsed[$class_id]) - { - $already_parsed[$class_id]++; - $class_id .= "_".$already_parsed[$class_id]; - } - else - { - $already_parsed[$class_id] = 1; - } - - $array['name'] = ""; - $array['description'] = ""; - - $parsed_css[$class_id] = $array; - } - - $css = ""; - foreach($parsed_css as $class_id => $array) - { - if($array['name'] || $array['description']) - { - $theme['css'] .= "/* "; - if($array['name']) - { - $array['css'] .= "Name: {$array['name']}"; - - if($array['description']) - { - $array['css'] .= "\n"; - } - } - - if($array['description']) - { - $array['css'] .= "Description: {$array['description']}"; - } - - $array['css'] .= " */\n"; - } - - $css .= "{$array['class_name']} {\n\t{$array['values']}\n}\n"; - } - - return $css; -} - diff --git a/html/forums/install/resources/upgrade18.php b/html/forums/install/resources/upgrade18.php deleted file mode 100644 index a151168..0000000 --- a/html/forums/install/resources/upgrade18.php +++ /dev/null @@ -1,58 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade18_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries...

    "; - - // Update the usergroup sequence for pgSQL - #1094 - if($mybb->config['database']['type'] == "pgsql") - { - $query = $db->simple_select("usergroups", "COUNT(gid) AS group_count"); - $group_count = $db->fetch_field($query, "group_count"); - - ++$group_count; - $db->query("ALTER SEQUENCE ".$mybb->config['database']['table_prefix']."usergroups_gid_seq RESTART WITH ".$group_count.""); - } - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("18_updatecache"); -} - -function upgrade18_updatecache() -{ - global $cache, $output; - - $output->print_header("Updating Cache"); - - echo "

    Updating cache...

    "; - - // Update the Moderator cache - #1200 - $cache->update_moderators(); - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("18_done"); -} diff --git a/html/forums/install/resources/upgrade19.php b/html/forums/install/resources/upgrade19.php deleted file mode 100644 index 3781351..0000000 --- a/html/forums/install/resources/upgrade19.php +++ /dev/null @@ -1,24 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do for 1.6.1 and 1.6.2 */ - diff --git a/html/forums/install/resources/upgrade2.php b/html/forums/install/resources/upgrade2.php deleted file mode 100644 index df32b86..0000000 --- a/html/forums/install/resources/upgrade2.php +++ /dev/null @@ -1,289 +0,0 @@ - 1, - "revert_all_themes" => 1, - "revert_all_settings" => 1, - "requires_deactivated_plugins" => 1, -); - -function upgrade2_dbchanges() -{ - global $db, $output; - - $output->print_header("Database Changes since Release Candidate 3"); - - $contents .= "

    Making necessary database modifications..."; - - $db->drop_table("badwords"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."badwords ( - bid smallint(6) NOT NULL auto_increment, - badword varchar(100) NOT NULL, - replacement varchar(100) NOT NULL, - PRIMARY KEY(bid) - );"); - - if($db->field_exists("icon", "attachtypes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachtypes DROP icon;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachtypes ADD icon varchar(100) NOT NULL;"); - - $db->delete_query("attachtypes"); - - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (1, 'Zip File', 'application/zip', 'zip', 1024, 'images/attachtypes/zip.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (2, 'JPEG Image', 'image/jpeg', 'jpg', 500, 'images/attachtypes/image.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (3, 'Text Document', 'text/plain', 'txt', 200, 'images/attachtypes/txt.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (4, 'GIF Image', 'image/gif', 'gif', 500, 'images/attachtypes/image.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (6, 'PHP File', 'application/octet-stream', 'php', 500, 'images/attachtypes/php.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (7, 'PNG Image', 'image/png', 'png', 500, 'images/attachtypes/image.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (8, 'Microsoft Word Document', 'application/msword', 'doc', 1024, 'images/attachtypes/doc.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (9, '', 'application/octet-stream', 'htm', 100, 'images/attachtypes/html.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (10, '', 'application/octet-stream', 'html', 100, 'images/attachtypes/html.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (11, '', 'image/jpeg', 'jpeg', 500, 'images/attachtypes/image.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (12, '', 'application/x-gzip', 'gz', 1024, 'images/attachtypes/tgz.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (13, '', 'application/x-tar', 'tar', 1024, 'images/attachtypes/tar.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (14, '', 'text/css', 'css', 100, 'images/attachtypes/css.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (15, '', 'application/pdf', 'pdf', 2048, 'images/attachtypes/pdf.gif');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (16, '', 'image/bmp', 'bmp', 500, 'images/attachtypes/image.gif');"); - - if($db->field_exists("outerwidth", "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP outerwidth;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes ADD outerwidth varchar(15) NOT NULL;"); - - if($db->field_exists("icon", "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP icon;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes ADD outercolor varchar(15) NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes CHANGE body bodybgcolor varchar(15) NOT NULL;"); - - if($db->field_exists("bodybgimage", "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP bodybgimage;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes ADD bodybgimage varchar(100) NOT NULL default '' AFTER bodybgcolor;"); - - if($db->field_exists("bodybgimageattributes", "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP bodydbimageattributes;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes ADD bodybgimageattributes varchar(100) NOT NULL default '' AFTER bodybgimage;"); - - - $db->write_query("UPDATE ".TABLE_PREFIX."themes SET outerwidth='0', bodybgcolor='#e3e3e3', bodybgimage='images/Light/logo_bg.png', bodybgimageattributes='repeat-x'"); - - $db->drop_table("regimages"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."regimages ( - imagehash varchar(32) NOT NULL, - imagestring varchar(8) NOT NULL, - dateline bigint(30) NOT NULL - );"); - - $db->write_query("UPDATE ".TABLE_PREFIX."adminoptions SET cpstyle=''"); - - if($db->field_exists("language", "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP language;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD language varchar(50) NOT NULL;"); - - if($db->field_exists("timeonline", "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP timeonline;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD timeonline bigint(30) NOT NULL default '0';"); - - if($db->field_exists("showcodebuttons", "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."user DROP showcodebuttons;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD showcodebuttons int(1) NOT NULL default '1';"); - - $db->write_query("UPDATE ".TABLE_PREFIX."users SET language='english', showcodebuttons=1"); - - if($db->field_exists("oldgroup", "awaitingactivation")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."awaitingactivation DROP oldgroup;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."awaitingactivation ADD oldgroup bigint(30) NOT NULL;"); - - if($db->field_exists("misc", "awaitingactivation")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."awaitingactivation DROP misc;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."awaitingactivation ADD misc varchar(255) NOT NULL;"); - - $db->write_query("DELETE FROM ".TABLE_PREFIX."awaitingactivation WHERE type='e'"); - - $db->drop_table("settings"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."settings ( - sid smallint(6) NOT NULL auto_increment, - name varchar(120) NOT NULL default '', - title varchar(120) NOT NULL default '', - description text NOT NULL, - optionscode text NOT NULL, - value text NOT NULL, - disporder smallint(6) NOT NULL default '0', - gid smallint(6) NOT NULL default '0', - PRIMARY KEY (sid) - );"); - - $db->drop_table("reportedposts"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."reportedposts ( - rid smallint(6) NOT NULL auto_increment, - pid smallint(6) NOT NULL, - tid smallint(6) NOT NULL, - fid smallint(6) NOT NULL, - uid smallint(6) NOT NULL, - reportstatus int(1) NOT NULL, - reason varchar(250) NOT NULL, - dateline bigint(30) NOT NULL, - PRIMARY KEY (rid) - );"); - - $db->drop_table("threadsread"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."threadsread ( - tid smallint(6) NOT NULL, - uid smallint(6) NOT NULL, - dateline int(10) NOT NULL, - UNIQUE KEY tiduid (tid, uid) - );"); - $contents .= "done

    "; - - $output->print_contents("$contents

    Please click next to continue with the upgrade process.

    "); - $output->print_footer("2_dbchanges2"); -} - -function upgrade2_dbchanges2() -{ - global $db, $output; - - $output->print_header("Database Changes since Release Candidate 3"); - $contents .= "

    Reinserting settings..."; - - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'boardclosed', 'Board Closed', 'If you need to close your forums to make some changes or perform an upgrade, this is the global switch. Viewers will not be able to view your forums, however, they will see a message with the reason you specify below.
    \r\n
    \r\nAdministrators will still be able to view the forums.', 'yesno', 'no', 1, 26);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'boardclosed_reason', 'Board Closed Reason', 'If your forum is closed, you can set a message here that your visitors will be able to see when they visit your forums.', 'textarea', 'These forums are currently closed for maintenance. Please check back later.', 2, 26);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'bbname', 'Board Name', 'The name of your message boards. We recommend that it is not over 75 characters.', 'text', 'MyBB Forums', 1, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'bburl', 'Board URL', 'The url to your forums.
    Include the http://. Do NOT include a trailing slash.', 'text', '', 2, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'homename', 'Homepage Name', 'The name of your homepage. This will appear in the footer with a link to it.', 'text', 'MyBB', 3, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'homeurl', 'Homepage URL', 'The full URL of your homepage. This will be linked to in the footer along with its name.', 'text', 'https://mybb.com', 4, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'dateformat', 'Date Format', 'The format of the dates used on the forum. This format uses the PHP date() function. We recommend not changing this unless you know what you\'re doing.', 'text', 'm-d-Y', 1, 3);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'adminemail', 'Admin Email', 'The administrator\'s email address. This will be used for outgoing emails sent via the forums.', 'text', '', 5, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'timeformat', 'Time Format', 'The format of the times used on the forum. This format uses PHP\'s date() function. We recommend not changing this unless you know what you\'re doing.', 'text', 'h:i A', 2, 3);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'threadsperpage', 'Threads Per Page', '', 'text', '20', 1, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'stickyprefix', 'Sticky Threads Prefix', 'The prefix of topics which have been made sticky by a moderator or administrator.', 'text', 'Sticky:', 2, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'hottopic', 'Replys For Hot Topic', 'The number of replies that is needed for a topic to be considered \'hot\'.', 'text', '20', 3, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'cookiedomain', 'Cookie Domain', 'The domain which cookies should be set to. This can remain blank. It should also start with a . so it covers all subdomains.', 'text', '', 8, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'cookiepath', 'Cookie Path', 'The path which cookies are set to, we recommend setting this to the full directory path to your forums with a trailing slash.', 'text', '', 9, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'pollprefix', 'Poll Prefix', 'The prefix on forum display which contain polls.', 'text', 'Poll:', 4, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'postsperpage', 'Posts Per Page:', 'The number of posts to display per page. We recommend its not higher than 20 for people with slower connections.', 'text', '10', 1, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'regdateformat', 'Registered Date Format', 'The format used on showthread where it shows when the user registered.', 'text', 'M Y', 3, 3);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'sigmycode', 'Allow MyCode in Signatures', 'Do you want to allow MyCode to be used in users\' signatures?', 'yesno', 'yes', 1, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'sigsmilies', 'Allow Smilies in Signatures', 'Do you want to allow smilies to be used in users\' signatures?', 'yesno', 'yes', 3, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'sightml', 'Allow HTML in Signatures', 'Do you want to allow HTML to be used in users\' signatures?', 'yesno', 'no', 4, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'sigimgcode', 'Allow [img] Code in Signatures', 'Do you want to allow [img] code to be used in users\' signatures?', 'yesno', 'yes', 5, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'quoteboxstyle', 'Fancy Quote Boxes', 'Selecting yes will cause quotes to be in a table and look more professional. Selecting no will show quotes in the traditional way.', 'yesno', 'yes', 1, 10);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'codeboxstyle', 'Fancy Code Boxes', 'Selecting yes will cause code to be in a table and look more professional. Selecting no will show code in the traditional way.', 'yesno', 'yes', 2, 10);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'threadusenetstyle', 'Usenet Style Thread View', 'Selecting yes will cause posts to look similar to how posts look in USENET. No will cause posts to look the modern way.', 'yesno', 'no', 4, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'pmsallowhtml', 'Allow HTML', 'Selecting yes will allow HTML to be used in private messages.', 'yesno', 'no', 1, 11);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'pmsallowmycode', 'Allow MyCode', 'Selecting yes will allow MyCode to be used in private messages.', 'yesno', 'yes', 2, 11);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'pmsallowsmilies', 'Allow Smilies', 'Selecting yes will allow Smilies to be used in private messages.', 'yesno', 'yes', 3, 11);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'pmsallowimgcode', 'Allow [img] Code', 'Selecting yes will allow [img] Code to be used in private messages.', 'yesno', 'yes', 4, 11);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'siglength', 'Length limit in Signatures', 'The maximum number of characters a user can place in a signature.', 'text', '255', 6, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'messagelength', 'Maximum Message Length', 'The maximum number of characters to allow in a message. A setting of 0 allows an unlimited length.', 'text', '0', 1, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'membersperpage', 'Members Per Page', 'The number of members to show per page on the member list.', 'text', '20', 1, 12);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'load', '*NIX Load Limiting', 'Limit the maximum server load before myBB rejects people. 0 for none. Recommended limit is 5.0.', 'text', '0', 5, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'emailkeep', 'Users Keep Email', 'If a current user has an email already registered in your banned list, should he be allowed to keep it.', 'yesno', 'no', 4, 14);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'ipban', 'Ban by IP', 'Here, you may specify IP addresses or a range of IP addresses. You must separate each IP with a space.', 'textarea', '', 2, 14);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'emailban', 'Ban by Email', 'You may specify specific email addresses to ban, or you may specify a domain. You must separate email addresses and domains with a space.', 'textarea', '', 3, 14);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'avatarsize', 'Max Uploaded Avatar Size', 'Maximum file size (in kilobytes) of uploaded avatars.', 'text', '10', 8, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'avatardir', 'Avatar Directory', 'The directory where your avatars are stored. These are used in the avatar list in the User CP.', 'text', 'images/avatars', 7, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showeditedby', 'Show \'edited by\' Messages', 'Once a post is edited by a regular user, do you want to show the edited by message?', 'yesno', 'yes', 6, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxposts', 'Maximum Posts Per Day', 'This is the total number of posts allowed per user per day. 0 for unlimited.', 'text', '0', 2, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showeditedbyadmin', 'Show \'edited by\' Message for Forum Staff', 'Do you want to show edited by messages for forum staff when they edit their posts?', 'yesno', 'yes', 7, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'bannedusernames', 'Banned Usernames', 'Ban users from registering certain usernames. Seperate them with a space.', 'textarea', 'drcracker Oops! hmmm', 1, 14);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxpolloptions', 'Maximum Number of Poll Options', 'The maximum number of options for polls that users can post.', 'text', '10', 3, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'dotfolders', 'Use \'dot\' Icons', 'Do you want to show dots on the thread indicators of threads users have participated in.', 'yesno', 'yes', 8, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'contactlink', 'Contact Us Link', 'This will be used for the Contact Us link on the bottom of all the forum pages. Can either be an email address (using mailto:email@website.com) or a hyperlink.', 'text', 'mailto:contact@mybb.com', 6, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showdescriptions', 'Show Forum Descriptions?', 'This option will allow you to turn off showing the descriptions for forums.', 'yesno', 'yes', 1, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showbirthdays', 'Show Today\'s Birthdays?', 'Do you want to show today\'s birthdays on the forum homepage?', 'yesno', 'yes', 2, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showwol', 'Show Who\'s Online?', 'Display the currently active users on the forum home page.', 'yesno', 'yes', 4, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'hideprivateforums', 'Hide Private Forums?', 'You can hide private forums by turning this option on. This option also hides forums on the forum jump and all subforums.', 'yesno', 'yes', 3, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showsimilarthreads', 'Show \'Similar Threads\' Table', 'The Similar Threads table shows threads that are relevant to the thread being read. You can set the relevancy below.', 'yesno', 'no', 5, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'similarityrating', 'Similar Threads Relevancy Rating', 'This allows you to limit similar threads to ones more relevant (0 being not relevant). This number should not be over 10 and should not be set low (<5) for large forums.', 'text', '1', 7, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'similarlimit', 'Similar Threads Limit', 'Here you can change the total amount of similar threads to be shown in the similar threads table. It is recommended that it is not over 15 for 56k users.', 'text', '10', 8, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'privateeventcolor', 'Private Events Color', 'The color that private events will be shown in on the main calendar page.', 'text', 'red', 2, 17);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'publiceventcolor', 'Public Events Color', 'The color that public events will be shown in on the main calendar page.', 'text', 'green', 1, 17);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'movedprefix', 'Moved Threads Prefix', 'The prefix that threads that have been moved to another forum should have.', 'text', 'Moved:', 5, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'hottopicviews', 'Views For Hot Topic', 'The number of views a thread can have before it is considered \'hot\'.', 'text', '150', 7, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'logip', 'Log Posting IP Addresses', 'Do you wish to log ip addresses of users who post, and who you want to show ip addresses to.', 'radio\r\nno=Do not log IP\r\nhide=Show to Admins & Mods\r\nshow=Show to all Users', 'hide', 3, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'statslimit', 'Stats Limit', 'The number of threads to show on the stats page for most replies and most views.', 'text', '15', 10, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'modlist', 'Forums\' Moderator Listing', 'Here you can turn on or off the listing of moderators for each forum on index.php and forumdisplay.php', 'onoff', 'on', 5, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'smilieinserter', 'Clickable Smilies Inserter', 'Clickable smilies will appear on the posting pages if this option is set to \'on\'.', 'onoff', 'on', 1, 20);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'smilieinsertertot', 'No. of Smilies to show', 'Enter the total number of smilies to show on the clickable smilie inserter.', 'text', '20', 2, 20);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'smilieinsertercols', 'No. of Smilie Cols to Show', 'Enter the number of columns you wish to show on the clickable smilie inserter.', 'text', '4', 3, 20);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showindexstats', 'Show Small Stats Section', 'Do you want to show the total number of threads, posts, members, and the last member on the forum home?', 'yesno', 'yes', 6, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'regtype', 'Registration Method', 'Please select the method of registration to use when users register.', 'select\r\ninstant=Instant Activation\r\nverify=Send Email Verification\r\nrandompass=Send Random Password', 'verify', 1, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'userpppoptions', 'User Selectable Posts Per Page', 'If you would like to allow users to select how many posts are shown per page in a thread, enter the options they should be able to select separated with commas. If this is left blank they will not be able to choose how many posts are shown per page.', 'text', '5,10,20,25,30,40,50', 2, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'usertppoptions', 'User Selectable Threads Per Page', 'If you would like to allow users to select how many threads per page are shown in a forum, enter the options they should be able to select separated with commas. If this is left blank they will not be able to choose how many threads are shown per page.', 'text', '10,20,25,30,40,50', 6, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'wolcutoffmins', 'Cut-off Time (mins)', 'The number of minutes before a user is marked offline. Recommended: 15.', 'text', '15', 1, 23);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'postfloodcheck', 'Post Flood Checking', 'Set to on if you want to enable flood checking for posts. Specifiy the time between posts below.', 'onoff', 'on', 4, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'postfloodsecs', 'Post Flood Time', 'Set the time (in seconds) users have to wait between posting, to be in effect; the option above must be on.', 'text', '60', 5, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'gzipoutput', 'Use GZip Page Compression?', 'Do you want to compress pages in GZip format when they are sent to the browser? This means quicker downloads for your visitors, and less traffic usage for you. The level of the compression is set by the server\'s load.', 'yesno', 'yes', 1, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'standardheaders', 'Send Standard Headers', 'With some web servers, this option can cause problems; with others, it is needed. ', 'yesno', 'no', 2, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'nocacheheaders', 'Send No Cache Headers', 'With this option you can prevent caching of the page by the browser.', 'yesno', 'no', 3, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxpostimages', 'Maximum Images per Post', 'Enter the maximum number of images (including smilies) a user can put in their post. Set to 0 to disable this.', 'text', '10', 8, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxsigimages', 'Maximum Number of Images per Signature', 'Enter the maximum number of images (including smilies) a user can put in their signature. Set to 0 to disable this.', 'text', '2', 2, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'browsingthisforum', 'Users Browsing this Forum', 'Here you can turn off the \'users browsing this forum\' feature.', 'onoff', 'on', 9, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'usereferrals', 'Use Referrals System', 'Do you want to use the user referrals system on these forums?', 'yesno', 'yes', 3, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'subscribeexcerpt', 'Amount of Characters for Subscription Previews', 'How many characters of the post do you want to send with the email notification of a new reply.', 'text', '100', 9, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'cpstyle', 'Control Panel Style', 'The Default style that the control panel will use. Styles are inside the styles folder. A folder name inside that folder becomes the style title and style.css inside the style title folder is the css style file.', 'cpstyle', 'Axiom', 2, 28);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'cplanguage', 'Control Panel Language', 'The language of the control panel.', 'adminlanguage', 'english', 1, 28);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'minnamelength', 'Minimum Username Length', 'The minimum number of characters a username can be when a user registers.', 'text', '3', 5, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxnamelength', 'Maximum Username Length', 'The maximum number of characters a username can be when a user registers.', 'text', '30', 6, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'redirects', 'Friendly Redirection Pages', 'This will enable friendly redirection pages instead of bumping the user directly to the page.', 'onoff', 'on', 4, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'betweenregstime', 'Time Between Registrations', 'The amount of time (in hours) to disallow registrations for users who have already registered an account under the same ip address.', 'text', '24', 2, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxregsbetweentime', 'Maximum Registrations Per IP Address', 'This option allows you to set the maximum amount of times a certain user can register within the timeframe specified above.', 'text', '2', 4, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showstats', 'Show forum statistics', 'Do you want to show the total number of posts, threads, members and the last registered member on the portal page?', 'yesno', 'yes', 5, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showpms', 'Show the number of PMs to users', 'Do you want to show the number of private messages the current user has in their pm system.', 'yesno', 'yes', 4, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showwelcome', 'Show the Welcome box', 'Do you want to show the welcome box to visitors / users.', 'yesno', 'yes', 3, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_numannouncements', 'Number of announcements to show', 'Please enter the number of announcements to show on the main page.', 'text', '10', 2, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showstats', 'Show forum statistics', 'Do you want to show the total number of posts, threads, members and the last registered member on the portal page?', 'yesno', 'yes', 5, 29);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showwol', 'Show Whos Online', 'Do you want to show the \'whos online\' information to users when they visit the portal page?', 'yesno', 'yes', 6, 29);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_announcementsfid', 'Forum ID to pull announcements from', 'Please enter the forum id (fid) of the forum you wish to pull the announcements from', 'text', '1', 1, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showdiscussionsnum', 'Number of latest discussions to show', 'Please enter the number of current forum discussions to show on the portal page.', 'text', '10', 8, 29);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showwol', 'Show Who\'s Online', 'Do you want to show the \'Who\'s online\' information to users when they visit the portal page?', 'yesno', 'yes', 6, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showsearch', 'Show Search Box', 'Do you want to show the search box, allowing users to quickly search the forums on the portal?', 'yesno', 'yes', 7, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showdiscussions', 'Show Latest Discussions', 'Do you wish to show the current forum discussions on the portal page?', 'yesno', 'yes', 8, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showdiscussionsnum', 'Number of latest discussions to show', 'Please enter the number of current forum discussions to show on the portal page.', 'text', '10', 9, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'attachthumbh', 'Attached Thumbnail Maximum Height', 'Enter the width that attached thumbnails should be generated at.', 'text', '60', 12, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'attachthumbw', 'Attached Thumbnail Maximum Width', 'Enter the width that attached thumbnails should be generated at.', 'text', '60', 13, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxattachments', 'Maximum Attachments Per Post', 'THe maximum number of attachments a user is allowed to upload per post.', 'text', '5', 10, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'attachthumbnails', 'Show Attached Thumbnails in Posts', 'Do you want to show the generated thumbnails for attached images inside the posts?', 'yesno', 'yes', 11, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'polloptionlimit', 'Maximum Poll Option Length', 'The maximum length that each poll option can be. (Set to 0 to disable).', 'text', '250', 1, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'timezoneoffset', 'Default Timezone Offset', 'Here you can set the default timezone offset for guests and members using the default offset.', 'text', '+10', 4, 3);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'bblanguage', 'Default Language', 'The default language that MyBB should use for guests and for users without a selected language in their user control panel.', 'language', 'english', 7, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'regimage', 'Antispam Registration Image', 'If yes, and GD is installed, an image will be shown during registration where users are required to enter the text contained within the image to continue with registration.', 'onoff', 'on', 1, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'reportmethod', 'Reported Posts Medium', 'Please select from the list how you want reported posts to be dealt with. Storing them in the database is probably the better of the options listed.', 'radio\r\ndb=Stored in the Database\r\npms=Sent as Private Messages\r\nemail=Sent via Email', 'db', 1, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'threadreadcut', 'Read Threads in Database (Days)', 'The number of days that you wish to keep thread read information in the database. For large boards, we do not recommend a high number as the board will become slower. Set to 0 to disable.', 'text', '7', 3, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'announcementlimit', 'Announcements Limit', 'The number of forum announcements to show in the thread listing on the forum display pages. Set to 0 to show all active announcements.', 'text', '2', 10, 7);"); - - $output->print_contents("$contents

    Please click next to continue with the upgrade process.

    "); - $output->print_footer("2_done"); -} diff --git a/html/forums/install/resources/upgrade20.php b/html/forums/install/resources/upgrade20.php deleted file mode 100644 index b3fd3be..0000000 --- a/html/forums/install/resources/upgrade20.php +++ /dev/null @@ -1,51 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade20_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Repairing Database Sequences"); - - echo "

    Performing necessary upgrade queries...

    "; - - // Update the sequences for pgSQL - #1094, #1248 - if($mybb->config['database']['type'] == "pgsql") - { - $db->query("SELECT setval('{$mybb->config['database']['table_prefix']}attachtypes_atid_seq', (SELECT max(atid) FROM {$mybb->config['database']['table_prefix']}attachtypes));"); - $db->query("SELECT setval('{$mybb->config['database']['table_prefix']}forums_fid_seq', (SELECT max(fid) FROM {$mybb->config['database']['table_prefix']}forums));"); - $db->query("SELECT setval('{$mybb->config['database']['table_prefix']}helpdocs_hid_seq', (SELECT max(hid) FROM {$mybb->config['database']['table_prefix']}helpdocs));"); - $db->query("SELECT setval('{$mybb->config['database']['table_prefix']}helpsections_sid_seq', (SELECT max(sid) FROM {$mybb->config['database']['table_prefix']}helpsections));"); - $db->query("SELECT setval('{$mybb->config['database']['table_prefix']}icons_iid_seq', (SELECT max(iid) FROM {$mybb->config['database']['table_prefix']}icons));"); - $db->query("SELECT setval('{$mybb->config['database']['table_prefix']}profilefields_fid_seq', (SELECT max(fid) FROM {$mybb->config['database']['table_prefix']}profilefields));"); - $db->query("SELECT setval('{$mybb->config['database']['table_prefix']}smilies_sid_seq', (SELECT max(sid) FROM {$mybb->config['database']['table_prefix']}smilies));"); - $db->query("SELECT setval('{$mybb->config['database']['table_prefix']}spiders_sid_seq', (SELECT max(sid) FROM {$mybb->config['database']['table_prefix']}spiders));"); - $db->query("SELECT setval('{$mybb->config['database']['table_prefix']}templategroups_gid_seq', (SELECT max(gid) FROM {$mybb->config['database']['table_prefix']}templategroups));"); - $db->query("SELECT setval('{$mybb->config['database']['table_prefix']}usergroups_gid_seq', (SELECT max(gid) FROM {$mybb->config['database']['table_prefix']}usergroups));"); - } - - $db->add_column("adminviews", "custom_profile_fields", "text NOT NULL AFTER conditions"); - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("20_done"); -} - diff --git a/html/forums/install/resources/upgrade21.php b/html/forums/install/resources/upgrade21.php deleted file mode 100644 index 0193e69..0000000 --- a/html/forums/install/resources/upgrade21.php +++ /dev/null @@ -1,104 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade21_dbchanges() -{ - global $cache, $db, $output, $mybb; - - $output->print_header("Updating Database"); - - echo "

    Performing necessary upgrade queries...

    "; - - $db->delete_query("settings", "name = 'standardheaders'"); - - if($db->field_exists('showinbirthdaylist', 'usergroups')) - { - $db->drop_column("usergroups", "showinbirthdaylist"); - } - - if($db->field_exists('canoverridepm', 'usergroups')) - { - $db->drop_column("usergroups", "canoverridepm"); - } - - if($db->field_exists('canusesig', 'usergroups')) - { - $db->drop_column("usergroups", "canusesig"); - } - - if($db->field_exists('canusesigxposts', 'usergroups')) - { - $db->drop_column("usergroups", "canusesigxposts"); - } - - if($db->field_exists('signofollow', 'usergroups')) - { - $db->drop_column("usergroups", "signofollow"); - } - - if($db->field_exists('postnum', 'profilefields')) - { - $db->drop_column("profilefields", "postnum"); - } - - switch($db->type) - { - case "pgsql": - case "sqlite": - $db->add_column("profilefields", "postnum", "bigint NOT NULL default '0'"); - $db->add_column("usergroups", "showinbirthdaylist", "int NOT NULL default '0'"); - $db->add_column("usergroups", "canoverridepm", "int NOT NULL default '0'"); - $db->add_column("usergroups", "canusesig", "int NOT NULL default '0'"); - $db->add_column("usergroups", "canusesigxposts", "bigint NOT NULL default '0'"); - $db->add_column("usergroups", "signofollow", "int NOT NULL default '0'"); - break; - default: - $db->add_column("profilefields", "postnum", "bigint(30) NOT NULL default '0'"); - $db->add_column("usergroups", "showinbirthdaylist", "int(1) NOT NULL default '0'"); - $db->add_column("usergroups", "canoverridepm", "int(1) NOT NULL default '0'"); - $db->add_column("usergroups", "canusesig", "int(1) NOT NULL default '0'"); - $db->add_column("usergroups", "canusesigxposts", "bigint(30) NOT NULL default '0'"); - $db->add_column("usergroups", "signofollow", "int(1) NOT NULL default '0'"); - break; - } - - // Update all usergroups to show in the birthday list - $db->update_query("usergroups", array("showinbirthdaylist" => 1)); - - // Update our nice usergroups to use a signature - $groups = $cache->read("usergroups"); - - foreach($groups as $group) - { - $disallowed_array = array(1, 5, 7); - if(in_array($group['gid'], $disallowed_array) || $group['isbannedgroup'] == 1) - { - continue; - } - - $db->update_query("usergroups", array("canusesig" => 1), "gid = '{$group['gid']}'"); - } - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("21_done"); -} - diff --git a/html/forums/install/resources/upgrade22.php b/html/forums/install/resources/upgrade22.php deleted file mode 100644 index 7ab55a5..0000000 --- a/html/forums/install/resources/upgrade22.php +++ /dev/null @@ -1,25 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do for 1.6.5 */ - diff --git a/html/forums/install/resources/upgrade23.php b/html/forums/install/resources/upgrade23.php deleted file mode 100644 index 338ab79..0000000 --- a/html/forums/install/resources/upgrade23.php +++ /dev/null @@ -1,58 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade23_dbchanges() -{ - global $db, $output; - - $output->print_header("Updating Database"); - echo "

    Performing necessary upgrade queries...

    "; - - if($db->field_exists('canusecustomtools', 'moderators')) - { - $db->drop_column('moderators', 'canusecustomtools'); - } - - if($db->field_exists('cansendemailoverride', 'usergroups')) - { - $db->drop_column('usergroups', 'cansendemailoverride'); - } - - switch($db->type) - { - case "pgsql": - case "sqlite": - $db->add_column('moderators', 'canusecustomtools', "int NOT NULL default '0'"); - $db->add_column('usergroups', 'cansendemailoverride', "int NOT NULL default '0'"); - break; - default: - $db->add_column('moderators', 'canusecustomtools', "int(1) NOT NULL default '0'"); - $db->add_column('usergroups', 'cansendemailoverride', "int(1) NOT NULL default '0'"); - break; - } - - $db->update_query('moderators', array('canusecustomtools' => 1), "canmanagethreads = '1'"); - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("23_done"); -} diff --git a/html/forums/install/resources/upgrade24.php b/html/forums/install/resources/upgrade24.php deleted file mode 100644 index f7b431c..0000000 --- a/html/forums/install/resources/upgrade24.php +++ /dev/null @@ -1,23 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do for 1.6.7 */ diff --git a/html/forums/install/resources/upgrade25.php b/html/forums/install/resources/upgrade25.php deleted file mode 100644 index e460bf5..0000000 --- a/html/forums/install/resources/upgrade25.php +++ /dev/null @@ -1,23 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do for 1.6.8 */ diff --git a/html/forums/install/resources/upgrade26.php b/html/forums/install/resources/upgrade26.php deleted file mode 100644 index 45177da..0000000 --- a/html/forums/install/resources/upgrade26.php +++ /dev/null @@ -1,55 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade26_dbchanges() -{ - global $db, $output; - - $output->print_header("Updating Database"); - echo "

    Performing necessary upgrade queries...

    "; - - $db->update_query("helpdocs", array('usetranslation' => 1)); - $db->update_query("helpsections", array('usetranslation' => 1)); - - if($db->type == 'pgsql') - { - $db->modify_column("polls", "numvotes", "text", "set"); - } - else - { - $db->modify_column("polls", "numvotes", "text NOT NULL"); - } - - if($db->field_exists('failedlogin', 'users')) - { - $db->drop_column("users", "failedlogin"); - } - - // We don't need the posthash after the post is inserted into the database - $db->update_query('attachments', "posthash=''", 'pid!=0'); - - // Column will be dropped in MyBB 1.8 - $db->update_query('posts', "posthash=''"); - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("26_done"); -} diff --git a/html/forums/install/resources/upgrade27.php b/html/forums/install/resources/upgrade27.php deleted file mode 100644 index 60fc489..0000000 --- a/html/forums/install/resources/upgrade27.php +++ /dev/null @@ -1,24 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - - -/* Nothing to do for 1.6.10 */ diff --git a/html/forums/install/resources/upgrade28.php b/html/forums/install/resources/upgrade28.php deleted file mode 100644 index 21fe166..0000000 --- a/html/forums/install/resources/upgrade28.php +++ /dev/null @@ -1,23 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do for 1.6.11 or 1.6.12 */ diff --git a/html/forums/install/resources/upgrade29.php b/html/forums/install/resources/upgrade29.php deleted file mode 100644 index 179786c..0000000 --- a/html/forums/install/resources/upgrade29.php +++ /dev/null @@ -1,24 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do for 1.6.13 */ - diff --git a/html/forums/install/resources/upgrade3.php b/html/forums/install/resources/upgrade3.php deleted file mode 100644 index 34e7d4d..0000000 --- a/html/forums/install/resources/upgrade3.php +++ /dev/null @@ -1,826 +0,0 @@ - 1, - "revert_all_themes" => 1, - "revert_all_settings" => 1, - "requires_deactivated_plugins" => 1, -); - -@set_time_limit(0); - -function upgrade3_dbchanges() -{ - global $db, $output; - - $output->print_header("Attachment Conversion to Files"); - - $contents = "

    The first step of the upgrade process from RC4 is to move your attachments and avatars to the file system.

    "; - - if(!@is_dir("../uploads/")) - { - $errors = "

    ../uploads/ Does not exist in your forums' directory. Please create this directory."; - } - else - { - if(!@is_writable("../uploads/")) - { - @my_chmod("../uploads", '0777'); - if(!@is_writable("../uploads/")) - { - $errors = "

    ../uploads/ is not writable! Please chmod this directory so it's writable (766 or 777)."; - } - } - } - if(!@is_dir("../uploads/avatars/")) - { - $errors .= "

    ../uploads/avatars/ Does not exist. Please create this directory."; - } - else - { - if(!@is_writable("../uploads/avatars/")) - { - @my_chmod("../uploads/avatars/", '0777'); - if(!is_writable("../uploads/avatars/")) - { - $errors = "

    ../uploads/avatars/ is not writable! Please chmod this directory so it's writable (766 or 777)."; - } - } - } - - if($errors) - { - $output->print_contents($contents."

    To be able to do this you must perform the following:

    $errors"); - $output->print_footer("3_dbchanges"); - exit; - } - - $contents .= "

    Okay, we've determined that the specified directory settings have been met.

    If you wish to change the number of attachments to process per page then you can do so below.

    "; - $contents .= "

    Attachments Per Page:

    "; - $contents .= "

    Once you're ready, press next to begin the conversion.

    "; - - $output->print_contents($contents); - $output->print_footer("3_convertattachments"); -} - -function upgrade3_convertattachments() -{ - global $db, $output, $settings; - - $output->print_header("Attachment Conversion to Files"); - - if(!$_POST['attachmentspage']) - { - $app = 50; - } - else - { - $app = (int)$_POST['attachmentspage']; - } - - if($_POST['attachmentstart']) - { - $startat = (int)$_POST['attachmentstart']; - $upper = $startat+$app; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $app; - $lower = 1; - } - - require_once MYBB_ROOT."inc/settings.php"; - - $query = $db->simple_select("attachments", "COUNT(aid) AS attachcount"); - $cnt = $db->fetch_array($query); - - $contents .= "

    Converting attachments $lower to $upper (".$cnt['attachcount']." Total)

    "; - echo "

    Converting attachments $lower to $upper (".$cnt['attachcount']." Total)

    "; - - if($db->field_exists("uid", "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP uid;"); - } - // Add uid column - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments ADD uid smallint(6) NOT NULL AFTER posthash;"); - - - if($db->field_exists("thumbnail", "attachments")) - { - // Drop thumbnail column - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP thumbnail"); - } - - if($db->field_exists("thumbnail", "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP thumbnail;"); - } - // Add thumbnail column - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments ADD thumbnail varchar(120) NOT NULL;"); - - if($db->field_exists("attachname", "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP attachname;"); - } - // Add attachname column - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments ADD attachname varchar(120) NOT NULL AFTER filesize;"); - - if(!$db->field_exists("donecon", "attachments")) - { - // Add temporary column - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments ADD donecon smallint(1) NOT NULL;"); - } - - $query = $db->query(" - SELECT a.*, p.uid AS puid, p.dateline - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - WHERE a.donecon != '1' - ORDER BY a.aid ASC LIMIT {$app} - "); - while($attachment = $db->fetch_array($query)) - { - $filename = "post_".$attachment['puid']."_".$attachment['dateline'].$attachment['aid'].".attach"; - $ext = my_strtolower(my_substr(strrchr($attachment['filename'], "."), 1)); - $fp = fopen("../uploads/".$filename, "wb"); - if(!$fp) - { - die("Unable to create file. Please check permissions and refresh page."); - } - fwrite($fp, $attachment['filedata']); - fclose($fp); - unset($attachment['filedata']); - if($ext == "gif" || $ext == "png" || $ext == "jpg" || $ext == "jpeg" || $ext == "jpe") - { - require_once MYBB_ROOT."inc/functions_image.php"; - $thumbname = str_replace(".attach", "_thumb.$ext", $filename); - $thumbnail = generate_thumbnail("../uploads/".$filename, "../uploads", $thumbname, $settings['attachthumbh'], $settings['attachthumbw']); - if($thumbnail['code'] == 4) - { - // Image was too small - fake a filename - $thumbnail['filename'] = "SMALL"; - } - } - $db->write_query("UPDATE ".TABLE_PREFIX."attachments SET attachname='".$filename."', donecon='1', uid='".$attachment['puid']."', thumbnail='".$thumbnail['filename']."' WHERE aid='".$attachment['aid']."'"); - unset($thumbnail); - } - - echo "

    Done.

    "; - $query = $db->simple_select("attachments", "COUNT(aid) AS attachrem", "donecon != '1'"); - $cnt = $db->fetch_array($query); - - if($cnt['attachrem'] != 0) - { - $nextact = "3_convertattachments"; - $startat = $startat+$app; - $contents .= "

    Done. Click Next to move on to the next set of attachments.

    "; - } - else - { - if($db->field_exists("donecon", "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP donecon"); - } - - if($db->field_exists("filedata", "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP filedata"); - } - - if($db->field_exists("thumbnailsm", "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP thumbnailsm"); - } - $nextact = "3_convertavatars"; - $contents .= "

    Done

    All attachments have been moved to the file system. The next step is converting avatars to the file system.

    "; - $contents .= "

    If you wish to change the number of uploaded avatars to process per page then you can do so below.

    "; - $contents .= "

    Avatars Per Page:

    "; - $contents .= "

    Once you're ready, press next to begin the conversion.

    "; - } - $output->print_contents($contents); - $output->print_footer($nextact); -} - -function upgrade3_convertavatars() -{ - global $db, $output; - - $output->print_header("Avatar Conversion to Files"); - - if(!$_POST['userspage']) - { - $app = 50; - } - else - { - $app = (int)$_POST['userspage']; - } - - if($_POST['avatarstart']) - { - $startat = (int)$_POST['avatarstart']; - $upper = $startat+$app; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $app; - $lower = 1; - } - - require_once MYBB_ROOT."inc/settings.php"; - - $query = $db->simple_select("avatars", "COUNT(uid) AS avatarcount"); - $cnt = $db->fetch_array($query); - - $contents .= "

    Converting avatars $lower to $upper (".$cnt['avatarcount']." Total)

    "; - - // Add temporary column - if(!$db->field_exists("donecon", "avatars")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."avatars ADD donecon smallint(1) NOT NULL;"); - } - - if($db->field_exists("avatartype", "attachments")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments DROP avatartype;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD avatartype varchar(10) NOT NULL AFTER avatar;"); - - $query = $db->simple_select("avatars", "*", "donecon != '1'", array('order_by' => 'uid', 'order_dir' => 'asc', 'limit' => $app)); - while($avatar = $db->fetch_array($query)) - { - $ext = ""; - switch($avatar['type']) - { - case "image/jpeg": - case "image/jpg": - case "image/pjpeg": - $ext = "jpg"; - break; - case "image/x-png": - case "image/png": - $ext = "png"; - break; - case "image/gif": - $ext = "gif"; - break; - } - - if($ext) - { - $filename = "avatar_".$avatar['uid'].".".$ext; - $fp = @fopen("../uploads/avatars/".$filename, "wb"); - if(!$fp) - { - die("Unable to create file. Please check permissions and refresh page."); - } - fwrite($fp, $avatar['avatar']); - fclose($fp); - $db->write_query("UPDATE ".TABLE_PREFIX."avatars SET donecon='1' WHERE uid='".$avatar['uid']."'"); - $db->write_query("UPDATE ".TABLE_PREFIX."users SET avatar='uploads/avatars/$filename', avatartype='upload' WHERE uid='".$avatar['uid']."'"); - } - } - - echo "

    Done.

    "; - $query = $db->simple_select("avatars", "COUNT(uid) AS avatarsrem", "donecon!='1'"); - $cnt = $db->fetch_array($query); - - if($cnt['avatarsrem'] != 0) - { - $nextact = "3_convertavatars"; - $startat = $startat+$app; - $contents .= "

    Done. Click Next to move on to the next set of avatars.

    "; - } - else - { - $db->drop_table("avatars"); - $nextact = "3_dbchanges2"; - $contents .= "

    Done

    All avatars have been moved to the file system. The next step is performing the necessary database modifications for MyBB Gold.

    "; - } - $output->print_contents($contents); - $output->print_footer($nextact); -} - -function upgrade3_dbchanges2() -{ - global $db, $output; - - $output->print_header("Database Changes"); - - $contents = "

    Performing necessary database changes.

    "; - - if($db->field_exists("additionalgroups", "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP additionalgroups;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD additionalgroups varchar(200) NOT NULL default '' AFTER usergroup;"); - - if($db->field_exists("displaygroup", "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP displaygroup;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD displaygroup smallint(6) NOT NULL default '0' AFTER additionalgroups;"); - - if($db->field_exists("candisplaygroup", "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP candisplaygroup;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD candisplaygroup varchar(3) NOT NULL;"); - - if($db->field_exists("reason", "banned")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned DROP reason;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned ADD reason varchar(200) NOT NULL"); - - if($db->field_exists("rulestype", "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP rulestype;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD rulestype smallint(1) NOT NULL;"); - - if($db->field_exists("rulestitle", "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP rulestitle;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD rulestitle varchar(200) NOT NULL;"); - - if($db->field_exists("rules", "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP rules;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD rules text NOT NULL;"); - - if($db->field_exists("usetranslation", "helpdocs")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP helpdocs;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpdocs ADD usetranslation CHAR( 3 ) NOT NULL AFTER document;"); - - if($db->field_exists("enabled", "helpdocs")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpdocs DROP enabled;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpdocs ADD enabled CHAR( 3 ) NOT NULL AFTER usetranslation;"); - - /* - - This will break the upgrade for users who have customised help documents - - $db->write_query("UPDATE ".TABLE_PREFIX."helpdocs SET hid='6' WHERE hid='7'"); - $db->write_query("UPDATE ".TABLE_PREFIX."helpdocs SET hid='7' WHERE hid='8'");*/ - - if($db->field_exists("usetranslation", "helpsections")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpsections DROP usetranslation;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpsections ADD usetranslation CHAR( 3 ) NOT NULL AFTER description;"); - - if($db->field_exists("enabled", "helpsections")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpsections DROP enabled;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpsections ADD enabled CHAR( 3 ) NOT NULL AFTER usetranslation;"); - - if($db->field_exists("firstpost", "threads")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads DROP firstpost;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads ADD firstpost int unsigned NOT NULL default '0' AFTER dateline;"); - - if($db->field_exists("attachquota", "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP attachquota;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD attachquota bigint(30) NOT NULL default '0';"); - - if($db->field_exists("cancustomtitle", "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP cancustomtitle;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD cancustomtitle varchar(3) NOT NULL;"); - - - $db->drop_table("groupleaders"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."groupleaders ( - lid smallint(6) NOT NULL auto_increment, - gid smallint(6) NOT NULL, - uid smallint(6) NOT NULL, - PRIMARY KEY(lid) - );"); - - $db->drop_table("joinrequests"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."joinrequests ( - rid smallint(6) NOT NULL auto_increment, - uid smallint(6) NOT NULL, - gid smallint(6) NOT NULL, - reason varchar(250) NOT NULL, - dateline bigint(30) NOT NULL, - PRIMARY KEY(rid) - );"); - - $db->drop_table("online"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."sessions ( - sid varchar(32) NOT NULL default '', - uid int unsigned NOT NULL default '0', - ip varchar(40) NOT NULL default '', - time bigint(30) NOT NULL default '0', - location varchar(150) NOT NULL default '', - useragent varchar(100) NOT NULL default '', - anonymous int(1) NOT NULL default '0', - nopermission int(1) NOT NULL default '0', - location1 int(10) NOT NULL default '0', - location2 int(10) NOT NULL default '0', - PRIMARY KEY(sid), - KEY location1 (location1), - KEY location2 (location2) - );"); - - if($db->field_exists("salt", "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP salt;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD salt varchar(10) NOT NULL AFTER password;"); - - - if($db->field_exists("loginkey", "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP loginkey;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD loginkey varchar(50) NOT NULL AFTER salt;"); - - - if($db->field_exists("pmnotify", "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP pmnotify;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD pmnotify varchar(3) NOT NULL AFTER pmpopup;"); - - $collation = $db->build_create_table_collation(); - - $db->drop_table("settinggroups"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."settinggroups ( - gid smallint(6) NOT NULL auto_increment, - name varchar(220) NOT NULL default '', - description text NOT NULL, - disporder smallint(6) NOT NULL default '0', - isdefault char(3) NOT NULL default '', - PRIMARY KEY (gid) - ) ENGINE=MyISAM{$collation};"); - - $db->drop_table("settings"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."settings ( - sid smallint(6) NOT NULL auto_increment, - name varchar(120) NOT NULL default '', - title varchar(120) NOT NULL default '', - description text NOT NULL, - optionscode text NOT NULL, - value text NOT NULL, - disporder smallint(6) NOT NULL default '0', - gid smallint(6) NOT NULL default '0', - PRIMARY KEY (sid) - ) ENGINE=MyISAM{$collation};"); - - $db->drop_table("datacache"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."datacache ( - title varchar(30) NOT NULL default '', - cache mediumtext NOT NULL, - PRIMARY KEY(title) - ) ENGINE=MyISAM{$collation};"); - - $contents .= "

    Done

    "; - $contents .= "

    Dropping settings and rebuilding them..."; - - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (1, 'General Configuration', 'This section contains various settings such as your board name and url, as well as your website name and url.', 2, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (3, 'Date and Time Formats', 'Here you can specify the different date and time formats used to display dates and times on the forums.', 4, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (7, 'Forum Display Options', 'This section allows you to manage the various settings used on the forum fisplay (forumdisplay.php) of your boards such as enabling and disabling different features.', 6, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (8, 'Show Thread Options', 'This section allows you to manage the various settings used on the thread display page (showthread.php) of your boards such as enabling and disabling different features.', 7, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (11, 'Private Messaging', 'Various options with relation to the MyBB Private Messaging system (private.php) can be managed and set here.', 11, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (12, 'Member List', 'This section allows you to control various aspects of the board member listing (memberlist.php), such as how many members to show per page, and which features to enable or disable.', 10, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (13, 'Posting', 'These options control the various elements in relation to posting messages on the forums.', 9, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (14, 'Banning Options', '', 15, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (16, 'Forum Home Options', 'This section allows you to manage the various settings used on the forum home (index.php) of your boards such as enabling and disabling different features.', 5, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (17, 'Calendar', 'The board calendar allows the public and private listing of events and members'' birthdays. This section allows you to control and manage the settings for the Calendar.', 12, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (27, 'Server and Optimization Options', 'These options allow you to set various server and optimization preferences allowing you to reduce the load on your server, and gain better performance on your board.', 3, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (19, 'User Registration and Profile Options', 'Here you can control various settings with relation to user account registration and account management.', 8, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (20, 'Clickable Smilies and BB Code', '', 17, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (23, 'Who''s Online', '', 13, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (26, 'Board Online / Offline', 'These settings allow you to globally turn your forums online or offline, and allow you to specify a reason for turning them off.', 1, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (28, 'Control Panel Preferences (Global)', '', 19, 'yes');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settinggroups (gid, name, description, disporder, isdefault) VALUES (30, 'Portal Settings', '', 14, 'yes');"); - - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'boardclosed', 'Board Closed', 'If you need to close your forums to make some changes or perform an upgrade, this is the global switch. Viewers will not be able to view your forums, however, they will see a message with the reason you specify below.
    \r\n
    \r\nAdministrators will still be able to view the forums.', 'yesno', 'no', 1, 26);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'boardclosed_reason', 'Board Closed Reason', 'If your forum is closed, you can set a message here that your visitors will be able to see when they visit your forums.', 'textarea', 'These forums are currently closed for maintenance. Please check back later.', 2, 26);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'bbname', 'Board Name', 'The name of your message boards. We recommend that it is not over 75 characters.', 'text', 'Your Forums', 1, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'bburl', 'Board URL', 'The url to your forums.
    Include the http://. Do NOT include a trailing slash.', 'text', 'http://', 2, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'homename', 'Homepage Name', 'The name of your homepage. This will appear in the footer with a link to it.', 'text', 'Your Website', 3, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'homeurl', 'Homepage URL', 'The full URL of your homepage. This will be linked to in the footer along with its name.', 'text', 'http://', 4, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'dateformat', 'Date Format', 'The format of the dates used on the forum. This format uses the PHP date() function. We recommend not changing this unless you know what you''re doing.', 'text', 'm-d-Y', 1, 3);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'adminemail', 'Admin Email', 'The administrator''s email address. This will be used for outgoing emails sent via the forums.', 'text', 'root@localhost', 5, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'timeformat', 'Time Format', 'The format of the times used on the forum. This format uses PHP''s date() function. We recommend not changing this unless you know what you''re doing.', 'text', 'h:i A', 2, 3);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'threadsperpage', 'Threads Per Page', '', 'text', '20', 1, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'hottopic', 'Replys For Hot Topic', 'The number of replies that is needed for a topic to be considered ''hot''.', 'text', '20', 3, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'cookiedomain', 'Cookie Domain', 'The domain which cookies should be set to. This can remain blank. It should also start with a . so it covers all subdomains.', 'text', '', 8, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'cookiepath', 'Cookie Path', 'The path which cookies are set to, we recommend setting this to the full directory path to your forums with a trailing slash.', 'text', '', 9, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'postsperpage', 'Posts Per Page:', 'The number of posts to display per page. We recommend its not higher than 20 for people with slower connections.', 'text', '10', 1, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'regdateformat', 'Registered Date Format', 'The format used on showthread where it shows when the user registered.', 'text', 'M Y', 3, 3);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'sigmycode', 'Allow MyCode in Signatures', 'Do you want to allow MyCode to be used in users'' signatures?', 'yesno', 'yes', 1, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'sigsmilies', 'Allow Smilies in Signatures', 'Do you want to allow smilies to be used in users'' signatures?', 'yesno', 'yes', 3, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'sightml', 'Allow HTML in Signatures', 'Do you want to allow HTML to be used in users'' signatures?', 'yesno', 'no', 4, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'sigimgcode', 'Allow [img] Code in Signatures', 'Do you want to allow [img] code to be used in users'' signatures?', 'yesno', 'yes', 5, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'threadusenetstyle', 'Usenet Style Thread View', 'Selecting yes will cause posts to look similar to how posts look in USENET. No will cause posts to look the modern way.', 'yesno', 'no', 4, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'pmsallowhtml', 'Allow HTML', 'Selecting yes will allow HTML to be used in private messages.', 'yesno', 'no', 1, 11);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'pmsallowmycode', 'Allow MyCode', 'Selecting yes will allow MyCode to be used in private messages.', 'yesno', 'yes', 2, 11);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'pmsallowsmilies', 'Allow Smilies', 'Selecting yes will allow Smilies to be used in private messages.', 'yesno', 'yes', 3, 11);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'pmsallowimgcode', 'Allow [img] Code', 'Selecting yes will allow [img] Code to be used in private messages.', 'yesno', 'yes', 4, 11);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'siglength', 'Length limit in Signatures', 'The maximum number of characters a user can place in a signature.', 'text', '255', 6, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'messagelength', 'Maximum Message Length', 'The maximum number of characters to allow in a message. A setting of 0 allows an unlimited length.', 'text', '0', 1, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'membersperpage', 'Members Per Page', 'The number of members to show per page on the member list.', 'text', '20', 1, 12);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'load', '*NIX Load Limiting', 'Limit the maximum server load before myBB rejects people. 0 for none. Recommended limit is 5.0.', 'text', '0', 5, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'emailkeep', 'Users Keep Email', 'If a current user has an email already registered in your banned list, should he be allowed to keep it.', 'yesno', 'no', 4, 14);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'ipban', 'Ban by IP', 'Here, you may specify IP addresses or a range of IP addresses. You must separate each IP with a space.', 'textarea', '', 2, 14);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'emailban', 'Ban by Email', 'You may specify specific email addresses to ban, or you may specify a domain. You must separate email addresses and domains with a space.', 'textarea', '', 3, 14);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'avatarsize', 'Max Uploaded Avatar Size', 'Maximum file size (in kilobytes) of uploaded avatars.', 'text', '10', 8, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'avatardir', 'Avatar Directory', 'The directory where your avatars are stored. These are used in the avatar list in the User CP.', 'text', 'images/avatars', 7, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showeditedby', 'Show ''edited by'' Messages', 'Once a post is edited by a regular user, do you want to show the edited by message?', 'yesno', 'yes', 6, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxposts', 'Maximum Posts Per Day', 'This is the total number of posts allowed per user per day. 0 for unlimited.', 'text', '0', 2, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showeditedbyadmin', 'Show ''edited by'' Message for Forum Staff', 'Do you want to show edited by messages for forum staff when they edit their posts?', 'yesno', 'yes', 7, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'bannedusernames', 'Banned Usernames', 'Ban users from registering certain usernames. Seperate them with a space.', 'textarea', '', 1, 14);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxpolloptions', 'Maximum Number of Poll Options', 'The maximum number of options for polls that users can post.', 'text', '10', 3, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'dotfolders', 'Use ''dot'' Icons', 'Do you want to show dots on the thread indicators of threads users have participated in.', 'yesno', 'yes', 8, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'contactlink', 'Contact Us Link', 'This will be used for the Contact Us link on the bottom of all the forum pages. Can either be an email address (using mailto:email@website.com) or a hyperlink.', 'text', '#', 6, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showdescriptions', 'Show Forum Descriptions?', 'This option will allow you to turn off showing the descriptions for forums.', 'yesno', 'yes', 1, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showbirthdays', 'Show Today''s Birthdays?', 'Do you want to show today''s birthdays on the forum homepage?', 'yesno', 'yes', 2, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showwol', 'Show Who''s Online?', 'Display the currently active users on the forum home page.', 'yesno', 'yes', 4, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'hideprivateforums', 'Hide Private Forums?', 'You can hide private forums by turning this option on. This option also hides forums on the forum jump and all subforums.', 'yesno', 'yes', 3, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showsimilarthreads', 'Show ''Similar Threads'' Table', 'The Similar Threads table shows threads that are relevant to the thread being read. You can set the relevancy below.', 'yesno', 'no', 5, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'similarityrating', 'Similar Threads Relevancy Rating', 'This allows you to limit similar threads to ones more relevant (0 being not relevant). This number should not be over 10 and should not be set low (<5) for large forums.', 'text', '1', 7, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'similarlimit', 'Similar Threads Limit', 'Here you can change the total amount of similar threads to be shown in the similar threads table. It is recommended that it is not over 15 for 56k users.', 'text', '10', 8, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'privateeventcolor', 'Private Events Color', 'The color that private events will be shown in on the main calendar page.', 'text', 'red', 2, 17);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'publiceventcolor', 'Public Events Color', 'The color that public events will be shown in on the main calendar page.', 'text', 'green', 1, 17);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'hottopicviews', 'Views For Hot Topic', 'The number of views a thread can have before it is considered ''hot''.', 'text', '150', 7, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'logip', 'Log Posting IP Addresses', 'Do you wish to log ip addresses of users who post, and who you want to show ip addresses to.', 'radio\r\nno=Do not log IP\r\nhide=Show to Admins & Mods\r\nshow=Show to all Users', 'hide', 3, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'statslimit', 'Stats Limit', 'The number of threads to show on the stats page for most replies and most views.', 'text', '15', 10, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'modlist', 'Forums'' Moderator Listing', 'Here you can turn on or off the listing of moderators for each forum on index.php and forumdisplay.php', 'onoff', 'on', 5, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'smilieinserter', 'Clickable Smilies Inserter', 'Clickable smilies will appear on the posting pages if this option is set to ''on''.', 'onoff', 'on', 1, 20);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'smilieinsertertot', 'No. of Smilies to show', 'Enter the total number of smilies to show on the clickable smilie inserter.', 'text', '20', 2, 20);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'smilieinsertercols', 'No. of Smilie Cols to Show', 'Enter the number of columns you wish to show on the clickable smilie inserter.', 'text', '4', 3, 20);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showindexstats', 'Show Small Stats Section', 'Do you want to show the total number of threads, posts, members, and the last member on the forum home?', 'yesno', 'yes', 6, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'regtype', 'Registration Method', 'Please select the method of registration to use when users register.', 'select\r\ninstant=Instant Activation\r\nverify=Send Email Verification\r\nrandompass=Send Random Password\r\nadmin=Administrator Activation', 'verify', 1, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'userpppoptions', 'User Selectable Posts Per Page', 'If you would like to allow users to select how many posts are shown per page in a thread, enter the options they should be able to select separated with commas. If this is left blank they will not be able to choose how many posts are shown per page.', 'text', '5,10,20,25,30,40,50', 2, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'usertppoptions', 'User Selectable Threads Per Page', 'If you would like to allow users to select how many threads per page are shown in a forum, enter the options they should be able to select separated with commas. If this is left blank they will not be able to choose how many threads are shown per page.', 'text', '10,20,25,30,40,50', 6, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'wolcutoffmins', 'Cut-off Time (mins)', 'The number of minutes before a user is marked offline. Recommended: 15.', 'text', '15', 1, 23);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'postfloodcheck', 'Post Flood Checking', 'Set to on if you want to enable flood checking for posts. Specifiy the time between posts below.', 'onoff', 'on', 4, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'postfloodsecs', 'Post Flood Time', 'Set the time (in seconds) users have to wait between posting, to be in effect; the option above must be on.', 'text', '60', 5, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'gzipoutput', 'Use GZip Page Compression?', 'Do you want to compress pages in GZip format when they are sent to the browser? This means quicker downloads for your visitors, and less traffic usage for you. The level of the compression is set by the server''s load.', 'yesno', 'yes', 1, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'standardheaders', 'Send Standard Headers', 'With some web servers, this option can cause problems; with others, it is needed. ', 'yesno', 'no', 2, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'nocacheheaders', 'Send No Cache Headers', 'With this option you can prevent caching of the page by the browser.', 'yesno', 'no', 3, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxpostimages', 'Maximum Images per Post', 'Enter the maximum number of images (including smilies) a user can put in their post. Set to 0 to disable this.', 'text', '10', 8, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxsigimages', 'Maximum Number of Images per Signature', 'Enter the maximum number of images (including smilies) a user can put in their signature. Set to 0 to disable this.', 'text', '2', 2, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'browsingthisforum', 'Users Browsing this Forum', 'Here you can turn off the ''users browsing this forum'' feature.', 'onoff', 'on', 9, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'usereferrals', 'Use Referrals System', 'Do you want to use the user referrals system on these forums?', 'yesno', 'yes', 3, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'subscribeexcerpt', 'Amount of Characters for Subscription Previews', 'How many characters of the post do you want to send with the email notification of a new reply.', 'text', '100', 9, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'cpstyle', 'Control Panel Style', 'The Default style that the control panel will use. Styles are inside the styles folder. A folder name inside that folder becomes the style title and style.css inside the style title folder is the css style file.', 'cpstyle', 'Axiom', 2, 28);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'cplanguage', 'Control Panel Language', 'The language of the control panel.', 'adminlanguage', 'english', 1, 28);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'minnamelength', 'Minimum Username Length', 'The minimum number of characters a username can be when a user registers.', 'text', '3', 5, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxnamelength', 'Maximum Username Length', 'The maximum number of characters a username can be when a user registers.', 'text', '30', 6, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'redirects', 'Friendly Redirection Pages', 'This will enable friendly redirection pages instead of bumping the user directly to the page.', 'onoff', 'on', 4, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'betweenregstime', 'Time Between Registrations', 'The amount of time (in hours) to disallow registrations for users who have already registered an account under the same ip address.', 'text', '24', 2, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxregsbetweentime', 'Maximum Registrations Per IP Address', 'This option allows you to set the maximum amount of times a certain user can register within the timeframe specified above.', 'text', '2', 4, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showstats', 'Show forum statistics', 'Do you want to show the total number of posts, threads, members and the last registered member on the portal page?', 'yesno', 'yes', 5, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showpms', 'Show the number of PMs to users', 'Do you want to show the number of private messages the current user has in their pm system.', 'yesno', 'yes', 4, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showwelcome', 'Show the Welcome box', 'Do you want to show the welcome box to visitors / users.', 'yesno', 'yes', 3, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_numannouncements', 'Number of announcements to show', 'Please enter the number of announcements to show on the main page.', 'text', '10', 2, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showstats', 'Show forum statistics', 'Do you want to show the total number of posts, threads, members and the last registered member on the portal page?', 'yesno', 'yes', 5, 29);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showwol', 'Show Whos Online', 'Do you want to show the ''whos online'' information to users when they visit the portal page?', 'yesno', 'yes', 6, 29);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_announcementsfid', 'Forum ID to pull announcements from', 'Please enter the forum id (fid) of the forum you wish to pull the announcements from', 'text', '1', 1, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showdiscussionsnum', 'Number of latest discussions to show', 'Please enter the number of current forum discussions to show on the portal page.', 'text', '10', 8, 29);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showwol', 'Show Who''s Online', 'Do you want to show the ''Who''s online'' information to users when they visit the portal page?', 'yesno', 'yes', 6, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showsearch', 'Show Search Box', 'Do you want to show the search box, allowing users to quickly search the forums on the portal?', 'yesno', 'yes', 7, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showdiscussions', 'Show Latest Discussions', 'Do you wish to show the current forum discussions on the portal page?', 'yesno', 'yes', 8, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'portal_showdiscussionsnum', 'Number of latest discussions to show', 'Please enter the number of current forum discussions to show on the portal page.', 'text', '10', 9, 30);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'attachthumbh', 'Attached Thumbnail Maximum Height', 'Enter the height that attached thumbnails should be generated at.', 'text', '60', 12, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'attachthumbw', 'Attached Thumbnail Maximum Width', 'Enter the width that attached thumbnails should be generated at.', 'text', '60', 13, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxattachments', 'Maximum Attachments Per Post', 'THe maximum number of attachments a user is allowed to upload per post.', 'text', '5', 10, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'attachthumbnails', 'Show Attached Thumbnails in Posts', 'Do you want to show the generated thumbnails for attached images inside the posts?', 'yesno', 'yes', 11, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'polloptionlimit', 'Maximum Option Length', 'The maximum length that each poll option can be. (Set to 0 to disable).', 'text', '250', 1, 13);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'timezoneoffset', 'Default Timezone Offset', 'Here you can set the default timezone offset for guests and members using the default offset.', 'text', '+10', 4, 3);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'bblanguage', 'Default Language', 'The default language that MyBB should use for guests and for users without a selected language in their user control panel.', 'language', 'english', 7, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'regimage', 'Antispam Registration Image', 'If yes, and GD is installed, an image will be shown during registration where users are required to enter the text contained within the image to continue with registration.', 'onoff', 'on', 1, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'reportmethod', 'Reported Posts Medium', 'Please select from the list how you want reported posts to be dealt with. Storing them in the database is probably the better of the options listed.', 'radio\r\ndb=Stored in the Database\r\npms=Sent as Private Messages\r\nemail=Sent via Email', 'db', 1, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'threadreadcut', 'Read Threads in Database (Days)', 'The number of days that you wish to keep thread read information in the database. For large boards, we do not recommend a high number as the board will become slower. Set to 0 to disable.', 'text', '7', 3, 8);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'announcementlimit', 'Announcements Limit', 'The number of forum announcements to show in the thread listing on the forum display pages. Set to 0 to show all active announcements.', 'text', '2', 10, 7);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'uploadspath', 'Uploads Path', 'The path used for all board uploads. It must be chmod 777 (on Unix servers).', 'text', './uploads', 1, 27);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'maxavatardims', 'Maximum Avatar Dimensions', 'The maximum dimensions that an avatar can be, in the format of widthxheight. If this is left blank then there will be no dimension restriction.', 'text', '10x10', 1, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'avataruploadpath', 'Avatar Upload Path', 'This is the path where custom avatars will be uploaded to. This directory must be chmod 777 (writable) for uploads to work.', 'text', './uploads/avatars', 1, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'subforumsindex', 'Subforums to show on Index listing', 'The number of subforums that you wish to show inside forums on the index and forumdisplay pages. Set to 0 to disable this', 'text', '2', 1, 16);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'disableregs', 'Disable Registrations', 'Allows you to turn off the capability for users to register with one click.', 'yesno', 'no', 9, 19);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'decpoint', 'Decimal Point', 'The decimal point you use in your region.', 'text', '.', 1, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'thousandssep', 'Thousands Numeric Separator', 'The punctuation you want to use . (for example, the setting \',\' with the number 1200 will give you a number such as 1,200)', 'text', ',', 1, 1);"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'showvernum', 'Show Version Numbers', 'Allows you to turn off the public display of version numbers in MyBB.', 'onoff', 'off', 1, 1);"); - - echo "Done

    "; - $output->print_contents($contents); - $output->print_footer("3_dbchanges3"); -} - -function upgrade3_dbchanges3() -{ - global $db, $output; - - $output->print_header("Database Field Size Changes"); - - $contents = "

    Performing necessary database field size changes.

    "; - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminlog CHANGE uid uid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions CHANGE uid uid int(10) NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."announcements CHANGE aid aid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."announcements CHANGE fid fid int(10) NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."announcements CHANGE uid uid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments CHANGE aid aid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments CHANGE visible visible int(1) NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachments CHANGE downloads downloads int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachtypes CHANGE atid atid int unsigned NOT NULL auto_increment;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."awaitingactivation CHANGE aid aid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."awaitingactivation CHANGE uid uid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."badwords CHANGE bid bid int unsigned NOT NULL auto_increment;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned CHANGE gid gid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned CHANGE oldgroup oldgroup int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned CHANGE admin admin int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events CHANGE eid eid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."events CHANGE author author int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."favorites CHANGE fid fid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."favorites CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."favorites CHANGE tid tid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forumpermissions CHANGE pid pid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forumpermissions CHANGE fid fid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forumpermissions CHANGE gid gid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums CHANGE fid fid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums CHANGE pid pid smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums CHANGE disporder disporder smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums CHANGE threads threads int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums CHANGE posts posts int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums CHANGE style style smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forumsubscriptions CHANGE fsid fsid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forumsubscriptions CHANGE fid fid smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forumsubscriptions CHANGE uid uid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."groupleaders CHANGE lid lid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."groupleaders CHANGE gid gid smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."groupleaders CHANGE uid uid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpdocs CHANGE hid hid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpdocs CHANGE sid sid smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpdocs CHANGE disporder disporder smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpsections CHANGE sid sid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."helpsections CHANGE disporder disporder smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."icons CHANGE iid iid smallint unsigned NOT NULL auto_increment;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."joinrequests CHANGE rid rid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."joinrequests CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."joinrequests CHANGE gid gid smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderatorlog CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderatorlog CHANGE fid fid smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderatorlog CHANGE tid tid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderatorlog CHANGE pid pid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderators CHANGE mid mid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderators CHANGE fid fid smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderators CHANGE uid uid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."polls CHANGE pid pid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."polls CHANGE tid tid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."polls CHANGE numoptions numoptions smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."polls CHANGE numvotes numvotes smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."pollvotes CHANGE vid vid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."pollvotes CHANGE pid pid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."pollvotes CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."pollvotes CHANGE voteoption voteoption smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts CHANGE pid pid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts CHANGE tid tid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts CHANGE replyto replyto int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts CHANGE fid fid smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts CHANGE icon icon smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts CHANGE edituid edituid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts CHANGE visible visible int(1) NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages CHANGE pmid pmid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages CHANGE toid toid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages CHANGE fromid fromid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages CHANGE folder folder smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."privatemessages CHANGE icon icon smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."profilefields CHANGE fid fid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."profilefields CHANGE disporder disporder smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."profilefields CHANGE length length smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."profilefields CHANGE maxlength maxlength smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."reportedposts CHANGE rid rid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."reportedposts CHANGE pid pid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."reportedposts CHANGE tid tid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."reportedposts CHANGE fid fid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."reportedposts CHANGE uid uid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."reputation CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."reputation CHANGE pid pid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."reputation CHANGE adduid adduid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."searchlog CHANGE sid sid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."searchlog CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."searchlog CHANGE limitto limitto smallint(4) NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."settinggroups CHANGE gid gid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."settinggroups CHANGE disporder disporder smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."settings CHANGE sid sid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."settings CHANGE disporder disporder smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."settings CHANGE gid gid smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."smilies CHANGE sid sid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."smilies CHANGE disporder disporder smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."templates CHANGE tid tid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."templates CHANGE sid sid int(10) NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."templatesets CHANGE sid sid smallint unsigned NOT NULL auto_increment;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes CHANGE tid tid smallint unsigned NOT NULL auto_increment;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadratings CHANGE rid rid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadratings CHANGE tid tid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadratings CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadratings CHANGE rating rating smallint unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE tid tid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE fid fid smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE icon icon smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE poll poll int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE uid uid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE replies replies int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE views views int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE sticky sticky int(1) NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE numratings numratings smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE totalratings totalratings smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads CHANGE visible visible int(1) NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadsread CHANGE tid tid int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threadsread CHANGE uid uid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."userfields CHANGE ufid ufid int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups CHANGE gid gid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups CHANGE stars stars smallint(4) NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE uid uid int unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE usergroup usergroup smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE displaygroup displaygroup smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE style style smallint unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE referrer referrer int unsigned NOT NULL;"); - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usertitles CHANGE utid utid smallint unsigned NOT NULL auto_increment;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usertitles CHANGE posts posts int unsigned NOT NULL;"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usertitles CHANGE stars stars smallint(4) NOT NULL;"); - - echo "Done

    "; - - $contents .= "WARNING: The next step will delete any custom themes or templates you have! Please back them up before continuing!

    "; - $output->print_contents($contents); - $output->print_footer("3_done"); -} diff --git a/html/forums/install/resources/upgrade30.php b/html/forums/install/resources/upgrade30.php deleted file mode 100644 index 0cf7603..0000000 --- a/html/forums/install/resources/upgrade30.php +++ /dev/null @@ -1,2511 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade30_dbchanges() -{ - global $cache, $output, $mybb, $db; - - $output->print_header("Updating Database"); - - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - $db->update_query('settings', array('value' => -1), 'name IN (\'postmergefignore\', \'postmergeuignore\') AND value=\'\''); - $db->update_query('settings', array('optionscode' => 'forumselect'), 'name IN (\'postmergefignore\', \'portal_announcementsfid\') AND optionscode=\'text\''); - $db->update_query('settings', array('optionscode' => 'groupselect'), 'name=\'postmergeuignore\' AND optionscode=\'text\''); - - if($db->type == "mysql" || $db->type == "mysqli") - { - if($db->index_exists('posts', 'tiddate')) - { - $db->drop_index('posts', 'tiddate'); - } - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts ADD INDEX (`tid`, `dateline`)"); - } - - if($db->field_exists('modposts', 'usergroups')) - { - $db->drop_column("usergroups", "modposts"); - } - - if($db->field_exists('modthreads', 'usergroups')) - { - $db->drop_column("usergroups", "modthreads"); - } - - if($db->field_exists('mod_edit_posts', 'usergroups')) - { - $db->drop_column("usergroups", "mod_edit_posts"); - } - - if($db->field_exists('modattachments', 'usergroups')) - { - $db->drop_column("usergroups", "modattachments"); - } - - if($db->field_exists('regex', 'profilefields')) - { - $db->drop_column("profilefields", "regex"); - } - - if($db->field_exists('allowhtml', 'profilefields')) - { - $db->drop_column("profilefields", "allowhtml"); - } - - if($db->field_exists('allowmycode', 'profilefields')) - { - $db->drop_column("profilefields", "allowmycode"); - } - - if($db->field_exists('allowsmilies', 'profilefields')) - { - $db->drop_column("profilefields", "allowsmilies"); - } - - if($db->field_exists('allowimgcode', 'profilefields')) - { - $db->drop_column("profilefields", "allowimgcode"); - } - - if($db->field_exists('allowvideocode', 'profilefields')) - { - $db->drop_column("profilefields", "allowvideocode"); - } - - if($db->field_exists('viewableby', 'profilefields')) - { - $db->drop_column("profilefields", "viewableby"); - } - - if($db->field_exists('editable`', 'profilefields')) - { - $db->drop_column("profilefields", "editable"); - } - - if($db->field_exists('editableby', 'profilefields')) - { - $db->drop_column("profilefields", "editableby"); - } - - if($db->field_exists('oldgroup', 'awaitingactivation')) - { - $db->drop_column("awaitingactivation", "oldgroup"); - } - - if($db->field_exists('status', 'forums')) - { - $db->drop_column("forums", "status"); - } - - if($db->field_exists('posthash', 'posts')) - { - $db->drop_column("posts", "posthash"); - } - - if($db->field_exists('isdefault', 'templategroups')) - { - $db->drop_column("templategroups", "isdefault"); - } - - if($db->table_exists('reportedposts')) - { - if($db->field_exists('type', 'reportedposts')) - { - $db->drop_column("reportedposts", "type"); - } - - if($db->field_exists('reports', 'reportedposts')) - { - $db->drop_column("reportedposts", "reports"); - } - - if($db->field_exists('reporters', 'reportedposts')) - { - $db->drop_column("reportedposts", "reporters"); - } - - if($db->field_exists('lastreport', 'reportedposts')) - { - $db->drop_column("reportedposts", "lastreport"); - } - } - - if($db->field_exists('warnings', 'promotions')) - { - $db->drop_column("promotions", "warnings"); - } - - if($db->field_exists('warningstype', 'promotions')) - { - $db->drop_column("promotions", "warningstype"); - } - - if($db->field_exists('useragent', 'adminsessions')) - { - $db->drop_column("adminsessions", "useragent"); - } - - if($db->field_exists('deletedthreads', 'forums')) - { - $db->drop_column("forums", "deletedthreads"); - } - - if($db->field_exists('deletedposts', 'forums')) - { - $db->drop_column("forums", "deletedposts"); - } - - if($db->field_exists('threads', 'promotions')) - { - $db->drop_column('promotions', 'threads'); - } - - if($db->field_exists('threadtype', 'promotions')) - { - $db->drop_column('promotions', 'threadtype'); - } - - if($db->field_exists('online', 'promotions')) - { - $db->drop_column('promotions', 'online'); - } - - if($db->field_exists('onlinetype', 'promotions')) - { - $db->drop_column('promotions', 'onlinetype'); - } - - if($db->field_exists('modposts', 'forums')) - { - $db->drop_column("forums", "modposts"); - } - - if($db->field_exists('modthreads', 'forums')) - { - $db->drop_column("forums", "modthreads"); - } - - if($db->field_exists('mod_edit_posts', 'forums')) - { - $db->drop_column("forums", "mod_edit_posts"); - } - - if($db->field_exists('modattachments', 'forums')) - { - $db->drop_column("forums", "modattachments"); - } - - // Avoid complex convert coding... - if($db->field_exists('hidden', 'profilefields')) - { - $db->update_query('profilefields', array('hidden' => 2), 'hidden=1'); - $db->update_query('profilefields', array('hidden' => 1), 'hidden=0'); - $db->update_query('profilefields', array('hidden' => 0), 'hidden=2'); - - switch($db->type) - { - case "pgsql": - $db->rename_column("profilefields", "hidden", "profile", "smallint", "set", "'0'"); - break; - default: - $db->rename_column("profilefields", "hidden", "profile", "tinyint(1) NOT NULL default '0'"); - break; - } - } - - switch($db->type) - { - case "pgsql": - $db->add_column("usergroups", "modposts", "smallint NOT NULL default '0' AFTER canratethreads"); - $db->add_column("usergroups", "modthreads", "smallint NOT NULL default '0' AFTER modposts"); - $db->add_column("usergroups", "mod_edit_posts", "smallint NOT NULL default '0' AFTER modthreads"); - $db->add_column("usergroups", "modattachments", "smallint NOT NULL default '0' AFTER mod_edit_posts"); - $db->add_column("profilefields", "regex", "text NOT NULL default ''"); - $db->add_column("profilefields", "allowhtml", "smallint NOT NULL default '0'"); - $db->add_column("profilefields", "allowmycode", "smallint NOT NULL default '0'"); - $db->add_column("profilefields", "allowsmilies", "smallint NOT NULL default '0'"); - $db->add_column("profilefields", "allowimgcode", "smallint NOT NULL default '0'"); - $db->add_column("profilefields", "allowvideocode", "smallint NOT NULL default '0'"); - $db->add_column("profilefields", "viewableby", "text NOT NULL default ''"); - $db->add_column("profilefields", "editableby", "text NOT NULL default ''"); - $db->add_column("templategroups", "isdefault", "smallint NOT NULL default '0'"); - if($db->table_exists('reportedposts')) - { - $db->add_column("reportedposts", "type", "varchar(50) NOT NULL default ''"); - $db->add_column("reportedposts", "reports", "int NOT NULL default '0'"); - $db->add_column("reportedposts", "reporters", "text NOT NULL default ''"); - $db->add_column("reportedposts", "lastreport", "bigint NOT NULL default '0'"); - } - $db->add_column("promotions", "threads", "int NOT NULL default '0' AFTER posttype"); - $db->add_column("promotions", "threadtype", "varchar(2) NOT NULL default '' AFTER threads"); - $db->add_column("promotions", "warnings", "int NOT NULL default '0' AFTER referralstype"); - $db->add_column("promotions", "warningstype", "varchar(2) NOT NULL default '' AFTER warnings"); - $db->add_column("promotions", "online", "int NOT NULL default '0' AFTER warningstype"); - $db->add_column("promotions", "onlinetype", "varchar(20) NOT NULL default '' AFTER online"); - $db->add_column("adminsessions", "useragent", "varchar(100) NOT NULL default ''"); - $db->add_column("forums", "deletedthreads", "int NOT NULL default '0' AFTER unapprovedposts"); - $db->add_column("forums", "deletedposts", "int NOT NULL default '0' AFTER deletedthreads"); - break; - case "sqlite": - $db->add_column("usergroups", "modposts", "tinyint(1) NOT NULL default '0' AFTER canratethreads"); - $db->add_column("usergroups", "modthreads", "tinyint(1) NOT NULL default '0' AFTER modposts"); - $db->add_column("usergroups", "mod_edit_posts", "tinyint(1) NOT NULL default '0' AFTER modthreads"); - $db->add_column("usergroups", "modattachments", "tinyint(1) NOT NULL default '0' AFTER mod_edit_posts"); - $db->add_column("profilefields", "regex", "text NOT NULL default ''"); - $db->add_column("profilefields", "allowhtml", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "allowmycode", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "allowsmilies", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "allowimgcode", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "allowvideocode", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "viewableby", "text NOT NULL default ''"); - $db->add_column("profilefields", "editableby", "text NOT NULL default ''"); - $db->add_column("templategroups", "isdefault", "tinyint(1) NOT NULL default '0'"); - if($db->table_exists('reportedposts')) - { - $db->add_column("reportedposts", "type", "varchar(50) NOT NULL default ''"); - $db->add_column("reportedposts", "reports", "int NOT NULL default '0'"); - $db->add_column("reportedposts", "reporters", "text NOT NULL default ''"); - $db->add_column("reportedposts", "lastreport", "bigint NOT NULL default '0'"); - } - $db->add_column("promotions", "warnings", "int NOT NULL default '0' AFTER referralstype"); - $db->add_column("promotions", "warningstype", "varchar(2) NOT NULL default '' AFTER warnings"); - $db->add_column("adminsessions", "useragent", "varchar(100) NOT NULL default ''"); - $db->add_column("forums", "deletedthreads", "int NOT NULL default '0' AFTER unapprovedposts"); - $db->add_column("forums", "deletedposts", "int NOT NULL default '0' AFTER deletedthreads"); - break; - default: - $db->add_column("usergroups", "modposts", "tinyint(1) NOT NULL default '0' AFTER canratethreads"); - $db->add_column("usergroups", "modthreads", "tinyint(1) NOT NULL default '0' AFTER modposts"); - $db->add_column("usergroups", "mod_edit_posts", "tinyint(1) NOT NULL default '0' AFTER modthreads"); - $db->add_column("usergroups", "modattachments", "tinyint(1) NOT NULL default '0' AFTER mod_edit_posts"); - $db->add_column("profilefields", "regex", "text NOT NULL"); - $db->add_column("profilefields", "allowhtml", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "allowmycode", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "allowsmilies", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "allowimgcode", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "allowvideocode", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "viewableby", "text NOT NULL"); - $db->add_column("profilefields", "editableby", "text NOT NULL"); - $db->add_column("templategroups", "isdefault", "tinyint(1) NOT NULL default '0'"); - if($db->table_exists('reportedposts')) - { - $db->add_column("reportedposts", "type", "varchar(50) NOT NULL default ''"); - $db->add_column("reportedposts", "reports", "int unsigned NOT NULL default '0'"); - $db->add_column("reportedposts", "reporters", "text NOT NULL"); - $db->add_column("reportedposts", "lastreport", "bigint(30) NOT NULL default '0'"); - } - $db->add_column("promotions", "threads", "int NOT NULL default '0' AFTER posttype"); - $db->add_column("promotions", "threadtype", "char(2) NOT NULL default '' AFTER threads"); - $db->add_column("promotions", "warnings", "int NOT NULL default '0' AFTER referralstype"); - $db->add_column("promotions", "warningstype", "char(2) NOT NULL default '' AFTER warnings"); - $db->add_column("promotions", "online", "int NOT NULL default '0' AFTER warningstype"); - $db->add_column("promotions", "onlinetype", "varchar(20) NOT NULL default '' AFTER online"); - $db->add_column("adminsessions", "useragent", "varchar(100) NOT NULL default ''"); - $db->add_column("forums", "deletedthreads", "int(10) NOT NULL default '0' AFTER unapprovedposts"); - $db->add_column("forums", "deletedposts", "int(10) NOT NULL default '0' AFTER deletedthreads"); - break; - } - - $db->update_query('profilefields', array('viewableby' => '-1', 'editableby' => '-1')); - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_dbchanges2"); -} - -function upgrade30_dbchanges2() -{ - global $cache, $output, $mybb, $db; - - $output->print_header("Updating Database"); - - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->field_exists('ipaddress', 'privatemessages')) - { - $db->drop_column('privatemessages', 'ipaddress'); - } - - if($db->field_exists('canonlyreplyownthreads', 'forumpermissions')) - { - $db->drop_column("forumpermissions", "canonlyreplyownthreads"); - } - - if($db->field_exists('modposts', 'forumpermissions')) - { - $db->drop_column("forumpermissions", "modposts"); - } - - if($db->field_exists('modthreads', 'forumpermissions')) - { - $db->drop_column("forumpermissions", "modthreads"); - } - - if($db->field_exists('mod_edit_posts', 'forumpermissions')) - { - $db->drop_column("forumpermissions", "mod_edit_posts"); - } - - if($db->field_exists('modattachments', 'forumpermissions')) - { - $db->drop_column("forumpermissions", "modattachments"); - } - - if($db->field_exists('canbereported', 'usergroups')) - { - $db->drop_column('usergroups', 'canbereported'); - } - - if($db->field_exists('edittimelimit', 'usergroups')) - { - $db->drop_column("usergroups", "edittimelimit"); - } - - if($db->field_exists('maxposts', 'usergroups')) - { - $db->drop_column("usergroups", "maxposts"); - } - - if($db->field_exists('showmemberlist', 'usergroups')) - { - $db->drop_column("usergroups", "showmemberlist"); - } - - if($db->field_exists('canviewboardclosed', 'usergroups')) - { - $db->drop_column("usergroups", "canviewboardclosed"); - } - - if($db->field_exists('deletedposts', 'threads')) - { - $db->drop_column("threads", "deletedposts"); - } - - if($db->field_exists('used', 'captcha')) - { - $db->drop_column("captcha", "used"); - } - - if($db->field_exists('editreason', 'posts')) - { - $db->drop_column("posts", "editreason"); - } - - if($db->field_exists('usethreadcounts', 'forums')) - { - $db->drop_column("forums", "usethreadcounts"); - } - - if($db->field_exists('requireprefix', 'forums')) - { - $db->drop_column("forums", "requireprefix"); - } - - if($db->field_exists('threadnum', 'users')) - { - $db->drop_column("users", "threadnum"); - } - - if($db->field_exists('canchangewebsite', 'usergroups')) - { - $db->drop_column("usergroups", "canchangewebsite"); - } - - switch($db->type) - { - case "pgsql": - $db->add_column("forumpermissions", "canonlyreplyownthreads", "smallint NOT NULL default '0' AFTER canpostreplys"); - $db->add_column("forumpermissions", "modposts", "smallint NOT NULL default '0' AFTER caneditattachments"); - $db->add_column("forumpermissions", "modthreads", "smallint NOT NULL default '0' AFTER modposts"); - $db->add_column("forumpermissions", "mod_edit_posts", "smallint NOT NULL default '0' AFTER modthreads"); - $db->add_column("forumpermissions", "modattachments", "smallint NOT NULL default '0' AFTER mod_edit_posts"); - $db->add_column("usergroups", "canbereported", "smallint NOT NULL default '0' AFTER canchangename"); - $db->add_column("usergroups", "canchangewebsite", "smallint NOT NULL default '1' AFTER canbereported"); - $db->add_column("usergroups", "edittimelimit", "int NOT NULL default '0'"); - $db->add_column("usergroups", "maxposts", "int NOT NULL default '0'"); - $db->add_column("usergroups", "showmemberlist", "smallint NOT NULL default '1'"); - $db->add_column("usergroups", "canviewboardclosed", "smallint NOT NULL default '0' AFTER candlattachments"); - $db->add_column("threads", "deletedposts", "int NOT NULL default '0' AFTER unapprovedposts"); - $db->add_column("captcha", "used", "smallint NOT NULL default '0'"); - $db->add_column("posts", "editreason", "varchar(150) NOT NULL default '' AFTER edittime"); - $db->add_column("forums", "usethreadcounts", "smallint NOT NULL default '0' AFTER usepostcounts"); - $db->add_column("forums", "requireprefix", "smallint NOT NULL default '0' AFTER usethreadcounts"); - $db->add_column("users", "threadnum", "int NOT NULL default '0' AFTER postnum"); - break; - default: - $db->add_column("forumpermissions", "canonlyreplyownthreads", "tinyint(1) NOT NULL default '0' AFTER canpostreplys"); - $db->add_column("forumpermissions", "modposts", "tinyint(1) NOT NULL default '0' AFTER caneditattachments"); - $db->add_column("forumpermissions", "modthreads", "tinyint(1) NOT NULL default '0' AFTER modposts"); - $db->add_column("forumpermissions", "mod_edit_posts", "tinyint(1) NOT NULL default '0' AFTER modthreads"); - $db->add_column("forumpermissions", "modattachments", "tinyint(1) NOT NULL default '0' AFTER mod_edit_posts"); - $db->add_column("usergroups", "canbereported", "tinyint(1) NOT NULL default '0' AFTER canchangename"); - $db->add_column("usergroups", "canchangewebsite", "tinyint(1) NOT NULL default '1' AFTER canbereported"); - $db->add_column("usergroups", "edittimelimit", "int(4) NOT NULL default '0'"); - $db->add_column("usergroups", "maxposts", "int(4) NOT NULL default '0'"); - $db->add_column("usergroups", "showmemberlist", "tinyint(1) NOT NULL default '1'"); - $db->add_column("usergroups", "canviewboardclosed", "tinyint(1) NOT NULL default '0' AFTER candlattachments"); - $db->add_column("threads", "deletedposts", "int(10) NOT NULL default '0' AFTER unapprovedposts"); - $db->add_column("captcha", "used", "tinyint(1) NOT NULL default '0'"); - $db->add_column("posts", "editreason", "varchar(150) NOT NULL default '' AFTER edittime"); - $db->add_column("forums", "usethreadcounts", "tinyint(1) NOT NULL default '0' AFTER usepostcounts"); - $db->add_column("forums", "requireprefix", "tinyint(1) NOT NULL default '0' AFTER usethreadcounts"); - $db->add_column("users", "threadnum", "int(10) NOT NULL default '0' AFTER postnum"); - break; - } - - $db->update_query('forums', array('usethreadcounts' => 1), 'usepostcounts = 1'); - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_dbchanges3"); -} - -function upgrade30_dbchanges3() -{ - global $cache, $output, $mybb, $db; - - $output->print_header("Updating Database"); - - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->field_exists('cansoftdeleteposts', 'moderators')) - { - $db->drop_column('moderators', 'cansoftdeleteposts'); - } - - if($db->field_exists('canrestoreposts', 'moderators')) - { - $db->drop_column("moderators", "canrestoreposts"); - } - - if($db->field_exists('cansoftdeletethreads', 'moderators')) - { - $db->drop_column('moderators', 'cansoftdeletethreads'); - } - - if($db->field_exists('canrestorethreads', 'moderators')) - { - $db->drop_column("moderators", "canrestorethreads"); - } - - if($db->field_exists('candeletethreads', 'moderators')) - { - $db->drop_column("moderators", "candeletethreads"); - } - - if($db->field_exists('canviewunapprove', 'moderators')) - { - $db->drop_column("moderators", "canviewunapprove"); - } - - if($db->field_exists('canviewdeleted', 'moderators')) - { - $db->drop_column("moderators", "canviewdeleted"); - } - - if($db->field_exists('canstickunstickthreads', 'moderators')) - { - $db->drop_column("moderators", "canstickunstickthreads"); - } - - if($db->field_exists('canapproveunapprovethreads', 'moderators')) - { - $db->drop_column("moderators", "canapproveunapprovethreads"); - } - - if($db->field_exists('canapproveunapproveposts', 'moderators')) - { - $db->drop_column("moderators", "canapproveunapproveposts"); - } - - if($db->field_exists('canapproveunapproveattachs', 'moderators')) - { - $db->drop_column("moderators", "canapproveunapproveattachs"); - } - - if($db->field_exists('canmanagepolls', 'moderators')) - { - $db->drop_column("moderators", "canmanagepolls"); - } - - if($db->field_exists('canpostclosedthreads', 'moderators')) - { - $db->drop_column("moderators", "canpostclosedthreads"); - } - - if($db->field_exists('canmanageannouncements', 'moderators')) - { - $db->drop_column("moderators", "canmanageannouncements"); - } - - if($db->field_exists('canmanagereportedposts', 'moderators')) - { - $db->drop_column("moderators", "canmanagereportedposts"); - } - - if($db->field_exists('canviewmodlog', 'moderators')) - { - $db->drop_column("moderators", "canviewmodlog"); - } - - switch($db->type) - { - case "pgsql": - $db->add_column("moderators", "cansoftdeleteposts", "smallint NOT NULL default '0' AFTER caneditposts"); - $db->add_column("moderators", "canrestoreposts", "smallint NOT NULL default '0' AFTER cansoftdeleteposts"); - $db->add_column("moderators", "cansoftdeletethreads", "smallint NOT NULL default '0' AFTER candeleteposts"); - $db->add_column("moderators", "canrestorethreads", "smallint NOT NULL default '0' AFTER cansoftdeletethreads"); - $db->add_column("moderators", "candeletethreads", "smallint NOT NULL default '0' AFTER canrestorethreads"); - $db->add_column("moderators", "canviewunapprove", "smallint NOT NULL default '0' AFTER canviewips"); - $db->add_column("moderators", "canviewdeleted", "smallint NOT NULL default '0' AFTER canviewunapprove"); - $db->add_column("moderators", "canstickunstickthreads", "smallint NOT NULL default '0' AFTER canopenclosethreads"); - $db->add_column("moderators", "canapproveunapprovethreads", "smallint NOT NULL default '0' AFTER canstickunstickthreads"); - $db->add_column("moderators", "canapproveunapproveposts", "smallint NOT NULL default '0' AFTER canapproveunapprovethreads"); - $db->add_column("moderators", "canapproveunapproveattachs", "smallint NOT NULL default '0' AFTER canapproveunapproveposts"); - $db->add_column("moderators", "canmanagepolls", "smallint NOT NULL default '0' AFTER canmanagethreads"); - $db->add_column("moderators", "canpostclosedthreads", "smallint NOT NULL default '0' AFTER canmanagepolls"); - $db->add_column("moderators", "canmanageannouncements", "smallint NOT NULL default '0' AFTER canusecustomtools"); - $db->add_column("moderators", "canmanagereportedposts", "smallint NOT NULL default '0' AFTER canmanageannouncements"); - $db->add_column("moderators", "canviewmodlog", "smallint NOT NULL default '0' AFTER canmanagereportedposts"); - break; - default: - $db->add_column("moderators", "cansoftdeleteposts", "tinyint(1) NOT NULL default '0' AFTER caneditposts"); - $db->add_column("moderators", "canrestoreposts", "tinyint(1) NOT NULL default '0' AFTER cansoftdeleteposts"); - $db->add_column("moderators", "cansoftdeletethreads", "tinyint(1) NOT NULL default '0' AFTER candeleteposts"); - $db->add_column("moderators", "canrestorethreads", "tinyint(1) NOT NULL default '0' AFTER cansoftdeletethreads"); - $db->add_column("moderators", "candeletethreads", "tinyint(1) NOT NULL default '0' AFTER canrestorethreads"); - $db->add_column("moderators", "canviewunapprove", "tinyint(1) NOT NULL default '0' AFTER canviewips"); - $db->add_column("moderators", "canviewdeleted", "tinyint(1) NOT NULL default '0' AFTER canviewunapprove"); - $db->add_column("moderators", "canstickunstickthreads", "tinyint(1) NOT NULL default '0' AFTER canopenclosethreads"); - $db->add_column("moderators", "canapproveunapprovethreads", "tinyint(1) NOT NULL default '0' AFTER canstickunstickthreads"); - $db->add_column("moderators", "canapproveunapproveposts", "tinyint(1) NOT NULL default '0' AFTER canapproveunapprovethreads"); - $db->add_column("moderators", "canapproveunapproveattachs", "tinyint(1) NOT NULL default '0' AFTER canapproveunapproveposts"); - $db->add_column("moderators", "canmanagepolls", "tinyint(1) NOT NULL default '0' AFTER canmanagethreads"); - $db->add_column("moderators", "canpostclosedthreads", "tinyint(1) NOT NULL default '0' AFTER canmanagepolls"); - $db->add_column("moderators", "canmanageannouncements", "tinyint(1) NOT NULL default '0' AFTER canusecustomtools"); - $db->add_column("moderators", "canmanagereportedposts", "tinyint(1) NOT NULL default '0' AFTER canmanageannouncements"); - $db->add_column("moderators", "canviewmodlog", "tinyint(1) NOT NULL default '0' AFTER canmanagereportedposts"); - break; - } - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_dbchanges4"); -} - -function upgrade30_dbchanges4() -{ - global $cache, $output, $mybb, $db; - - $output->print_header("Updating Database"); - - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->field_exists('emailfloodtime', 'usergroups')) - { - $db->drop_column("usergroups", "emailfloodtime"); - } - - if($db->field_exists('canmanageannounce', 'usergroups')) - { - $db->drop_column("usergroups", "canmanageannounce"); - } - - if($db->field_exists('canmanagemodqueue', 'usergroups')) - { - $db->drop_column("usergroups", "canmanagemodqueue"); - } - - if($db->field_exists('canmanagereportedcontent', 'usergroups')) - { - $db->drop_column("usergroups", "canmanagereportedcontent"); - } - - if($db->field_exists('canviewmodlogs', 'usergroups')) - { - $db->drop_column("usergroups", "canviewmodlogs"); - } - - if($db->field_exists('caneditprofiles', 'usergroups')) - { - $db->drop_column("usergroups", "caneditprofiles"); - } - - if($db->field_exists('canbanusers', 'usergroups')) - { - $db->drop_column("usergroups", "canbanusers"); - } - - if($db->field_exists('canviewwarnlogs', 'usergroups')) - { - $db->drop_column("usergroups", "canviewwarnlogs"); - } - - if($db->field_exists('canuseipsearch', 'usergroups')) - { - $db->drop_column("usergroups", "canuseipsearch"); - } - - if($db->field_exists('type', 'maillogs')) - { - $db->drop_column("maillogs", "type"); - } - - if($db->field_exists('groups', 'modtools')) - { - $db->drop_column("modtools", "groups"); - } - - switch($db->type) - { - case "pgsql": - $db->add_column("usergroups", "emailfloodtime", "int NOT NULL default '5' AFTER maxemails"); - $db->add_column("usergroups", "canmanageannounce", "smallint NOT NULL default '0' AFTER showmemberlist"); - $db->add_column("usergroups", "canmanagemodqueue", "smallint NOT NULL default '0' AFTER canmanageannounce"); - $db->add_column("usergroups", "canmanagereportedcontent", "smallint NOT NULL default '0' AFTER canmanagemodqueue"); - $db->add_column("usergroups", "canviewmodlogs", "smallint NOT NULL default '0' AFTER canmanagereportedcontent"); - $db->add_column("usergroups", "caneditprofiles", "smallint NOT NULL default '0' AFTER canviewmodlogs"); - $db->add_column("usergroups", "canbanusers", "smallint NOT NULL default '0' AFTER caneditprofiles"); - $db->add_column("usergroups", "canviewwarnlogs", "smallint NOT NULL default '0' AFTER canbanusers"); - $db->add_column("usergroups", "canuseipsearch", "smallint NOT NULL default '0' AFTER canviewwarnlogs"); - $db->add_column("maillogs", "type", "smallint NOT NULL default '0'"); - break; - default: - $db->add_column("usergroups", "emailfloodtime", "int(3) NOT NULL default '5' AFTER maxemails"); - $db->add_column("usergroups", "canmanageannounce", "tinyint(1) NOT NULL default '0' AFTER showmemberlist"); - $db->add_column("usergroups", "canmanagemodqueue", "tinyint(1) NOT NULL default '0' AFTER canmanageannounce"); - $db->add_column("usergroups", "canmanagereportedcontent", "tinyint(1) NOT NULL default '0' AFTER canmanagemodqueue"); - $db->add_column("usergroups", "canviewmodlogs", "tinyint(1) NOT NULL default '0' AFTER canmanagereportedcontent"); - $db->add_column("usergroups", "caneditprofiles", "tinyint(1) NOT NULL default '0' AFTER canviewmodlogs"); - $db->add_column("usergroups", "canbanusers", "tinyint(1) NOT NULL default '0' AFTER caneditprofiles"); - $db->add_column("usergroups", "canviewwarnlogs", "tinyint(1) NOT NULL default '0' AFTER canbanusers"); - $db->add_column("usergroups", "canuseipsearch", "tinyint(1) NOT NULL default '0' AFTER canviewwarnlogs"); - $db->add_column("maillogs", "type", "tinyint(1) NOT NULL default '0'"); - break; - } - - switch($db->type) - { - case "sqlite": - $db->add_column("modtools", "groups", "text NOT NULL default ''"); - break; - default: - $db->add_column("modtools", "groups", "text NOT NULL"); - break; - } - - $update_array = array( - "canmanageannounce" => 1, - "canmanagemodqueue" => 1, - "canmanagereportedcontent" => 1, - "canviewmodlogs" => 1, - "caneditprofiles" => 1, - "canbanusers" => 1, - "canviewwarnlogs" => 1, - "canuseipsearch" => 1 - ); - $db->update_query("usergroups", $update_array, "canmodcp= '1'"); - - $update_array = array( - "type" => 1 - ); - $db->update_query("maillogs", $update_array, "tid= '0'"); - - $update_array = array( - "type" => 2 - ); - $db->update_query("maillogs", $update_array, "tid > '0'"); - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_dbchanges5"); -} - -function upgrade30_dbchanges5() -{ - global $cache, $output, $mybb, $db; - - $output->print_header("Updating Database"); - - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->table_exists("questions")) - { - $db->drop_table("questions"); - } - - if($db->table_exists("questionsessions")) - { - $db->drop_table("questionsessions"); - } - - if($db->table_exists("spamlog")) - { - $db->drop_table("spamlog"); - } - - $collation = $db->build_create_table_collation(); - - switch($db->type) - { - case "sqlite": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."questions ( - qid INTEGER PRIMARY KEY, - question varchar(200) NOT NULL default '', - answer varchar(150) NOT NULL default '', - shown int unsigned NOT NULL default 0, - correct int unsigned NOT NULL default 0, - incorrect int unsigned NOT NULL default 0, - active tinyint(1) NOT NULL default '0' - );"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."questionsessions ( - sid varchar(32) NOT NULL default '', - qid int unsigned NOT NULL default '0', - dateline int unsigned NOT NULL default '0' - );"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."spamlog ( - sid INTEGER PRIMARY KEY, - username varchar(120) NOT NULL DEFAULT '', - email varchar(220) NOT NULL DEFAULT '', - ipaddress blob(16) NOT NULL default '', - dateline int unsigned NOT NULL default '0', - data TEXT NOT NULL - );"); - break; - case "pgsql": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."questions ( - qid serial, - question varchar(200) NOT NULL default '', - answer varchar(150) NOT NULL default '', - shown int NOT NULL default 0, - correct int NOT NULL default 0, - incorrect int NOT NULL default 0, - active smallint NOT NULL default '0', - PRIMARY KEY (qid) - );"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."questionsessions ( - sid varchar(32) NOT NULL default '', - qid int NOT NULL default '0', - dateline int NOT NULL default '0', - UNIQUE (sid) - );"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."spamlog ( - sid serial, - username varchar(120) NOT NULL DEFAULT '', - email varchar(220) NOT NULL DEFAULT '', - ipaddress bytea NOT NULL default '', - dateline numeric(30,0) NOT NULL default '0', - data text NOT NULL default '', - PRIMARY KEY (sid) - );"); - break; - default: - $db->write_query("CREATE TABLE ".TABLE_PREFIX."questions ( - qid int unsigned NOT NULL auto_increment, - question varchar(200) NOT NULL default '', - answer varchar(150) NOT NULL default '', - shown int unsigned NOT NULL default 0, - correct int unsigned NOT NULL default 0, - incorrect int unsigned NOT NULL default 0, - active tinyint(1) NOT NULL default '0', - PRIMARY KEY (qid) - ) ENGINE=MyISAM{$collation}"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."questionsessions ( - sid varchar(32) NOT NULL default '', - qid int unsigned NOT NULL default '0', - dateline int unsigned NOT NULL default '0', - PRIMARY KEY (sid) - ) ENGINE=MyISAM{$collation}"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."spamlog ( - sid int unsigned NOT NULL auto_increment, - username varchar(120) NOT NULL DEFAULT '', - email varchar(220) NOT NULL DEFAULT '', - ipaddress varbinary(16) NOT NULL default '', - dateline int unsigned NOT NULL default '0', - data text NOT NULL, - PRIMARY KEY (sid) - ) ENGINE=MyISAM{$collation}"); - } - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_dbchanges6"); -} - -function upgrade30_dbchanges6() -{ - global $cache, $output, $mybb, $db; - - $output->print_header("Updating Database"); - - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->table_exists("buddyrequests")) - { - $db->drop_table("buddyrequests"); - } - - $collation = $db->build_create_table_collation(); - - switch($db->type) - { - case "pgsql": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."buddyrequests ( - id serial, - uid int NOT NULL, - touid int NOT NULL, - date int NOT NULL, - PRIMARY KEY (id) - );"); - break; - case "sqlite": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."buddyrequests ( - id INTEGER PRIMARY KEY, - uid bigint unsigned NOT NULL, - touid bigint unsigned NOT NULL, - date int unsigned NOT NULL - );"); - break; - default: - $db->write_query("CREATE TABLE ".TABLE_PREFIX."buddyrequests ( - id int(10) UNSIGNED NOT NULL auto_increment, - uid bigint(30) UNSIGNED NOT NULL, - touid bigint(30) UNSIGNED NOT NULL, - date int(11) UNSIGNED NOT NULL, - KEY (uid), - KEY (touid), - PRIMARY KEY (id) - ) ENGINE=MyISAM{$collation};"); - break; - } - - if($db->field_exists('msn', 'users')) - { - $db->drop_column("users", "msn"); - } - - if($db->field_exists('postbit', 'profilefields')) - { - $db->drop_column("profilefields", "postbit"); - } - - if($db->field_exists('skype', 'users')) - { - $db->drop_column("users", "skype"); - } - - if($db->field_exists('google', 'users')) - { - $db->drop_column("users", "google"); - } - - if($db->field_exists('cplanguage', 'adminoptions')) - { - $db->drop_column("adminoptions", "cplanguage"); - } - - if($db->field_exists('showimages', 'users')) - { - $db->drop_column("users", "showimages"); - } - - if($db->field_exists('showvideos', 'users')) - { - $db->drop_column("users", "showvideos"); - } - - if($db->field_exists('caninvitemembers', 'groupleaders')) - { - $db->drop_column("groupleaders", "caninvitemembers"); - } - - if($db->field_exists('invite', 'joinrequests')) - { - $db->drop_column("joinrequests", "invite"); - } - - if($db->field_exists('registration', 'profilefields')) - { - $db->drop_column("profilefields", "registration"); - } - - if($db->field_exists('validated', 'awaitingactivation')) - { - $db->drop_column("awaitingactivation", "validated"); - } - - if($db->field_exists('sourceeditor', 'users')) - { - $db->drop_column("users", "sourceeditor"); - } - - if($db->field_exists('buddyrequestspm', 'users')) - { - $db->drop_column("users", "buddyrequestspm"); - } - - if($db->field_exists('buddyrequestsauto', 'users')) - { - $db->drop_column("users", "buddyrequestsauto"); - } - - if($db->field_exists('ipaddress', 'privatemessages')) - { - $db->drop_column("privatemessages", "ipaddress"); - } - - if($db->field_exists('maxoptions', 'polls')) - { - $db->drop_column("polls", "maxoptions"); - } - - switch($db->type) - { - case "pgsql": - $db->add_column("profilefields", "postbit", "smallint NOT NULL default '0' AFTER profile"); - $db->add_column("users", "skype", "varchar(75) NOT NULL default '' AFTER yahoo"); - $db->add_column("users", "google", "varchar(75) NOT NULL default '' AFTER skype"); - $db->add_column("adminoptions", "cplanguage", "varchar(50) NOT NULL default '' AFTER cpstyle"); - $db->add_column("users", "showimages", "smallint NOT NULL default '1' AFTER threadmode"); - $db->add_column("users", "showvideos", "smallint NOT NULL default '1' AFTER showimages"); - $db->add_column("users", "buddyrequestspm", "smallint NOT NULL default '1' AFTER pmnotify"); - $db->add_column("users", "buddyrequestsauto", "smallint NOT NULL default '0' AFTER buddyrequestspm"); - $db->add_column("groupleaders", "caninvitemembers", "smallint NOT NULL default '0'"); - $db->add_column("joinrequests", "invite", "smallint NOT NULL default '0'"); - $db->add_column("profilefields", "registration", "smallint NOT NULL default '0' AFTER required"); - $db->add_column("awaitingactivation", "validated", "smallint NOT NULL default '0' AFTER type"); - $db->add_column("users", "sourceeditor", "smallint NOT NULL default '0'"); - break; - default: - $db->add_column("profilefields", "postbit", "tinyint(1) NOT NULL default '0' AFTER profile"); - $db->add_column("users", "skype", "varchar(75) NOT NULL default '' AFTER yahoo"); - $db->add_column("users", "google", "varchar(75) NOT NULL default '' AFTER skype"); - $db->add_column("adminoptions", "cplanguage", "varchar(50) NOT NULL default '' AFTER cpstyle"); - $db->add_column("users", "showimages", "tinyint(1) NOT NULL default '1' AFTER threadmode"); - $db->add_column("users", "showvideos", "tinyint(1) NOT NULL default '1' AFTER showimages"); - $db->add_column("users", "buddyrequestspm", "tinyint(1) NOT NULL default '1' AFTER pmnotify"); - $db->add_column("users", "buddyrequestsauto", "tinyint(1) NOT NULL default '0' AFTER buddyrequestspm"); - $db->add_column("groupleaders", "caninvitemembers", "tinyint(1) NOT NULL default '0'"); - $db->add_column("joinrequests", "invite", "tinyint(1) NOT NULL default '0'"); - $db->add_column("profilefields", "registration", "tinyint(1) NOT NULL default '0' AFTER required"); - $db->add_column("awaitingactivation", "validated", "tinyint(1) NOT NULL default '0' AFTER type"); - $db->add_column("users", "sourceeditor", "tinyint(1) NOT NULL default '0'"); - break; - } - - switch($db->type) - { - case "pgsql": - $db->add_column("privatemessages", "ipaddress", "bytea NOT NULL default ''"); - $db->add_column("polls", "maxoptions", "smallint NOT NULL default '0'"); - break; - case "sqlite": - $db->add_column("privatemessages", "ipaddress", "blob(16) NOT NULL default ''"); - $db->add_column("polls", "maxoptions", "smallint NOT NULL default '0'"); - break; - default: - $db->add_column("privatemessages", "ipaddress", "varbinary(16) NOT NULL default ''"); - $db->add_column("polls", "maxoptions", "smallint unsigned NOT NULL default '0'"); - break; - } - - $groups = range(1, 39); - - $sql = implode(',', $groups); - $db->update_query("templategroups", array('isdefault' => 1), "gid IN ({$sql})"); - - if($db->table_exists('reportedposts')) - { - $db->update_query("reportedposts", array('type' => 'post')); - } - - $db->insert_query("questions", array('question' => 'What does 2 + 2 equal?', 'answer' => '4\nFour', 'active' => '1')); - - $query = $db->simple_select("attachtypes", "COUNT(*) as numexists", "extension='psd'"); - if($db->fetch_field($query, "numexists") == 0) - { - $db->insert_query("attachtypes", array('name' => "Adobe Photoshop File", 'mimetype' => 'application/x-photoshop', 'extension' => "psd", 'maxsize' => '1024', 'icon' => 'images/attachtypes/psd.png')); - } - // SQLite... As we modify tables below we need to close all cursors before... - if($db->type == "sqlite") - { - $query->closeCursor(); - } - - $query = $db->simple_select("templategroups", "COUNT(*) as numexists", "prefix='video'"); - if($db->fetch_field($query, "numexists") == 0) - { - $db->insert_query("templategroups", array('prefix' => 'video', 'title' => '', 'isdefault' => '1')); - } - // SQLite... As we modify tables below we need to close all cursors before... - if($db->type == "sqlite") - { - $query->closeCursor(); - } - - $query = $db->simple_select("templategroups", "COUNT(*) as numexists", "prefix='php'"); - if($db->fetch_field($query, "numexists") != 0) - { - $db->update_query("templategroups", array('prefix' => 'announcement', 'title' => ''), "prefix='php'"); - } - // SQLite... As we modify tables below we need to close all cursors before... - if($db->type == "sqlite") - { - $query->closeCursor(); - } - - $query = $db->simple_select("templategroups", "COUNT(*) as numexists", "prefix='redirect'"); - if($db->fetch_field($query, "numexists") != 0) - { - $db->update_query("templategroups", array('prefix' => 'posticons', 'title' => ''), "prefix='redirect'"); - } - // SQLite... As we modify tables below we need to close all cursors before... - if($db->type == "sqlite") - { - $query->closeCursor(); - } - - // Sync usergroups with canbereported; no moderators or banned groups - echo "

    Updating usergroup permissions...

    "; - $groups = array(); - $usergroups = $cache->read('usergroups'); - - foreach($usergroups as $group) - { - if($group['canmodcp'] || $group['isbannedgroup']) - { - continue; - } - - $groups[] = "'{$group['gid']}'"; - } - - if(!empty($groups)) - { - $usergroups = implode(',', $groups); - $db->update_query('usergroups', array('canbereported' => 1), "gid IN ({$usergroups})"); - } - - $db->update_query('usergroups', array('canviewboardclosed' => 1), 'cancp = 1'); - - if($db->table_exists('reportedposts')) - { - if($db->field_exists("pid", "reportedposts") && !$db->field_exists("id", "reportedposts")) - { - switch($db->type) - { - case "pgsql": - $db->rename_column("reportedposts", "pid", "id", "int", true, "'0'"); - break; - default: - $db->rename_column("reportedposts", "pid", "id", "int unsigned NOT NULL default '0'"); - } - } - - if($db->field_exists("tid", "reportedposts") && !$db->field_exists("id2", "reportedposts")) - { - switch($db->type) - { - case "pgsql": - $db->rename_column("reportedposts", "tid", "id2", "int", true, "'0'"); - break; - default: - $db->rename_column("reportedposts", "tid", "id2", "int unsigned NOT NULL default '0'"); - } - } - - if($db->field_exists("fid", "reportedposts") && !$db->field_exists("id3", "reportedposts")) - { - switch($db->type) - { - case "pgsql": - $db->rename_column("reportedposts", "fid", "id3", "int", true, "'0'"); - break; - default: - $db->rename_column("reportedposts", "fid", "id3", "int unsigned NOT NULL default '0'"); - } - } - } - - if($db->table_exists('reportedposts')) - { - if($db->table_exists("reportedcontent")) - { - $db->drop_table("reportedcontent"); - } - - $db->rename_table("reportedposts", "reportedcontent"); - - $cache->delete('reportedposts'); - } - - $db->update_query("settings", array('optionscode' => 'select\r\n0=No CAPTCHA\r\n1=MyBB Default CAPTCHA\r\n2=reCAPTCHA\r\n3=Are You a Human'), "name='captchaimage'"); - $db->update_query("settings", array('optionscode' => 'select\r\ninstant=Instant Activation\r\nverify=Send Email Verification\r\nrandompass=Send Random Password\r\nadmin=Administrator Activation\r\nboth=Email Verification & Administrator Activation'), "name='regtype'"); - $db->update_query("settings", array('optionscode' => $db->escape_string('php -')), "name='timezoneoffset'"); - - // Update tasks - $added_tasks = sync_tasks(); - - // For the version check task, set a random date and hour (so all MyBB installs don't query mybb.com all at the same time) - $update_array = array( - 'hour' => rand(0, 23), - 'weekday' => rand(0, 6) - ); - - $db->update_query("tasks", $update_array, "file = 'versioncheck'"); - - echo "

    Added {$added_tasks} new tasks.

    "; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_threadcount"); -} - -function upgrade30_threadcount() -{ - global $db, $output; - - $output->print_header("Counting user thread count"); - - if(!$_POST['theadspage']) - { - $threads = 500; - } - else - { - $threads = (int)$_POST['theadspage']; - } - - if($_POST['threadstart']) - { - $startat = (int)$_POST['threadstart']; - $upper = $startat+$threads; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $threads; - $lower = 0; - } - - $query = $db->simple_select("users", "COUNT(uid) AS usercount"); - $cnt = $db->fetch_array($query); - - if($upper > $cnt['usercount']) - { - $upper = $cnt['usercount']; - } - - echo "

    Counting thread count of user #{$lower} to #{$upper} ({$cnt['usercount']} Total)

    "; - flush(); - - $threadnum = false; - - $query = $db->simple_select("users", "threadnum, uid", "", array('limit_start' => $lower, 'limit' => $threads)); - while($thread = $db->fetch_array($query)) - { - $query2 = $db->simple_select("threads", "COUNT(tid) AS thread_count", "uid='{$thread['uid']}' AND visible = 1"); - $num_threads = $db->fetch_field($query2, "thread_count"); - - $db->update_query("users", array('threadnum' => $num_threads), "uid = '{$thread['uid']}'"); - - $threadnum = true; - } - - $remaining = $upper-$cnt['usercount']; - if($remaining && $threadnum) - { - $nextact = "30_threadcount"; - $startat = $startat+$threads; - $contents = "

    Done. Click Next to move on to the next set of thread counts.

    "; - } - else - { - $nextact = "30_dbchanges_optimize1"; - $contents = "

    Done

    All users have had their thread count counted. Click next to continue.

    "; - } - $output->print_contents($contents); - - global $footer_extra; - $footer_extra = ""; - - $output->print_footer($nextact); -} - -function upgrade30_dbchanges_optimize1() -{ - global $output, $mybb, $db; - - $output->print_header("Optimizing Database"); - - echo "

    Performing necessary optimization queries...

    "; - flush(); - - switch($db->type) - { - case "pgsql": - $db->modify_column("adminoptions", "loginattempts", "smallint", "set", "'0'"); - $db->modify_column("adminviews", "perpage", "smallint", "set", "'0'"); - $db->modify_column("calendars", "disporder", "smallint", "set", "'0'"); - $db->modify_column("calendars", "eventlimit", "smallint", "set", "'0'"); - $db->modify_column("events", "timezone", "varchar(5)", "set", "''"); - $db->modify_column("forums", "lastposttid", "int", "set", "'0'"); - $db->modify_column("mailerrors", "smtpcode", "smallint", "set", "'0'"); - $db->modify_column("maillogs", "touid", "int", "set", "'0'"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."polls ALTER COLUMN numvotes DROP DEFAULT"); // We need to drop the default first as PostgreSQL can't cast default values - $db->modify_column("polls", "numvotes", "int USING (trim(numvotes)::int)", "set", "'0'"); - $db->modify_column("profilefields", "postnum", "smallint", "set", "'0'"); - $db->modify_column("reputation", "reputation", "smallint", "set", "'0'"); - $db->modify_column("spiders", "theme", "smallint", "set", "'0'"); - $db->modify_column("spiders", "usergroup", "smallint", "set", "'0'"); - $db->modify_column("templates", "sid", "smallint", "set", "'0'"); - $db->modify_column("themestylesheets", "tid", "smallint", "set", "'0'"); - $db->modify_column("usergroups", "canusesigxposts", "smallint", "set", "'0'"); - $db->modify_column("users", "timezone", "varchar(5)", "set", "''"); - $db->modify_column("users", "reputation", "int", "set", "'0'"); - $db->modify_column("warninglevels", "percentage", "smallint", "set", "'0'"); - $db->modify_column("warningtypes", "points", "smallint", "set", "'0'"); - $db->modify_column("warnings", "points", "smallint", "set", "'0'"); - break; - case "sqlite": - $db->modify_column("adminoptions", "loginattempts", "smallint NOT NULL default '0'"); - $db->modify_column("adminviews", "perpage", "smallint NOT NULL default '0'"); - $db->modify_column("calendars", "disporder", "smallint NOT NULL default '0'"); - $db->modify_column("calendars", "eventlimit", "smallint NOT NULL default '0'"); - $db->modify_column("events", "timezone", "varchar(5) NOT NULL default ''"); - $db->modify_column("forums", "lastposttid", "int NOT NULL default '0'"); - $db->modify_column("mailerrors", "smtpcode", "smallint NOT NULL default '0'"); - $db->modify_column("maillogs", "touid", "int NOT NULL default '0'"); - $db->modify_column("polls", "numvotes", "int NOT NULL default '0'"); - $db->modify_column("profilefields", "postnum", "smallint NOT NULL default '0'"); - $db->modify_column("reputation", "reputation", "smallint NOT NULL default '0'"); - $db->modify_column("spiders", "theme", "smallint NOT NULL default '0'"); - $db->modify_column("spiders", "usergroup", "smallint NOT NULL default '0'"); - $db->modify_column("templates", "sid", "smallint NOT NULL default '0'"); - $db->modify_column("themestylesheets", "tid", "smallint NOT NULL default '0'"); - $db->modify_column("usergroups", "canusesigxposts", "smallint NOT NULL default '0'"); - $db->modify_column("users", "timezone", "varchar(5) NOT NULL default ''"); - $db->modify_column("users", "reputation", "int NOT NULL default '0'"); - $db->modify_column("warninglevels", "percentage", "smallint NOT NULL default '0'"); - $db->modify_column("warningtypes", "points", "smallint NOT NULL default '0'"); - $db->modify_column("warnings", "points", "smallint NOT NULL default '0'"); - break; - default: - $db->modify_column("adminoptions", "loginattempts", "smallint unsigned NOT NULL default '0'"); - $db->modify_column("adminviews", "perpage", "smallint(4) NOT NULL default '0'"); - $db->modify_column("calendars", "disporder", "smallint unsigned NOT NULL default '0'"); - $db->modify_column("calendars", "eventlimit", "smallint(3) NOT NULL default '0'"); - $db->modify_column("events", "timezone", "varchar(5) NOT NULL default ''"); - $db->modify_column("forums", "lastposttid", "int unsigned NOT NULL default '0'"); - $db->modify_column("mailerrors", "smtpcode", "smallint(5) unsigned NOT NULL default '0'"); - $db->modify_column("maillogs", "touid", "int unsigned NOT NULL default '0'"); - $db->modify_column("polls", "numvotes", "int unsigned NOT NULL default '0'"); - $db->modify_column("profilefields", "postnum", "smallint unsigned NOT NULL default '0'"); - $db->modify_column("reputation", "reputation", "smallint NOT NULL default '0'"); - $db->modify_column("spiders", "theme", "smallint unsigned NOT NULL default '0'"); - $db->modify_column("spiders", "usergroup", "smallint unsigned NOT NULL default '0'"); - $db->modify_column("templates", "sid", "smallint NOT NULL default '0'"); - $db->modify_column("themestylesheets", "tid", "smallint unsigned NOT NULL default '0'"); - $db->modify_column("usergroups", "canusesigxposts", "smallint unsigned NOT NULL default '0'"); - $db->modify_column("users", "timezone", "varchar(5) NOT NULL default ''"); - $db->modify_column("users", "reputation", "int NOT NULL default '0'"); - $db->modify_column("warninglevels", "percentage", "smallint(3) NOT NULL default '0'"); - $db->modify_column("warningtypes", "points", "smallint unsigned NOT NULL default '0'"); - $db->modify_column("warnings", "points", "smallint unsigned NOT NULL default '0'"); - break; - } - - if($db->type != "pgsql") - { - // PgSQL doesn't support longtext - if($db->type == "sqlite") - { - // And SQLite doesn't like text columns without a default value... - $db->modify_column("themestylesheets", "stylesheet", "longtext NOT NULL default ''"); - } - else - { - // ...while MySQL hates text columns with a default value - $db->modify_column("themestylesheets", "stylesheet", "longtext NOT NULL"); - } - } - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_dbchanges_optimize2"); -} - -function upgrade30_dbchanges_optimize2() -{ - global $output, $mybb, $db; - - $output->print_header("Optimizing Database"); - - echo "

    Performing necessary optimization queries...

    "; - echo "

    Adding indexes to tables...

    "; - flush(); - - if($db->index_exists('sessions', 'location1')) - { - $db->drop_index('sessions', 'location1'); - } - - if($db->index_exists('sessions', 'location2')) - { - $db->drop_index('sessions', 'location2'); - } - - if($db->type == "mysql" || $db->type == "mysqli") - { - $update_data = array( - 'adminlog' => 'uid', - 'banfilters' => 'type', - 'events' => 'cid', - 'forumsubscriptions' => 'uid', - 'moderatorlog' => array('uid', 'fid'), - 'polls' => 'tid', - 'reportedcontent' => 'reportstatus', - 'settings' => 'gid', - 'themestylesheets' => 'tid', - 'warnings' => 'uid', - 'forumpermissions' => array('fid' => array('fid', 'gid')), - 'sessions' => array('location' => array('location1', 'location2')), - 'templates' => array('sid' => array('sid', 'title')) - ); - - foreach($update_data as $table => $index) - { - if(!is_array($index)) - { - $index = array($index); - } - - foreach($index as $_index => $keys) - { - if(!is_array($keys)) - { - if(!$db->index_exists($table, $keys)) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."{$table} ADD INDEX (`{$keys}`)"); - } - } - else - { - if(!$db->index_exists($table, $_index)) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."{$table} ADD INDEX `{$_index}`(`".implode('`, `', $keys)."`)"); - } - } - } - } - } - - echo "

    Dropping old indexes from tables...

    "; - - if($db->index_exists('attachments', 'posthash')) - { - $db->drop_index('attachments', 'posthash'); - } - - if($db->index_exists('reportedcontent', 'dateline')) - { - $db->drop_index('reportedcontent', 'dateline'); - } - - if($db->index_exists('reputation', 'pid')) - { - $db->drop_index('reputation', 'pid'); - } - - if($db->index_exists('reputation', 'dateline')) - { - $db->drop_index('reputation', 'dateline'); - } - - if($db->index_exists('users', 'birthday')) - { - $db->drop_index('users', 'birthday'); - } - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_dbchanges_optimize3"); -} - -function upgrade30_dbchanges_optimize3() -{ - global $cache, $output, $mybb, $db; - - $output->print_header("Optimizing Database"); - - echo "

    Performing necessary optimization queries...

    "; - flush(); - - $to_tinyint = array( - "adminoptions" => array("codepress"), - "adminviews" => array("visibility"), - "announcements" => array("allowhtml", "allowmycode", "allowsmilies"), - "attachments" => array("visible"), - "banfilters" => array("type"), - "calendars" => array("startofweek", "showbirthdays", "moderation", "allowhtml", "allowmycode", "allowimgcode", "allowvideocode", "allowsmilies"), - "calendarpermissions" => array("canviewcalendar", "canaddevents", "canbypasseventmod", "canmoderateevents"), - "events" => array("visible", "private", "ignoretimezone", "usingtime"), - "forumpermissions" => array("canview", "canviewthreads", "canonlyviewownthreads", "candlattachments", "canpostthreads", "canpostreplys", "canpostattachments", "canratethreads", "caneditposts", "candeleteposts", "candeletethreads", "caneditattachments", "canpostpolls", "canvotepolls", "cansearch"), - "forums" => array("active", "open", "allowhtml", "allowmycode", "allowsmilies", "allowimgcode", "allowvideocode", "allowpicons", "allowtratings", "usepostcounts", "showinjump", "overridestyle", "rulestype"), - "groupleaders" => array("canmanagemembers", "canmanagerequests"), - "helpdocs" => array("usetranslation", "enabled"), - "helpsections" => array("usetranslation", "enabled"), - "moderators" => array("isgroup", "caneditposts", "candeleteposts", "canviewips", "canopenclosethreads", "canmanagethreads", "canmovetononmodforum", "canusecustomtools"), - "mycode" => array("active"), - "polls" => array("closed", "multiple", "public"), - "posts" => array("includesig", "smilieoff", "visible"), - "privatemessages" => array("status", "includesig", "smilieoff", "receipt"), - "profilefields" => array("required"), - "reportedcontent" => array("reportstatus"), - "sessions" => array("anonymous", "nopermission"), - "settinggroups" => array("isdefault"), - "settings" => array("isdefault"), - "smilies" => array("showclickable"), - "tasks" => array("enabled", "logging"), - "themes" => array("def"), - "threads" => array("sticky", "visible"), - "threadsubscriptions" => array("notification"), - "usergroups" => array("isbannedgroup", "canview", "canviewthreads", "canviewprofiles", "candlattachments", "canviewboardclosed", "canpostthreads", "canpostreplys", "canpostattachments", "canratethreads", "caneditposts", "candeleteposts", "candeletethreads", "caneditattachments", "canpostpolls", "canvotepolls", "canundovotes", "canusepms", "cansendpms", "cantrackpms", "candenypmreceipts", "cansendemail", "cansendemailoverride", "canviewmemberlist", "canviewcalendar", "canaddevents", "canbypasseventmod", "canmoderateevents", "canviewonline", "canviewwolinvis", "canviewonlineips", "cancp", "issupermod", "cansearch", "canusercp", "canuploadavatars", "canratemembers", "canchangename", "canbereported", "showforumteam", "usereputationsystem", "cangivereputations", "candisplaygroup", "cancustomtitle", "canwarnusers", "canreceivewarnings", "canmodcp", "showinbirthdaylist", "canoverridepm", "canusesig", "signofollow"), - "users" => array("allownotices", "hideemail", "subscriptionmethod", "invisible", "receivepms", "receivefrombuddy", "pmnotice", "pmnotify", "showsigs", "showavatars", "showquickreply", "showredirect", "showcodebuttons", "coppauser", "classicpostbit"), - "warnings" => array("expired") - ); - - foreach($to_tinyint as $table => $columns) - { - echo "

    {$table}: Converting column type to tinyint

    "; - $change_column = array(); - foreach($columns as $column) - { - if($db->type == "pgsql") - { - $db->modify_column($table, $column, "smallint", "set", "'0'"); - } - else if($db->type == "sqlite") - { - $change_column[] = "CHANGE {$column} {$column} tinyint(1) NOT NULL default '0'"; - } - else - { - $change_column[] = "MODIFY {$column} tinyint(1) NOT NULL default '0'"; - } - } - if($db->type != "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."{$table} ".implode(", ", $change_column)); - } - } - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_dbchanges_optimize4"); -} - -function upgrade30_dbchanges_optimize4() -{ - global $cache, $output, $mybb, $db; - - $output->print_header("Optimizing Database"); - - echo "

    Performing necessary optimization queries...

    "; - flush(); - - $to_int = array( - "adminlog" => array("dateline"), - "adminsessions" => array("dateline", "lastactive"), - "announcements" => array("startdate", "enddate"), - "attachments" => array("dateuploaded"), - "awaitingactivation" => array("dateline"), - "banfilters" => array("lastuse", "dateline"), - "banned" => array("dateline", "lifted"), - "captcha" => array("dateline"), - "delayedmoderation" => array("delaydateline", "dateline"), - "forumsread" => array("dateline"), - "joinrequests" => array("dateline"), - "massemails" => array("dateline", "senddate"), - "mailerrors" => array("dateline"), - "maillogs" => array("dateline"), - "moderatorlog" => array("dateline"), - "polls" => array("dateline", "timeout"), - "pollvotes" => array("dateline"), - "posts" => array("dateline", "edittime"), - "privatemessages" => array("dateline", "deletetime", "statustime", "readtime"), - "promotionlogs" => array("dateline"), - "reportedcontent" => array("dateline", "lastreport"), - "reputation" => array("dateline"), - "searchlog" => array("dateline"), - "sessions" => array("time"), - "spiders" => array("lastvisit"), - "stats" => array("dateline"), - "tasks" => array("nextrun", "lastrun", "locked"), - "tasklog" => array("dateline"), - "templates" => array("dateline"), - "themestylesheets" => array("lastmodified"), - "threads" => array("dateline", "lastpost"), - "threadsread" => array("dateline"), - "threadsubscriptions" => array("dateline"), - "threadsread" => array("dateline"), - "usergroups" => array("reputationpower", "maxreputationsday", "maxreputationsperuser", "maxreputationsperthread", "attachquota"), - "users" => array("regdate", "lastactive", "lastvisit", "lastpost", "timeonline", "moderationtime", "suspensiontime", "suspendsigtime"), - "warningtypes" => array("expirationtime"), - "warnings" => array("dateline", "expires", "daterevoked") - ); - - foreach($to_int as $table => $columns) - { - echo "

    {$table}: Converting column type to int

    "; - $change_column = array(); - foreach($columns as $column) - { - if($db->type == "pgsql") - { - $db->modify_column($table, $column, "int", "set", "'0'"); - } - else if($db->type == "sqlite") - { - $change_column[] = "CHANGE {$column} {$column} int unsigned NOT NULL default '0'"; - } - else - { - $change_column[] = "MODIFY {$column} int unsigned NOT NULL default '0'"; - } - } - if($db->type != "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."{$table} ".implode(", ", $change_column)); - } - } - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_dbchanges_smilies"); -} - -function upgrade30_dbchanges_smilies() -{ - global $cache, $output, $db; - - $output->print_header("Updating Smilies"); - - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->type == 'pgsql') - { - $db->modify_column("smilies", "find", "text", "set"); - } - else - { - $db->modify_column("smilies", "find", "text NOT NULL"); - } - - $query = $db->simple_select('smilies', 'sid, image, find', '', array('order_by' => 'image, sid')); - $last_image = null; - $last_sid = 0; - $skip = array(); - while($smilie = $db->fetch_array($query)) - { - if(in_array($smilie['sid'], $skip)) - { - continue; - } - - if($smilie['image'] == $last_image && $smilie['image'] != null) - { - $dupe_query = $db->simple_select('smilies', 'sid, find', 'image = "'.$db->escape_string($smilie['image']).'"'); - $dupes = ''; - $find = array(); - $skip = array(); - while($dupe = $db->fetch_array($dupe_query)) - { - if($dupe['sid'] != $last_sid) - { - $dupes .= (int)$dupe['sid'].','; - $find[] = trim($dupe['find']); - $skip[] = (int)$dupe['sid']; - } - else - { - $find[] = $dupe['find']; - } - } - $dupes = rtrim($dupes, ','); - $db->delete_query('smilies', 'sid IN('.$dupes.')'); - $db->update_query('smilies', array('find' => implode("\n", $find)), 'sid = "'.(int)$last_sid.'"'); - $db->free_result($dupe_query); - } - else - { - $last_sid = $smilie['sid']; - $last_image = $smilie['image']; - } - } - - $cache->update_smilies(); - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("30_dbchanges_ip"); -} - -function upgrade30_dbchanges_ip() -{ - global $mybb, $db, $output; - - $output->print_header("IP Conversion"); - - $ipstart = $iptable = ''; - - switch($mybb->input['iptask']) - { - case 8: - echo "

    Adding database indices (3/3)...

    "; - flush(); - - if(!$db->index_exists('users', 'lastip')) - { - // This may take a while - if($db->type == "mysql" || $db->type == "mysqli") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD INDEX lastip (lastip)"); - } - elseif($db->type == "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD INDEX (`lastip`)"); - } - } - $next_task = 9; - break; - case 7: - echo "

    Adding database indices (2/3)...

    "; - flush(); - - if(!$db->index_exists('users', 'regip')) - { - // This may take a while - if($db->type == "mysql" || $db->type == "mysqli") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD INDEX regip (regip)"); - } - elseif($db->type == "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD INDEX (`regip`)"); - } - } - $next_task = 8; - break; - case 6: - echo "

    Adding database indices (1/3)...

    "; - flush(); - - if(!$db->index_exists('posts', 'ipaddress')) - { - // This may take a while - if($db->type == "mysql" || $db->type == "mysqli") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts ADD INDEX ipaddress (ipaddress)"); - } - elseif($db->type == "pgsql") - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts ADD INDEX (`ipaddress`)"); - } - } - $next_task = 7; - break; - case 5: - if(!$_POST['ipspage']) - { - $ipp = 5000; - } - else - { - $ipp = (int)$_POST['ipspage']; - } - - if($_POST['ipstart']) - { - $startat = (int)$_POST['ipstart']; - $upper = $startat+$ipp-1; - $lower = $startat; - } - else - { - $startat = 0; - $upper = $ipp; - $lower = 0; - } - - $next_task = 5; - switch($mybb->input['iptable']) - { - case 7: - echo "

    Converting user IPs...

    "; - flush(); - $query = $db->simple_select("users", "COUNT(uid) AS ipcount"); - if($db->type == "mysql" || $db->type == "mysqli") - { - $next_task = 6; - } - else - { - $next_task = 9; - } - break; - case 6: - echo "

    Converting thread rating IPs...

    "; - flush(); - $query = $db->simple_select("threadratings", "COUNT(rid) AS ipcount"); - break; - case 5: - echo "

    Converting session IPs...

    "; - flush(); - $query = $db->simple_select("sessions", "COUNT(sid) AS ipcount"); - break; - case 4: - echo "

    Converting post IPs...

    "; - flush(); - $query = $db->simple_select("posts", "COUNT(pid) AS ipcount"); - break; - case 3: - echo "

    Converting moderator log IPs...

    "; - flush(); - $query = $db->simple_select("moderatorlog", "COUNT(DISTINCT ipaddress) AS ipcount"); - break; - case 2: - echo "

    Converting mail log IPs...

    "; - flush(); - $query = $db->simple_select("maillogs", "COUNT(mid) AS ipcount"); - break; - default: - echo "

    Converting admin log IPs...

    "; - flush(); - $query = $db->simple_select("adminlog", "COUNT(DISTINCT ipaddress) AS ipcount"); - break; - } - $cnt = $db->fetch_array($query); - - if($upper > $cnt['ipcount']) - { - $upper = $cnt['ipcount']; - } - - echo "

    Converting ip {$lower} to {$upper} ({$cnt['ipcount']} Total)

    "; - flush(); - - $ipaddress = false; - - switch($mybb->input['iptable']) - { - case 7: - $query = $db->simple_select("users", "uid, regip, lastip", "", array('limit_start' => $lower, 'limit' => $ipp)); - break; - case 6: - $query = $db->simple_select("threadratings", "rid, ipaddress", "", array('limit_start' => $lower, 'limit' => $ipp)); - break; - case 5: - $query = $db->simple_select("sessions", "sid, ip", "", array('limit_start' => $lower, 'limit' => $ipp)); - break; - case 4: - $query = $db->simple_select("posts", "pid, ipaddress", "", array('limit_start' => $lower, 'limit' => $ipp)); - break; - case 3: - $query = $db->simple_select("moderatorlog", "DISTINCT(ipaddress)", "", array('limit_start' => $lower, 'limit' => $ipp)); - break; - case 2: - $query = $db->simple_select("maillogs", "mid, ipaddress", "", array('limit_start' => $lower, 'limit' => $ipp)); - break; - default: - $query = $db->simple_select("adminlog", "DISTINCT(ipaddress)", "", array('limit_start' => $lower, 'limit' => $ipp)); - $mybb->input['iptable'] = 1; - break; - } - while($data = $db->fetch_array($query)) - { - // Skip invalid IPs - switch($mybb->input['iptable']) - { - case 7: - $ip1 = my_inet_pton($db->unescape_binary($data['regip'])); - $ip2 = my_inet_pton($db->unescape_binary($data['lastip'])); - if($ip1 === false && $ip2 === false) - { - continue; - } - break; - case 5: - $ip = my_inet_pton($db->unescape_binary($data['ip'])); - if($ip === false) - { - continue; - } - break; - case 6: - case 4: - case 3: - case 2: - default: - $ip = my_inet_pton($db->unescape_binary($data['ipaddress'])); - if($ip === false) - { - continue; - } - break; - } - - switch($mybb->input['iptable']) - { - case 7: - $db->update_query("users", array('regip' => $db->escape_binary($ip1), 'lastip' => $db->escape_binary($ip2)), "uid = '".(int)$data['uid']."'"); - break; - case 6: - $db->update_query("threadratings", array('ipaddress' => $db->escape_binary($ip)), "rid = '".(int)$data['rid']."'"); - break; - case 5: - $db->update_query("sessions", array('ip' => $db->escape_binary($ip)), "sid = '".(int)$data['sid']."'"); - break; - case 4: - $db->update_query("posts", array('ipaddress' => $db->escape_binary($ip)), "pid = '".(int)$data['pid']."'"); - break; - case 3: - $db->update_query("moderatorlog", array('ipaddress' => $db->escape_binary($ip)), "ipaddress = '".$db->escape_string($data['ipaddress'])."'"); - break; - case 2: - $db->update_query("maillogs", array('ipaddress' => $db->escape_binary($ip)), "mid = '".(int)$data['mid']."'"); - break; - default: - $db->update_query("adminlog", array('ipaddress' => $db->escape_binary($ip)), "ipaddress = '".$db->escape_string($data['ipaddress'])."'"); - break; - } - $ipaddress = true; - } - - $remaining = $upper-$cnt['ipcount']; - if($remaining && $ipaddress) - { - $startat = $startat+$ipp; - $ipstart = ""; - $iptable = $mybb->input['iptable']; - } - else - { - $iptable = $mybb->input['iptable']+1; - } - if($iptable <= 10) - { - $iptable = ""; - } - break; - case 4: - $next_task = 4; - switch($mybb->input['iptable']) - { - case 10: - echo "

    Updating user table (4/4)...

    "; - flush(); - - $table = 'users'; - $column = 'lastip'; - $next_task = 5; - break; - case 9: - echo "

    Updating user table (3/4)...

    "; - flush(); - - $table = 'users'; - $column = 'regip'; - break; - case 8: - echo "

    Updating threadreating table...

    "; - flush(); - - $table = 'threadratings'; - $column = 'ipaddress'; - break; - case 7: - echo "

    Updating session table...

    "; - flush(); - - $table = 'sessions'; - $column = 'ip'; - break; - case 6: - echo "

    Updating searchlog table...

    "; - flush(); - - $table = 'searchlog'; - $column = 'ipaddress'; - // Skip conversion - $db->delete_query('searchlog'); - break; - case 5: - echo "

    Updating post table (2/2)...

    "; - flush(); - - $table = 'posts'; - $column = 'ipaddress'; - break; - case 4: - echo "

    Updating moderatorlog table...

    "; - flush(); - - $table = 'moderatorlog'; - $column = 'ipaddress'; - break; - case 3: - echo "

    Updating maillog table...

    "; - flush(); - - $table = 'maillogs'; - $column = 'ipaddress'; - break; - case 2: - echo "

    Updating adminsession table...

    "; - flush(); - - $table = 'adminsessions'; - $column = 'ip'; - // Skip conversion - $db->delete_query('adminsessions'); - break; - default: - echo "

    Updating adminlog table...

    "; - flush(); - - $mybb->input['iptable'] = 1; - $table = 'adminlog'; - $column = 'ipaddress'; - break; - } - // Truncate invalid IPs - $db->write_query("UPDATE ".TABLE_PREFIX."{$table} SET {$column} = SUBSTR({$column}, 16) WHERE LENGTH({$column})>16"); - switch($db->type) - { - case "pgsql": - // Drop default value before converting the column - $db->modify_column($table, $column, false, false); - $db->modify_column($table, $column, "bytea USING {$column}::bytea", 'set', "''"); - break; - case "sqlite": - $db->modify_column($table, $column, "blob(16) NOT NULL default ''"); - break; - default: - $db->modify_column($table, $column, "varbinary(16) NOT NULL default ''"); - break; - } - if($mybb->input['iptable'] < 10) - { - $iptable = "input['iptable']+1)."\" />"; - } - break; - case 3: - echo "

    Updating user table (2/4)...

    "; - flush(); - - if($db->field_exists('longlastip', 'users')) - { - // This may take a while - $db->drop_column("users", "longlastip"); - } - $next_task = 4; - break; - case 2: - echo "

    Updating user table (1/4)...

    "; - flush(); - - if($db->field_exists('longregip', 'users')) - { - // This may take a while - $db->drop_column("users", "longregip"); - } - $next_task = 3; - break; - default: - echo "

    Updating post table (1/2)...

    "; - flush(); - - if($db->field_exists('longipaddress', 'posts')) - { - // This may take a while - $db->drop_column("posts", "longipaddress"); - } - $next_task = 2; - break; - } - - if($next_task == 9) - { - $contents = "

    Click next to continue with the upgrade process.

    "; - $nextact = "30_updatetheme"; - } - else - { - $contents = "

    {$iptable}{$ipstart}Done. Click Next to continue the IP conversion.

    "; - - global $footer_extra; - $footer_extra = ""; - $nextact = "30_dbchanges_ip"; - } - - $output->print_contents($contents); - - $output->print_footer($nextact); -} - -function upgrade30_updatetheme() -{ - global $db, $mybb, $output, $config; - - if(file_exists(MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php")) - { - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php"; - } - else if(file_exists(MYBB_ROOT."admin/inc/functions_themes.php")) - { - require_once MYBB_ROOT."admin/inc/functions_themes.php"; - } - else - { - $output->print_error("Please make sure your admin directory is uploaded correctly."); - } - - $output->print_header("Updating Themes"); - - // New default user star - $contents = "

    Updating the Default user star image... "; - $db->update_query("usergroups", array('starimage' => 'images/star.png'), "starimage='images/star.gif'"); - $contents .= "done.

    "; - - $contents .= "

    Adding new stylesheets... "; - - $query = $db->simple_select("themes", "*", "tid='1'"); - - $theme = $db->fetch_array($query); - $properties = my_unserialize($theme['properties']); - $stylesheets = my_unserialize($theme['stylesheets']); - - $old = array("global.css", "usercp.css", "modcp.css", "star_ratings.css"); - require_once MYBB_ROOT."inc/class_xml.php"; - $colors = @file_get_contents(INSTALL_ROOT.'resources/mybb_theme.xml'); - $parser = new XMLParser($colors); - $tree = $parser->get_tree(); - - if(is_array($tree) && is_array($tree['theme'])) - { - if(is_array($tree['theme']['stylesheets'])) - { - foreach($tree['theme']['stylesheets']['stylesheet'] as $stylesheet) - { - $new_stylesheet = array( - "name" => $db->escape_string($stylesheet['attributes']['name']), - "tid" => 1, - "attachedto" => $db->escape_string($stylesheet['attributes']['attachedto']), - "stylesheet" => $db->escape_string($stylesheet['value']), - "lastmodified" => TIME_NOW, - "cachefile" => $db->escape_string($stylesheet['attributes']['name']) - ); - - if(in_array($new_stylesheet['name'], $old)) - { - // We can update the disporder here - $properties['disporder'][$stylesheet['attributes']['name']] = $stylesheet['attributes']['disporder']; - } - else - { - // Insert new stylesheet - $sid = $db->insert_query("themestylesheets", $new_stylesheet); - $css_url = "css.php?stylesheet={$sid}"; - - $cached = cache_stylesheet($tid, $stylesheet['attributes']['name'], $stylesheet['value']); - - if($cached) - { - $css_url = $cached; - } - - // Add to display and stylesheet list - $properties['disporder'][$stylesheet['attributes']['name']] = $stylesheet['attributes']['disporder']; - $attachedto = $stylesheet['attributes']['attachedto']; - if(!$attachedto) - { - $attachedto = "global"; - } - - // private.php?compose,folders|usercp.php,global|global - $attachedto = explode("|", $attachedto); - foreach($attachedto as $attached_file) - { - $attached_actions = explode(",", $attached_file); - $attached_file = array_shift($attached_actions); - if(count($attached_actions) == 0) - { - $attached_actions = array("global"); - } - - foreach($attached_actions as $action) - { - $stylesheets[$attached_file][$action][] = $css_url; - } - } - } - } - } - } - - $update_array = array( - "properties" => $db->escape_string(my_serialize($properties)), - "stylesheets" => $db->escape_string(my_serialize($stylesheets)) - ); - - $db->update_query("themes", $update_array, "tid = '1'"); - - $contents .= "done.

    "; - - $contents .= "

    Adding a disporder to all stylesheets... "; - - $query = $db->simple_select("themes", "tid,properties,stylesheets"); - while($theme = $db->fetch_array($query)) - { - $properties = my_unserialize($theme['properties']); - $stylesheets = my_unserialize($theme['stylesheets']); - - // Disporder already set? - if(isset($properties['disporder']) && !empty($properties['disporder'])) - { - continue; - } - - $disporder = 1; - - // First go through all own stylesheets - $query2 = $db->simple_select("themestylesheets", "name", "tid='{$theme['tid']}'"); - while($name = $db->fetch_field($query2, "name")) - { - $properties['disporder'][$name] = $disporder; - $disporder++; - } - - // Next go through the inherited stylesheets - if(!empty($stylesheets)) - { - foreach($stylesheets as $a) - { - foreach($a as $file => $stylesheet) - { - // Don't ask me... Throws an error otherwise - if(empty($stylesheet)) - { - continue; - } - foreach($stylesheet as $s) - { - $name = pathinfo($s, PATHINFO_BASENAME); - if(empty($properties['disporder']) || !in_array($name, array_keys($properties['disporder']))) - { - $properties['disporder'][$name] = $disporder; - $disporder++; - } - } - } - } - } - - $db->update_query("themes", array("properties" => $db->escape_string(my_serialize($properties))), "tid='{$theme['tid']}'"); - } - - $contents .= "done.

    "; - - $contents .= "

    Adding the Default colors... "; - - $query = $db->simple_select("themes", "*", "tid = '2'"); - - // Someone deleted the default theme... :o - if($db->num_rows($query) != 0) - { - $theme = $db->fetch_array($query); - $properties = my_unserialize($theme['properties']); - $stylesheets = my_unserialize($theme['stylesheets']); - - $properties['editortheme'] = "mybb.css"; // New editor, so reset the theme for it - $properties['tablespace'] = 5; - $properties['borderwidth'] = 0; - // Reset the logo if it's still the default one - if($properties['logo'] == "images/logo.gif") - { - $properties['logo'] = "images/logo.png"; - } - - require_once MYBB_ROOT."inc/class_xml.php"; - $colors = @file_get_contents(INSTALL_ROOT.'resources/mybb_theme_colors.xml'); - $parser = new XMLParser($colors); - $tree = $parser->get_tree(); - - if(is_array($tree) && is_array($tree['colors'])) - { - if(is_array($tree['colors']['scheme'])) - { - foreach($tree['colors']['scheme'] as $tag => $value) - { - $exp = explode("=", $value['value']); - - $properties['colors'][$exp[0]] = $exp[1]; - } - } - - if(is_array($tree['colors']['stylesheets'])) - { - $count = count($properties['disporder']) + 1; - foreach($tree['colors']['stylesheets']['stylesheet'] as $stylesheet) - { - $new_stylesheet = array( - "name" => $db->escape_string($stylesheet['attributes']['name']), - "tid" => 2, - "attachedto" => $db->escape_string($stylesheet['attributes']['attachedto']), - "stylesheet" => $db->escape_string($stylesheet['value']), - "lastmodified" => TIME_NOW, - "cachefile" => $db->escape_string($stylesheet['attributes']['name']) - ); - - $sid = $db->insert_query("themestylesheets", $new_stylesheet); - $css_url = "css.php?stylesheet={$sid}"; - - $cached = cache_stylesheet($tid, $stylesheet['attributes']['name'], $stylesheet['value']); - - if($cached) - { - $css_url = $cached; - } - - // Add to display and stylesheet list - $properties['disporder'][$stylesheet['attributes']['name']] = $count; - $stylesheets[$stylesheet['attributes']['attachedto']]['global'][] = $css_url; - - ++$count; - } - } - - $update_array = array( - "properties" => $db->escape_string(my_serialize($properties)), - "stylesheets" => $db->escape_string(my_serialize($stylesheets)) - ); - - $db->update_query("themes", $update_array, "tid = '2'"); - } - } - - $contents .= "done.

    "; - - $contents .= '

    Re-caching and minifying existing stylesheets...

    '; - - $num_re_cached = recache_existing_styles(); - - $contents .= "Done. {$num_re_cached} stylesheets re-cached."; - - echo $contents; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - - if(!isset($config['secret_pin']) && is_writable(MYBB_ROOT."inc/config.php")) - { - $output->print_footer("30_acppin"); - } - else - { - $output->print_footer("30_done"); - } -} - -function upgrade30_acppin() -{ - global $config, $output; - - $output->print_header("Add an ACP PIN"); - - echo "

    We added a new security function in 1.8: The possibility to set a security PIN which you need to enter the ACP.
    \n"; - echo "If you don't want to set a PIN you can simply skip this step (leave the field below empty). You can still set the PIN later (see the docs to see how).

    \n"; - echo '
    -
    ACP PIN Configuration
    - - - - - - - - - - -
    ACP Security PIN
    -
    '; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - - $output->print_footer("30_acppin_submit"); -} - -function upgrade30_acppin_submit() -{ - global $db, $mybb, $output, $config; - - $output->print_header("Writing the config file"); - - $content = "

    We're now writing your PIN (if you've entered one) to the config.php file... "; - - if(!is_writable(MYBB_ROOT."inc/config.php")) - { - $content .= "Failed (config.php not writable)"; - } - else if(isset($config['secret_pin'])) - { - $content .= "Skipped (PIN already set)"; - } - else - { - $pin = addslashes($mybb->get_input('pin')); - - $file = @fopen(MYBB_ROOT."inc/config.php", "r+"); - - $contents = ''; - while(!@feof($file)) - { - $contents .= @fread($file, 8436); - } - - $contents_temp = str_replace(array("\r", "\t", "\n", " ", "\0", "\x0B"), '', $contents); - - // Set the pointer before the closing php tag to remove it - $pos = strrpos($contents, "?>"); - if(my_substr($contents_temp, -2) == "?>") - { - @fseek($file, $pos, SEEK_SET); - } - - @fwrite($file, " -/** - * Admin CP Secret PIN - * If you wish to request a PIN - * when someone tries to login - * on your Admin CP, enter it below. - */ - -\$config['secret_pin'] = '{$pin}';"); - - @fclose($file); - - $content .= "Done"; - } - - echo $content."

    "; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - - $output->print_footer("30_done"); -} - -/** - * Re-cache the existing stylesheets so that they get minified. - * - * @return int The number of re-cached stylesheets. - */ -function recache_existing_styles() -{ - global $db; - - $query = $db->simple_select('themestylesheets', '*'); - - $num_updated = 0; - - while($stylesheet = $db->fetch_array($query)) - { - if (cache_stylesheet((int) $stylesheet['tid'], $stylesheet['name'], $stylesheet['stylesheet'])) - { - ++$num_updated; - } - } - - return $num_updated; -} diff --git a/html/forums/install/resources/upgrade31.php b/html/forums/install/resources/upgrade31.php deleted file mode 100644 index 8066626..0000000 --- a/html/forums/install/resources/upgrade31.php +++ /dev/null @@ -1,59 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade31_dbchanges() -{ - global $db, $output; - - $output->print_header("Updating Database"); - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - $query = $db->simple_select("templategroups", "COUNT(*) as numexists", "prefix='sendthread'"); - if($db->fetch_field($query, "numexists") == 0) - { - $db->insert_query("templategroups", array('prefix' => 'sendthread', 'title' => '', 'isdefault' => '1')); - } - - $db->update_query('settings', array('optionscode' => 'numeric'), 'name IN (\'statslimit\', \'maxmultipagelinks\', \'deleteinvites\', \'gziplevel\', \'subforumsindex\', \'showbirthdayspostlimit\', \'threadsperpage\') AND optionscode=\'text\''); - $db->update_query('settings', array('optionscode' => 'numeric'), 'name IN (\'hottopic\', \'hottopicviews\', \'announcementlimit\', \'postsperpage\', \'threadreadcut\', \'similarityrating\', \'similarlimit\') AND optionscode=\'text\''); - $db->update_query('settings', array('optionscode' => 'numeric'), 'name IN (\'minnamelength\', \'maxnamelength\', \'minpasswordlength\', \'maxpasswordlength\', \'betweenregstime\', \'maxregsbetweentime\', \'failedcaptchalogincount\') AND optionscode=\'text\''); - $db->update_query('settings', array('optionscode' => 'numeric'), 'name IN (\'failedlogincount\', \'failedlogintime\', \'regtime\', \'maxsigimages\', \'siglength\', \'avatarsize\', \'customtitlemaxlength\') AND optionscode=\'text\''); - $db->update_query('settings', array('optionscode' => 'numeric'), 'name IN (\'minmessagelength\', \'maxmessagelength\', \'postfloodsecs\', \'postmergemins\', \'maxpostimages\', \'maxpostvideos\', \'subscribeexcerpt\') AND optionscode=\'text\''); - $db->update_query('settings', array('optionscode' => 'numeric'), 'name IN (\'wordwrap\', \'maxquotedepth\', \'polloptionlimit\', \'maxpolloptions\', \'polltimelimit\', \'maxattachments\', \'attachthumbh\') AND optionscode=\'text\''); - $db->update_query('settings', array('optionscode' => 'numeric'), 'name IN (\'attachthumbw\', \'membersperpage\', \'repsperpage\', \'maxreplength\', \'minreplength\', \'maxwarningpoints\', \'pmfloodsecs\') AND optionscode=\'text\''); - $db->update_query('settings', array('optionscode' => 'numeric'), 'name IN (\'maxpmquotedepth\', \'wolcutoffmins\', \'refreshwol\', \'prunepostcount\', \'dayspruneregistered\', \'dayspruneunactivated\', \'portal_numannouncements\') AND optionscode=\'text\''); - $db->update_query('settings', array('optionscode' => 'numeric'), 'name IN (\'portal_showdiscussionsnum\', \'searchfloodtime\', \'minsearchword\', \'searchhardlimit\', \'smilieinsertertot\', \'smilieinsertercols\', \'maxloginattempts\') AND optionscode=\'text\''); - $db->update_query('settings', array('optionscode' => 'numeric'), 'name IN (\'loginattemptstimeout\', \'contact_maxsubjectlength\', \'contact_minmessagelength\', \'contact_maxmessagelength\', \'purgespammerpostlimit\', \'purgespammerbangroup\', \'statscachetime\') AND optionscode=\'text\''); - - // Update help documents - $query = $db->simple_select('helpdocs', 'document', 'hid=\'3\''); - $helpdoc = $db->fetch_array($query); - if(my_strpos($helpdoc['document'], ';key={1}') !== false) - { - $helpdoc['document'] = str_replace(';key={1}', ';my_post_key={1}', $helpdoc['document']); - } - $db->update_query('helpdocs', array('document' => $db->escape_string($helpdoc['document'])), 'hid=\'3\''); - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("31_done"); -} \ No newline at end of file diff --git a/html/forums/install/resources/upgrade32.php b/html/forums/install/resources/upgrade32.php deleted file mode 100644 index bd3d7b1..0000000 --- a/html/forums/install/resources/upgrade32.php +++ /dev/null @@ -1,86 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade32_dbchanges() -{ - global $db, $output; - - // Unset old ACP cookies from front-end since they're not needed anymore - my_unsetcookie('adminsid'); - my_unsetcookie('acploginattempts'); - my_unsetcookie('acp_view'); - my_unsetcookie('inlinemod_useracp'); - - $output->print_header("Updating Database"); - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->field_exists('candeletereputations', 'usergroups')) - { - $db->drop_column("usergroups", "candeletereputations"); - } - - if($db->field_exists('authsecret', 'adminoptions')) - { - $db->drop_column("adminoptions", "authsecret"); - } - - if($db->field_exists('recovery_codes', 'adminoptions')) - { - $db->drop_column("adminoptions", "recovery_codes"); - } - - if($db->field_exists('authenticated', 'adminsessions')) - { - $db->drop_column("adminsessions", "authenticated"); - } - - switch($db->type) - { - case "pgsql": - $db->add_column("usergroups", "candeletereputations", "smallint NOT NULL default '0' AFTER cangivereputations"); - $db->add_column("adminoptions", "authsecret", "varchar(16) NOT NULL default ''"); - $db->add_column("adminoptions", "recovery_codes", "varchar(177) NOT NULL default ''"); - $db->add_column("adminsessions", "authenticated", "smallint NOT NULL default '0'"); - break; - case "sqlite": - $db->add_column("usergroups", "candeletereputations", "tinyint(1) NOT NULL default '0'"); - $db->add_column("adminoptions", "authsecret", "varchar(16) NOT NULL default ''"); - $db->add_column("adminoptions", "recovery_codes", "varchar(177) NOT NULL default ''"); - $db->add_column("adminsessions", "authenticated", "tinyint(1) NOT NULL default '0'"); - break; - default: - $db->add_column("usergroups", "candeletereputations", "tinyint(1) NOT NULL default '0' AFTER cangivereputations"); - $db->add_column("adminoptions", "authsecret", "varchar(16) NOT NULL default ''"); - $db->add_column("adminoptions", "recovery_codes", "varchar(177) NOT NULL default ''"); - $db->add_column("adminsessions", "authenticated", "tinyint(1) NOT NULL default '0'"); - break; - } - - // Delete forumpermissions belonging to a deleted forum - $db->delete_query("forumpermissions", "fid NOT IN(SELECT fid FROM {$db->table_prefix}forums)"); - - $db->update_query("settings", array('optionscode' => 'select\r\n0=No CAPTCHA\r\n1=MyBB Default CAPTCHA\r\n2=reCAPTCHA\r\n3=Are You a Human\r\n4=NoCAPTCHA reCAPTCHA'), "name='captchaimage'"); - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("32_done"); -} \ No newline at end of file diff --git a/html/forums/install/resources/upgrade33.php b/html/forums/install/resources/upgrade33.php deleted file mode 100644 index a02c3b3..0000000 --- a/html/forums/install/resources/upgrade33.php +++ /dev/null @@ -1,38 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade33_dbchanges() -{ - global $db, $output; - - $output->print_header("Updating Database"); - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->field_exists('2fasecret', 'adminoptions') && !$db->field_exists('authsecret', 'adminoptions')) - { - $db->rename_column('adminoptions', '2fasecret', 'authsecret', "varchar(16) NOT NULL default ''"); - } - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("33_done"); -} diff --git a/html/forums/install/resources/upgrade34.php b/html/forums/install/resources/upgrade34.php deleted file mode 100644 index 83c30c8..0000000 --- a/html/forums/install/resources/upgrade34.php +++ /dev/null @@ -1,23 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do for 1.8.5 */ diff --git a/html/forums/install/resources/upgrade35.php b/html/forums/install/resources/upgrade35.php deleted file mode 100644 index 07c15b9..0000000 --- a/html/forums/install/resources/upgrade35.php +++ /dev/null @@ -1,188 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade35_dbchanges() -{ - global $db, $output; - - $output->print_header("Updating Database"); - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->field_exists('subscriptionkey', 'threadsubscriptions')) - { - $db->drop_column("threadsubscriptions", "subscriptionkey"); - } - - if($db->type != 'pgsql') - { - $db->modify_column('adminsessions', 'useragent', "varchar(200) NOT NULL default ''"); - $db->modify_column('sessions', 'useragent', "varchar(200) NOT NULL default ''"); - } - else - { - $db->modify_column('adminsessions', 'useragent', "varchar(200)", "set", "''"); - $db->modify_column('sessions', 'useragent', "varchar(200)", "set", "''"); - } - - // Remove "Are You a Human" captcha - $db->update_query('settings', array('value' => '1'), "name='captchaimage' AND value='3'"); - $db->delete_query('settings', "name IN ('ayahpublisherkey', 'ayahscoringkey')"); - $db->delete_query('templates', "title IN ('member_register_regimage_ayah', 'post_captcha_ayah')"); - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("35_dbchanges2"); -} - -function upgrade35_dbchanges2() -{ - global $db, $output; - - $output->print_header("Updating Database"); - echo "

    Performing necessary optimization queries...

    "; - flush(); - - switch($db->type) - { - // PostgreSQL and SQLite do not support unsigned ints - case "pgsql": - $db->modify_column("buddyrequests", "uid", "int", "set", "'0'"); - $db->modify_column("buddyrequests", "touid", "int", "set", "'0'"); - $db->modify_column("buddyrequests", "date", "int", "set", "'0'"); - break; - case "sqlite": - $db->modify_column("threadratings", "rating", "tinyint(1) NOT NULL default '0'"); - $db->modify_column("buddyrequests", "uid", "int NOT NULL default '0'"); - $db->modify_column("buddyrequests", "touid", "int NOT NULL default '0'"); - $db->modify_column("buddyrequests", "date", "int NOT NULL default '0'"); - break; - default: - $db->modify_column("adminviews", "perpage", "smallint(4) unsigned NOT NULL default '0'"); - $db->modify_column("attachments", "filesize", "int(10) unsigned NOT NULL default '0'"); - $db->modify_column("attachtypes", "maxsize", "int(15) unsigned NOT NULL default '0'"); - $db->modify_column("banned", "olddisplaygroup", "int unsigned NOT NULL default '0'"); - $db->modify_column("buddyrequests", "uid", "int unsigned NOT NULL default '0'"); - $db->modify_column("buddyrequests", "touid", "int unsigned NOT NULL default '0'"); - $db->modify_column("buddyrequests", "date", "int unsigned NOT NULL default '0'"); - $db->modify_column("calendars", "eventlimit", "smallint(3) unsigned NOT NULL default '0'"); - $db->modify_column("massemails", "perpage", "smallint(4) unsigned NOT NULL default '50'"); - $db->modify_column("promotions", "posts", "int unsigned NOT NULL default '0'"); - $db->modify_column("promotions", "threads", "int unsigned NOT NULL default '0'"); - $db->modify_column("promotions", "registered", "int unsigned NOT NULL default '0'"); - $db->modify_column("promotions", "online", "int unsigned NOT NULL default '0'"); - $db->modify_column("promotions", "referrals", "int unsigned NOT NULL default '0'"); - $db->modify_column("promotions", "warnings", "int unsigned NOT NULL default '0'"); - $db->modify_column("sessions", "location1", "int(10) unsigned NOT NULL default '0'"); - $db->modify_column("sessions", "location2", "int(10) unsigned NOT NULL default '0'"); - $db->modify_column("threadratings", "rating", "tinyint(1) unsigned NOT NULL default '0'"); - $db->modify_column("threads", "views", "int(100) unsigned NOT NULL default '0'"); - $db->modify_column("threads", "replies", "int(100) unsigned NOT NULL default '0'"); - break; - } - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("35_dbchanges3"); -} - -function upgrade35_dbchanges3() -{ - global $db, $output; - - $output->print_header("Updating Database"); - echo "

    Performing necessary optimization queries...

    "; - flush(); - - switch($db->type) - { - // PostgreSQL and SQLite do not support unsigned ints - case "sqlite": - $db->modify_column("usergroups", "type", "tinyint(1) NOT NULL default '2'"); - $db->modify_column("users", "loginattempts", "smallint(2) NOT NULL default '1'"); - break; - case "mysql": - case "mysqli": - $db->modify_column("usergroups", "type", "tinyint(1) unsigned NOT NULL default '2'"); - $db->modify_column("usergroups", "stars", "smallint(4) unsigned NOT NULL default '0'"); - $db->modify_column("usergroups", "pmquota", "int(3) unsigned NOT NULL default '0'"); - $db->modify_column("usergroups", "maxpmrecipients", "int(4) unsigned NOT NULL default '5'"); - $db->modify_column("usergroups", "maxemails", "int(3) unsigned NOT NULL default '5'"); - $db->modify_column("usergroups", "emailfloodtime", "int(3) unsigned NOT NULL default '5'"); - $db->modify_column("usergroups", "maxwarningsday", "int(3) unsigned NOT NULL default '3'"); - $db->modify_column("usergroups", "edittimelimit", "int(4) unsigned NOT NULL default '0'"); - $db->modify_column("usergroups", "maxposts", "int(4) unsigned NOT NULL default '0'"); - $db->modify_column("users", "postnum", "int(10) unsigned NOT NULL default '0'"); - $db->modify_column("users", "threadnum", "int(10) unsigned NOT NULL default '0'"); - $db->modify_column("users", "ppp", "smallint(6) unsigned NOT NULL default '0'"); - $db->modify_column("users", "tpp", "smallint(6) unsigned NOT NULL default '0'"); - $db->modify_column("users", "daysprune", "smallint(6) unsigned NOT NULL default '0'"); - $db->modify_column("users", "totalpms", "int(10) unsigned NOT NULL default '0'"); - $db->modify_column("users", "unreadpms", "int(10) unsigned NOT NULL default '0'"); - $db->modify_column("users", "warningpoints", "int(3) unsigned NOT NULL default '0'"); - $db->modify_column("users", "loginattempts", "smallint(2) unsigned NOT NULL default '1'"); - $db->modify_column("usertitles", "stars", "smallint(4) unsigned NOT NULL default '0'"); - $db->modify_column("warninglevels", "percentage", "smallint(3) unsigned NOT NULL default '0'"); - break; - } - - global $footer_extra; - $footer_extra = ""; - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("35_dbchanges4"); -} - -function upgrade35_dbchanges4() -{ - global $mybb, $output; - - $output->print_header("Adding index files"); - echo "

    Adding index files to attachment directories...

    "; - flush(); - - $dir = @opendir('../'.$mybb->settings['uploadspath']); - if($dir) - { - while(($file = @readdir($dir)) !== false) - { - $filename = "../{$mybb->settings['uploadspath']}/{$file}"; - $indexfile = "{$filename}/index.html"; - - if(preg_match('#^[0-9]{6}$#', $file) && @is_dir($filename) && @is_writable($filename) && !file_exists($indexfile)) - { - $index = @fopen($indexfile, 'w'); - @fwrite($index, "\n\n\n\n\n \n\n"); - @fclose($index); - } - } - - @closedir($dir); - } - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("35_done"); -} diff --git a/html/forums/install/resources/upgrade36.php b/html/forums/install/resources/upgrade36.php deleted file mode 100644 index 302e159..0000000 --- a/html/forums/install/resources/upgrade36.php +++ /dev/null @@ -1,235 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade36_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Updating Database"); - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->field_exists('enabled', 'attachtypes')) - { - $db->drop_column('attachtypes', 'enabled'); - } - - if($db->field_exists('groups', 'attachtypes')) - { - $db->drop_column('attachtypes', 'groups'); - } - - if($db->field_exists('forums', 'attachtypes')) - { - $db->drop_column('attachtypes', 'forums'); - } - - if($db->field_exists('avatarfile', 'attachtypes')) - { - $db->drop_column('attachtypes', 'avatarfile'); - } - - switch($db->type) - { - case "pgsql": - $db->add_column('attachtypes', 'enabled', "smallint NOT NULL default '1'"); - $db->add_column('attachtypes', 'groups', "text NOT NULL default '-1'"); - $db->add_column('attachtypes', 'forums', "text NOT NULL default '-1'"); - $db->add_column('attachtypes', 'avatarfile', "smallint NOT NULL default '0'"); - break; - default: - $db->add_column('attachtypes', 'enabled', "tinyint(1) NOT NULL default '1'"); - $db->add_column('attachtypes', 'groups', "TEXT NOT NULL"); - $db->add_column('attachtypes', 'forums', "TEXT NOT NULL"); - $db->add_column('attachtypes', 'avatarfile', "tinyint(1) NOT NULL default '0'"); - - $db->update_query('attachtypes', array('groups' => '-1', 'forums' => '-1')); - break; - } - - $db->update_query('attachtypes', array('avatarfile' => 1), "atid IN (2, 4, 7, 11)"); - - if($mybb->settings['username_method'] == 1 || $mybb->settings['username_method'] == 2) - { - $query = $db->simple_select('users', 'email, COUNT(email) AS duplicates', "email!=''", array('group_by' => 'email HAVING duplicates>1')); - if($db->num_rows($query)) - { - $db->update_query('settings', array('value' => 0), "name='username_method'"); - } - else - { - $db->update_query('settings', array('value' => 0), "name='allowmultipleemails'"); - } - } - - $query = $db->simple_select("templategroups", "COUNT(*) as numexists", "prefix='mycode'"); - if($db->fetch_field($query, "numexists") == 0) - { - $db->insert_query("templategroups", array('prefix' => 'mycode', 'title' => '', 'isdefault' => '1')); - } - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("36_dbchanges2"); -} - -function upgrade36_dbchanges2() -{ - global $output, $db, $cache; - - $output->print_header("Updating Database"); - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->field_exists('reasonid', 'reportedcontent')) - { - $db->drop_column("reportedcontent", "reasonid"); - } - - switch($db->type) - { - case "pgsql": - case "sqlite": - $db->add_column("reportedcontent", "reasonid", "smallint NOT NULL default '0' AFTER reportstatus"); - break; - default: - $db->add_column("reportedcontent", "reasonid", "smallint unsigned NOT NULL default '0' AFTER reportstatus"); - break; - } - - - if($db->table_exists("reportreasons")) - { - $db->drop_table("reportreasons"); - } - - $collation = $db->build_create_table_collation(); - - switch($db->type) - { - case "pgsql": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."reportreasons ( - rid serial, - title varchar(250) NOT NULL default '', - appliesto varchar(250) NOT NULL default '', - extra smallint NOT NULL default '0', - disporder smallint NOT NULL default '0', - PRIMARY KEY (rid) - );"); - break; - case "sqlite": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."reportreasons ( - rid INTEGER PRIMARY KEY, - title varchar(250) NOT NULL default '', - appliesto varchar(250) NOT NULL default '', - extra tinyint(1) NOT NULL default '0', - disporder smallint NOT NULL default '0', - );"); - break; - default: - $db->write_query("CREATE TABLE ".TABLE_PREFIX."reportreasons ( - rid int unsigned NOT NULL auto_increment, - title varchar(250) NOT NULL default '', - appliesto varchar(250) NOT NULL default '', - extra tinyint(1) NOT NULL default '0', - disporder smallint unsigned NOT NULL default '0', - PRIMARY KEY (rid) - ) ENGINE=MyISAM{$collation};"); - break; - } - - $reportreasons = array( - array( - 'rid' => 1, - 'title' => "", - 'appliesto' => "all", - 'extra' => 1, - 'disporder' => 99 - ), - array( - 'rid' => 2, - 'title' => "", - 'appliesto' => "all", - 'extra' => 0, - 'disporder' => 1 - ), - array( - 'rid' => 3, - 'title' => "", - 'appliesto' => "all", - 'extra' => 0, - 'disporder' => 2 - ), - array( - 'rid' => 4, - 'title' => "", - 'appliesto' => "all", - 'extra' => 0, - 'disporder' => 3 - ), - array( - 'rid' => 5, - 'title' => "", - 'appliesto' => "post", - 'extra' => 0, - 'disporder' => 4 - ) - ); - - $db->insert_query_multiple('reportreasons', $reportreasons); - - $templang = new MyLanguage(); - $templang->set_path(MYBB_ROOT."inc/languages"); - - $langs = array_keys($templang->get_languages()); - - foreach($langs as $langname) - { - unset($templang); - $templang = new MyLanguage(); - $templang->set_path(MYBB_ROOT."inc/languages"); - $templang->set_language($langname); - $templang->load("report"); - - if(!empty($templang->report_reason_rules) && $templang->report_reason_rules != '') - { - $db->update_query("reportedcontent", array("reasonid" => 2, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_rules)."'"); - } - if(!empty($templang->report_reason_bad) && $templang->report_reason_bad != '') - { - $db->update_query("reportedcontent", array("reasonid" => 3, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_bad)."'"); - } - if(!empty($templang->report_reason_spam) && $templang->report_reason_spam != '') - { - $db->update_query("reportedcontent", array("reasonid" => 4, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_spam)."'"); - } - if(!empty($templang->report_reason_wrong) && $templang->report_reason_wrong != '') - { - $db->update_query("reportedcontent", array("reasonid" => 5, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_wrong)."'"); - } - } - - // Any reason not converted is treated as "Other" with extra text specified - $db->update_query("reportedcontent", array('reasonid' => 1), "reason != ''"); - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("36_done"); -} diff --git a/html/forums/install/resources/upgrade37.php b/html/forums/install/resources/upgrade37.php deleted file mode 100644 index f37bc73..0000000 --- a/html/forums/install/resources/upgrade37.php +++ /dev/null @@ -1,55 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -function upgrade37_dbchanges() -{ - global $db, $output; - - $output->print_header("Updating Database"); - echo "

    Performing necessary upgrade queries...

    "; - flush(); - - if($db->field_exists('canviewdeletionnotice', 'usergroups')) - { - $db->drop_column("usergroups", "canviewdeletionnotice"); - } - - if($db->field_exists('canviewdeletionnotice', 'forumpermissions')) - { - $db->drop_column("forumpermissions", "canviewdeletionnotice"); - } - - switch($db->type) - { - case "pgsql": - $db->add_column("forumpermissions", "canviewdeletionnotice", "smallint NOT NULL default '0' AFTER caneditattachments"); - $db->add_column("usergroups", "canviewdeletionnotice", "smallint NOT NULL default '0' AFTER caneditattachments"); - break; - default: - $db->add_column("forumpermissions", "canviewdeletionnotice", "tinyint(1) NOT NULL default '0' AFTER caneditattachments"); - $db->add_column("usergroups", "canviewdeletionnotice", "tinyint(1) NOT NULL default '0' AFTER caneditattachments"); - break; - } - - $output->print_contents("

    Click next to continue with the upgrade process.

    "); - $output->print_footer("37_done"); -} \ No newline at end of file diff --git a/html/forums/install/resources/upgrade38.php b/html/forums/install/resources/upgrade38.php deleted file mode 100644 index 9e0d8ff..0000000 --- a/html/forums/install/resources/upgrade38.php +++ /dev/null @@ -1,23 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do for 1.8.9 */ diff --git a/html/forums/install/resources/upgrade39.php b/html/forums/install/resources/upgrade39.php deleted file mode 100644 index 3d2a191..0000000 --- a/html/forums/install/resources/upgrade39.php +++ /dev/null @@ -1,23 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do for 1.8.10 */ diff --git a/html/forums/install/resources/upgrade4.php b/html/forums/install/resources/upgrade4.php deleted file mode 100644 index d944bcb..0000000 --- a/html/forums/install/resources/upgrade4.php +++ /dev/null @@ -1,81 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 1, - "requires_deactivated_plugins" => 1, -); - -@set_time_limit(0); - -function upgrade4_dbchanges() -{ - global $db, $output; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - - $db->write_query("UPDATE ".TABLE_PREFIX."users SET style='0' WHERE style='-1';"); - $db->write_query("UPDATE ".TABLE_PREFIX."users SET displaygroup='0' WHERE displaygroup='-1';"); - $db->write_query("UPDATE ".TABLE_PREFIX."forums SET style='0' WHERE style='-1';"); - $query = $db->simple_select("adminoptions", "uid='0'"); - $test = $db->fetch_array($query); - if(!isset($test['uid'])) - { - $db->write_query("UPDATE ".TABLE_PREFIX."adminoptions SET uid='0' WHERE uid='-1';"); - } - - if($db->field_exists('messageindex', "threads")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads DROP messageindex;"); - } - if($db->field_exists('subjectindex', "threads")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads DROP subjectindex;"); - } - if($db->field_exists('moderators', "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP moderators;"); - } - - if($db->field_exists('version', "templates")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."templates DROP version;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."templates ADD version varchar(20) NOT NULL default '0';"); - - if($db->field_exists('status', "templates")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."templates DROP status;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."templates ADD status varchar(10) NOT NULL default '';"); - - if($db->field_exists('dateline', "templates")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."templates DROP dateline;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."templates ADD dateline int(10) NOT NULL default '0';"); - - $db->write_query("UPDATE ".TABLE_PREFIX."templates SET version='100.06' WHERE sid>0"); - - echo "Done

    "; - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("4_done"); -} - diff --git a/html/forums/install/resources/upgrade40.php b/html/forums/install/resources/upgrade40.php deleted file mode 100644 index 67ad591..0000000 --- a/html/forums/install/resources/upgrade40.php +++ /dev/null @@ -1,23 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do for 1.8.11 */ diff --git a/html/forums/install/resources/upgrade5.php b/html/forums/install/resources/upgrade5.php deleted file mode 100644 index 0600c8b..0000000 --- a/html/forums/install/resources/upgrade5.php +++ /dev/null @@ -1,639 +0,0 @@ - 1, - "revert_all_themes" => 1, - "revert_all_settings" => 2, - "requires_deactivated_plugins" => 1, -); - -@set_time_limit(0); - -function upgrade5_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users CHANGE avatartype avatartype varchar(10) NOT NULL;"); - if($db->field_exists('totalpms', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP totalpms;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD totalpms int(10) NOT NULL default '0' AFTER showcodebuttons;"); - - - if($db->field_exists('newpms', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP newpms;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD newpms int(10) NOT NULL default '0' AFTER totalpms;"); - - - if($db->field_exists('unreadpms', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP unreadpms;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD unreadpms int(10) NOT NULL default '0' AFTER newpms;"); - - - if($db->field_exists('showredirect', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP showredirect;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD showredirect char(3) NOT NULL default '' AFTER showquickreply;"); - - - if($db->field_exists('avatardimensions', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP avatardimensions;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD avatardimensions varchar(10) NOT NULL default '' AFTER avatar;"); - - - if($db->field_exists('unapprovedposts', "threads")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads DROP unapprovedposts;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads ADD unapprovedposts INT(10) unsigned NOT NULL default '0' AFTER visible;"); - - - if($db->field_exists('unapprovedthreads', "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP unapprovedthreads;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD unapprovedthreads INT(10) unsigned NOT NULL default '0' AFTER rules;"); - - - if($db->field_exists('unapprovedposts', "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP unapprovedposts;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD unapprovedposts INT(10) unsigned NOT NULL default '0' AFTER rules;"); - - - if($db->field_exists('defaultdatecut', "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP defaultdatecut;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD defaultdatecut smallint(4) unsigned NOT NULL default '0' AFTER unapprovedposts;"); - - - if($db->field_exists('defaultsortby', "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP defaultsortby;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD defaultsortby varchar(10) NOT NULL default '' AFTER defaultdatecut;"); - - - if($db->field_exists('defaultsortorder', "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP defaultsortorder;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD defaultsortorder varchar(4) NOT NULL default '' AFTER defaultsortby;"); - - - if($db->field_exists('lastposteruid', "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP lastposteruid;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD lastposteruid int(10) unsigned NOT NULL default '0' AFTER lastposter;"); - - - if($db->field_exists('lastpostsubject', "forums")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums DROP lastpostsubject;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forums ADD lastpostsubject varchar(120) NOT NULL default '' AFTER lastposttid"); - - - if($db->field_exists('lastposteruid', "threads")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads DROP lastposteruid;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads ADD lastposteruid int unsigned NOT NULL default '0' AFTER lastposter"); - - - if($db->field_exists('canmanagemembers', "groupleaders")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."groupleaders DROP canmanagemembers;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."groupleaders ADD canmanagemembers char(3) NOT NULL default '' AFTER uid;"); - - - if($db->field_exists('canmanagerequests', "groupleaders")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."groupleaders DROP canmanagerequests;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."groupleaders ADD canmanagerequests char(3) NOT NULL default '' AFTER canmanagemembers;"); - - - if($db->field_exists('caneditlangs', "adminoptions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions DROP caneditlangs;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions ADD caneditlangs char(3) NOT NULL default '' AFTER canedithelp;"); - - - if($db->field_exists('canrundbtools', "adminoptions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions DROP canrundbtools;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."adminoptions ADD canrundbtools char(3) NOT NULL default ''"); - - - if($db->field_exists('allowedgroups', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP allowedgroups;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes ADD allowedgroups text NOT NULL AFTER extracss;"); - - - if($db->field_exists('canmovetononmodforum', "moderators")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderators DROP canmovetononmodforum;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderators ADD canmovetononmodforum char(3) NOT NULL default '' AFTER canmanagethreads;"); - - - if($db->field_exists('csscached', "themes")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes DROP csscached;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."themes ADD csscached bigint(30) NOT NULL default '0'"); - - - $db->write_query("UPDATE ".TABLE_PREFIX."adminoptions SET caneditlangs='yes' WHERE canrunmaint='yes'"); - $db->write_query("UPDATE ".TABLE_PREFIX."adminoptions SET caneditlangs='no' WHERE canrunmaint='no'"); - $db->write_query("UPDATE ".TABLE_PREFIX."adminoptions SET canrundbtools='yes' WHERE canrunmaint='yes'"); - $db->write_query("UPDATE ".TABLE_PREFIX."adminoptions SET canrundbtools='no' WHERE canrunmaint='no'"); - $db->write_query("UPDATE ".TABLE_PREFIX."settings SET optionscode='select\r\ninstant=Instant Activation\r\nverify=Send Email Verification\r\nrandompass=Send Random Password\r\nadmin=Administrator Activation' WHERE name = 'regtype'"); - $db->write_query("UPDATE ".TABLE_PREFIX."users SET totalpms='-1', newpms='-1', unreadpms='-1'"); - $db->write_query("UPDATE ".TABLE_PREFIX."settings SET name='maxmessagelength' WHERE name='messagelength'"); - - $collation = $db->build_create_table_collation(); - - $db->drop_table("mycode"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."mycode ( - cid int unsigned NOT NULL auto_increment, - title varchar(100) NOT NULL default '', - description text NOT NULL, - regex text NOT NULL, - replacement text NOT NULL, - active char(3) NOT NULL default '', - PRIMARY KEY(cid) - ) ENGINE=MyISAM{$collation};"); - - $db->drop_table("templategroups"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."templategroups ( - gid int unsigned NOT NULL auto_increment, - prefix varchar(50) NOT NULL default '', - title varchar(100) NOT NULL default '', - PRIMARY KEY (gid) - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('1','calendar','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('2','editpost','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('3','email','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('4','emailsubject','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('5','forumbit','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('6','forumjump','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('7','forumdisplay','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('8','index','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('9','error','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('10','memberlist','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('11','multipage','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('12','private','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('13','portal','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('14','postbit','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('15','redirect','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('16','showthread','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('17','usercp','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('18','online','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('19','moderation','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('20','nav','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('21','search','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('22','showteam','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('23','reputation','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('24','newthread','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('25','newreply','');"); - $db->write_query("INSERT INTO ".TABLE_PREFIX."templategroups (gid,prefix,title) VALUES ('26','member','');"); - - $db->drop_table("searchlog"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."searchlog ( - sid varchar(32) NOT NULL default '', - uid int unsigned NOT NULL default '0', - dateline bigint(30) NOT NULL default '0', - ipaddress varchar(120) NOT NULL default '', - threads text NOT NULL, - posts text NOT NULL, - searchtype varchar(10) NOT NULL default '', - resulttype varchar(10) NOT NULL default '', - querycache text NOT NULL, - keywords text NOT NULL, - PRIMARY KEY (sid) - ) ENGINE=MyISAM{$collation};"); - - $db->write_query("UPDATE ".TABLE_PREFIX."settings SET name='bannedemails' WHERE name='emailban' LIMIT 1"); - $db->write_query("UPDATE ".TABLE_PREFIX."settings SET name='bannedips' WHERE name='ipban' LIMIT 1"); - - $query = $db->simple_select("settings", "value", "name='bannedusernames'"); - $bannedusernames = $db->fetch_field($query, 'sid'); - $bannedusernames = explode(" ", $bannedusernames); - $bannedusernames = implode(",", $bannedusernames); - $query = $db->write_query("UPDATE ".TABLE_PREFIX."settings SET value='".$db->escape_string($bannedusernames)."' WHERE name='bannedusernames'"); - - $query = $db->simple_select("settings", "value", "name='bannedemails'"); - $bannedemails = $db->fetch_field($query, 'sid'); - $bannedemails = explode(" ", $bannedemails); - $bannedemails = implode(",", $bannedemails); - $query = $db->write_query("UPDATE ".TABLE_PREFIX."settings SET value='".$db->escape_string($bannedemails)."' WHERE name='bannedemails'"); - - $query = $db->simple_select("settings", "value", "name='bannedips'"); - $bannedips = $db->fetch_field($query, 'sid'); - $bannedips = explode(" ", $bannedips); - $bannedips = implode(",", $bannedips); - $db->update_query("settings", array('value' => $db->escape_string($bannedips)), "name='bannedips'"); - - $db->drop_table("reputation"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."reputation ( - rid int unsigned NOT NULL auto_increment, - uid int unsigned NOT NULL default '0', - adduid int unsigned NOT NULL default '0', - reputation bigint(30) NOT NULL default '0', - dateline bigint(30) NOT NULL default '0', - comments text NOT NULL, - PRIMARY KEY(rid) - ) ENGINE=MyISAM{$collation};"); - - $db->drop_table("mailqueue"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."mailqueue ( - mid int unsigned NOT NULL auto_increment, - mailto varchar(200) NOT NULL, - mailfrom varchar(200) NOT NULL, - subject varchar(200) NOT NULL, - message text NOT NULL, - headers text NOT NULL, - PRIMARY KEY(mid) - ) ENGINE=MyISAM{$collation};"); - - $db->update_query("users", array('reputation' => 0)); - - $db->update_query("usergroups", array('reputationpower' => 1)); - $db->update_query("usergroups", array('reputationpower' => 2), "cancp='yes'"); - - if($db->field_exists('rating', "users")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP rating;"); - } - - if($db->field_exists('attachmentcount', "threads")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads DROP attachmentcount;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads ADD attachmentcount int(10) unsigned NOT NULL default '0'"); - - - if($db->field_exists('posthash', "posts")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts DROP posthash;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts ADD posthash varchar(32) NOT NULL default '' AFTER visible"); - - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."attachtypes CHANGE extension extension varchar(10) NOT NULL;"); - - if($db->field_exists('deletetime', "threads")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads DROP deletetime;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."threads ADD deletetime int(10) unsigned NOT NULL default '0' AFTER attachmentcount"); - - - if($db->field_exists('loginattempts', "sessions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."sessions DROP loginattempts;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."sessions ADD loginattempts tinyint(2) NOT NULL default '1'"); - - - if($db->field_exists('failedlogin', "sessions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."sessions DROP failedlogin;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."sessions ADD failedlogin bigint(30) NOT NULL default '0'"); - - - if($db->field_exists('canviewthreads', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP canviewthreads;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD canviewthreads char(3) NOT NULL default '' AFTER canview"); - - - if($db->field_exists('canviewthreads', "forumpermissions")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forumpermissions DROP canviewthreads;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."forumpermissions ADD canviewthreads char(3) NOT NULL default '' AFTER canview"); - - - $db->drop_table("captcha"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."captcha ( - imagehash varchar(32) NOT NULL default '', - imagestring varchar(8) NOT NULL default '', - dateline bigint(30) NOT NULL default '0' - ) ENGINE=MyISAM{$collation};"); - - if($db->field_exists('data', "moderatorlog")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderatorlog DROP data;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."moderatorlog ADD data text NOT NULL AFTER action;"); - - - $db->drop_table("adminsessions"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."adminsessions ( - sid varchar(32) NOT NULL default '', - uid int unsigned NOT NULL default '0', - loginkey varchar(50) NOT NULL default '', - ip varchar(40) NOT NULL default '', - dateline bigint(30) NOT NULL default '0', - lastactive bigint(30) NOT NULL default '0' - ) ENGINE=MyISAM{$collation};"); - - $db->drop_table("modtools"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."modtools ( - tid smallint unsigned NOT NULL auto_increment, - name varchar(200) NOT NULL, - description text NOT NULL, - forums text NOT NULL, - type char(1) NOT NULL default '', - postoptions text NOT NULL, - threadoptions text NOT NULL, - PRIMARY KEY (tid) - ) ENGINE=MyISAM{$collation};"); - - if($db->field_exists('disporder', "usergroups")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups DROP disporder;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."usergroups ADD disporder smallint(6) NOT NULL default '0' AFTER image"); - - - $db->write_query("UPDATE ".TABLE_PREFIX."usergroups SET canviewthreads=canview"); - $db->write_query("UPDATE ".TABLE_PREFIX."forumpermissions SET canviewthreads=canview"); - - $contents .= "Done

    "; - $contents .= "

    Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("5_redoconfig"); -} - -function upgrade5_redoconfig() -{ - global $db, $output, $config, $mybb; - $output->print_header("Rewriting config.php"); - - $uid = 0; - if($mybb->input['username'] != '' && !$mybb->input['uid']) - { - $user = get_user_by_username($mybb->input['username']); - - $uid = (int)$user['uid']; - - if(!$uid) - { - echo "

    The username you entered could not be found.
    Please ensure you corectly enter a valid username.

    "; - } - } - else if($mybb->input['uid']) - { - $uid = $mybb->input['uid']; - } - - if(!$uid) - { - echo "

    Please enter your primary administrator username. The user ID of the username you enter here will be written in to the new configuration file which will prevent this account from being banned, edited or deleted.

    "; - echo "

    Username:

    "; - echo "

    "; - $output->print_footer("5_redoconfig"); - exit; - } - - $fh = @fopen(MYBB_ROOT."inc/config.php", "w"); - if(!$fh) - { - echo "

    Unable to open inc/config.php
    Before the upgrade process can continue, you need to changes the permissions of inc/config.php so it is writable.

    "; - $output->print_footer("5_redoconfig"); - exit; - } - - if(!$config['admindir']) - { - $config['admindir'] = "admin"; - } - - if(!$config['cachestore']) - { - $config['cachestore'] = "db"; - } - $configdata = ""; - - fwrite($fh, $configdata); - fclose($fh); - echo "

    The configuration file has successfully been rewritten.

    "; - echo "

    Click next to continue with the upgrade process.

    "; - $output->print_footer("5_lastposts"); - -} - -function upgrade5_lastposts() -{ - global $db, $output; - $output->print_header("Rebuilding Last Post Columns"); - - if(!$_POST['tpp']) - { - echo "

    The next step in the upgrade process involves rebuilding the last post information for every thread in your forum. Below, please enter the number of threads to process per page.

    "; - echo "

    Threads Per Page:

    "; - echo "

    Once you're ready, press next to begin the rebuild process.

    "; - $output->print_footer("5_lastposts"); - } - else - { - $query = $db->simple_select("threads", "COUNT(*) as num_threads", "closed NOT LIKE 'moved|%'"); - $num_threads = $db->fetch_field($query, 'num_threads'); - $tpp = (int)$_POST['tpp']; - $start = (int)$_POST['start']; - $end = $start+$tpp; - if($end > $num_threads) - { - $end = $num_threads; - } - echo "

    Updating {$start} to {$end} of {$num_threads}...

    "; - - $query = $db->simple_select("threads", "tid, firstpost", "closed NOT LIKE 'moved|%'", array("order_by" => "tid", "order_dir" => "asc", "limit" => $tpp, "limit_start" => $start)); - - while($thread = $db->fetch_array($query)) - { - $recount_thread = get_thread($thread['tid']); - $count = array(); - - $query = $db->simple_select("posts", "COUNT(pid) AS replies", "tid='{$thread['tid']}' AND pid!='{$recount_thread['firstpost']}' AND visible='1'"); - $count['replies'] = $db->fetch_field($query, "replies"); - - // Unapproved posts - $query = $db->simple_select("posts", "COUNT(pid) AS unapprovedposts", "tid='{$thread['tid']}' AND pid != '{$recount_thread['firstpost']}' AND visible='0'"); - $count['unapprovedposts'] = $db->fetch_field($query, "unapprovedposts"); - - // Attachment count - $query = $db->query(" - SELECT COUNT(aid) AS attachment_count - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (a.pid=p.pid) - WHERE p.tid='{$thread['tid']}' AND a.visible=1 - "); - $count['attachmentcount'] = $db->fetch_field($query, "attachment_count"); - - $db->update_query("threads", $count, "tid='{$thread['tid']}'"); - update_thread_data($thread['tid']); - - if($thread['firstpost'] == 0) - { - update_first_post($thread['tid']); - } - } - echo "

    Done

    "; - if($end >= $num_threads) - { - echo "

    The rebuild process has completed successfully. Click next to continue with the upgrade."; - $output->print_footer("5_forumlastposts"); - } - else - { - echo "

    Click Next to continue with the build process.

    "; - echo ""; - echo ""; - $output->print_footer("5_lastposts"); - } - } -} - -function upgrade5_forumlastposts() -{ - global $db, $output; - $output->print_header("Rebuilding Forum Last Posts"); - echo "

    Rebuilding last post information for forums..

    "; - $query = $db->simple_select("forums", "fid"); - while($forum = $db->fetch_array($query)) - { - update_forum_lastpost($forum['fid']); - } - echo "

    Done"; - echo "

    Click next to continue with the upgrade process.

    "; - $output->print_footer("5_indexes"); -} - -function upgrade5_indexes() -{ - global $db, $output; - - $output->print_header("Indexing"); - echo "

    Checking and creating fulltext database indexes..

    "; - - - if($db->is_fulltext("threads", "subject")) - { - $db->drop_index("threads", "subject"); - } - if($db->is_fulltext("threads", "subject_2")) - { - $db->drop_index("threads", "subject_2"); - } - - if($db->supports_fulltext("threads")) - { - $db->create_fulltext_index("threads", "subject"); - } - if($db->supports_fulltext_boolean("posts")) - { - if(!$db->is_fulltext("posts", "message")) - { - $db->create_fulltext_index("posts", "message"); - } - } - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("5_done"); -} diff --git a/html/forums/install/resources/upgrade6.php b/html/forums/install/resources/upgrade6.php deleted file mode 100644 index 4364b82..0000000 --- a/html/forums/install/resources/upgrade6.php +++ /dev/null @@ -1,41 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0, - "requires_deactivated_plugins" => 0, -); - -@set_time_limit(0); - -function upgrade6_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - - $db->write_query("ALTER TABLE ".TABLE_PREFIX."mycode CHANGE regex regex text NOT NULL"); - $db->write_query("ALTER TABLE ".TABLE_PREFIX."mycode CHANGE replacement replacement text NOT NULL"); - - $contents = "Done

    "; - $contents .= "

    Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("6_done"); -} - diff --git a/html/forums/install/resources/upgrade7.php b/html/forums/install/resources/upgrade7.php deleted file mode 100644 index 04b0bb6..0000000 --- a/html/forums/install/resources/upgrade7.php +++ /dev/null @@ -1,26 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0, - "requires_deactivated_plugins" => 0, -); - -@set_time_limit(0); - -/* Nothing to do from 1.2.1 to 1.2.2 */ - diff --git a/html/forums/install/resources/upgrade8.php b/html/forums/install/resources/upgrade8.php deleted file mode 100644 index d1c66eb..0000000 --- a/html/forums/install/resources/upgrade8.php +++ /dev/null @@ -1,50 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0, - "requires_deactivated_plugins" => 0, -); - -@set_time_limit(0); - -function upgrade8_dbchanges() -{ - global $db, $output, $mybb; - - $output->print_header("Performing Queries"); - - echo "

    Performing necessary upgrade queries..

    "; - - if($db->field_exists('oldadditionalgroups', "banned")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned DROP oldadditionalgroups;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned ADD oldadditionalgroups TEXT NOT NULL AFTER oldgroup"); - - - if($db->field_exists('olddisplaygroup', "banned")) - { - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned DROP olddisplaygroup;"); - } - $db->write_query("ALTER TABLE ".TABLE_PREFIX."banned ADD olddisplaygroup int NOT NULL default '0' AFTER oldadditionalgroups"); - - $contents .= "Click next to continue with the upgrade process.

    "; - $output->print_contents($contents); - $output->print_footer("8_done"); -} - diff --git a/html/forums/install/resources/upgrade9.php b/html/forums/install/resources/upgrade9.php deleted file mode 100644 index 40bc0c6..0000000 --- a/html/forums/install/resources/upgrade9.php +++ /dev/null @@ -1,25 +0,0 @@ - 0, - "revert_all_themes" => 0, - "revert_all_settings" => 0 -); - -@set_time_limit(0); - -/* Nothing to do from 1.2.3 to 1.2.7 */ - diff --git a/html/forums/install/resources/usergroups.xml b/html/forums/install/resources/usergroups.xml deleted file mode 100644 index 4cb9553..0000000 --- a/html/forums/install/resources/usergroups.xml +++ /dev/null @@ -1,641 +0,0 @@ - - - - - - <![CDATA[Guests]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <![CDATA[Registered]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <![CDATA[Super Moderators]]> - - {username}]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <![CDATA[Administrators]]> - - {username}]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <![CDATA[Awaiting Activation]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <![CDATA[Moderators]]> - - {username}]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <![CDATA[Banned]]> - - {username}]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/html/forums/install/stylesheet.css b/html/forums/install/stylesheet.css deleted file mode 100644 index fff7f22..0000000 --- a/html/forums/install/stylesheet.css +++ /dev/null @@ -1,387 +0,0 @@ -/** - * MyBB Installer CSS - * (c) 2014 MyBB Group - */ - -body { - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - font-size: 12px; - background: #fff; - color: #333; - margin: 0; -} - -a { - color: #035488; - text-decoration: none; -} - -a:hover { - color: #444; - text-decoration: underline; -} - -#container { - margin: auto auto; - width: 880px; -} - -/* Logo */ -#logo h1 { - background: #fff url('images/logo.png') no-repeat 0 5px; - height: 82px; - margin: 0 0 2px 0; - padding: 3px; -} - -/* Header */ -#header { - clear: both; - background: #efefef; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; - padding: 12px; - font-size: 20px; - color: #444; - margin-bottom: 20px; -} - -/* Inner Container */ -#inner_container { - background: #fff; -} - -/* Progress Side bar */ -#progress { - width: 230px; - float: left; - margin: 0; - padding: 10px 0 0 5px; - padding-right: 0px; - font-size: 11px; - border-right: 1px solid #e7e7e7; -} -#progress ul { - list-style: none; - padding: 0 0 0 10px; - margin: 0; -} - -#progress li { - color: #888; - font-weight: normal; - margin: 4px 0 12px; - padding: 2px 0 1px 24px; - background-image: url("images/inactive.png"); - background-position: 0 0; - background-repeat: no-repeat; -} - -#progress li.active { - background-image: url("images/active.png"); - color: #333; - padding-top: 0; - font-size: 14px; - font-weight: bold; -} - -#progress li.intro { - background-position: 0 -20px; -} - -#progress li.license { - background-position: 0 -40px; -} - -#progress li.requirements_check { - background-position: 0 -60px; -} - -#progress li.database_info { - background-position: 0 -80px; -} - -#progress li.create_tables { - background-position: 0 -100px; -} - -#progress li.populate_tables { - background-position: 0 -120px; -} - -#progress li.templates { - background-position: 0 -140px; -} - -#progress li.configuration { - background-position: 0 -160px; -} - -#progress li.adminuser { - background-position: 0 -180px; -} - -#progress li.final { - background-position: 0 -200px; -} - -/* Content Area */ -#content { - margin-left: 235px; - width: 580px; - padding: 10px 20px 0 30px; - border-left: 1px solid #e7e7e7; -} - -* html #content { - width: 580px; -} - -/* Heading Styles */ -h2 { - margin: 0; - font-size: 20px; - padding-bottom: 5px; - border-bottom: 1px dotted #ccc; -} - -h3 { - font-size: 14px; - margin: 5px 0; -} - -h4 { - font-size: 12px; - margin: 5px 0; -} - -/* License Agreement */ -.license_agreement { - margin: 10px auto; - padding: 10px; - overflow: scroll; - height: 400px; - width: 560px; - border: 1px solid #ccc; -} - -.license_agreement ul { - padding: 0; - margin: 15px; -} - -/* Next Button */ -#next_button, .next_button { - text-align: right; - width: auto; -} - -/* Footer */ -#footer { - clear: both; - background: #f5f5f5; - margin-top: 20px; - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - padding: 8px; - font-size: 11px; - text-align: right; - vertical-align: middle; - color: #666; - margin-bottom: 20px; -} - -/* Tables */ -.border_wrapper { - margin: 0; - padding: 1px; - margin-top: 14px; - border-top: 0; - border: 1px solid #ccc; - border-radius: 6px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; -} - -.border_wrapper div.title { - background: #0066a2 url(images/thead.png) top left repeat-x; - color: #fff; - border-bottom: 1px solid #263c30; - padding: 8px; - font-weight: bold; - text-align: left; - font-size: 120%; - border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - -webkit-border-radius: 5px 5px 0 0; -} - -.border_wrapper div.title a { - color: #fff; - text-decoration: none; -} - -table.general { - background: #ccc; - width: 100%; -} - -table.general td { - border-top: 1px solid #fafafa; - border-bottom: 1px solid #ccc; - border-right: 1px solid #ccc; - border-left: 1px solid #fafafa; -} - -table.general tr td:last-child { - border-right: 0; -} - -table.general tr td:first-child { - border-left: 0; -} - -table.general tr:last-child td { - border-bottom: 0; -} - -table.bottom_cell_border td { - border-right: 0; - border-left: 0; -} - -table.general tr.last td { - border-bottom: 0; -} - -table.bottom_cell_border td { - border-right: 0; - border-left: 0; -} - -table.general td { - background: #f5f5f5; - padding: 6px; - vertical-align: top; -} - -table.general th { - background: #0f0f0f url(images/tcat.png) repeat-x; - color: #fff; - border-top: 1px solid #444; - border-bottom: 1px solid #000; - padding: 8px; - font-size: 96%; - font-weight: bold; - text-align: left; -} - -table.general th a, table.general th { - color: #fff; - text-decoration: none; -} - -table .alt_row td { - background: #f1f1f1; -} - -/* Forms */ -input.text_input { - border: 1px solid #aaa; - width: 300px; - padding: 4px; - font-size: 13px; - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - outline: 0; -} - -select { - border: 1px solid #aaa; - padding: 4px; - font-size: 12px; - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - outline: 0; -} - -input.text_input:focus, select:focus { - border: 1px solid #777; -} - -input.submit_button { - border: 1px solid #999; - padding: 4px 7px; - background: #e3e3e3 url(images/submit_bg.png) repeat-x top; - color: #444; - font-weight: bold; - font-family: 'Lucida Grande', Tahoma, Verdana, Arial, sans-serif; - margin-right: 3px; - font-size: 1.1em; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - margin-top: 4px; - margin-right: 3px; -} - -input.submit_button:hover { - border: 1px solid #666; - cursor: pointer; -} - -label { - font-weight: bold; -} - -.field_description, small { - color: #444; - font-size: 11px; -} - -/* Misc */ -.invisible { - display: none; -} - -.pass { - color: green; -} - -.fail { - color: red; -} - -.error { - background: #FFF6BF; - border: 1px solid #FFD324; - margin: 10px auto; - padding: 5px 10px 10px 10px; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -.error p { - margin-bottom: 0; -} - -.success { - background: #D6ECA6; - border: 1px solid #8DC93E; - text-align: center; - margin: 10px auto; - padding: 10px; - font-weight: bold; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; -} - -.upgrade_note { - background: #efefef; -} \ No newline at end of file diff --git a/html/forums/install/upgrade.php b/html/forums/install/upgrade.php deleted file mode 100644 index c0e3915..0000000 --- a/html/forums/install/upgrade.php +++ /dev/null @@ -1,1142 +0,0 @@ - $config['dbtype'], - "database" => $config['database'], - "table_prefix" => $config['table_prefix'], - "hostname" => $config['hostname'], - "username" => $config['username'], - "password" => $config['password'], - "encoding" => $config['db_encoding'], - ); -} -$mybb->config = &$config; - -// Include the files necessary for installation -require_once MYBB_ROOT."inc/class_timers.php"; -require_once MYBB_ROOT."inc/class_xml.php"; -require_once MYBB_ROOT.'inc/class_language.php'; - -$lang = new MyLanguage(); -$lang->set_path(MYBB_ROOT.'install/resources/'); -$lang->load('language'); - -// If we're upgrading from an SQLite installation, make sure we still work. -if($config['database']['type'] == 'sqlite3' || $config['database']['type'] == 'sqlite2') -{ - $config['database']['type'] = 'sqlite'; -} - -// Load DB interface -require_once MYBB_ROOT."inc/db_base.php"; - -require_once MYBB_ROOT."inc/db_{$config['database']['type']}.php"; -switch($config['database']['type']) -{ - case "sqlite": - $db = new DB_SQLite; - break; - case "pgsql": - $db = new DB_PgSQL; - break; - case "mysqli": - $db = new DB_MySQLi; - break; - default: - $db = new DB_MySQL; -} - -// Connect to Database -define('TABLE_PREFIX', $config['database']['table_prefix']); -$db->connect($config['database']); -$db->set_table_prefix(TABLE_PREFIX); -$db->type = $config['database']['type']; - -// Load Settings -if(file_exists(MYBB_ROOT."inc/settings.php")) -{ - require_once MYBB_ROOT."inc/settings.php"; -} - -if(!file_exists(MYBB_ROOT."inc/settings.php") || !$settings) -{ - if(function_exists('rebuild_settings')) - { - rebuild_settings(); - } - else - { - $options = array( - "order_by" => "title", - "order_dir" => "ASC" - ); - - $query = $db->simple_select("settings", "value, name", "", $options); - - $settings = array(); - while($setting = $db->fetch_array($query)) - { - $setting['value'] = str_replace("\"", "\\\"", $setting['value']); - $settings[$setting['name']] = $setting['value']; - } - } -} - -$settings['wolcutoff'] = $settings['wolcutoffmins']*60; -$settings['bbname_orig'] = $settings['bbname']; -$settings['bbname'] = strip_tags($settings['bbname']); - -// Fix for people who for some specify a trailing slash on the board URL -if(substr($settings['bburl'], -1) == "/") -{ - $settings['bburl'] = my_substr($settings['bburl'], 0, -1); -} - -$mybb->settings = &$settings; -$mybb->parse_cookies(); - -require_once MYBB_ROOT."inc/class_datacache.php"; -$cache = new datacache; - -// Load cache -$cache->cache(); - -$mybb->cache = &$cache; - -require_once MYBB_ROOT."inc/class_session.php"; -$session = new session; -$session->init(); -$mybb->session = &$session; - -// Include the necessary contants for installation -$grouppermignore = array("gid", "type", "title", "description", "namestyle", "usertitle", "stars", "starimage", "image"); -$groupzerogreater = array("pmquota", "maxpmrecipients", "maxreputationsday", "attachquota", "maxemails", "maxwarningsday", "maxposts", "edittimelimit", "canusesigxposts", "maxreputationsperuser", "maxreputationsperthread", "emailfloodtime"); -$displaygroupfields = array("title", "description", "namestyle", "usertitle", "stars", "starimage", "image"); -$fpermfields = array('canview', 'canviewthreads', 'candlattachments', 'canpostthreads', 'canpostreplys', 'canpostattachments', 'canratethreads', 'caneditposts', 'candeleteposts', 'candeletethreads', 'caneditattachments', 'canpostpolls', 'canvotepolls', 'cansearch', 'modposts', 'modthreads', 'modattachments', 'mod_edit_posts'); - -// Include the installation resources -require_once INSTALL_ROOT."resources/output.php"; -$output = new installerOutput; -$output->script = "upgrade.php"; -$output->title = "MyBB Upgrade Wizard"; - -if(file_exists("lock")) -{ - $output->print_error($lang->locked); -} -else -{ - $mybb->input['action'] = $mybb->get_input('action'); - if($mybb->input['action'] == "logout" && $mybb->user['uid']) - { - // Check session ID if we have one - if($mybb->get_input('logoutkey') !== $mybb->user['logoutkey']) - { - $output->print_error("Your user ID could not be verified to log you out. This may have been because a malicious Javascript was attempting to log you out automatically. If you intended to log out, please click the Log Out button at the top menu."); - } - - my_unsetcookie("mybbuser"); - - if($mybb->user['uid']) - { - $time = TIME_NOW; - $lastvisit = array( - "lastactive" => $time-900, - "lastvisit" => $time, - ); - $db->update_query("users", $lastvisit, "uid='".$mybb->user['uid']."'"); - } - header("Location: upgrade.php"); - } - else if($mybb->input['action'] == "do_login" && $mybb->request_method == "post") - { - require_once MYBB_ROOT."inc/functions_user.php"; - - if(!username_exists($mybb->get_input('username'))) - { - $output->print_error("The username you have entered appears to be invalid."); - } - $options = array( - 'fields' => array('username', 'password', 'salt', 'loginkey') - ); - $user = get_user_by_username($mybb->get_input('username'), $options); - - if(!$user['uid']) - { - $output->print_error("The username you have entered appears to be invalid."); - } - else - { - $user = validate_password_from_uid($user['uid'], $mybb->get_input('password'), $user); - if(!$user['uid']) - { - $output->print_error("The password you entered is incorrect. If you have forgotten your password, click here. Otherwise, go back and try again."); - } - } - - my_setcookie("mybbuser", $user['uid']."_".$user['loginkey'], null, true); - - header("Location: ./upgrade.php"); - } - - $output->steps = array($lang->upgrade); - - if($mybb->user['uid'] == 0) - { - $output->print_header($lang->please_login, "errormsg", 0, 1); - - $output->print_contents('

    '.$lang->login_desc.'

    -
    -
    - - - - - - - - - - - - - - - - -
    '.$lang->login.'
    '.$lang->login_username.':
    '.$lang->login_password.':
    '.$lang->login_password_desc.'
    -
    -
    - - -
    -
    '); - $output->print_footer(""); - - exit; - } - else if($mybb->usergroup['cancp'] != 1 && $mybb->usergroup['cancp'] != 'yes') - { - $output->print_error($lang->sprintf($lang->no_permision, $mybb->user['logoutkey'])); - } - - if(!$mybb->input['action'] || $mybb->input['action'] == "intro") - { - $output->print_header(); - - if($db->table_exists("upgrade_data")) - { - $db->drop_table("upgrade_data"); - } - $db->write_query("CREATE TABLE ".TABLE_PREFIX."upgrade_data ( - title varchar(30) NOT NULL, - contents text NOT NULL, - UNIQUE (title) - );"); - - $dh = opendir(INSTALL_ROOT."resources"); - - $upgradescripts = array(); - while(($file = readdir($dh)) !== false) - { - if(preg_match("#upgrade([0-9]+).php$#i", $file, $match)) - { - $upgradescripts[$match[1]] = $file; - $key_order[] = $match[1]; - } - } - closedir($dh); - natsort($key_order); - $key_order = array_reverse($key_order); - - // Figure out which version we last updated from (as of 1.6) - $version_history = $cache->read("version_history"); - - // If array is empty then we must be upgrading to 1.6 since that's when this feature was added - if(empty($version_history)) - { - $next_update_version = 17; // 16+1 - } - else - { - $next_update_version = (int)(end($version_history)+1); - } - - $vers = ''; - foreach($key_order as $k => $key) - { - $file = $upgradescripts[$key]; - $upgradescript = file_get_contents(INSTALL_ROOT."resources/$file"); - preg_match("#Upgrade Script:(.*)#i", $upgradescript, $verinfo); - preg_match("#upgrade([0-9]+).php$#i", $file, $keynum); - if(trim($verinfo[1])) - { - if($keynum[1] == $next_update_version) - { - $vers .= "\n"; - } - else - { - $vers .= "\n"; - } - } - } - unset($upgradescripts); - unset($upgradescript); - - $output->print_contents($lang->sprintf($lang->upgrade_welcome, $mybb->version)."

    ".$lang->upgrade_send_stats); - $output->print_footer("doupgrade"); - } - elseif($mybb->input['action'] == "doupgrade") - { - add_upgrade_store("allow_anonymous_info", $mybb->get_input('allow_anonymous_info', MyBB::INPUT_INT)); - require_once INSTALL_ROOT."resources/upgrade".$mybb->get_input('from', MyBB::INPUT_INT).".php"; - if($db->table_exists("datacache") && $upgrade_detail['requires_deactivated_plugins'] == 1 && $mybb->get_input('donewarning') != "true") - { - $plugins = $cache->read('plugins', true); - if(!empty($plugins['active'])) - { - $output->print_header(); - $lang->plugin_warning = "get_input('from', MyBB::INPUT_INT)."\" />\n\n

    Warning:

    There are still ".count($plugins['active'])." plugin(s) active. Active plugins can sometimes cause problems during an upgrade procedure or may break your forum afterward. It is strongly reccommended that you deactivate your plugins before continuing.


    "; - $output->print_contents($lang->sprintf($lang->plugin_warning, $mybb->version)); - $output->print_footer("doupgrade"); - } - else - { - add_upgrade_store("startscript", $mybb->get_input('from', MyBB::INPUT_INT)); - $runfunction = next_function($mybb->get_input('from', MyBB::INPUT_INT)); - } - } - else - { - add_upgrade_store("startscript", $mybb->get_input('from', MyBB::INPUT_INT)); - $runfunction = next_function($mybb->get_input('from', MyBB::INPUT_INT)); - } - } - $currentscript = get_upgrade_store("currentscript"); - $system_upgrade_detail = get_upgrade_store("upgradedetail"); - - if($mybb->input['action'] == "templates") - { - $runfunction = "upgradethemes"; - } - elseif($mybb->input['action'] == "rebuildsettings") - { - $runfunction = "buildsettings"; - } - elseif($mybb->input['action'] == "buildcaches") - { - $runfunction = "buildcaches"; - } - elseif($mybb->input['action'] == "finished") - { - $runfunction = "upgradedone"; - } - else // Busy running modules, come back later - { - $bits = explode("_", $mybb->input['action'], 2); - if($bits[1]) // We're still running a module - { - $from = $bits[0]; - $runfunction = next_function($bits[0], $bits[1]); - - } - } - - // Fetch current script we're in - if(function_exists($runfunction)) - { - $runfunction(); - } -} - -/** - * Do the upgrade changes - */ -function upgradethemes() -{ - global $output, $db, $system_upgrade_detail, $lang, $mybb; - - $output->print_header($lang->upgrade_templates_reverted); - - $charset = $db->build_create_table_collation(); - - if($system_upgrade_detail['revert_all_templates'] > 0) - { - $db->drop_table("templates"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."templates ( - tid int unsigned NOT NULL auto_increment, - title varchar(120) NOT NULL default '', - template text NOT NULL, - sid int(10) NOT NULL default '0', - version varchar(20) NOT NULL default '0', - status varchar(10) NOT NULL default '', - dateline int(10) NOT NULL default '0', - PRIMARY KEY (tid) - ) ENGINE=MyISAM{$charset};"); - } - - if($system_upgrade_detail['revert_all_themes'] > 0) - { - $db->drop_table("themes"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."themes ( - tid smallint unsigned NOT NULL auto_increment, - name varchar(100) NOT NULL default '', - pid smallint unsigned NOT NULL default '0', - def smallint(1) NOT NULL default '0', - properties text NOT NULL, - stylesheets text NOT NULL, - allowedgroups text NOT NULL, - PRIMARY KEY (tid) - ) ENGINE=MyISAM{$charset};"); - - $db->drop_table("themestylesheets"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."themestylesheets( - sid int unsigned NOT NULL auto_increment, - name varchar(30) NOT NULL default '', - tid int unsigned NOT NULL default '0', - attachedto text NOT NULL, - stylesheet text NOT NULL, - cachefile varchar(100) NOT NULL default '', - lastmodified bigint(30) NOT NULL default '0', - PRIMARY KEY(sid) - ) ENGINE=MyISAM{$charset};"); - - $contents = @file_get_contents(INSTALL_ROOT.'resources/mybb_theme.xml'); - if(file_exists(MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php")) - { - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php"; - } - else if(file_exists(MYBB_ROOT."admin/inc/functions_themes.php")) - { - require_once MYBB_ROOT."admin/inc/functions_themes.php"; - } - else - { - $output->print_error("Please make sure your admin directory is uploaded correctly."); - } - import_theme_xml($contents, array("templateset" => -2, "no_templates" => 1, "version_compat" => 1)); - $tid = build_new_theme("Default", null, 1); - - $db->update_query("themes", array("def" => 1), "tid='{$tid}'"); - $db->update_query("users", array('style' => $tid)); - $db->update_query("forums", array('style' => 0)); - - $db->drop_table("templatesets"); - $db->write_query("CREATE TABLE ".TABLE_PREFIX."templatesets ( - sid smallint unsigned NOT NULL auto_increment, - title varchar(120) NOT NULL default '', - PRIMARY KEY (sid) - ) ENGINE=MyISAM{$charset};"); - - $db->insert_query("templatesets", array('title' => 'Default Templates')); - } - else - { - // Re-import master - $contents = @file_get_contents(INSTALL_ROOT.'resources/mybb_theme.xml'); - if(file_exists(MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php")) - { - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions.php"; - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions_themes.php"; - } - elseif(file_exists(MYBB_ROOT."admin/inc/functions_themes.php")) - { - require_once MYBB_ROOT."admin/inc/functions.php"; - require_once MYBB_ROOT."admin/inc/functions_themes.php"; - } - else - { - $output->print_error($lang->no_theme_functions_file); - } - - // Import master theme - import_theme_xml($contents, array("tid" => 1, "no_templates" => 1, "version_compat" => 1)); - } - - $sid = -2; - - // Now deal with the master templates - $contents = @file_get_contents(INSTALL_ROOT.'resources/mybb_theme.xml'); - $parser = new XMLParser($contents); - $tree = $parser->get_tree(); - - $theme = $tree['theme']; - - if(is_array($theme['templates'])) - { - $templates = $theme['templates']['template']; - foreach($templates as $template) - { - $templatename = $db->escape_string($template['attributes']['name']); - $templateversion = (int)$template['attributes']['version']; - $templatevalue = $db->escape_string($template['value']); - $time = TIME_NOW; - $query = $db->simple_select("templates", "tid", "sid='-2' AND title='".$db->escape_string($templatename)."'"); - $oldtemp = $db->fetch_array($query); - if($oldtemp['tid']) - { - $update_array = array( - 'template' => $templatevalue, - 'version' => $templateversion, - 'dateline' => $time - ); - $db->update_query("templates", $update_array, "title='".$db->escape_string($templatename)."' AND sid='-2'"); - } - else - { - $insert_array = array( - 'title' => $templatename, - 'template' => $templatevalue, - 'sid' => $sid, - 'version' => $templateversion, - 'dateline' => $time - ); - - $db->insert_query("templates", $insert_array); - ++$newcount; - } - } - } - - $output->print_contents($lang->upgrade_templates_reverted_success); - $output->print_footer("rebuildsettings"); -} - -/** - * Update the settings - */ -function buildsettings() -{ - global $db, $output, $system_upgrade_detail, $lang; - - if(!is_writable(MYBB_ROOT."inc/settings.php")) - { - $output->print_header("Rebuilding Settings"); - echo "

    Error: Unable to open inc/settings.php

    Before the upgrade process can continue, you need to changes the permissions of inc/settings.php so it is writable.

    "; - $output->print_footer("rebuildsettings"); - exit; - } - $synccount = sync_settings($system_upgrade_detail['revert_all_settings']); - - $output->print_header($lang->upgrade_settings_sync); - $output->print_contents($lang->sprintf($lang->upgrade_settings_sync_success, $synccount[1], $synccount[0])); - $output->print_footer("buildcaches"); -} - -/** - * Rebuild caches - */ -function buildcaches() -{ - global $db, $output, $cache, $lang, $mybb; - - $output->print_header($lang->upgrade_datacache_building); - - $contents .= $lang->upgrade_building_datacache; - - $cache->update_version(); - $cache->update_attachtypes(); - $cache->update_smilies(); - $cache->update_badwords(); - $cache->update_usergroups(); - $cache->update_forumpermissions(); - $cache->update_stats(); - $cache->update_statistics(); - $cache->update_moderators(); - $cache->update_forums(); - $cache->update_usertitles(); - $cache->update_reportedcontent(); - $cache->update_awaitingactivation(); - $cache->update_mycode(); - $cache->update_profilefields(); - $cache->update_posticons(); - $cache->update_update_check(); - $cache->update_tasks(); - $cache->update_spiders(); - $cache->update_bannedips(); - $cache->update_banned(); - $cache->update_birthdays(); - $cache->update_most_replied_threads(); - $cache->update_most_viewed_threads(); - $cache->update_groupleaders(); - $cache->update_threadprefixes(); - $cache->update_forumsdisplay(); - $cache->update_reportreasons(true); - - $contents .= $lang->done."

    "; - - $output->print_contents("$contents

    ".$lang->upgrade_continue."

    "); - $output->print_footer("finished"); -} - -/** - * Called as latest function. Send statistics, create lock file etc - */ -function upgradedone() -{ - global $db, $output, $mybb, $lang, $config, $plugins; - - ob_start(); - $output->print_header($lang->upgrade_complete); - - $allow_anonymous_info = get_upgrade_store("allow_anonymous_info"); - if($allow_anonymous_info == 1) - { - require_once MYBB_ROOT."inc/functions_serverstats.php"; - $build_server_stats = build_server_stats(0, '', $mybb->version_code, $mybb->config['database']['encoding']); - - if($build_server_stats['info_sent_success'] == false) - { - echo $build_server_stats['info_image']; - } - } - ob_end_flush(); - - // Attempt to run an update check - require_once MYBB_ROOT.'inc/functions_task.php'; - $query = $db->simple_select('tasks', 'tid', "file='versioncheck'"); - $update_check = $db->fetch_array($query); - if($update_check) - { - // Load plugin system for update check - require_once MYBB_ROOT."inc/class_plugins.php"; - $plugins = new pluginSystem; - - run_task($update_check['tid']); - } - - if(is_writable("./")) - { - $lock = @fopen("./lock", "w"); - $written = @fwrite($lock, "1"); - @fclose($lock); - if($written) - { - $lock_note = $lang->sprintf($lang->upgrade_locked, $config['admin_dir']); - } - } - if(!$written) - { - $lock_note = "

    ".$lang->upgrade_removedir."

    "; - } - - // Rebuild inc/settings.php at the end of the upgrade - if(function_exists('rebuild_settings')) - { - rebuild_settings(); - } - else - { - $options = array( - "order_by" => "title", - "order_dir" => "ASC" - ); - - $query = $db->simple_select("settings", "value, name", "", $options); - while($setting = $db->fetch_array($query)) - { - $setting['value'] = str_replace("\"", "\\\"", $setting['value']); - $settings[$setting['name']] = $setting['value']; - } - } - - $output->print_contents($lang->sprintf($lang->upgrade_congrats, $mybb->version, $lock_note)); - $output->print_footer(); -} - -/** - * Show the finish page - */ -function whatsnext() -{ - global $output, $db, $system_upgrade_detail, $lang; - - if($system_upgrade_detail['revert_all_templates'] > 0) - { - $output->print_header($lang->upgrade_template_reversion); - $output->print_contents($lang->upgrade_template_reversion_success); - $output->print_footer("templates"); - } - else - { - upgradethemes(); - } -} - -/** - * Determine the next function we need to call - * - * @param int $from - * @param string $func - * - * @return string - */ -function next_function($from, $func="dbchanges") -{ - global $oldvers, $system_upgrade_detail, $currentscript, $cache; - - load_module("upgrade".$from.".php"); - if(function_exists("upgrade".$from."_".$func)) - { - $function = "upgrade".$from."_".$func; - } - else - { - // We're done with our last upgrade script, so add it to the upgrade scripts we've already completed. - $version_history = $cache->read("version_history"); - $version_history[$from] = $from; - $cache->update("version_history", $version_history); - - $from = $from+1; - if(file_exists(INSTALL_ROOT."resources/upgrade".$from.".php")) - { - $function = next_function($from); - } - } - - if(!$function) - { - $function = "whatsnext"; - } - return $function; -} - -/** - * @param string $module - */ -function load_module($module) -{ - global $system_upgrade_detail, $currentscript, $upgrade_detail; - - require_once INSTALL_ROOT."resources/".$module; - if($currentscript != $module) - { - foreach($upgrade_detail as $key => $val) - { - if(!$system_upgrade_detail[$key] || $val > $system_upgrade_detail[$key]) - { - $system_upgrade_detail[$key] = $val; - } - } - add_upgrade_store("upgradedetail", $system_upgrade_detail); - add_upgrade_store("currentscript", $module); - } -} - -/** - * Get a value from our upgrade data cache - * - * @param string $title - * - * @return mixed - */ -function get_upgrade_store($title) -{ - global $db; - - $query = $db->simple_select("upgrade_data", "*", "title='".$db->escape_string($title)."'"); - $data = $db->fetch_array($query); - return my_unserialize($data['contents']); -} - -/** - * @param string $title - * @param mixed $contents - */ -function add_upgrade_store($title, $contents) -{ - global $db; - - $replace_array = array( - "title" => $db->escape_string($title), - "contents" => $db->escape_string(my_serialize($contents)) - ); - $db->replace_query("upgrade_data", $replace_array, "title"); -} - -/** - * @param int $redo 2 means that all setting tables will be dropped and recreated - * - * @return array - */ -function sync_settings($redo=0) -{ - global $db; - - $settingcount = $groupcount = 0; - $settings = $settinggroups = array(); - if($redo == 2) - { - $db->drop_table("settinggroups"); - switch($db->type) - { - case "pgsql": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."settinggroups ( - gid serial, - name varchar(100) NOT NULL default '', - title varchar(220) NOT NULL default '', - description text NOT NULL default '', - disporder smallint NOT NULL default '0', - isdefault int NOT NULL default '0', - PRIMARY KEY (gid) - );"); - break; - case "sqlite": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."settinggroups ( - gid INTEGER PRIMARY KEY, - name varchar(100) NOT NULL default '', - title varchar(220) NOT NULL default '', - description TEXT NOT NULL, - disporder smallint NOT NULL default '0', - isdefault int(1) NOT NULL default '0' - );"); - break; - case "mysql": - default: - $db->write_query("CREATE TABLE ".TABLE_PREFIX."settinggroups ( - gid smallint unsigned NOT NULL auto_increment, - name varchar(100) NOT NULL default '', - title varchar(220) NOT NULL default '', - description text NOT NULL, - disporder smallint unsigned NOT NULL default '0', - isdefault int(1) NOT NULL default '0', - PRIMARY KEY (gid) - ) ENGINE=MyISAM;"); - } - - $db->drop_table("settings"); - - switch($db->type) - { - case "pgsql": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."settings ( - sid serial, - name varchar(120) NOT NULL default '', - title varchar(120) NOT NULL default '', - description text NOT NULL default '', - optionscode text NOT NULL default '', - value text NOT NULL default '', - disporder smallint NOT NULL default '0', - gid smallint NOT NULL default '0', - isdefault int NOT NULL default '0', - PRIMARY KEY (sid) - );"); - break; - case "sqlite": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."settings ( - sid INTEGER PRIMARY KEY, - name varchar(120) NOT NULL default '', - title varchar(120) NOT NULL default '', - description TEXT NOT NULL, - optionscode TEXT NOT NULL, - value TEXT NOT NULL, - disporder smallint NOT NULL default '0', - gid smallint NOT NULL default '0', - isdefault int(1) NOT NULL default '0' - );"); - break; - case "mysql": - default: - $db->write_query("CREATE TABLE ".TABLE_PREFIX."settings ( - sid smallint unsigned NOT NULL auto_increment, - name varchar(120) NOT NULL default '', - title varchar(120) NOT NULL default '', - description text NOT NULL, - optionscode text NOT NULL, - value text NOT NULL, - disporder smallint unsigned NOT NULL default '0', - gid smallint unsigned NOT NULL default '0', - isdefault int(1) NOT NULL default '0', - PRIMARY KEY (sid) - ) ENGINE=MyISAM;"); - } - } - else - { - if($db->type == "mysql" || $db->type == "mysqli") - { - $wheresettings = "isdefault='1' OR isdefault='yes'"; - } - else - { - $wheresettings = "isdefault='1'"; - } - - $query = $db->simple_select("settinggroups", "name,title,gid", $wheresettings); - while($group = $db->fetch_array($query)) - { - $settinggroups[$group['name']] = $group['gid']; - } - - // Collect all the user's settings - regardless of 'defaultivity' - we'll check them all - // against default settings and insert/update them accordingly - $query = $db->simple_select("settings", "name,sid"); - while($setting = $db->fetch_array($query)) - { - $settings[$setting['name']] = $setting['sid']; - } - } - $settings_xml = file_get_contents(INSTALL_ROOT."resources/settings.xml"); - $parser = new XMLParser($settings_xml); - $parser->collapse_dups = 0; - $tree = $parser->get_tree(); - $settinggroupnames = array(); - $settingnames = array(); - - foreach($tree['settings'][0]['settinggroup'] as $settinggroup) - { - $settinggroupnames[] = $settinggroup['attributes']['name']; - - $groupdata = array( - "name" => $db->escape_string($settinggroup['attributes']['name']), - "title" => $db->escape_string($settinggroup['attributes']['title']), - "description" => $db->escape_string($settinggroup['attributes']['description']), - "disporder" => (int)$settinggroup['attributes']['disporder'], - "isdefault" => $settinggroup['attributes']['isdefault'] - ); - if(!$settinggroups[$settinggroup['attributes']['name']] || $redo == 2) - { - $gid = $db->insert_query("settinggroups", $groupdata); - ++$groupcount; - } - else - { - $gid = $settinggroups[$settinggroup['attributes']['name']]; - $db->update_query("settinggroups", $groupdata, "gid='{$gid}'"); - } - - if(!$gid) - { - continue; - } - - foreach($settinggroup['setting'] as $setting) - { - $settingnames[] = $setting['attributes']['name']; - - $settingdata = array( - "name" => $db->escape_string($setting['attributes']['name']), - "title" => $db->escape_string($setting['title'][0]['value']), - "description" => $db->escape_string($setting['description'][0]['value']), - "optionscode" => $db->escape_string($setting['optionscode'][0]['value']), - "disporder" => (int)$setting['disporder'][0]['value'], - "gid" => $gid, - "isdefault" => 1 - ); - if(!$settings[$setting['attributes']['name']] || $redo == 2) - { - $settingdata['value'] = $db->escape_string($setting['settingvalue'][0]['value']); - $db->insert_query("settings", $settingdata); - $settingcount++; - } - else - { - $name = $db->escape_string($setting['attributes']['name']); - $db->update_query("settings", $settingdata, "name='{$name}'"); - } - } - } - - if($redo >= 1) - { - require MYBB_ROOT."inc/settings.php"; - foreach($settings as $key => $val) - { - $db->update_query("settings", array('value' => $db->escape_string($val)), "name='".$db->escape_string($key)."'"); - } - } - unset($settings); - $query = $db->simple_select("settings", "*", "", array('order_by' => 'title')); - while($setting = $db->fetch_array($query)) - { - $setting['value'] = str_replace("\"", "\\\"", $setting['value']); - $settings .= "\$settings['{$setting['name']}'] = \"".$setting['value']."\";\n"; - } - $settings = "drop_table("tasks"); - switch($db->type) - { - case "pgsql": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."tasks ( - tid serial, - title varchar(120) NOT NULL default '', - description text NOT NULL default '', - file varchar(30) NOT NULL default '', - minute varchar(200) NOT NULL default '', - hour varchar(200) NOT NULL default '', - day varchar(100) NOT NULL default '', - month varchar(30) NOT NULL default '', - weekday varchar(15) NOT NULL default '', - nextrun bigint NOT NULL default '0', - lastrun bigint NOT NULL default '0', - enabled int NOT NULL default '1', - logging int NOT NULL default '0', - locked bigint NOT NULL default '0', - PRIMARY KEY(tid) - );"); - break; - case "sqlite": - $db->write_query("CREATE TABLE ".TABLE_PREFIX."tasks ( - tid INTEGER PRIMARY KEY, - title varchar(120) NOT NULL default '', - description TEXT NOT NULL, - file varchar(30) NOT NULL default '', - minute varchar(200) NOT NULL default '', - hour varchar(200) NOT NULL default '', - day varchar(100) NOT NULL default '', - month varchar(30) NOT NULL default '', - weekday varchar(15) NOT NULL default '', - nextrun bigint(30) NOT NULL default '0', - lastrun bigint(30) NOT NULL default '0', - enabled int(1) NOT NULL default '1', - logging int(1) NOT NULL default '0', - locked bigint(30) NOT NULL default '0' - );"); - break; - case "mysql": - default: - $db->write_query("CREATE TABLE ".TABLE_PREFIX."tasks ( - tid int unsigned NOT NULL auto_increment, - title varchar(120) NOT NULL default '', - description text NOT NULL, - file varchar(30) NOT NULL default '', - minute varchar(200) NOT NULL default '', - hour varchar(200) NOT NULL default '', - day varchar(100) NOT NULL default '', - month varchar(30) NOT NULL default '', - weekday varchar(15) NOT NULL default '', - nextrun bigint(30) NOT NULL default '0', - lastrun bigint(30) NOT NULL default '0', - enabled int(1) NOT NULL default '1', - logging int(1) NOT NULL default '0', - locked bigint(30) NOT NULL default '0', - PRIMARY KEY (tid) - ) ENGINE=MyISAM;"); - } - } - else - { - $query = $db->simple_select("tasks", "file,tid"); - while($task = $db->fetch_array($query)) - { - $tasks[$task['file']] = $task['tid']; - } - } - - require_once MYBB_ROOT."inc/functions_task.php"; - $task_file = file_get_contents(INSTALL_ROOT.'resources/tasks.xml'); - $parser = new XMLParser($task_file); - $parser->collapse_dups = 0; - $tree = $parser->get_tree(); - - // Resync tasks - foreach($tree['tasks'][0]['task'] as $task) - { - if(!$tasks[$task['file'][0]['value']] || $redo == 2) - { - $new_task = array( - 'title' => $db->escape_string($task['title'][0]['value']), - 'description' => $db->escape_string($task['description'][0]['value']), - 'file' => $db->escape_string($task['file'][0]['value']), - 'minute' => $db->escape_string($task['minute'][0]['value']), - 'hour' => $db->escape_string($task['hour'][0]['value']), - 'day' => $db->escape_string($task['day'][0]['value']), - 'weekday' => $db->escape_string($task['weekday'][0]['value']), - 'month' => $db->escape_string($task['month'][0]['value']), - 'enabled' => $db->escape_string($task['enabled'][0]['value']), - 'logging' => $db->escape_string($task['logging'][0]['value']) - ); - - $new_task['nextrun'] = fetch_next_run($new_task); - - $db->insert_query("tasks", $new_task); - $taskcount++; - } - else - { - $update_task = array( - 'title' => $db->escape_string($task['title'][0]['value']), - 'description' => $db->escape_string($task['description'][0]['value']), - 'file' => $db->escape_string($task['file'][0]['value']), - ); - - $db->update_query("tasks", $update_task, "file='".$db->escape_string($task['file'][0]['value'])."'"); - } - } - - return $taskcount; -} - -/** - * Write our settings to the settings file - */ -function write_settings() -{ - global $db; - $query = $db->simple_select("settings", "*", "", array('order_by' => 'title')); - while($setting = $db->fetch_array($query)) - { - $setting['value'] = $db->escape_string($setting['value']); - $settings .= "\$settings['{$setting['name']}'] = \"{$setting['value']}\";\n"; - } - if(!empty($settings)) - { - $settings = "' + - '.sceditor-dropdown { text-align: ' + ($('body').css('direction') === 'rtl' ? 'right' :'left') + '; }' + - '').appendTo('body'); - - - - /******************************************** - * Update editor to use align= as alignment * - ********************************************/ - $.sceditor.plugins.bbcode.bbcode - .set('align', { - html: function(element, attrs, content) { - return '
    ' + content + '
    '; - }, - isInline: false - }) - .set('center', { format: '[align=center]{0}[/align]' }) - .set('left', { format: '[align=left]{0}[/align]' }) - .set('right', { format: '[align=right]{0}[/align]' }) - .set('justify', { format: '[align=justify]{0}[/align]' }); - - $.sceditor.command - .set('center', { txtExec: ['[align=center]', '[/align]'] }) - .set('left', { txtExec: ['[align=left]', '[/align]'] }) - .set('right', { txtExec: ['[align=right]', '[/align]'] }) - .set('justify', { txtExec: ['[align=justify]', '[/align]'] }); - - - - /************************************************ - * Update font to support MyBB's BBCode dialect * - ************************************************/ - $.sceditor.plugins.bbcode.bbcode - .set('list', { - html: function(element, attrs, content) { - var type = (attrs.defaultattr === '1' ? 'ol' : 'ul'); - - if(attrs.defaultattr === 'a') - type = 'ol type="a"'; - - return '<' + type + '>' + content + ''; - }, - - breakAfter: false - }) - .set('ul', { format: '[list]{0}[/list]' }) - .set('ol', { - format: function($elm, content) { - var type = ($elm.attr('type') === 'a' ? 'a' : '1'); - - return '[list=' + type + ']' + content + '[/list]'; - } - }) - .set('li', { format: '[*]{0}', excludeClosing: true }) - .set('*', { excludeClosing: true, isInline: true }); - - $.sceditor.command - .set('bulletlist', { txtExec: ['[list]\n[*]', '\n[/list]'] }) - .set('orderedlist', { txtExec: ['[list=1]\n[*]', '\n[/list]'] }); - - - - /*********************************************************** - * Update size tag to use xx-small-xx-large instead of 1-7 * - ***********************************************************/ - $.sceditor.plugins.bbcode.bbcode.set('size', { - format: function($elm, content) { - var fontSize, - sizes = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'], - size = $elm.attr('size');; - - if (!size) { - fontSize = $elm.css('fontSize'); - // Most browsers return px value but IE returns 1-7 - if(fontSize.indexOf('px') > -1) { - // convert size to an int - fontSize = fontSize.replace('px', '') - 0; - size = 1; - - if(fontSize > 9) - size = 2; - if(fontSize > 12) - size = 3; - if(fontSize > 15) - size = 4; - if(fontSize > 17) - size = 5; - if(fontSize > 23) - size = 6; - if(fontSize > 31) - size = 7; - } - else { - size = (~~fontSize) + 1; - } - - if(size > 7) - size = 7; - if(size < 1) - size = 1; - - size = sizes[size-1]; - } - else { - size = sizes[size-1]; - } - - return '[size=' + size + ']' + content + '[/size]'; - }, - html: function(token, attrs, content) { - var sizes = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'], - size = $.inArray(attrs.defaultattr, sizes)+1; - if (!isNaN(attrs.defaultattr)) { - size = attrs.defaultattr; - if(size > 7) - size = 7; - if(size < 1) - size = 1; - } - if (size < 0) { - size = 0; - } - return '' + content + ''; - } - }); - - $.sceditor.command.set('size', { - _dropDown: function(editor, caller, callback) { - var content = $('
    '), - clickFunc = function (e) { - callback($(this).data('size')); - editor.closeDropDown(true); - e.preventDefault(); - }; - - for (var i=1; i <= 7; i++) - content.append($('' + i + '').click(clickFunc)); - - editor.createDropDown(caller, 'fontsize-picker', content); - }, - exec: function (caller) { - var editor = this; - - $.sceditor.command.get('size')._dropDown( - editor, - caller, - function(fontSize) { - editor.execCommand('fontsize', fontSize); - } - ); - }, - txtExec: function(caller) { - var editor = this, - sizes = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large']; - - $.sceditor.command.get('size')._dropDown( - editor, - caller, - function(size) { - size = (~~size); - size = (size > 7) ? 7 : ( (size < 1) ? 1 : size ); - - editor.insertText('[size=' + sizes[size-1] + ']', '[/size]'); - } - ); - } - }); - - - - /******************************************** - * Update quote to support pid and dateline * - ********************************************/ - $.sceditor.plugins.bbcode.bbcode.set('quote', { - format: function(element, content) { - var author = '', - $elm = $(element), - $cite = $elm.children('cite').first(); - $cite.html($cite.text()); - - if($cite.length === 1 || $elm.data('author')) - { - author = $cite.text() || $elm.data('author'); - - $elm.data('author', author); - $cite.remove(); - - content = this.elementToBbcode($(element)); - author = '=' + author.replace(/(^\s+|\s+$)/g, ''); - - $elm.prepend($cite); - } - - if($elm.data('pid')) - author += " pid='" + $elm.data('pid') + "'"; - - if($elm.data('dateline')) - author += " dateline='" + $elm.data('dateline') + "'"; - - return '[quote' + author + ']' + content + '[/quote]'; - }, - html: function(token, attrs, content) { - var data = ''; - - if(attrs.pid) - data += ' data-pid="' + attrs.pid + '"'; - - if(attrs.dateline) - data += ' data-dateline="' + attrs.dateline + '"'; - - if(typeof attrs.defaultattr !== "undefined") - content = '' + attrs.defaultattr.replace(/ /g, ' ') + '' + content; - - return '' + content + ''; - }, - quoteType: function(val, name) { - return "'" + val.replace("'", "\\'") + "'"; - }, - breakStart: true, - breakEnd: true - }); - - - - /************************************************************ - * Update font tag to allow limiting to only first in stack * - ************************************************************/ - $.sceditor.plugins.bbcode.bbcode.set('font', { - format: function(element, content) { - var font; - - if(element[0].nodeName.toLowerCase() !== 'font' || !(font = element.attr('face'))) - font = element.css('font-family'); - - - if(typeof font == 'string' && font != '' && font != 'defaultattr') - { - return '[font=' + this.stripQuotes(font) + ']' + content + '[/font]'; - } - else - { - return content; - } - }, - html: function(token, attrs, content) { - if(typeof attrs.defaultattr == 'string' && attrs.defaultattr != '' && attrs.defaultattr != '{defaultattr}') - { - return '' + content + ''; - } - else - { - return content; - } - } - }); - - - - /************************ - * Add MyBB PHP command * - ************************/ - $.sceditor.plugins.bbcode.bbcode.set('php', { - allowsEmpty: true, - isInline: false, - allowedChildren: ['#', '#newline'], - format: '[php]{0}[/php]', - html: '{0}' - }); - - $.sceditor.command.set("php", { - _dropDown: function (editor, caller) { - var $content; - - $content = $( - '
    ' + - ' ' + - '",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/\s*$/g,ra={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:k.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("'; - } else { - msgbox += '
    '; - } - msgbox += '
    '+ - '
    '+ - '
    '+ opts.closeText +'
    '+ - '
    '+ - ''+ - '
    '+ - ''; - - t.jqib = $(msgbox).appendTo($body); - t.jqi = t.jqib.children('.'+ opts.prefix); - t.jqif = t.jqib.children('.'+ opts.prefix +'fade'); - - //if a string was passed, convert to a single state - if(message.constructor === String){ - message = { - state0: { - title: opts.title, - html: message, - buttons: opts.buttons, - position: opts.position, - focus: opts.focus, - defaultButton: opts.defaultButton, - submit: opts.submit - } - }; - } - - //build the states - t.options.states = {}; - var k,v; - for(k in message){ - v = $.extend({},Imp.defaults.state,{name:k},message[k]); - t.addState(v.name, v); - - if(t.currentStateName === ''){ - t.currentStateName = v.name; - } - } - - //Events - t.jqi.on('click', '.'+ opts.prefix +'buttons button', function(e){ - var $t = $(this), - $state = $t.parents('.'+ opts.prefix +'state'), - statename = $state.data('jqi-name'), - stateobj = t.options.states[statename], - msg = $state.children('.'+ opts.prefix +'message'), - clicked = stateobj.buttons[$t.text()] || stateobj.buttons[$t.html()], - forminputs = {}; - - // disable for a moment to prevent multiple clicks - if(t.options.buttonTimeout > 0){ - t.disableStateButtons(statename); - setTimeout(function(){ - t.enableStateButtons(statename); - }, t.options.buttonTimeout); - } - - // if for some reason we couldn't get the value - if(clicked === undefined){ - for(var i in stateobj.buttons){ - if(stateobj.buttons[i].title === $t.text() || stateobj.buttons[i].title === $t.html()){ - clicked = stateobj.buttons[i].value; - } - } - } - - //collect all form element values from all states. - $.each(t.jqi.children('form').serializeArray(),function(i,obj){ - if (forminputs[obj.name] === undefined) { - forminputs[obj.name] = obj.value; - } else if (typeof forminputs[obj.name] === Array || typeof forminputs[obj.name] === 'object') { - forminputs[obj.name].push(obj.value); - } else { - forminputs[obj.name] = [forminputs[obj.name],obj.value]; - } - }); - - // trigger an event - var promptsubmite = new $.Event('impromptu:submit'); - promptsubmite.stateName = stateobj.name; - promptsubmite.state = $state; - $state.trigger(promptsubmite, [clicked, msg, forminputs]); - - if(!promptsubmite.isDefaultPrevented()){ - t.close(true, clicked,msg,forminputs); - } - }); - - // if the fade is clicked blink the prompt - var fadeClicked = function(){ - if(opts.persistent){ - var offset = (opts.top.toString().indexOf('%') >= 0? ($window.height()*(parseInt(opts.top,10)/100)) : parseInt(opts.top,10)), - top = parseInt(t.jqi.css('top').replace('px',''),10) - offset; - - //$window.scrollTop(top); - $('html,body').animate({ scrollTop: top }, 'fast', function(){ - var i = 0; - t.jqib.addClass(opts.prefix +'warning'); - var intervalid = setInterval(function(){ - t.jqib.toggleClass(opts.prefix +'warning'); - if(i++ > 1){ - clearInterval(intervalid); - t.jqib.removeClass(opts.prefix +'warning'); - } - }, 100); - }); - } - else { - t.close(true); - } - }; - - // listen for esc or tab keys - var keyDownEventHandler = function(e){ - var key = (window.event) ? event.keyCode : e.keyCode; - - //escape key closes - if(key === 27) { - fadeClicked(); - } - - //enter key pressed trigger the default button if its not on it, ignore if it is a textarea - if(key === 13){ - var $defBtn = t.getCurrentState().find('.'+ opts.prefix +'defaultbutton'); - var $tgt = $(e.target); - - if($tgt.is('textarea,.'+opts.prefix+'button') === false && $defBtn.length > 0){ - e.preventDefault(); - $defBtn.click(); - } - } - - //constrain tabs, tabs should iterate through the state and not leave - if (key === 9){ - var $inputels = $('input,select,textarea,button',t.getCurrentState()); - var fwd = !e.shiftKey && e.target === $inputels[$inputels.length-1]; - var back = e.shiftKey && e.target === $inputels[0]; - if (fwd || back) { - setTimeout(function(){ - if (!$inputels){ - return; - } - var el = $inputels[back===true ? $inputels.length-1 : 0]; - - if (el){ - el.focus(); - } - },10); - return false; - } - } - }; - - t.position(); - t.style(); - - // store copy of the window resize function for interal use only - t._windowResize = function(e){ - t.position(e); - }; - $window.resize({ animate: false }, t._windowResize); - - t.jqif.click(fadeClicked); - t.jqi.find('.'+ opts.prefix +'close').click(function(){ t.close(); }); - t.jqi.find('.'+ opts.prefix +'form').submit(function(){ return false; }); - t.jqib.on("keydown",keyDownEventHandler) - .on('impromptu:loaded', opts.loaded) - .on('impromptu:close', opts.close) - .on('impromptu:statechanging', opts.statechanging) - .on('impromptu:statechanged', opts.statechanged); - - // Show it - t.jqif[opts.show](opts.overlayspeed); - t.jqi[opts.show](opts.promptspeed, function(){ - - t.goToState( - isNaN(opts.initialState) ? opts.initialState : - t.jqi.find('.'+ opts.prefix +'states .'+ opts.prefix +'state').eq(opts.initialState).data('jqi-name') - ); - - t.jqib.trigger('impromptu:loaded'); - }); - - // Timeout - if(opts.timeout > 0){ - t.timeout = setTimeout(function(){ t.close(true); },opts.timeout); - } - - return t; - }, - - /** - * close - Closes the prompt - * @param callback Function - called when the transition is complete - * @param clicked String - value of the button clicked (only used internally) - * @param msg jQuery - The state message body (only used internally) - * @param forvals Object - key/value pairs of all form field names and values (only used internally) - * @return Imp - the instance of this Impromptu object - */ - close: function(callCallback, clicked, msg, formvals){ - var t = this; - Imp.removeFromStack(t.id); - - if(t.timeout){ - clearTimeout(t.timeout); - t.timeout = false; - } - - if(t.jqib){ - t.jqib[t.options.hide]('fast',function(){ - - t.jqib.trigger('impromptu:close', [clicked,msg,formvals]); - - t.jqib.remove(); - - $(window).off('resize', t._windowResize); - - if(typeof callCallback === 'function'){ - callCallback(); - } - }); - } - t.currentStateName = ""; - - return t; - }, - - /** - * addState - Injects a state into the prompt - * @param statename String - Name of the state - * @param stateobj Object - options for the state - * @param afterState String - selector of the state to insert after - * @return jQuery - the newly created state - */ - addState: function(statename, stateobj, afterState) { - var t = this, - state = '', - $state = null, - arrow = '', - title = '', - opts = t.options, - $jqistates = t.jqi.find('.'+ opts.prefix +'states'), - buttons = [], - showHtml,defbtn,k,v,l,i=0; - - stateobj = $.extend({},Imp.defaults.state, {name:statename}, stateobj); - - if(stateobj.position.arrow !== null){ - arrow = '
    '; - } - if(stateobj.title && stateobj.title !== ''){ - title = '
    '+ stateobj.title +'
    '; - } - - showHtml = stateobj.html; - if (typeof stateobj.html === 'function') { - showHtml = 'Error: html function must return text'; - } - - state += '
    '+ - arrow + title + - '
    ' + showHtml +'
    '+ - '
    '; - - // state buttons may be in object or array, lets convert objects to arrays - if($.isArray(stateobj.buttons)){ - buttons = stateobj.buttons; - } - else if($.isPlainObject(stateobj.buttons)){ - for(k in stateobj.buttons){ - if(stateobj.buttons.hasOwnProperty(k)){ - buttons.push({ title: k, value: stateobj.buttons[k] }); - } - } - } - - // iterate over each button and create them - for(i=0, l=buttons.length; i' + v.title + ''; - } - - state += '
    '; - - $state = $(state).css({display:'none'}); - - $state.on('impromptu:submit', stateobj.submit); - - if(afterState !== undefined){ - t.getState(afterState).after($state); - } - else{ - $jqistates.append($state); - } - - t.options.states[statename] = stateobj; - - return $state; - }, - - /** - * removeState - Removes a state from the prompt - * @param state String - Name of the state - * @param newState String - Name of the state to transition to - * @return Boolean - returns true on success, false on failure - */ - removeState: function(state, newState) { - var t = this, - $state = t.getState(state), - rm = function(){ $state.remove(); }; - - if($state.length === 0){ - return false; - } - - // transition away from it before deleting - if($state.css('display') !== 'none'){ - if(newState !== undefined && t.getState(newState).length > 0){ - t.goToState(newState, false, rm); - } - else if($state.next().length > 0){ - t.nextState(rm); - } - else if($state.prev().length > 0){ - t.prevState(rm); - } - else{ - t.close(); - } - } - else{ - $state.slideUp('slow', rm); - } - - return true; - }, - - /** - * getApi - Get the api, so you can extract it from $.prompt stack - * @return jQuery - the prompt - */ - getApi: function() { - return this; - }, - - /** - * getBox - Get the box containing fade and prompt - * @return jQuery - the prompt - */ - getBox: function() { - return this.jqib; - }, - - /** - * getPrompt - Get the prompt - * @return jQuery - the prompt - */ - getPrompt: function() { - return this.jqi; - }, - - /** - * getState - Get the state by its name - * @param statename String - Name of the state - * @return jQuery - the state - */ - getState: function(statename) { - return this.jqi.find('[data-jqi-name="'+ statename +'"]'); - }, - - /** - * getCurrentState - Get the current visible state - * @return jQuery - the current visible state - */ - getCurrentState: function() { - return this.getState(this.getCurrentStateName()); - }, - - /** - * getCurrentStateName - Get the name of the current visible state/substate - * @return String - the current visible state's name - */ - getCurrentStateName: function() { - return this.currentStateName; - }, - - /** - * disableStateButtons - Disables the buttons in a state - * @param statename String - Name of the state containing buttons - * @param buttons Array - Array of button values to disable. By default all are disabled - * @param enable Boolean - True to enable the buttons instead of disabling (internally use only) - * @return Void - */ - disableStateButtons: function(statename, buttons, enable) { - var t = this; - - if($.isArray(statename)){ - buttons = statename; - statename = null; - } - - t.getState(statename || t.getCurrentStateName()).find('.'+ t.options.prefix + 'button').each(function(i,btn){ - if(buttons === undefined || $.inArray(btn.value, buttons) !== -1){ - btn.disabled = !enable; - } - }); - }, - - /** - * enableStateButtons - Enables the buttons in a state - * @param statename String - Name of the state containing buttons. Defaults to current state - * @param buttons Array - Array of button values to enable. By default all are enabled - * @return Void - */ - enableStateButtons: function(statename, buttons) { - this.disableStateButtons(statename, buttons, true); - }, - - /** - * position - Repositions the prompt (Used internally) - * @return void - */ - position: function(e){ - var t = this, - restoreFx = $.fx.off, - $state = t.getCurrentState(), - stateObj = t.options.states[$state.data('jqi-name')], - pos = stateObj? stateObj.position : undefined, - $window = $(window), - bodyHeight = document.body.scrollHeight, //$(document.body).outerHeight(true), - windowHeight = $(window).height(), - documentHeight = $(document).height(), - height = (bodyHeight > windowHeight) ? bodyHeight : windowHeight, - scrollTop = parseInt($window.scrollTop(),10), - top = scrollTop + (t.options.top.toString().indexOf('%') >= 0? - (windowHeight*(parseInt(t.options.top,10)/100)) : parseInt(t.options.top,10)); - - // when resizing the window turn off animation - if(e !== undefined && e.data.animate === false){ - $.fx.off = true; - } - - t.jqib.css({ - position: "absolute", - height: height, - width: "100%", - top: 0, - left: 0, - right: 0, - bottom: 0 - }); - t.jqif.css({ - position: "fixed", - height: height, - width: "100%", - top: 0, - left: 0, - right: 0, - bottom: 0 - }); - - // tour positioning - if(pos && pos.container){ - var offset = $(pos.container).offset(), - hasScrolled = false; - - if($.isPlainObject(offset) && offset.top !== undefined){ - top = (offset.top + pos.y) - (t.options.top.toString().indexOf('%') >= 0? (windowHeight*(parseInt(t.options.top,10)/100)) : parseInt(t.options.top,10)); - - t.jqi.css({ - position: "absolute" - }); - t.jqi.animate({ - top: offset.top + pos.y, - left: offset.left + pos.x, - marginLeft: 0, - width: (pos.width !== undefined)? pos.width : null - }, function(){ - // if it didn't scroll before, check that the bottom is within view. Since width - // is animated we must use the callback before we know the height - if(!hasScrolled && (offset.top + pos.y + t.jqi.outerHeight(true)) > (scrollTop + windowHeight)){ - $('html,body').animate({ scrollTop: top }, 'slow', 'swing', function(){}); - hasScrolled = true; - } - }); - - // scroll if the top is out of the viewing area - if(top < scrollTop || top > scrollTop + windowHeight){ - $('html,body').animate({ scrollTop: top }, 'slow', 'swing', function(){}); - hasScrolled = true; - } - } - } - // custom state width animation - else if(pos && pos.width){ - t.jqi.css({ - position: "absolute", - left: '50%' - }); - t.jqi.animate({ - top: pos.y || top, - left: pos.x || '50%', - marginLeft: ((pos.width/2)*-1), - width: pos.width - }); - } - // standard prompt positioning - else{ - t.jqi.css({ - position: "absolute", - top: top, - left: '50%',//$window.width()/2, - marginLeft: ((t.jqi.outerWidth(false)/2)*-1) - }); - } - - // restore fx settings - if(e !== undefined && e.data.animate === false){ - $.fx.off = restoreFx; - } - }, - - /** - * style - Restyles the prompt (Used internally) - * @return void - */ - style: function(){ - var t = this; - - t.jqif.css({ - zIndex: t.options.zIndex, - display: "none", - opacity: t.options.opacity - }); - t.jqi.css({ - zIndex: t.options.zIndex+1, - display: "none" - }); - t.jqib.css({ - zIndex: t.options.zIndex - }); - }, - - /** - * goToState - Goto the specified state - * @param state String - name of the state to transition to - * @param subState Boolean - true to be a sub state within the currently open state - * @param callback Function - called when the transition is complete - * @return jQuery - the newly active state - */ - goToState: function(state, subState, callback) { - var t = this, - $jqi = t.jqi, - jqiopts = t.options, - $state = t.getState(state), - stateobj = jqiopts.states[$state.data('jqi-name')], - promptstatechanginge = new $.Event('impromptu:statechanging'), - opts = t.options; - - if(stateobj !== undefined){ - - - if (typeof stateobj.html === 'function') { - var contentLaterFunc = stateobj.html; - $state.find('.' + opts.prefix +'message ').html(contentLaterFunc()); - } - - // subState can be ommitted - if(typeof subState === 'function'){ - callback = subState; - subState = false; - } - - t.jqib.trigger(promptstatechanginge, [t.getCurrentStateName(), state]); - - if(!promptstatechanginge.isDefaultPrevented() && $state.length > 0){ - t.jqi.find('.'+ opts.prefix +'parentstate').removeClass(opts.prefix +'parentstate'); - - if(subState){ // hide any open substates - // get rid of any substates - t.jqi.find('.'+ opts.prefix +'substate').not($state) - .slideUp(jqiopts.promptspeed) - .removeClass('.'+ opts.prefix +'substate') - .find('.'+ opts.prefix +'arrow').hide(); - - // add parent state class so it can be visible, but blocked - t.jqi.find('.'+ opts.prefix +'state:visible').addClass(opts.prefix +'parentstate'); - - // add substate class so we know it will be smaller - $state.addClass(opts.prefix +'substate'); - } - else{ // hide any open states - t.jqi.find('.'+ opts.prefix +'state').not($state) - .slideUp(jqiopts.promptspeed) - .find('.'+ opts.prefix +'arrow').hide(); - } - t.currentStateName = stateobj.name; - - $state.slideDown(jqiopts.promptspeed,function(){ - var $t = $(this); - t.enableStateButtons(); - - // if focus is a selector, find it, else its button index - if(typeof(stateobj.focus) === 'string'){ - $t.find(stateobj.focus).eq(0).focus(); - } - else{ - $t.find('.'+ opts.prefix +'defaultbutton').focus(); - } - - $t.find('.'+ opts.prefix +'arrow').show(jqiopts.promptspeed); - - if (typeof callback === 'function'){ - t.jqib.on('impromptu:statechanged', callback); - } - t.jqib.trigger('impromptu:statechanged', [state]); - if (typeof callback === 'function'){ - t.jqib.off('impromptu:statechanged', callback); - } - }); - if(!subState){ - t.position(); - } - } // end isDefaultPrevented() - }// end stateobj !== undefined - - return $state; - }, - - /** - * nextState - Transition to the next state - * @param callback Function - called when the transition is complete - * @return jQuery - the newly active state - */ - nextState: function(callback) { - var t = this, - $next = t.getCurrentState().next(); - if($next.length > 0){ - t.goToState( $next.data('jqi-name'), callback ); - } - return $next; - }, - - /** - * prevState - Transition to the previous state - * @param callback Function - called when the transition is complete - * @return jQuery - the newly active state - */ - prevState: function(callback) { - var t = this, - $prev = t.getCurrentState().prev(); - if($prev.length > 0){ - t.goToState( $prev.data('jqi-name'), callback ); - } - return $prev; - } - - }; - - // ######################################################################## - // $.prompt will manage a queue of Impromptu instances - // ######################################################################## - - /** - * $.prompt create a new Impromptu instance and push it on the stack of instances - * @param message String/Object - String of html or Object of states - * @param options Object - Options to set the prompt - * @return jQuery - the jQuery object of the prompt within the modal - */ - $.prompt = function(message, options){ - var api = new Imp(message, options); - return api.jqi; - }; - - /** - * Copy over static methods - */ - $.each(Imp, function(k,v){ - $.prompt[k] = v; - }); - - /** - * Create a proxy for accessing all instance methods. The close method pops from queue. - */ - $.each(Imp.prototype, function(k,v){ - $.prompt[k] = function(){ - var api = Imp.getLast(); // always use the last instance on the stack - - if(api && typeof api[k] === "function"){ - return api[k].apply(api, arguments); - } - }; - }); - - // ######################################################################## - // jQuery Plugin and public access - // ######################################################################## - - /** - * Enable using $('.selector').prompt({}); - * This will grab the html within the prompt as the prompt message - */ - $.fn.prompt = function(options){ - if(options === undefined){ - options = {}; - } - if(options.withDataAndEvents === undefined){ - options.withDataAndEvents = false; - } - - $.prompt($(this).clone(options.withDataAndEvents).html(),options); - }; - - /** - * Export it as Impromptu and $.prompt - * Can be used from here forth as new Impromptu(states, opts) - */ - window.Impromptu = Imp; - -})); - -/*! - * jQuery Cookie Plugin v1.4.1 - * https://github.com/carhartl/jquery-cookie - * - * Copyright 2013 Klaus Hartl - * Released under the MIT license - */ -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD - define(['jquery'], factory); - } else if (typeof exports === 'object') { - // CommonJS - factory(require('jquery')); - } else { - // Browser globals - factory(jQuery); - } -}(function ($) { - - var pluses = /\+/g; - - function encode(s) { - return config.raw ? s : encodeURIComponent(s); - } - - function decode(s) { - return config.raw ? s : decodeURIComponent(s); - } - - function stringifyCookieValue(value) { - return encode(config.json ? JSON.stringify(value) : String(value)); - } - - function parseCookieValue(s) { - if (s.indexOf('"') === 0) { - // This is a quoted cookie as according to RFC2068, unescape... - s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); - } - - try { - // Replace server-side written pluses with spaces. - // If we can't decode the cookie, ignore it, it's unusable. - // If we can't parse the cookie, ignore it, it's unusable. - s = decodeURIComponent(s.replace(pluses, ' ')); - return config.json ? JSON.parse(s) : s; - } catch(e) {} - } - - function read(s, converter) { - var value = config.raw ? s : parseCookieValue(s); - return $.isFunction(converter) ? converter(value) : value; - } - - var config = $.cookie = function (key, value, options) { - - // Write - - if (value !== undefined && !$.isFunction(value)) { - options = $.extend({}, config.defaults, options); - - if (typeof options.expires === 'number') { - var days = options.expires, t = options.expires = new Date(); - t.setTime(+t + days * 864e+5); - } - - return (document.cookie = [ - encode(key), '=', stringifyCookieValue(value), - options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE - options.path ? '; path=' + options.path : '', - options.domain ? '; domain=' + options.domain : '', - options.secure ? '; secure' : '' - ].join('')); - } - - // Read - - var result = key ? undefined : {}; - - // To prevent the for loop in the first place assign an empty array - // in case there are no cookies at all. Also prevents odd result when - // calling $.cookie(). - var cookies = document.cookie ? document.cookie.split('; ') : []; - - for (var i = 0, l = cookies.length; i < l; i++) { - var parts = cookies[i].split('='); - var name = decode(parts.shift()); - var cookie = parts.join('='); - - if (key && key === name) { - // If second argument (value) is a function it's a converter... - result = read(cookie, value); - break; - } - - // Prevent storing a cookie that we couldn't decode. - if (!key && (cookie = read(cookie)) !== undefined) { - result[name] = cookie; - } - } - - return result; - }; - - config.defaults = {}; - - $.removeCookie = function (key, options) { - if ($.cookie(key) === undefined) { - return false; - } - - // Must not alter options, thus extending a fresh object... - $.cookie(key, '', $.extend({}, options, { expires: -1 })); - return !$.cookie(key); - }; - -})); \ No newline at end of file diff --git a/html/forums/jscripts/jquery.plugins.min.js b/html/forums/jscripts/jquery.plugins.min.js deleted file mode 100644 index b86cec5..0000000 --- a/html/forums/jscripts/jquery.plugins.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){t.jGrowl=function(e,i){0===t("#jGrowl").length&&t('
    ').addClass(i&&i.position?i.position:t.jGrowl.defaults.position).appendTo(i&&i.appendTo?i.appendTo:t.jGrowl.defaults.appendTo),t("#jGrowl").jGrowl(e,i)},t.fn.jGrowl=function(e,i){if(void 0===i&&t.isPlainObject(e)&&(i=e,e=i.message),t.isFunction(this.each)){var o=arguments;return this.each(function(){void 0===t(this).data("jGrowl.instance")&&(t(this).data("jGrowl.instance",t.extend(new t.fn.jGrowl,{notifications:[],element:null,interval:null})),t(this).data("jGrowl.instance").startup(this)),t.isFunction(t(this).data("jGrowl.instance")[e])?t(this).data("jGrowl.instance")[e].apply(t(this).data("jGrowl.instance"),t.makeArray(o).slice(1)):t(this).data("jGrowl.instance").create(e,i)})}},t.extend(t.fn.jGrowl.prototype,{defaults:{pool:0,header:"",group:"",sticky:!1,position:"top-right",appendTo:"body",glue:"after",theme:"default",themeState:"highlight",corners:"10px",check:250,life:3e3,closeDuration:"normal",openDuration:"normal",easing:"swing",closer:!0,closeTemplate:"×",closerTemplate:"
    [ close all ]
    ",log:function(){},beforeOpen:function(){},afterOpen:function(){},open:function(){},beforeClose:function(){},close:function(){},click:function(){},animateOpen:{opacity:"show"},animateClose:{opacity:"hide"}},notifications:[],element:null,interval:null,create:function(e,i){var o=t.extend({},this.defaults,i);"undefined"!=typeof o.speed&&(o.openDuration=o.speed,o.closeDuration=o.speed),this.notifications.push({message:e,options:o}),o.log.apply(this.element,[this.element,e,o])},render:function(e){var i=this,o=e.message,n=e.options;n.themeState=""===n.themeState?"":"ui-state-"+n.themeState;var s=t("
    ").addClass("jGrowl-notification alert "+n.themeState+" ui-corner-all"+(void 0!==n.group&&""!==n.group?" "+n.group:"")).append(t("";return c+="
    ",p=t(c).css({display:"none"}),p.on("impromptu:submit",o.submit),void 0!==n?u.getState(n).after(p):g.append(p),u.options.states[i]=o,p},removeState:function(t,e){var i=this,o=i.getState(t),n=function(){o.remove()};return 0===o.length?!1:("none"!==o.css("display")?void 0!==e&&i.getState(e).length>0?i.goToState(e,!1,n):o.next().length>0?i.nextState(n):o.prev().length>0?i.prevState(n):i.close():o.slideUp("slow",n),!0)},getApi:function(){return this},getBox:function(){return this.jqib},getPrompt:function(){return this.jqi},getState:function(t){return this.jqi.find('[data-jqi-name="'+t+'"]')},getCurrentState:function(){return this.getState(this.getCurrentStateName())},getCurrentStateName:function(){return this.currentStateName},disableStateButtons:function(e,i,o){var n=this;t.isArray(e)&&(i=e,e=null),n.getState(e||n.getCurrentStateName()).find("."+n.options.prefix+"button").each(function(e,n){(void 0===i||-1!==t.inArray(n.value,i))&&(n.disabled=!o)})},enableStateButtons:function(t,e){this.disableStateButtons(t,e,!0)},position:function(e){var i=this,o=t.fx.off,n=i.getCurrentState(),s=i.options.states[n.data("jqi-name")],a=s?s.position:void 0,r=t(window),l=document.body.scrollHeight,d=t(window).height(),u=(t(document).height(),l>d?l:d),c=parseInt(r.scrollTop(),10),p=c+(i.options.top.toString().indexOf("%")>=0?d*(parseInt(i.options.top,10)/100):parseInt(i.options.top,10));if(void 0!==e&&e.data.animate===!1&&(t.fx.off=!0),i.jqib.css({position:"absolute",height:u,width:"100%",top:0,left:0,right:0,bottom:0}),i.jqif.css({position:"fixed",height:u,width:"100%",top:0,left:0,right:0,bottom:0}),a&&a.container){var f=t(a.container).offset(),h=!1;t.isPlainObject(f)&&void 0!==f.top&&(p=f.top+a.y-(i.options.top.toString().indexOf("%")>=0?d*(parseInt(i.options.top,10)/100):parseInt(i.options.top,10)),i.jqi.css({position:"absolute"}),i.jqi.animate({top:f.top+a.y,left:f.left+a.x,marginLeft:0,width:void 0!==a.width?a.width:null},function(){!h&&f.top+a.y+i.jqi.outerHeight(!0)>c+d&&(t("html,body").animate({scrollTop:p},"slow","swing",function(){}),h=!0)}),(c>p||p>c+d)&&(t("html,body").animate({scrollTop:p},"slow","swing",function(){}),h=!0))}else a&&a.width?(i.jqi.css({position:"absolute",left:"50%"}),i.jqi.animate({top:a.y||p,left:a.x||"50%",marginLeft:a.width/2*-1,width:a.width})):i.jqi.css({position:"absolute",top:p,left:"50%",marginLeft:i.jqi.outerWidth(!1)/2*-1});void 0!==e&&e.data.animate===!1&&(t.fx.off=o)},style:function(){var t=this;t.jqif.css({zIndex:t.options.zIndex,display:"none",opacity:t.options.opacity}),t.jqi.css({zIndex:t.options.zIndex+1,display:"none"}),t.jqib.css({zIndex:t.options.zIndex})},goToState:function(e,i,o){var n=this,s=(n.jqi,n.options),a=n.getState(e),r=s.states[a.data("jqi-name")],l=new t.Event("impromptu:statechanging"),d=n.options;if(void 0!==r){if("function"==typeof r.html){var u=r.html;a.find("."+d.prefix+"message ").html(u())}"function"==typeof i&&(o=i,i=!1),n.jqib.trigger(l,[n.getCurrentStateName(),e]),!l.isDefaultPrevented()&&a.length>0&&(n.jqi.find("."+d.prefix+"parentstate").removeClass(d.prefix+"parentstate"),i?(n.jqi.find("."+d.prefix+"substate").not(a).slideUp(s.promptspeed).removeClass("."+d.prefix+"substate").find("."+d.prefix+"arrow").hide(),n.jqi.find("."+d.prefix+"state:visible").addClass(d.prefix+"parentstate"),a.addClass(d.prefix+"substate")):n.jqi.find("."+d.prefix+"state").not(a).slideUp(s.promptspeed).find("."+d.prefix+"arrow").hide(),n.currentStateName=r.name,a.slideDown(s.promptspeed,function(){var i=t(this);n.enableStateButtons(),"string"==typeof r.focus?i.find(r.focus).eq(0).focus():i.find("."+d.prefix+"defaultbutton").focus(),i.find("."+d.prefix+"arrow").show(s.promptspeed),"function"==typeof o&&n.jqib.on("impromptu:statechanged",o),n.jqib.trigger("impromptu:statechanged",[e]),"function"==typeof o&&n.jqib.off("impromptu:statechanged",o)}),i||n.position())}return a},nextState:function(t){var e=this,i=e.getCurrentState().next();return i.length>0&&e.goToState(i.data("jqi-name"),t),i},prevState:function(t){var e=this,i=e.getCurrentState().prev();return i.length>0&&e.goToState(i.data("jqi-name"),t),i}},t.prompt=function(t,i){var o=new e(t,i);return o.jqi},t.each(e,function(e,i){t.prompt[e]=i}),t.each(e.prototype,function(i){t.prompt[i]=function(){var t=e.getLast();return t&&"function"==typeof t[i]?t[i].apply(t,arguments):void 0}}),t.fn.prompt=function(e){void 0===e&&(e={}),void 0===e.withDataAndEvents&&(e.withDataAndEvents=!1),t.prompt(t(this).clone(e.withDataAndEvents).html(),e)},window.Impromptu=e}),function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t("object"==typeof exports?require("jquery"):jQuery)}(function(t){function e(t){return r.raw?t:encodeURIComponent(t)}function i(t){return r.raw?t:decodeURIComponent(t)}function o(t){return e(r.json?JSON.stringify(t):String(t))}function n(t){0===t.indexOf('"')&&(t=t.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return t=decodeURIComponent(t.replace(a," ")),r.json?JSON.parse(t):t}catch(e){}}function s(e,i){var o=r.raw?e:n(e);return t.isFunction(i)?i(o):o}var a=/\+/g,r=t.cookie=function(n,a,l){if(void 0!==a&&!t.isFunction(a)){if(l=t.extend({},r.defaults,l),"number"==typeof l.expires){var d=l.expires,u=l.expires=new Date;u.setTime(+u+864e5*d)}return document.cookie=[e(n),"=",o(a),l.expires?"; expires="+l.expires.toUTCString():"",l.path?"; path="+l.path:"",l.domain?"; domain="+l.domain:"",l.secure?"; secure":""].join("")}for(var c=n?void 0:{},p=document.cookie?document.cookie.split("; "):[],f=0,h=p.length;h>f;f++){var m=p[f].split("="),g=i(m.shift()),v=m.join("=");if(n&&n===g){c=s(v,a);break}n||void 0===(v=s(v))||(c[g]=v)}return c};r.defaults={},t.removeCookie=function(e,i){return void 0===t.cookie(e)?!1:(t.cookie(e,"",t.extend({},i,{expires:-1})),!t.cookie(e))}}); \ No newline at end of file diff --git a/html/forums/jscripts/post.js b/html/forums/jscripts/post.js deleted file mode 100644 index 23905c1..0000000 --- a/html/forums/jscripts/post.js +++ /dev/null @@ -1,122 +0,0 @@ -var Post = { - init: function() - { - $(document).ready(function(){ - }); - }, - - loadMultiQuoted: function() - { - if(use_xmlhttprequest == 1) - { - tid = document.input.tid.value; - - $.ajax( - { - url: 'xmlhttp.php?action=get_multiquoted&tid='+tid, - type: 'get', - complete: function (request, status) - { - Post.multiQuotedLoaded(request, status); - } - }); - - return false; - } - else - { - return true; - } - }, - - loadMultiQuotedAll: function() - { - if(use_xmlhttprequest == 1) - { - $.ajax( - { - url: 'xmlhttp.php?action=get_multiquoted&load_all=1', - type: 'get', - complete: function (request, status) - { - Post.multiQuotedLoaded(request, status); - } - }); - - return false; - } - else - { - return true; - } - }, - - multiQuotedLoaded: function(request) - { - var json = $.parseJSON(request.responseText); - if(typeof response == 'object') - { - if(json.hasOwnProperty("errors")) - { - $.each(json.errors, function(i, message) - { - $.jGrowl(lang.post_fetch_error + ' ' + message, {theme:'jgrowl_error'}); - }); - return false; - } - } - - var id = 'message'; - if(typeof $('textarea').sceditor != 'undefined') - { - $('textarea').sceditor('instance').insert(json.message); - } - else - { - if($('#' + id).value) - { - $('#' + id).value += "\n"; - } - $('#' + id).val($('#' + id).val() + json.message); - } - - $('#multiquote_unloaded').hide(); - document.input.quoted_ids.value = 'all'; - }, - - clearMultiQuoted: function() - { - $('#multiquote_unloaded').hide(); - Cookie.unset('multiquote'); - }, - - removeAttachment: function(aid) - { - $.prompt(removeattach_confirm, { - buttons:[ - {title: yes_confirm, value: true}, - {title: no_confirm, value: false} - ], - submit: function(e,v,m,f){ - if(v == true) - { - document.input.attachmentaid.value = aid; - document.input.attachmentact.value = "remove"; - - $("input[name=rem]").parents('form').append(''); - $('#rem_submit').click(); - } - } - }); - - return false; - }, - - attachmentAction: function(aid,action) - { - document.input.attachmentaid.value = aid; - document.input.attachmentact.value = action; - } -}; - -Post.init(); \ No newline at end of file diff --git a/html/forums/jscripts/question.js b/html/forums/jscripts/question.js deleted file mode 100644 index c8ffea6..0000000 --- a/html/forums/jscripts/question.js +++ /dev/null @@ -1,39 +0,0 @@ -var question = { - refresh: function() - { - var question_id = $('#question_id').val(); - - $.ajax( - { - url: 'xmlhttp.php?action=refresh_question&question_id='+question_id, - method: 'get', - dataType: 'json', - complete: function (request) - { - question.refresh_complete(request); - } - }); - - return false; - }, - - refresh_complete: function(request) - { - var json = $.parseJSON(request.responseText); - if(json.hasOwnProperty("errors")) - { - $.each(json.errors, function(i, message) - { - $.jGrowl(lang.question_fetch_failure + ' ' + message, {theme:'jgrowl_error'}); - }); - } - else if(json.question && json.sid) - { - $("#question").text(json.question); - $("#question_id").val(json.sid); - } - - $('#answer').removeClass('error valid').val('').removeAttr('aria-invalid').removeData('previousValue') - .next('label').remove(); - } -}; \ No newline at end of file diff --git a/html/forums/jscripts/rating.js b/html/forums/jscripts/rating.js deleted file mode 100644 index adcc4da..0000000 --- a/html/forums/jscripts/rating.js +++ /dev/null @@ -1,136 +0,0 @@ -var Rating = { - init: function() - { - var rating_elements = $(".star_rating"); - rating_elements.each(function() - { - var rating_element = $(this); - var elements = rating_element.find("li a"); - if(rating_element.hasClass("star_rating_notrated")) - { - elements.each(function() - { - var element = $(this); - element.click(function() - { - var parameterString = element.attr("href").replace(/.*\?(.*)/, "$1"); - return Rating.add_rating(parameterString); - }); - }); - } - else - { - elements.each(function() - { - var element = $(this); - element.attr("onclick", "return false;"); - element.css("cursor", "default"); - var element_id = element.attr("href").replace(/.*\?(.*)/, "$1").match(/tid=(.*)&(.*)&/)[1]; - element.attr("title", $("#current_rating_"+element_id).text()); - }); - } - }); - }, - - build_forumdisplay: function(tid, options) - { - var list = $("#rating_thread_"+tid); - if(!list.length) - { - return; - } - - list.addClass("star_rating") - .addClass(options.extra_class); - - list_classes = new Array(); - list_classes[1] = 'one_star'; - list_classes[2] = 'two_stars'; - list_classes[3] = 'three_stars'; - list_classes[4] = 'four_stars'; - list_classes[5] = 'five_stars'; - - for(var i = 1; i <= 5; i++) - { - var list_element = $("
  • "); - var list_element_a = $(""); - list_element_a.addClass(list_classes[i]) - .attr("title", lang.stars[i]) - .attr("href", "./ratethread.php?tid="+tid+"&rating="+i+"&my_post_key="+my_post_key) - .html(i); - list_element.append(list_element_a); - list.append(list_element); - } - }, - - add_rating: function(parameterString) - { - var tid = parameterString.match(/tid=(.*)&(.*)&/)[1]; - var rating = parameterString.match(/rating=(.*)&(.*)/)[1]; - $.ajax( - { - url: 'ratethread.php?ajax=1&my_post_key='+my_post_key+'&tid='+tid+'&rating='+rating, - async: true, - method: 'post', - dataType: 'json', - complete: function (request) - { - Rating.rating_added(request, tid); - } - }); - return false; - }, - - rating_added: function(request, element_id) - { - var json = $.parseJSON(request.responseText); - if(json.hasOwnProperty("errors")) - { - $.each(json.errors, function(i, error) - { - $.jGrowl(lang.ratings_update_error + ' ' + error, {theme:'jgrowl_error'}); - }); - } - else if(json.hasOwnProperty("success")) - { - var element = $("#rating_thread_"+element_id); - element.parent().before(element.next()); - element.removeClass("star_rating_notrated"); - - $.jGrowl(json.success, {theme:'jgrowl_success'}); - if(json.hasOwnProperty("average")) - { - $("#current_rating_"+element_id).html(json.average); - } - - var rating_elements = $(".star_rating"); - rating_elements.each(function() - { - var rating_element = $(this); - var elements = rating_element.find("li a"); - if(rating_element.hasClass('star_rating_notrated')) - { - elements.each(function() - { - var element = $(this); - if(element.attr("id") == "rating_thread_" + element_id) - { - element.attr("onclick", "return false;") - .css("cursor", "default") - .attr("title", $("#current_rating_"+element_id).text()); - } - }); - } - }); - $("#current_rating_"+element_id).css("width", json.width+"%"); - } - } -}; - -if(use_xmlhttprequest == 1) -{ - $(function() - { - Rating.init(); - }); -} \ No newline at end of file diff --git a/html/forums/jscripts/report.js b/html/forums/jscripts/report.js deleted file mode 100644 index 8bc1199..0000000 --- a/html/forums/jscripts/report.js +++ /dev/null @@ -1,49 +0,0 @@ -var Report = { - init: function() - { - $(document).ready(function(){ - }); - }, - - reportPost: function(pid) - { - MyBB.popupWindow("/report.php?modal=1&type=post&pid="+pid); - }, - - reportUser: function(pid) - { - MyBB.popupWindow("/report.php?modal=1&type=profile&pid="+pid); - }, - - reportReputation: function(pid) - { - MyBB.popupWindow("/report.php?modal=1&type=reputation&pid="+pid); - }, - - submitReport: function(pid) - { - // Get form, serialize it and send it - var datastring = $(".reportData_"+pid).serialize(); - $.ajax({ - type: "POST", - url: "report.php?modal=1", - data: datastring, - dataType: "html", - success: function(data) { - // Replace modal HTML - $('.modal_'+pid).fadeOut('slow', function() { - $('.modal_'+pid).html(data); - $('.modal_'+pid).fadeIn('slow'); - $('.modal').fadeIn('slow'); - }); - }, - error: function(){ - alert(lang.unknown_error); - } - }); - - return false; - } -}; - -Report.init(); \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_plugins/bbcode.js b/html/forums/jscripts/sceditor/editor_plugins/bbcode.js deleted file mode 100644 index 8ef5841..0000000 --- a/html/forums/jscripts/sceditor/editor_plugins/bbcode.js +++ /dev/null @@ -1,2 +0,0 @@ -/* SCEditor v1.4.7 | (C) 2015, Sam Clarke | sceditor.com/license */ -!function(a,b,c){"use strict";var d=a.sceditor,e=d.plugins,f=d.escapeEntities,g=d.escapeUriScheme,h=d.ie,i=h&&11>h,j=d.command.get,k={bold:{txtExec:["[b]","[/b]"]},italic:{txtExec:["[i]","[/i]"]},underline:{txtExec:["[u]","[/u]"]},strike:{txtExec:["[s]","[/s]"]},subscript:{txtExec:["[sub]","[/sub]"]},superscript:{txtExec:["[sup]","[/sup]"]},left:{txtExec:["[left]","[/left]"]},center:{txtExec:["[center]","[/center]"]},right:{txtExec:["[right]","[/right]"]},justify:{txtExec:["[justify]","[/justify]"]},font:{txtExec:function(a){var b=this;j("font")._dropDown(b,a,function(a){b.insertText("[font="+a+"]","[/font]")})}},size:{txtExec:function(a){var b=this;j("size")._dropDown(b,a,function(a){b.insertText("[size="+a+"]","[/size]")})}},color:{txtExec:function(a){var b=this;j("color")._dropDown(b,a,function(a){b.insertText("[color="+a+"]","[/color]")})}},bulletlist:{txtExec:function(b,c){var d="";a.each(c.split(/\r?\n/),function(){d+=(d?"\n":"")+"[li]"+this+"[/li]"}),this.insertText("[ul]\n"+d+"\n[/ul]")}},orderedlist:{txtExec:function(b,c){var d="";a.each(c.split(/\r?\n/),function(){d+=(d?"\n":"")+"[li]"+this+"[/li]"}),e.bbcode.bbcode.get(""),this.insertText("[ol]\n"+d+"\n[/ol]")}},table:{txtExec:["[table][tr][td]","[/td][/tr][/table]"]},horizontalrule:{txtExec:["[hr]"]},code:{txtExec:["[code]","[/code]"]},image:{txtExec:function(a,b){var c=this,d=prompt(c._("Enter the image URL:"),b);d&&c.insertText("[img]"+d+"[/img]")}},email:{txtExec:function(a,b){var c=this,d=b&&b.indexOf("@")>-1?null:b,e=prompt(c._("Enter the e-mail address:"),d?"":b),f=prompt(c._("Enter the displayed text:"),d||e)||e;e&&c.insertText("[email="+e+"]"+f+"[/email]")}},link:{txtExec:function(b,c){var d=this,e=/^[a-z]+:\/\//i.test(a.trim(c))?null:c,f=prompt(d._("Enter URL:"),e?"http://":a.trim(c)),g=prompt(d._("Enter the displayed text:"),e||f)||f;f&&d.insertText("[url="+f+"]"+g+"[/url]")}},quote:{txtExec:["[quote]","[/quote]"]},youtube:{txtExec:function(a){var b=this;j("youtube")._dropDown(b,a,function(a){b.insertText("[youtube]"+a+"[/youtube]")})}},rtl:{txtExec:["[rtl]","[/rtl]"]},ltr:{txtExec:["[ltr]","[/ltr]"]}},l=function(a){return a?a.replace(/\\(.)/g,"$1").replace(/^(["'])(.*?)\1$/,"$2"):a},m=function(){var a,b=arguments;return b[0].replace(/\{(\d+)\}/g,function(c,d){return b[d-0+1]!==a?b[d-0+1]:"{"+d+"}"})},n={OPEN:"open",CONTENT:"content",NEWLINE:"newline",CLOSE:"close"},o=function(a,b,c,d,e,f){var g=this;g.type=a,g.name=b,g.val=c,g.attrs=d||{},g.children=e||[],g.closing=f||null};o.prototype={clone:function(a){var b=this;return new o(b.type,b.name,b.val,b.attrs,a?b.children:[],b.closing?b.closing.clone():null)},splitAt:function(b){var c,d=this,e=0,f=d.children.length;if("number"!=typeof b&&(b=a.inArray(b,d.children)),0>b||b>f)return null;for(;f--;)f>=b?e++:f=0;return c=d.clone(),c.children=d.children.splice(b,e),c}};var p=function(b){if(!(this instanceof p))return new p(b);var d,g,j,k,m,q,r,s,t,u,v,w,x,y,z,A=this;d=function(){A.bbcodes=e.bbcode.bbcodes,A.opts=a.extend({},p.defaults,b)},A.tokenize=function(a){var b,c,d,e=[],f=[{type:n.CLOSE,regex:/^\[\/[^\[\]]+\]/},{type:n.OPEN,regex:/^\[[^\[\]]+\]/},{type:n.NEWLINE,regex:/^(\r\n|\r|\n)/},{type:n.CONTENT,regex:/^([^\[\r\n]+|\[)/}];f.reverse();a:for(;a.length;){for(d=f.length;d--;)if(c=f[d].type,(b=a.match(f[d].regex))&&b[0]){e.push(g(c,b[0])),a=a.substr(b[0].length);continue a}a.length&&e.push(g(n.CONTENT,a)),a=""}return e},g=function(b,c){var d,f,g,h=/\[([^\]\s=]+)(?:([^\]]+))?\]/,i=/\[\/([^\[\]]+)\]/;return b===n.OPEN&&(d=c.match(h))&&(g=y(d[1]),d[2]&&(d[2]=a.trim(d[2]))&&(f=j(d[2]))),b===n.CLOSE&&(d=c.match(i))&&(g=y(d[1])),b===n.NEWLINE&&(g="#newline"),g&&(b!==n.OPEN&&b!==n.CLOSE||e.bbcode.bbcodes[g])||(b=n.CONTENT,g="#"),new o(b,g,c,f)},j=function(a){var b,c=/([^\s=]+)=(?:(?:(["'])((?:\\\2|[^\2])*?)\2)|((?:.(?!\s\S+=))*.))/g,d={};if("="===a.charAt(0)&&a.indexOf("=",1)<0)d.defaultattr=l(a.substr(1));else for("="===a.charAt(0)&&(a="defaultattr"+a);b=c.exec(a);)d[y(b[1])]=l(b[3])||b[4];return d},A.parse=function(a,b){var c=k(A.tokenize(a)),d=A.opts;return d.fixInvalidChildren&&t(c),d.removeEmptyTags&&s(c),d.fixInvalidNesting&&q(c),m(c,null,b),d.removeEmptyTags&&s(c),c},w=function(a,b,c){for(var d=c.length;d--;)if(c[d].type===b&&c[d].name===a)return!0;return!1},r=function(b,c){var d=b?A.bbcodes[b.name]:{},e=d.allowedChildren;return A.opts.fixInvalidChildren&&e?a.inArray(c.name||"#",e)>-1:!0},k=function(b){for(var c,d,e,f,g,h,i,j=[],k=[],l=[],m=function(){return z(l)},o=function(a){m()?m().children.push(a):k.push(a)},p=function(b){return m()&&(d=A.bbcodes[m().name])&&d.closedBy&&a.inArray(b,d.closedBy)>-1};c=b.shift();){switch(i=b[0],c.type){case n.OPEN:p(c.name)&&l.pop(),o(c),d=A.bbcodes[c.name],d&&d.isSelfClosing||!d.closedBy&&!w(c.name,n.CLOSE,b)?d&&d.isSelfClosing||(c.type=n.CONTENT):l.push(c);break;case n.CLOSE:if(m()&&c.name!==m().name&&p("/"+c.name)&&l.pop(),m()&&c.name===m().name)m().closing=c,l.pop();else if(w(c.name,n.OPEN,l)){for(;e=l.pop();){if(e.name===c.name){e.closing=c;break}f=e.clone(),j.length>1&&f.children.push(z(j)),j.push(f)}for(o(z(j)),g=j.length;g--;)l.push(j[g]);j.length=0}else c.type=n.CONTENT,o(c);break;case n.NEWLINE:m()&&i&&p((i.type===n.CLOSE?"/":"")+i.name)&&(i.type!==n.CLOSE||i.name!==m().name)&&(d=A.bbcodes[m().name],d&&d.breakAfter?l.pop():d&&d.isInline===!1&&A.opts.breakAfterBlock&&d.breakAfter!==!1&&l.pop()),o(c);break;default:o(c)}h=c}return k},m=function(a,b,c){var d,e,f,g,h,i,j,k,l=a.length;b&&(g=A.bbcodes[b.name]);for(var o=l;o--;)if(d=a[o])if(d.type===n.NEWLINE){if(e=o>0?a[o-1]:null,f=l-1>o?a[o+1]:null,k=!1,!c&&g&&g.isSelfClosing!==!0&&(e?i||f||(g.isInline===!1&&A.opts.breakEndBlock&&g.breakEnd!==!1&&(k=!0),g.breakEnd&&(k=!0),i=k):(g.isInline===!1&&A.opts.breakStartBlock&&g.breakStart!==!1&&(k=!0),g.breakStart&&(k=!0))),e&&e.type===n.OPEN&&(h=A.bbcodes[e.name])&&(c?h.isInline===!1&&(k=!0):(h.isInline===!1&&A.opts.breakAfterBlock&&h.breakAfter!==!1&&(k=!0),h.breakAfter&&(k=!0))),!c&&!j&&f&&f.type===n.OPEN&&(h=A.bbcodes[f.name])&&(h.isInline===!1&&A.opts.breakBeforeBlock&&h.breakBefore!==!1&&(k=!0),h.breakBefore&&(k=!0),j=k,k)){a.splice(o,1);continue}k&&a.splice(o,1),j=!1}else d.type===n.OPEN&&m(d.children,d,c)},q=function(b,c,d,e){var f,g,h,i,j,k,l=function(a){var b=A.bbcodes[a.name];return!b||b.isInline!==!1};for(c=c||[],e=e||b,g=0;g1?c[c.length-2].children:e,i=a.inArray(h,j),i>-1))return k.children.splice(a.inArray(f,k.children),1),void j.splice(i+1,0,f,k);c.push(f),q(f.children,c,d||l(f),e),c.pop(f)}},t=function(a,b){for(var c,d,e=a.length;e--;)(c=a[e])&&(r(b,c)||(c.name=null,c.type=n.CONTENT,r(b,c)?(d=[e+1,0].concat(c.children),c.closing&&(c.closing.name=null,c.closing.type=n.CONTENT,d.push(c.closing)),e+=d.length-1,Array.prototype.splice.apply(a,d)):b.children.splice(e,1)),c.type===n.OPEN&&t(c.children,c))},s=function(b){for(var c,d,e=function(a){for(var b=a.length;b--;){var c=a[b].type;if(c===n.OPEN||c===n.CLOSE)return!1;if(c===n.CONTENT&&/\S|\u00A0/.test(a[b].val))return!1}return!0},f=b.length;f--;)(c=b[f])&&c.type===n.OPEN&&(d=A.bbcodes[c.name],s(c.children),e(c.children)&&d&&!d.isSelfClosing&&!d.allowsEmpty&&b.splice.apply(b,a.merge([f,1],c.children)))},A.toHTML=function(a,b){return u(A.parse(a,b),!0)},u=function(b,d){var g,j,k,l,m,o,p,q,r,s=[];for(q=function(a){return(!a||(a.isHtmlInline!==g?a.isHtmlInline:a.isInline))!==!1};b.length>0;)if(j=b.shift()){if(j.type===n.OPEN)r=j.children[j.children.length-1]||{},k=A.bbcodes[j.name],o=d&&q(k),l=u(j.children,!1),k&&k.html?(q(k)||!q(A.bbcodes[r.name])||k.isPreFormatted||k.skipLastLineBreak||i||(l+="
    "),a.isFunction(k.html)?m=k.html.call(A,j,j.attrs,l):(j.attrs[0]=l,m=e.bbcode.formatBBCodeString(k.html,j.attrs))):m=j.val+l+(j.closing?j.closing.val:"");else{if(j.type===n.NEWLINE){if(!d){s.push("
    ");continue}p||(s.push("
    "),(8>h||c.documentMode&&c.documentMode<8)&&s.push(" ")),i||s.push("
    "),b.length||s.push("
    "),s.push("
    \n"),p=!1;continue}o=d,m=f(j.val,!0)}o&&!p?(s.push("
    "),p=!0):!o&&p&&(s.push("
    \n"),p=!1),s.push(m)}return p&&s.push("\n"),s.join("")},A.toBBCode=function(a,b){return v(A.parse(a,b))},v=function(a){for(var b,c,d,e,f,g,h,i,j,k,l=[];a.length>0;)if(b=a.shift())if(d=A.bbcodes[b.name],e=!(!d||d.isInline!==!1),f=d&&d.isSelfClosing,h=e&&A.opts.breakBeforeBlock&&d.breakBefore!==!1||d&&d.breakBefore,i=e&&!f&&A.opts.breakStartBlock&&d.breakStart!==!1||d&&d.breakStart,j=e&&A.opts.breakEndBlock&&d.breakEnd!==!1||d&&d.breakEnd,k=e&&A.opts.breakAfterBlock&&d.breakAfter!==!1||d&&d.breakAfter,g=(d?d.quoteType:null)||A.opts.quoteType||p.QuoteType.auto,d||b.type!==n.OPEN)if(b.type===n.OPEN){if(h&&l.push("\n"),l.push("["+b.name),b.attrs){b.attrs.defaultattr&&(l.push("=",x(b.attrs.defaultattr,g,"defaultattr")),delete b.attrs.defaultattr);for(c in b.attrs)b.attrs.hasOwnProperty(c)&&l.push(" ",c,"=",x(b.attrs[c],g,c))}l.push("]"),i&&l.push("\n"),b.children&&l.push(v(b.children)),f||d.excludeClosing||(j&&l.push("\n"),l.push("[/"+b.name+"]")),k&&l.push("\n"),b.closing&&f&&l.push(b.closing.val)}else l.push(b.val);else l.push(b.val),b.children&&l.push(v(b.children)),b.closing&&l.push(b.closing.val);return l.join("")},x=function(b,c,d){var e=p.QuoteType,f=/\s|=/.test(b);return a.isFunction(c)?c(b,d):c===e.never||c===e.auto&&!f?b:'"'+b.replace("\\","\\\\").replace('"','\\"')+'"'},z=function(a){return a.length?a[a.length-1]:null},y=function(a){return a.toLowerCase()},d()};p.QuoteType={always:1,never:2,auto:3},p.defaults={breakBeforeBlock:!1,breakStartBlock:!1,breakEndBlock:!1,breakAfterBlock:!0,removeEmptyTags:!0,fixInvalidNesting:!0,fixInvalidChildren:!0,quoteType:p.QuoteType.auto},a.sceditorBBCodePlugin=e.bbcode=function(){var b,f,g,h,j=this;j.bbcodes=e.bbcode.bbcodes,j.stripQuotes=l;var n={},o={},q={ul:["li","ol","ul"],ol:["li","ol","ul"],table:["tr"],tr:["td","th"],code:["br","p","div"]};j.init=function(){j.opts=this.opts,b(),this.commands=a.extend(!0,{},k,this.commands),this.toBBCode=j.signalToSource,this.fromBBCode=j.signalToWysiwyg},b=function(){a.each(j.bbcodes,function(b){var c,d=j.bbcodes[b].tags,e=j.bbcodes[b].styles;d&&a.each(d,function(a,d){c=j.bbcodes[b].isInline===!1,n[a]=n[a]||{},n[a][c]=n[a][c]||{},n[a][c][b]=d}),e&&a.each(e,function(a,d){c=j.bbcodes[b].isInline===!1,o[c]=o[c]||{},o[c][a]=o[c][a]||{},o[c][a][b]=d})})},f=function(b,c,e){var f,g,h=d.dom.getStyle;return e=!!e,o[e]?(a.each(o[e],function(d,e){f=h(b[0],d),f&&h(b.parent()[0],d)!==f&&a.each(e,function(d,e){(!e||a.inArray(f.toString(),e)>-1)&&(g=j.bbcodes[d].format,c=a.isFunction(g)?g.call(j,b,c):m(g,c))})}),c):c},g=function(b,c,e){var f,g,h=b[0],k=h.nodeName.toLowerCase();e=!!e,n[k]&&n[k][e]&&a.each(n[k][e],function(d,e){(!e||(f=!1,a.each(e,function(c,d){return!b.attr(c)||d&&a.inArray(b.attr(c),d)<0?void 0:(f=!0,!1)}),f))&&(g=j.bbcodes[d].format,c=a.isFunction(g)?g.call(j,b,c):m(g,c))});var l=d.dom.isInline;if(e&&(!l(h,!0)||"br"===k)){for(var o,p,q,r=h.previousSibling;r&&(a(r).hasClass("sceditor-ignore")||1===r.nodeType&&!a(r).is("br")&&l(r,!0)&&!r.firstChild);)r=r.previousSibling;do{for(p=h.parentNode,q=p.lastChild;a(q).hasClass("sceditor-ignore");)q=q.previousSibling;o=q===h,h=p}while(p&&o&&l(p,!0));(!o||"li"===k||"br"===k&&i)&&(c+="\n"),"br"!==k&&r&&!a(r).is("br")&&l(r,!0)&&(c="\n"+c)}return c},j.signalToSource=function(b,e){var f,g,h=new p(j.opts.parserOptions);return e||("string"==typeof b?(f=a("
    ").css("visibility","hidden").appendTo(c.body).html(b),e=f):e=a(b)),e&&e.jquery?(d.dom.removeWhiteSpace(e[0]),g=j.elementToBbcode(e),f&&f.remove(),g=h.toBBCode(g,!0),j.opts.bbcodeTrim&&(g=a.trim(g)),g):""},j.elementToBbcode=function(b){var c=function(b,e){var h="";return d.dom.traverse(b,function(b){var d=a(b),j="",k=b.nodeType,l=b.nodeName.toLowerCase(),m=q[l],n=b.firstChild,o=!0;if("object"==typeof e&&(o=a.inArray(l,e)>-1,d.is("img")&&d.data("sceditor-emoticon")&&(o=!0),o||(m=e)),3===k||1===k)if(1===k){if(d.hasClass("sceditor-ignore"))return;if(d.hasClass("sceditor-nlf")&&(!n||!i&&1===b.childNodes.length&&/br/i.test(n.nodeName)))return;"iframe"!==l&&(j=c(b,m)),o?("code"!==l&&(j=f(d,j),j=g(d,j),j=f(d,j,!0)),h+=g(d,j,!0)):h+=j}else h+=b.nodeValue},!1,!0),h};return c(b[0])},j.signalToWysiwyg=function(b,c){var d=new p(j.opts.parserOptions),e=d.toHTML(j.opts.bbcodeTrim?a.trim(b):b);return c?h(e):e},h=function(b){var e,f,g,h=a("
    ").hide().appendTo(c.body),j=h[0];return g=function(b,e){if(!d.dom.hasStyling(b)){if(i||1!==b.childNodes.length||!a(b.firstChild).is("br"))for(;f=b.firstChild;)j.insertBefore(f,b);if(e){var g=j.lastChild;b!==g&&a(g).is("div")&&b.nextSibling===g&&j.insertBefore(c.createElement("br"),b)}j.removeChild(b)}},j.innerHTML=b.replace(/<\/div>\n/g,"
    "),(e=j.firstChild)&&a(e).is("div")&&g(e,!0),(e=j.lastChild)&&a(e).is("div")&&g(e),j=j.innerHTML,h.remove(),j}},e.bbcode.formatBBCodeString=function(a,b){return a.replace(/\{([^}]+)\}/g,function(a,c){var d,e=!0;return"!"===c.charAt(0)&&(e=!1,c=c.substring(1)),"0"===c&&(e=!1),b[c]===d?a:e?f(b[c],!0):b[c]})};var q=function(a){return a=parseInt(a,10),isNaN(a)?"00":(a=Math.max(0,Math.min(a,255)).toString(16),a.length<2?"0"+a:a)},r=function(a){var b;return a=a||"#000",(b=a.match(/rgb\((\d{1,3}),\s*?(\d{1,3}),\s*?(\d{1,3})\)/i))?"#"+q(b[1])+q(b[2]-0)+q(b[3]-0):(b=a.match(/#([0-f])([0-f])([0-f])\s*?$/i))?"#"+b[1]+b[1]+b[2]+b[2]+b[3]+b[3]:a},s={b:{tags:{b:null,strong:null},styles:{"font-weight":["bold","bolder","401","700","800","900"]},format:"[b]{0}[/b]",html:"{0}"},i:{tags:{i:null,em:null},styles:{"font-style":["italic","oblique"]},format:"[i]{0}[/i]",html:"{0}"},u:{tags:{u:null},styles:{"text-decoration":["underline"]},format:"[u]{0}[/u]",html:"{0}"},s:{tags:{s:null,strike:null},styles:{"text-decoration":["line-through"]},format:"[s]{0}[/s]",html:"{0}"},sub:{tags:{sub:null},format:"[sub]{0}[/sub]",html:"{0}"},sup:{tags:{sup:null},format:"[sup]{0}[/sup]",html:"{0}"},font:{tags:{font:{face:null}},styles:{"font-family":null},quoteType:p.QuoteType.never,format:function(a,b){var c;return a.is("font")&&(c=a.attr("face"))||(c=a.css("font-family")),"[font="+l(c)+"]"+b+"[/font]"},html:'{0}'},size:{tags:{font:{size:null}},styles:{"font-size":null},format:function(a,b){var c=a.attr("size"),d=2;return c||(c=a.css("fontSize")),c.indexOf("px")>-1?(c=c.replace("px","")-0,12>c&&(d=1),c>15&&(d=3),c>17&&(d=4),c>23&&(d=5),c>31&&(d=6),c>47&&(d=7)):d=c,"[size="+d+"]"+b+"[/size]"},html:'{!0}'},color:{tags:{font:{color:null}},styles:{color:null},quoteType:p.QuoteType.never,format:function(a,b){var c;return a.is("font")&&(c=a.attr("color"))||(c=a[0].style.color||a.css("color")),"[color="+r(c)+"]"+b+"[/color]"},html:function(a,b,c){return''+c+""}},ul:{tags:{ul:null},breakStart:!0,isInline:!1,skipLastLineBreak:!0,format:"[ul]{0}[/ul]",html:"
      {0}
    "},list:{breakStart:!0,isInline:!1,skipLastLineBreak:!0,html:"
      {0}
    "},ol:{tags:{ol:null},breakStart:!0,isInline:!1,skipLastLineBreak:!0,format:"[ol]{0}[/ol]",html:"
      {0}
    "},li:{tags:{li:null},isInline:!1,closedBy:["/ul","/ol","/list","*","li"],format:"[li]{0}[/li]",html:"
  • {0}
  • "},"*":{isInline:!1,closedBy:["/ul","/ol","/list","*","li"],html:"
  • {0}
  • "},table:{tags:{table:null},isInline:!1,isHtmlInline:!0,skipLastLineBreak:!0,format:"[table]{0}[/table]",html:"
    {0}
    "},tr:{tags:{tr:null},isInline:!1,skipLastLineBreak:!0,format:"[tr]{0}[/tr]",html:"{0}"},th:{tags:{th:null},allowsEmpty:!0,isInline:!1,format:"[th]{0}[/th]",html:"{0}"},td:{tags:{td:null},allowsEmpty:!0,isInline:!1,format:"[td]{0}[/td]",html:"{0}"},emoticon:{allowsEmpty:!0,tags:{img:{src:null,"data-sceditor-emoticon":null}},format:function(a,b){return a.data("sceditor-emoticon")+b},html:"{0}"},hr:{tags:{hr:null},allowsEmpty:!0,isSelfClosing:!0,isInline:!1,format:"[hr]{0}",html:"
    "},img:{allowsEmpty:!0,tags:{img:{src:null}},allowedChildren:["#"],quoteType:p.QuoteType.never,format:function(a,b){var c,d,e="",f=a[0],g=function(a){return f.style?f.style[a]:null};return a.attr("data-sceditor-emoticon")?b:(c=a.attr("width")||g("width"),d=a.attr("height")||g("height"),(f.complete&&(c||d)||c&&d)&&(e="="+a.width()+"x"+a.height()),"[img"+e+"]"+a.attr("src")+"[/img]")},html:function(a,b,c){var d,e,h,i,j="";return e=b.width,h=b.height,b.defaultattr&&(i=b.defaultattr.split(/x/i),e=i[0],h=2===i.length?i[1]:i[0]),e!==d&&(j+=' width="'+f(e,!0)+'"'),h!==d&&(j+=' height="'+f(h,!0)+'"'),"'}},url:{allowsEmpty:!0,tags:{a:{href:null}},quoteType:p.QuoteType.never,format:function(a,b){var c=a.attr("href");return"mailto:"===c.substr(0,7)?'[email="'+c.substr(7)+'"]'+b+"[/email]":"[url="+c+"]"+b+"[/url]"},html:function(a,b,c){return b.defaultattr=f(b.defaultattr,!0)||c,''+c+""}},email:{quoteType:p.QuoteType.never,html:function(a,b,c){return''+c+""}},quote:{tags:{blockquote:null},isInline:!1,quoteType:p.QuoteType.never,format:function(b,c){var d="",e=a(b),f=e.children("cite").first();return(1===f.length||e.data("author"))&&(d=f.text()||e.data("author"),e.data("author",d),f.remove(),c=this.elementToBbcode(a(b)),d="="+d.replace(/(^\s+|\s+$)/g,""),e.prepend(f)),"[quote"+d+"]"+c+"[/quote]"},html:function(a,b,c){return b.defaultattr&&(c=""+f(b.defaultattr)+""+c),"
    "+c+"
    "}},code:{tags:{code:null},isInline:!1,allowedChildren:["#","#newline"],format:"[code]{0}[/code]",html:"{0}"},left:{styles:{"text-align":["left","-webkit-left","-moz-left","-khtml-left"]},isInline:!1,format:"[left]{0}[/left]",html:'
    {0}
    '},center:{styles:{"text-align":["center","-webkit-center","-moz-center","-khtml-center"]},isInline:!1,format:"[center]{0}[/center]",html:'
    {0}
    '},right:{styles:{"text-align":["right","-webkit-right","-moz-right","-khtml-right"]},isInline:!1,format:"[right]{0}[/right]",html:'
    {0}
    '},justify:{styles:{"text-align":["justify","-webkit-justify","-moz-justify","-khtml-justify"]},isInline:!1,format:"[justify]{0}[/justify]",html:'
    {0}
    '},youtube:{allowsEmpty:!0,tags:{iframe:{"data-youtube-id":null}},format:function(a,b){return a=a.attr("data-youtube-id"),a?"[youtube]"+a+"[/youtube]":b},html:''},rtl:{styles:{direction:["rtl"]},format:"[rtl]{0}[/rtl]",html:'
    {0}
    '},ltr:{styles:{direction:["ltr"]},format:"[ltr]{0}[/ltr]",html:'
    {0}
    '},ignore:{}};e.bbcode.bbcode={get:function(a){return s[a]||null},set:function(b,c){return b&&c?(c=a.extend(s[b]||{},c),c.remove=function(){delete s[b]},s[b]=c,this):!1},rename:function(a,b){return a in s?(s[b]=s[a],delete s[a],this):!1},remove:function(a){return a in s&&delete s[a],this}},a.fn.sceditorBBCodePlugin=function(b){return b=b||{},a.isPlainObject(b)&&(b.plugins=(b.plugins||"")+"bbcode"),this.sceditor(b)},e.bbcode.normaliseColour=r,e.bbcode.formatString=m,e.bbcode.stripQuotes=l,e.bbcode.bbcodes=s,d.BBCodeParser=p}(jQuery,window,document); \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_plugins/format.js b/html/forums/jscripts/sceditor/editor_plugins/format.js deleted file mode 100644 index 5072de2..0000000 --- a/html/forums/jscripts/sceditor/editor_plugins/format.js +++ /dev/null @@ -1,2 +0,0 @@ -/* SCEditor v1.4.7 | (C) 2015, Sam Clarke | sceditor.com/license */ -!function(a){"use strict";a.sceditor.plugins.format=function(){var b,c,d=this,e={p:"Paragraph",h1:"Heading 1",h2:"Heading 2",h3:"Heading 3",h4:"Heading 4",h5:"Heading 5",h6:"Heading 6",address:"Address",pre:"Preformatted Text"};d.init=function(){var b=this.opts,d=b.paragraphformat;b.plugins&&b.plugins.indexOf("bbcode")>-1||(d&&(d.tags&&(e=d.tags),d.excludeTags&&a.each(d.excludeTags,function(a,b){delete e[b]})),this.commands.format||(this.commands.format={exec:c,txtExec:c,tooltip:"Format Paragraph"}),b.toolbar===a.sceditor.defaultOptions.toolbar&&(b.toolbar=b.toolbar.replace(",color,",",color,format,")))},b=function(a,b){a.sourceMode()?a.insert("<"+b+">",""):a.execCommand("formatblock","<"+b+">")},c=function(c){var d=this,f=a("
    ");a.each(e,function(c,e){a(''+(e.name||e)+"").click(function(){return d.closeDropDown(!0),e.exec?e.exec(d):b(d,c),!1}).appendTo(f)}),d.createDropDown(c,"format",f)}}}(jQuery); \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_plugins/index.html b/html/forums/jscripts/sceditor/editor_plugins/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/jscripts/sceditor/editor_plugins/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_plugins/undo.js b/html/forums/jscripts/sceditor/editor_plugins/undo.js deleted file mode 100644 index 541d7cb..0000000 --- a/html/forums/jscripts/sceditor/editor_plugins/undo.js +++ /dev/null @@ -1,2 +0,0 @@ -/* SCEditor v1.4.7 | (C) 2015, Sam Clarke | sceditor.com/license */ -!function(a){"use strict";a.sceditor.plugins.undo=function(){var a,b,c=this,d=0,e=50,f=[],g=[],h=!1,i=function(c){h=!0,b=c.value,a.sourceMode(c.sourceMode),a.val(c.value,!1),a.focus(),c.sourceMode?a.sourceEditorCaret(c.caret):a.getRangeHelper().restoreRange(),h=!1},j=function(a,b){var c,d,e,f,g=a.length,h=b.length,i=Math.max(g,h);for(c=0;i>c&&a.charAt(c)===b.charAt(c);c++);for(e=h>g?h-g:0,f=g>h?g-h:0,d=i-1;d>=0&&a.charAt(d-e)===b.charAt(d-f);d--);return d-c+1};c.init=function(){a=this,e=a.undoLimit||e,a.addShortcut("ctrl+z",c.undo),a.addShortcut("ctrl+shift+z",c.redo),a.addShortcut("ctrl+y",c.redo)},c.undo=function(){var b=g.pop(),c=a.val(null,!1);return b&&!f.length&&c===b.value&&(b=g.pop()),b&&(f.length||f.push({caret:a.sourceEditorCaret(),sourceMode:a.sourceMode(),value:c}),f.push(b),i(b)),!1},c.redo=function(){var a=f.pop();return g.length||(g.push(a),a=f.pop()),a&&(g.push(a),i(a)),!1},c.signalReady=function(){var c=a.val(null,!1);b=c,g.push({caret:this.sourceEditorCaret(),sourceMode:this.sourceMode(),value:c})},c.signalValuechangedEvent=function(c){var i=c.rawValue;e>0&&g.length>e&&g.shift(),!h&&b&&b!==i&&(f.length=0,d+=j(b,i),20>d||50>d&&!/\s$/g.test(c.rawValue)||(g.push({caret:a.sourceEditorCaret(),sourceMode:a.sourceMode(),value:i}),d=0,b=i))}}}(jQuery); \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_plugins/xhtml.js b/html/forums/jscripts/sceditor/editor_plugins/xhtml.js deleted file mode 100644 index 100dc95..0000000 --- a/html/forums/jscripts/sceditor/editor_plugins/xhtml.js +++ /dev/null @@ -1,2 +0,0 @@ -/* SCEditor v1.4.7 | (C) 2015, Sam Clarke | sceditor.com/license */ -!function(a){"use strict";var b=a.sceditor,c=b.plugins,d=b.dom,e={bold:{txtExec:["",""]},italic:{txtExec:["",""]},underline:{txtExec:['',""]},strike:{txtExec:['',""]},subscript:{txtExec:["",""]},superscript:{txtExec:["",""]},left:{txtExec:['
    ',"
    "]},center:{txtExec:['
    ',"
    "]},right:{txtExec:['
    ',"
    "]},justify:{txtExec:['
    ',"
    "]},font:{txtExec:function(a){var c=this;b.command.get("font")._dropDown(c,a,function(a){c.insertText('',"")})}},size:{txtExec:function(a){var c=this;b.command.get("size")._dropDown(c,a,function(a){c.insertText('',"")})}},color:{txtExec:function(a){var c=this;b.command.get("color")._dropDown(c,a,function(a){c.insertText('',"")})}},bulletlist:{txtExec:["
    • ","
    "]},orderedlist:{txtExec:["
    1. ","
    "]},table:{txtExec:["
    ","
    "]},horizontalrule:{txtExec:["
    "]},code:{txtExec:["",""]},image:{txtExec:function(a,b){var c=prompt(this._("Enter the image URL:"),b);c&&this.insertText('')}},email:{txtExec:function(a,b){var c,d,e=b&&b.indexOf("@")>-1?null:b;c=prompt(this._("Enter the e-mail address:"),e?"":b),d=prompt(this._("Enter the displayed text:"),e||c)||c,c&&this.insertText(''+d+"")}},link:{txtExec:function(a,b){var c=b&&b.indexOf("http://")>-1?null:b,d=prompt(this._("Enter URL:"),c?"http://":b),e=prompt(this._("Enter the displayed text:"),c||d)||d;d&&this.insertText(''+e+"")}},quote:{txtExec:["
    ","
    "]},youtube:{txtExec:function(a){var c=this;b.command.get("youtube")._dropDown(c,a,function(a){c.insertText('')})}},rtl:{txtExec:['
    ',"
    "]},ltr:{txtExec:['
    ',"
    "]}};b.XHTMLSerializer=function(){var c,e,f,g,h,i,j,k,l,m,n=this,o={indentStr:" "},p=[],q=0;c=function(a){var b={"&":"&","<":"<",">":">",'"':"""};return a?a.replace(/[&<>"]/g,function(a){return b[a]||a}):""},e=function(a){return a.replace(/[\r\n]/," ").replace(/[^\S|\u00A0]+/g," ")},n.serialize=function(a,b){if(p=[],b)for(a=a.firstChild;a;)f(a),a=a.nextSibling;else f(a);return p.join("")},f=function(a,b){switch(a.nodeType){case 1:var c=a.nodeName.toLowerCase();"!"===c?j(a):h(a,b);break;case 3:k(a,b);break;case 4:i(a);break;case 8:j(a);break;case 9:case 11:g(a);break;case 2:case 5:case 6:case 7:case 10:case 12:}},g=function(a){for(var b=a.firstChild;b;)f(b),b=b.nextSibling},h=function(e,g){var h,i,j,k=e.nodeName.toLowerCase(),n="iframe"===k,o=e.attributes.length,p=e.firstChild,r=g||/pre(?:\-wrap)?$/i.test(a(e).css("whiteSpace")),s=!e.firstChild&&!d.canHaveChildren(e)&&!n;if(!a(e).hasClass("sceditor-ignore")){for(l("<"+k,!g&&m(e));o--;)i=e.attributes[o],(!b.ie||i.specified||"input"===k&&"value"===i.name)&&(j=b.ie<8&&/style/i.test(i.name)?e.style.cssText:i.value,l(" "+i.name.toLowerCase()+'="'+c(j)+'"',!1));for(l(s?" />":">",!1),n||(h=p);h;)q++,f(h,r),h=h.nextSibling,q--;s||l("",!r&&!n&&m(e)&&p&&m(p))}},i=function(a){l("")},j=function(a){l("")},k=function(a,b){var d=a.nodeValue;b||(d=e(d)),d&&l(c(d),!b&&m(a))},l=function(a,b){var c=q;if(b!==!1)for(p.length&&p.push("\n");c--;)p.push(o.indentStr);p.push(a)},m=function(a){var b=a.previousSibling;return 1!==a.nodeType&&b?!d.isInline(b):b||d.isInline(a.parentNode)?!d.isInline(a):!0}},c.xhtml=function(){var f,g,h,i,j,k,l,m=this,n={},o={};m.init=function(){a.isEmptyObject(c.xhtml.converters||{})||a.each(c.xhtml.converters,function(b,c){a.each(c.tags,function(a){n[a]||(n[a]=[]),n[a].push(c)})}),this.commands=a.extend(!0,{},e,this.commands)},m.signalToSource=function(a,c){return c=c.jquery?c[0]:c,f(c),i(c),k(c),l(c),(new b.XHTMLSerializer).serialize(c,!0)},m.signalToWysiwyg=function(a){return a},m.convertTagTo=d.convertElement,g=function(c,d,e){n[c]&&a.each(n[c],function(f,g){g.tags[c]?a.each(g.tags[c],function(c,f){e.getAttributeNode&&(c=e.getAttributeNode(c),!c||b.ie<8&&!c.specified||f&&a.inArray(c.value,f)<0||g.conv.call(m,e,d))}):g.conv&&g.conv.call(m,e,d)})},f=function(b){d.traverse(b,function(b){var c=a(b),d=b.nodeName.toLowerCase();g("*",c,b),g(d,c,b)},!0)},h=function(a,b){var c=a.childNodes,e=a.nodeName.toLowerCase(),f=a.nodeValue,g=c.length;if(b&&"br"===e)return!0;if(!d.canHaveChildren(a))return!1;if(f&&/\S|\u00A0/.test(f))return!1;for(;g--;)if(!h(c[g],!a.previousSibling&&!a.nextSibling))return!1;return!0},i=function(b){d.traverse(b,function(b){var e,f=b.nodeName.toLowerCase(),g="iframe"!==f&&h(b),i=b.parentNode,j=b.nodeType,k=!d.isInline(b),l=b.previousSibling,m=b.nextSibling,n=b.ownerDocument,o=c.xhtml.allowedTags,p=c.xhtml.disallowedTags;if(3!==j&&(4===j?f="!cdata":("!"===f||8===j)&&(f="!comment"),g?e=!0:o&&o.length?e=a.inArray(f,o)<0:p&&p.length&&(e=a.inArray(f,p)>-1),e)){if(!g){for(k&&l&&d.isInline(l)&&i.insertBefore(n.createTextNode(" "),b);b.firstChild;)i.insertBefore(b.firstChild,m);k&&m&&d.isInline(m)&&i.insertBefore(n.createTextNode(" "),m)}i.removeChild(b)}},!0)},j=function(b,c){var d={};return b&&a.extend(d,b),c?(a.each(c,function(b,c){a.isArray(c)?d[b]=a.merge(d[b]||[],c):d[b]||(d[b]=null)}),d):d},l=function(b){var c=[],e=function(){c.length&&(a("

    ",b.ownerDocument).insertBefore(c[0]).append(c),c=[])};d.removeWhiteSpace(b);for(var f=b.firstChild;f;)d.isInline(f)&&!a(f).is(".sceditor-ignore")?c.push(f):e(),f=f.nextSibling;e()},k=function(b){var e,f,g,h,i,k,l=c.xhtml.allowedAttribs,m=l&&!a.isEmptyObject(l),n=c.xhtml.disallowedAttribs,p=n&&!a.isEmptyObject(n);o={},d.traverse(b,function(b){if(b.attributes&&(e=b.nodeName.toLowerCase(),h=b.attributes.length))for(o[e]||(o[e]=m?j(l["*"],l[e]):j(n["*"],n[e]));h--;)f=b.attributes[h],g=f.name,i=o[e][g],k=!1,m?k=null!==i&&(!a.isArray(i)||a.inArray(f.value,i)<0):p&&(k=null===i||a.isArray(i)&&a.inArray(f.value,i)>-1),k&&b.removeAttribute(g)})}},c.xhtml.converters=[{tags:{"*":{width:null}},conv:function(a,b){b.css("width",b.attr("width")).removeAttr("width")}},{tags:{"*":{height:null}},conv:function(a,b){b.css("height",b.attr("height")).removeAttr("height")}},{tags:{li:{value:null}},conv:function(a,c){b.ie<8?a.removeAttribute("value"):c.removeAttr("value")}},{tags:{"*":{text:null}},conv:function(a,b){b.css("color",b.attr("text")).removeAttr("text")}},{tags:{"*":{color:null}},conv:function(a,b){b.css("color",b.attr("color")).removeAttr("color")}},{tags:{"*":{face:null}},conv:function(a,b){b.css("fontFamily",b.attr("face")).removeAttr("face")}},{tags:{"*":{align:null}},conv:function(a,b){b.css("textAlign",b.attr("align")).removeAttr("align")}},{tags:{"*":{border:null}},conv:function(a,b){b.css("borderWidth",b.attr("border")).removeAttr("border")}},{tags:{applet:{name:null},img:{name:null},layer:{name:null},map:{name:null},object:{name:null},param:{name:null}},conv:function(a,b){b.attr("id")||b.attr("id",b.attr("name")),b.removeAttr("name")}},{tags:{"*":{vspace:null}},conv:function(a,b){b.css("marginTop",b.attr("vspace")-0).css("marginBottom",b.attr("vspace")-0).removeAttr("vspace")}},{tags:{"*":{hspace:null}},conv:function(a,b){b.css("marginLeft",b.attr("hspace")-0).css("marginRight",b.attr("hspace")-0).removeAttr("hspace")}},{tags:{hr:{noshade:null}},conv:function(a,b){b.css("borderStyle","solid").removeAttr("noshade")}},{tags:{"*":{nowrap:null}},conv:function(a,b){b.css("white-space","nowrap").removeAttr("nowrap")}},{tags:{big:null},conv:function(b){a(this.convertTagTo(b,"span")).css("fontSize","larger")}},{tags:{small:null},conv:function(b){a(this.convertTagTo(b,"span")).css("fontSize","smaller")}},{tags:{b:null},conv:function(b){a(this.convertTagTo(b,"strong"))}},{tags:{u:null},conv:function(b){a(this.convertTagTo(b,"span")).css("textDecoration","underline")}},{tags:{i:null},conv:function(b){a(this.convertTagTo(b,"em"))}},{tags:{s:null,strike:null},conv:function(b){a(this.convertTagTo(b,"span")).css("textDecoration","line-through")}},{tags:{dir:null},conv:function(a){this.convertTagTo(a,"ul")}},{tags:{center:null},conv:function(b){a(this.convertTagTo(b,"div")).css("textAlign","center")}},{tags:{font:{size:null}},conv:function(a,c){var d=c.css("fontSize"),e=d;"+0"!==e&&(b.ie<9&&(e=10,d>1&&(e=13),d>2&&(e=16),d>3&&(e=18),d>4&&(e=24),d>5&&(e=32),d>6&&(e=48)),c.css("fontSize",e)),c.removeAttr("size")}},{tags:{font:null},conv:function(a){this.convertTagTo(a,"span")}},{tags:{"*":{type:["_moz"]}},conv:function(a,b){b.removeAttr("type")}},{tags:{"*":{_moz_dirty:null}},conv:function(a,b){b.removeAttr("_moz_dirty")}},{tags:{"*":{_moz_editor_bogus_node:null}},conv:function(a,b){b.remove()}}],c.xhtml.allowedAttribs={},c.xhtml.disallowedAttribs={},c.xhtml.allowedTags=[],c.xhtml.disallowedTags=[]}(jQuery); \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/buttons.css b/html/forums/jscripts/sceditor/editor_themes/buttons.css deleted file mode 100644 index b1f7213..0000000 --- a/html/forums/jscripts/sceditor/editor_themes/buttons.css +++ /dev/null @@ -1,763 +0,0 @@ -/** - * Buttons theme - * - * Copyright (C) 2013, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * Icons by Mark James (http://www.famfamfam.com/lab/icons/silk/) - * Licensed under the Creative Commons CC-BY license (http://creativecommons.org/licenses/by/3.0/) - */ -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -@font-face { - font-family: 'Monocons'; - src: url('monocons/monocons.eot'); - src: url('monocons/monocons.eot?#iefix') format('embedded-opentype'), url('monocons/monocons.ttf') format('truetype'); - font-weight: normal; - font-style: normal; -} -.sceditor-button div:before, -div.sceditor-grip { - font-family: 'Monocons'; - font-size: 16px; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; -} -.sceditor-button-youtube div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e000'); -} -.sceditor-button-unlink div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e001'); -} -.sceditor-button-underline div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e002'); -} -.sceditor-button-time div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e003'); -} -.sceditor-button-table div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e004'); -} -.sceditor-button-superscript div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e005'); -} -.sceditor-button-subscript div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e006'); -} -.sceditor-button-strike div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e007'); -} -.sceditor-button-source div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e008'); -} -.sceditor-button-size div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e009'); -} -.sceditor-button-rtl div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00a'); -} -.sceditor-button-right div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00b'); -} -.sceditor-button-removeformat div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00c'); -} -.sceditor-button-quote div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00d'); -} -.sceditor-button-print div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00e'); -} -.sceditor-button-pastetext div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00f'); -} -.sceditor-button-paste div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e010'); -} -.sceditor-button-orderedlist div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e011'); -} -.sceditor-button-maximize div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e012'); -} -.sceditor-button-ltr div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e013'); -} -.sceditor-button-link div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e014'); -} -.sceditor-button-left div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e015'); -} -.sceditor-button-justify div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e016'); -} -.sceditor-button-italic div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e017'); -} -.sceditor-button-image div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e018'); -} -.sceditor-button-horizontalrule div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e019'); -} -.sceditor-button-format div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01c'); -} -.sceditor-button-font div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01d'); -} -.sceditor-button-emoticon div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01e'); -} -.sceditor-button-email div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01f'); -} -.sceditor-button-bold div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e020'); -} -.sceditor-button-date div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e021'); -} -.sceditor-button-cut div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e022'); -} -.sceditor-button-copy div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e023'); -} -.sceditor-button-color div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e024'); -} -.sceditor-button-code div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e025'); -} -.sceditor-button-center div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e026'); -} -.sceditor-button-bulletlist div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e027'); -} -div.sceditor-grip { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01b'); -} -.rtl div.sceditor-grip { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01a'); -} -.sceditor-button-youtube div:before { - content: "\e000"; -} -.sceditor-button-unlink div:before { - content: "\e001"; -} -.sceditor-button-underline div:before { - content: "\e002"; -} -.sceditor-button-time div:before { - content: "\e003"; -} -.sceditor-button-table div:before { - content: "\e004"; -} -.sceditor-button-superscript div:before { - content: "\e005"; -} -.sceditor-button-subscript div:before { - content: "\e006"; -} -.sceditor-button-strike div:before { - content: "\e007"; -} -.sceditor-button-source div:before { - content: "\e008"; -} -.sceditor-button-size div:before { - content: "\e009"; -} -.sceditor-button-rtl div:before { - content: "\e00a"; -} -.sceditor-button-right div:before { - content: "\e00b"; -} -.sceditor-button-removeformat div:before { - content: "\e00c"; -} -.sceditor-button-quote div:before { - content: "\e00d"; -} -.sceditor-button-print div:before { - content: "\e00e"; -} -.sceditor-button-pastetext div:before { - content: "\e00f"; -} -.sceditor-button-paste div:before { - content: "\e010"; -} -.sceditor-button-orderedlist div:before { - content: "\e011"; -} -.sceditor-button-maximize div:before { - content: "\e012"; -} -.sceditor-button-ltr div:before { - content: "\e013"; -} -.sceditor-button-link div:before { - content: "\e014"; -} -.sceditor-button-left div:before { - content: "\e015"; -} -.sceditor-button-justify div:before { - content: "\e016"; -} -.sceditor-button-italic div:before { - content: "\e017"; -} -.sceditor-button-image div:before { - content: "\e018"; -} -.sceditor-button-horizontalrule div:before { - content: "\e019"; -} -.sceditor-button-format div:before { - content: "\e01c"; -} -.sceditor-button-font div:before { - content: "\e01d"; -} -.sceditor-button-emoticon div:before { - content: "\e01e"; -} -.sceditor-button-email div:before { - content: "\e01f"; -} -.sceditor-button-bold div:before { - content: "\e020"; -} -.sceditor-button-date div:before { - content: "\e021"; -} -.sceditor-button-cut div:before { - content: "\e022"; -} -.sceditor-button-copy div:before { - content: "\e023"; -} -.sceditor-button-color div:before { - content: "\e024"; -} -.sceditor-button-code div:before { - content: "\e025"; -} -.sceditor-button-center div:before { - content: "\e026"; -} -.sceditor-button-bulletlist div:before { - content: "\e027"; -} -div.sceditor-grip:before { - content: "\e01b"; -} -.rtl div.sceditor-grip:before { - content: "\e01a"; -} -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -/*--------------------------------------------------- - LESS Elements 0.7 - --------------------------------------------------- - A set of useful LESS mixins - More info at: http://lesselements.com - ---------------------------------------------------*/ -.sceditor-container { - position: relative; - background: #fff; - border: 1px solid #d9d9d9; - font-size: 13px; - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - color: #222; - line-height: 1; - font-weight: bold; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 100% !important; -} -.sceditor-container, -.sceditor-container div, -div.sceditor-dropdown, -div.sceditor-dropdown div { - padding: 0; - margin: 0; - z-index: 3; -} -.sceditor-container iframe, -.sceditor-container textarea { - line-height: 1; - border: 0; - outline: none; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 13px; - color: #111; - padding: 0; - margin: 5px; - resize: none; - background: #fff; - display: block; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 99% !important; -} -div.sceditor-resize-cover { - position: absolute; - top: 0; - left: 0; - background: #000; - width: 100%; - height: 100%; - z-index: 10; - opacity: 0.3; -} -.ie6 div.sceditor-resize-cover, -.ie7 div.sceditor-resize-cover, -.ie8 div.sceditor-resize-cover { - background: #efefef; -} -.sceditor-container.ie6 { - overflow: hidden; -} -div.sceditor-grip { - overflow: hidden; - width: 10px; - height: 10px; - cursor: pointer; - position: absolute; - bottom: 0; - right: 0; - z-index: 3; -} -.sceditor-maximize { - position: fixed; - top: 0; - left: 0; - height: 100% !important; - width: 100% !important; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - z-index: 2000; -} -html.sceditor-maximize, -body.sceditor-maximize { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - overflow: hidden; -} -.ie6.sceditor-maximize { - position: absolute; -} -.sceditor-maximize div.sceditor-grip { - display: none; -} -.sceditor-maximize div.sceditor-toolbar { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -/** - * Dropdown styleing - */ -div.sceditor-dropdown { - position: absolute; - border: 1px solid #ccc; - background: #fff; - color: #333; - z-index: 4000; - padding: 10px; - line-height: 1; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); -} -div.sceditor-dropdown a, -div.sceditor-dropdown a:link { - color: #333; -} -div.sceditor-dropdown form { - margin: 0; -} -div.sceditor-dropdown label { - display: block; - font-weight: bold; - color: #3c3c3c; - padding: 4px 0; -} -div.sceditor-dropdown input, -div.sceditor-dropdown textarea { - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - outline: 0; - padding: 4px; - border: 1px solid #ccc; - border-top-color: #888; - margin: 0 0 .75em; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-dropdown textarea { - padding: 6px; -} -div.sceditor-dropdown input:focus, -div.sceditor-dropdown textarea:focus { - border-color: #aaa; - border-top-color: #666; - -webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); -} -div.sceditor-dropdown .button { - font-weight: bold; - color: #444; - padding: 6px 12px; - background: #ececec; - border: solid 1px #ccc; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - cursor: pointer; - margin: .3em 0 0; -} -div.sceditor-dropdown .button:hover { - background: #f3f3f3; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); -} -div.sceditor-font-picker, -div.sceditor-fontsize-picker, -div.sceditor-format { - padding: 6px 0; -} -div.sceditor-emoticons, -div.sceditor-more-emoticons, -div.sceditor-color-picker { - padding: 0; -} -.sceditor-pastetext textarea { - border: 1px solid #bbb; - width: 20em; -} -.sceditor-emoticons img, -.sceditor-more-emoticons img { - padding: 0; - cursor: pointer; - margin: 2px; -} -.sceditor-more { - border-top: 1px solid #bbb; - display: block; - text-align: center; - cursor: pointer; - font-weight: bold; - padding: 6px 0; -} -.sceditor-dropdown a:hover { - background: #eee; -} -.sceditor-fontsize-option, -.sceditor-font-option, -.sceditor-format a { - display: block; - padding: 7px 10px; - cursor: pointer; - text-decoration: none; - color: #222; -} -.sceditor-fontsize-option { - padding: 7px 13px; -} -.sceditor-color-column { - float: left; -} -.sceditor-color-option { - display: block; - border: 1px solid #fff; - height: 10px; - width: 10px; - overflow: hidden; -} -.sceditor-color-option:hover { - border: 1px solid #333; -} -/** - * Toolbar styleing - */ -div.sceditor-toolbar { - overflow: hidden; - padding: 3px 5px 2px; - background: #f7f7f7; - border-bottom: 1px solid #c0c0c0; - line-height: 0; - text-align: left; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-group { - display: inline-block; - background: #ddd; - margin: 1px 5px 1px 0; - padding: 1px; - border-bottom: 1px solid #aaa; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.ie6 div.sceditor-group, -.ie7 div.sceditor-group { - display: inline; - zoom: 1; -} -.sceditor-button { - float: left; - cursor: pointer; - padding: 3px 5px; - width: 16px; - height: 20px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - /* Needed for Safari 5? */ - - text-indent: -9999px; -} -.ie .sceditor-button { - text-indent: 0; -} -.ie6 .sceditor-button, -.ie7 .sceditor-button { - float: none !important; - display: inline; - zoom: 1; -} -.ie6 .sceditor-button { - padding: 0; -} -.ie6 .sceditor-button div { - margin: 5px; -} -.ie7 .sceditor-button div { - margin: 5px 0; -} -.sceditor-button:hover, -.sceditor-button:active, -.sceditor-button.active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); -} -.sceditor-button:active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); -} -.sceditor-button.disabled:hover { - background: inherit; - cursor: default; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.sceditor-button, -.sceditor-button div { - display: block; -} -.sceditor-button div { - margin: 2px 0; - padding: 0; - overflow: hidden; - line-height: 0; - font-size: 0; - color: transparent; -} -.sceditor-button.disabled div { - filter: alpha(opacity=30); - opacity: 0.3; -} -.text .sceditor-button, -.text .sceditor-button div, -.sceditor-button.text, -.sceditor-button.text div, -.text-icon .sceditor-button, -.text-icon .sceditor-button div, -.sceditor-button.text-icon, -.sceditor-button.text-icon div { - width: auto; - overflow: visible; - line-height: 16px; - font-size: 1em; - color: inherit; - text-indent: 0; -} -.text .sceditor-button div, -.sceditor-button.text div { - padding: 0 2px; - background: none; -} -.text-icon .sceditor-button div, -.sceditor-button.text-icon div { - padding: 0 2px 0 20px; -} -.rtl div.sceditor-toolbar { - text-align: right; -} -.rtl .sceditor-button { - float: right; -} -.rtl div.sceditor-grip { - right: auto; - left: 0; -} -.ie7 .sceditor-button div, -.ie6 .sceditor-button div { - font-family: 'Monocons'; - overflow: visible; - font-size: 16px; - line-height: 1; - text-indent: 0; -} -div.sceditor-grip { - height: 16px; - width: 16px; -} -.sceditor-button div:before, -div.sceditor-grip:before { - text-indent: 0; - line-height: 17px; - width: 16px; - height: 16px; - display: block; - color: #333; - text-shadow: 0 1px #fff; -} -.sceditor-container { - border-color: #111; -} -div.sceditor-toolbar { - color: #fff; - background: #2b2b2b; - border-color: #111; -} -div.sceditor-group { - margin: 2px 5px 2px 0; - border: 0; - background: #777777; - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzc3Nzc3NyIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjQwJSIgc3RvcC1jb2xvcj0iIzU1NTU1NSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM0NDQ0NDQiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); - background: -moz-linear-gradient(top, #777777 0%, #555555 40%, #444444 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #777777), color-stop(40%, #555555), color-stop(100%, #444444)); - background: -webkit-linear-gradient(top, #777777 0%, #555555 40%, #444444 100%); - background: -o-linear-gradient(top, #777777 0%, #555555 40%, #444444 100%); - background: -ms-linear-gradient(top, #777777 0%, #555555 40%, #444444 100%); - background: linear-gradient(to bottom, #777777 0%, #555555 40%, #444444 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#777777', endColorstr='#444444', GradientType=0); -} -.sceditor-button div:before, -div.sceditor-grip:before { - color: #ddd; - text-shadow: 0 1px #000; -} -.sceditor-container.sourceMode { - background: #1f1f1f; -} -.sceditor-container textarea { - color: #fff; - background: #1f1f1f; -} - -/* Additional buttons (for MyBB) */ -.sceditor-button-video div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e000'); -} - -.sceditor-button-video div:before { - content: "\e000"; -} - -.sceditor-button-php div { - *zoom: expression(this.runtimeStyle['zoom'] = '0', this.innerHTML = '\24C5'); -} - -.sceditor-button-php div:before { - content: "\24C5"; - font-size: 17px; - line-height: 0.85; -} - -.sceditor-button-php:hover { - text-decoration: none; -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/default.css b/html/forums/jscripts/sceditor/editor_themes/default.css deleted file mode 100644 index b1a1f0b..0000000 --- a/html/forums/jscripts/sceditor/editor_themes/default.css +++ /dev/null @@ -1,559 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -div.sceditor-grip, -.sceditor-button div { - background-image: url('famfamfam.png'); - background-repeat: no-repeat; - width: 16px; - height: 16px; -} -.sceditor-button-youtube div { - background-position: 0px 0px; -} -.sceditor-button-link div { - background-position: 0px -16px; -} -.sceditor-button-unlink div { - background-position: 0px -32px; -} -.sceditor-button-underline div { - background-position: 0px -48px; -} -.sceditor-button-time div { - background-position: 0px -64px; -} -.sceditor-button-table div { - background-position: 0px -80px; -} -.sceditor-button-superscript div { - background-position: 0px -96px; -} -.sceditor-button-subscript div { - background-position: 0px -112px; -} -.sceditor-button-strike div { - background-position: 0px -128px; -} -.sceditor-button-source div { - background-position: 0px -144px; -} -.sceditor-button-size div { - background-position: 0px -160px; -} -.sceditor-button-rtl div { - background-position: 0px -176px; -} -.sceditor-button-right div { - background-position: 0px -192px; -} -.sceditor-button-removeformat div { - background-position: 0px -208px; -} -.sceditor-button-quote div { - background-position: 0px -224px; -} -.sceditor-button-print div { - background-position: 0px -240px; -} -.sceditor-button-pastetext div { - background-position: 0px -256px; -} -.sceditor-button-paste div { - background-position: 0px -272px; -} -.sceditor-button-orderedlist div { - background-position: 0px -288px; -} -.sceditor-button-maximize div { - background-position: 0px -304px; -} -.sceditor-button-ltr div { - background-position: 0px -320px; -} -.sceditor-button-left div { - background-position: 0px -336px; -} -.sceditor-button-justify div { - background-position: 0px -352px; -} -.sceditor-button-italic div { - background-position: 0px -368px; -} -.sceditor-button-image div { - background-position: 0px -384px; -} -.sceditor-button-horizontalrule div { - background-position: 0px -400px; -} -.sceditor-button-format div { - background-position: 0px -416px; -} -.sceditor-button-font div { - background-position: 0px -432px; -} -.sceditor-button-emoticon div { - background-position: 0px -448px; -} -.sceditor-button-email div { - background-position: 0px -464px; -} -.sceditor-button-date div { - background-position: 0px -480px; -} -.sceditor-button-cut div { - background-position: 0px -496px; -} -.sceditor-button-copy div { - background-position: 0px -512px; -} -.sceditor-button-color div { - background-position: 0px -528px; -} -.sceditor-button-code div { - background-position: 0px -544px; -} -.sceditor-button-center div { - background-position: 0px -560px; -} -.sceditor-button-bulletlist div { - background-position: 0px -576px; -} -.sceditor-button-bold div { - background-position: 0px -592px; -} -div.sceditor-grip { - background-position: 0px -608px; - width: 10px; - height: 10px; -} -.rtl div.sceditor-grip { - background-position: 0px -618px; - width: 10px; - height: 10px; -} -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -/*--------------------------------------------------- - LESS Elements 0.7 - --------------------------------------------------- - A set of useful LESS mixins - More info at: http://lesselements.com - ---------------------------------------------------*/ -.sceditor-container { - position: relative; - background: #fff; - border: 1px solid #d9d9d9; - font-size: 13px; - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - color: #222; - line-height: 1; - font-weight: bold; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 100% !important; -} -.sceditor-container, -.sceditor-container div, -div.sceditor-dropdown, -div.sceditor-dropdown div { - padding: 0; - margin: 0; - z-index: 3; -} -.sceditor-container iframe, -.sceditor-container textarea { - line-height: 1; - border: 0; - outline: none; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 13px; - color: #111; - padding: 0; - margin: 5px; - resize: none; - background: #fff; - display: block; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 99% !important; -} -div.sceditor-resize-cover { - position: absolute; - top: 0; - left: 0; - background: #000; - width: 100%; - height: 100%; - z-index: 10; - opacity: 0.3; -} -.ie6 div.sceditor-resize-cover, -.ie7 div.sceditor-resize-cover, -.ie8 div.sceditor-resize-cover { - background: #efefef; -} -.sceditor-container.ie6 { - overflow: hidden; -} -div.sceditor-grip { - overflow: hidden; - width: 10px; - height: 10px; - cursor: pointer; - position: absolute; - bottom: 0; - right: 0; - z-index: 3; -} -.sceditor-maximize { - position: fixed; - top: 0; - left: 0; - height: 100% !important; - width: 100% !important; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - z-index: 2000; -} -html.sceditor-maximize, -body.sceditor-maximize { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - overflow: hidden; -} -.ie6.sceditor-maximize { - position: absolute; -} -.sceditor-maximize div.sceditor-grip { - display: none; -} -.sceditor-maximize div.sceditor-toolbar { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -/** - * Dropdown styleing - */ -div.sceditor-dropdown { - position: absolute; - border: 1px solid #ccc; - background: #fff; - color: #333; - z-index: 4000; - padding: 10px; - line-height: 1; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); -} -div.sceditor-dropdown a, -div.sceditor-dropdown a:link { - color: #333; -} -div.sceditor-dropdown form { - margin: 0; -} -div.sceditor-dropdown label { - display: block; - font-weight: bold; - color: #3c3c3c; - padding: 4px 0; -} -div.sceditor-dropdown input, -div.sceditor-dropdown textarea { - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - outline: 0; - padding: 4px; - border: 1px solid #ccc; - border-top-color: #888; - margin: 0 0 .75em; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-dropdown textarea { - padding: 6px; -} -div.sceditor-dropdown input:focus, -div.sceditor-dropdown textarea:focus { - border-color: #aaa; - border-top-color: #666; - -webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); -} -div.sceditor-dropdown .button { - font-weight: bold; - color: #444; - padding: 6px 12px; - background: #ececec; - border: solid 1px #ccc; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - cursor: pointer; - margin: .3em 0 0; -} -div.sceditor-dropdown .button:hover { - background: #f3f3f3; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); -} -div.sceditor-font-picker, -div.sceditor-fontsize-picker, -div.sceditor-format { - padding: 6px 0; -} -div.sceditor-emoticons, -div.sceditor-more-emoticons, -div.sceditor-color-picker { - padding: 0; -} -.sceditor-pastetext textarea { - border: 1px solid #bbb; - width: 20em; -} -.sceditor-emoticons img, -.sceditor-more-emoticons img { - padding: 0; - cursor: pointer; - margin: 2px; -} -.sceditor-more { - border-top: 1px solid #bbb; - display: block; - text-align: center; - cursor: pointer; - font-weight: bold; - padding: 6px 0; -} -.sceditor-dropdown a:hover { - background: #eee; -} -.sceditor-fontsize-option, -.sceditor-font-option, -.sceditor-format a { - display: block; - padding: 7px 10px; - cursor: pointer; - text-decoration: none; - color: #222; -} -.sceditor-fontsize-option { - padding: 7px 13px; -} -.sceditor-color-column { - float: left; -} -.sceditor-color-option { - display: block; - border: 1px solid #fff; - height: 10px; - width: 10px; - overflow: hidden; -} -.sceditor-color-option:hover { - border: 1px solid #333; -} -/** - * Toolbar styleing - */ -div.sceditor-toolbar { - overflow: hidden; - padding: 3px 5px 2px; - background: #f7f7f7; - border-bottom: 1px solid #c0c0c0; - line-height: 0; - text-align: left; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-group { - display: inline-block; - background: #ddd; - margin: 1px 5px 1px 0; - padding: 1px; - border-bottom: 1px solid #aaa; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.ie6 div.sceditor-group, -.ie7 div.sceditor-group { - display: inline; - zoom: 1; -} -.sceditor-button { - float: left; - cursor: pointer; - padding: 3px 5px; - width: 16px; - height: 20px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - /* Needed for Safari 5? */ - - text-indent: -9999px; -} -.ie .sceditor-button { - text-indent: 0; -} -.ie6 .sceditor-button, -.ie7 .sceditor-button { - float: none !important; - display: inline; - zoom: 1; -} -.ie6 .sceditor-button { - padding: 0; -} -.ie6 .sceditor-button div { - margin: 5px; -} -.ie7 .sceditor-button div { - margin: 5px 0; -} -.sceditor-button:hover, -.sceditor-button:active, -.sceditor-button.active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); -} -.sceditor-button:active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); -} -.sceditor-button.disabled:hover { - background: inherit; - cursor: default; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.sceditor-button, -.sceditor-button div { - display: block; -} -.sceditor-button div { - margin: 2px 0; - padding: 0; - overflow: hidden; - line-height: 0; - font-size: 0; - color: transparent; -} -.sceditor-button.disabled div { - filter: alpha(opacity=30); - opacity: 0.3; -} -.text .sceditor-button, -.text .sceditor-button div, -.sceditor-button.text, -.sceditor-button.text div, -.text-icon .sceditor-button, -.text-icon .sceditor-button div, -.sceditor-button.text-icon, -.sceditor-button.text-icon div { - width: auto; - overflow: visible; - line-height: 16px; - font-size: 1em; - color: inherit; - text-indent: 0; -} -.text .sceditor-button div, -.sceditor-button.text div { - padding: 0 2px; - background: none; -} -.text-icon .sceditor-button div, -.sceditor-button.text-icon div { - padding: 0 2px 0 20px; -} -.rtl div.sceditor-toolbar { - text-align: right; -} -.rtl .sceditor-button { - float: right; -} -.rtl div.sceditor-grip { - right: auto; - left: 0; -} - -/* Additional buttons (for MyBB) */ -.sceditor-button-video div { - - background-image: url(video.png); - -} -.sceditor-button-php div { - - background-image: url(php.png); - -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/alien.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/alien.png deleted file mode 100644 index 1f61c7e..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/alien.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/angel.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/angel.png deleted file mode 100644 index c366ed8..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/angel.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/angry.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/angry.png deleted file mode 100644 index 08987d7..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/angry.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/blink.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/blink.png deleted file mode 100644 index 96a1a85..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/blink.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/blush.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/blush.png deleted file mode 100644 index 5a92167..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/blush.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/cheerful.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/cheerful.png deleted file mode 100644 index 5a04b02..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/cheerful.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/cool.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/cool.png deleted file mode 100644 index a57cce9..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/cool.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/credits.txt b/html/forums/jscripts/sceditor/editor_themes/emoticons/credits.txt deleted file mode 100644 index 2ffdaeb..0000000 --- a/html/forums/jscripts/sceditor/editor_themes/emoticons/credits.txt +++ /dev/null @@ -1,9 +0,0 @@ -Presenting, Nomicons: The Full Monty :o - -Credits: -Oscar Gruno, aka Nominell v. 2.0 -> oscargruno@mac.com -Andy Fedosjeenko, aka Nightwolf -> bobo@animevanguard.com - -Copyright (C) 2001-Infinity, Oscar Gruno & Andy Fedosjeenko - -You can redistribute these files as much as you like, as long as you keep this file with them and give us the proper credit. You may even rape them if you please, just give us credit for our work. \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/cwy.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/cwy.png deleted file mode 100644 index 135f697..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/cwy.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/devil.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/devil.png deleted file mode 100644 index d90da8b..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/devil.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/dizzy.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/dizzy.png deleted file mode 100644 index 3811676..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/dizzy.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/ermm.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/ermm.png deleted file mode 100644 index 502c401..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/ermm.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/face.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/face.png deleted file mode 100644 index d0cdafa..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/face.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/getlost.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/getlost.png deleted file mode 100644 index 203c59d..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/getlost.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/grin.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/grin.png deleted file mode 100644 index 297a16e..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/grin.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/happy.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/happy.png deleted file mode 100644 index 63261a7..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/happy.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/heart.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/heart.png deleted file mode 100644 index 7b0810e..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/heart.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/kissing.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/kissing.png deleted file mode 100644 index e868974..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/kissing.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/laughing.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/laughing.png deleted file mode 100644 index 6049cf4..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/laughing.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/ninja.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/ninja.png deleted file mode 100644 index fd3c6bb..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/ninja.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/pinch.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/pinch.png deleted file mode 100644 index 8a80bc6..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/pinch.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/pouty.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/pouty.png deleted file mode 100644 index 77cee99..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/pouty.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/sad.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/sad.png deleted file mode 100644 index 66696d6..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/sad.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/shocked.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/shocked.png deleted file mode 100644 index 525ce5f..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/shocked.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/sick.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/sick.png deleted file mode 100644 index d3c0e68..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/sick.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/sideways.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/sideways.png deleted file mode 100644 index cd652a2..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/sideways.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/silly.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/silly.png deleted file mode 100644 index b66dcfe..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/silly.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/sleeping.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/sleeping.png deleted file mode 100644 index 51e8fb2..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/sleeping.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/smile.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/smile.png deleted file mode 100644 index 9942e83..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/smile.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/tongue.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/tongue.png deleted file mode 100644 index 26538dd..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/tongue.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/unsure.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/unsure.png deleted file mode 100644 index b888212..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/unsure.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/w00t.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/w00t.png deleted file mode 100644 index 4ed21f2..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/w00t.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/wassat.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/wassat.png deleted file mode 100644 index 7f9376b..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/wassat.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/whistling.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/whistling.png deleted file mode 100644 index 28a40ac..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/whistling.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/wink.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/wink.png deleted file mode 100644 index d3e610b..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/wink.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/emoticons/wub.png b/html/forums/jscripts/sceditor/editor_themes/emoticons/wub.png deleted file mode 100644 index 75c3531..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/emoticons/wub.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/famfamfam.png b/html/forums/jscripts/sceditor/editor_themes/famfamfam.png deleted file mode 100644 index 8ff9b64..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/famfamfam.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/index.html b/html/forums/jscripts/sceditor/editor_themes/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/jscripts/sceditor/editor_themes/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/modern.css b/html/forums/jscripts/sceditor/editor_themes/modern.css deleted file mode 100644 index 852aeac..0000000 --- a/html/forums/jscripts/sceditor/editor_themes/modern.css +++ /dev/null @@ -1,650 +0,0 @@ -/** - * Modern theme - * - * Copyright (C) 2012, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * Icons by Mark James (http://www.famfamfam.com/lab/icons/silk/) - * Licensed under the Creative Commons CC-BY license (http://creativecommons.org/licenses/by/3.0/) - */ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -div.sceditor-grip, -.sceditor-button div { - background-image: url('famfamfam.png'); - background-repeat: no-repeat; - width: 16px; - height: 16px; -} -.sceditor-button-youtube div { - background-position: 0px 0px; -} -.sceditor-button-link div { - background-position: 0px -16px; -} -.sceditor-button-unlink div { - background-position: 0px -32px; -} -.sceditor-button-underline div { - background-position: 0px -48px; -} -.sceditor-button-time div { - background-position: 0px -64px; -} -.sceditor-button-table div { - background-position: 0px -80px; -} -.sceditor-button-superscript div { - background-position: 0px -96px; -} -.sceditor-button-subscript div { - background-position: 0px -112px; -} -.sceditor-button-strike div { - background-position: 0px -128px; -} -.sceditor-button-source div { - background-position: 0px -144px; -} -.sceditor-button-size div { - background-position: 0px -160px; -} -.sceditor-button-rtl div { - background-position: 0px -176px; -} -.sceditor-button-right div { - background-position: 0px -192px; -} -.sceditor-button-removeformat div { - background-position: 0px -208px; -} -.sceditor-button-quote div { - background-position: 0px -224px; -} -.sceditor-button-print div { - background-position: 0px -240px; -} -.sceditor-button-pastetext div { - background-position: 0px -256px; -} -.sceditor-button-paste div { - background-position: 0px -272px; -} -.sceditor-button-orderedlist div { - background-position: 0px -288px; -} -.sceditor-button-maximize div { - background-position: 0px -304px; -} -.sceditor-button-ltr div { - background-position: 0px -320px; -} -.sceditor-button-left div { - background-position: 0px -336px; -} -.sceditor-button-justify div { - background-position: 0px -352px; -} -.sceditor-button-italic div { - background-position: 0px -368px; -} -.sceditor-button-image div { - background-position: 0px -384px; -} -.sceditor-button-horizontalrule div { - background-position: 0px -400px; -} -.sceditor-button-format div { - background-position: 0px -416px; -} -.sceditor-button-font div { - background-position: 0px -432px; -} -.sceditor-button-emoticon div { - background-position: 0px -448px; -} -.sceditor-button-email div { - background-position: 0px -464px; -} -.sceditor-button-date div { - background-position: 0px -480px; -} -.sceditor-button-cut div { - background-position: 0px -496px; -} -.sceditor-button-copy div { - background-position: 0px -512px; -} -.sceditor-button-color div { - background-position: 0px -528px; -} -.sceditor-button-code div { - background-position: 0px -544px; -} -.sceditor-button-center div { - background-position: 0px -560px; -} -.sceditor-button-bulletlist div { - background-position: 0px -576px; -} -.sceditor-button-bold div { - background-position: 0px -592px; -} -div.sceditor-grip { - background-position: 0px -608px; - width: 10px; - height: 10px; -} -.rtl div.sceditor-grip { - background-position: 0px -618px; - width: 10px; - height: 10px; -} -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -/*--------------------------------------------------- - LESS Elements 0.7 - --------------------------------------------------- - A set of useful LESS mixins - More info at: http://lesselements.com - ---------------------------------------------------*/ -.sceditor-container { - position: relative; - background: #fff; - border: 1px solid #d9d9d9; - font-size: 13px; - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - color: #222; - line-height: 1; - font-weight: bold; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 100% !important; -} -.sceditor-container, -.sceditor-container div, -div.sceditor-dropdown, -div.sceditor-dropdown div { - padding: 0; - margin: 0; - z-index: 3; -} -.sceditor-container iframe, -.sceditor-container textarea { - line-height: 1; - border: 0; - outline: none; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 13px; - color: #111; - padding: 0; - margin: 5px; - resize: none; - background: #fff; - display: block; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 99% !important; -} -div.sceditor-resize-cover { - position: absolute; - top: 0; - left: 0; - background: #000; - width: 100%; - height: 100%; - z-index: 10; - opacity: 0.3; -} -.ie6 div.sceditor-resize-cover, -.ie7 div.sceditor-resize-cover, -.ie8 div.sceditor-resize-cover { - background: #efefef; -} -.sceditor-container.ie6 { - overflow: hidden; -} -div.sceditor-grip { - overflow: hidden; - width: 10px; - height: 10px; - cursor: pointer; - position: absolute; - bottom: 0; - right: 0; - z-index: 3; -} -.sceditor-maximize { - position: fixed; - top: 0; - left: 0; - height: 100% !important; - width: 100% !important; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - z-index: 2000; -} -html.sceditor-maximize, -body.sceditor-maximize { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - overflow: hidden; -} -.ie6.sceditor-maximize { - position: absolute; -} -.sceditor-maximize div.sceditor-grip { - display: none; -} -.sceditor-maximize div.sceditor-toolbar { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -/** - * Dropdown styleing - */ -div.sceditor-dropdown { - position: absolute; - border: 1px solid #ccc; - background: #fff; - color: #333; - z-index: 4000; - padding: 10px; - line-height: 1; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); -} -div.sceditor-dropdown a, -div.sceditor-dropdown a:link { - color: #333; -} -div.sceditor-dropdown form { - margin: 0; -} -div.sceditor-dropdown label { - display: block; - font-weight: bold; - color: #3c3c3c; - padding: 4px 0; -} -div.sceditor-dropdown input, -div.sceditor-dropdown textarea { - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - outline: 0; - padding: 4px; - border: 1px solid #ccc; - border-top-color: #888; - margin: 0 0 .75em; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-dropdown textarea { - padding: 6px; -} -div.sceditor-dropdown input:focus, -div.sceditor-dropdown textarea:focus { - border-color: #aaa; - border-top-color: #666; - -webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); -} -div.sceditor-dropdown .button { - font-weight: bold; - color: #444; - padding: 6px 12px; - background: #ececec; - border: solid 1px #ccc; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - cursor: pointer; - margin: .3em 0 0; -} -div.sceditor-dropdown .button:hover { - background: #f3f3f3; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); -} -div.sceditor-font-picker, -div.sceditor-fontsize-picker, -div.sceditor-format { - padding: 6px 0; -} -div.sceditor-emoticons, -div.sceditor-more-emoticons, -div.sceditor-color-picker { - padding: 0; -} -.sceditor-pastetext textarea { - border: 1px solid #bbb; - width: 20em; -} -.sceditor-emoticons img, -.sceditor-more-emoticons img { - padding: 0; - cursor: pointer; - margin: 2px; -} -.sceditor-more { - border-top: 1px solid #bbb; - display: block; - text-align: center; - cursor: pointer; - font-weight: bold; - padding: 6px 0; -} -.sceditor-dropdown a:hover { - background: #eee; -} -.sceditor-fontsize-option, -.sceditor-font-option, -.sceditor-format a { - display: block; - padding: 7px 10px; - cursor: pointer; - text-decoration: none; - color: #222; -} -.sceditor-fontsize-option { - padding: 7px 13px; -} -.sceditor-color-column { - float: left; -} -.sceditor-color-option { - display: block; - border: 1px solid #fff; - height: 10px; - width: 10px; - overflow: hidden; -} -.sceditor-color-option:hover { - border: 1px solid #333; -} -/** - * Toolbar styleing - */ -div.sceditor-toolbar { - overflow: hidden; - padding: 3px 5px 2px; - background: #f7f7f7; - border-bottom: 1px solid #c0c0c0; - line-height: 0; - text-align: left; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-group { - display: inline-block; - background: #ddd; - margin: 1px 5px 1px 0; - padding: 1px; - border-bottom: 1px solid #aaa; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.ie6 div.sceditor-group, -.ie7 div.sceditor-group { - display: inline; - zoom: 1; -} -.sceditor-button { - float: left; - cursor: pointer; - padding: 3px 5px; - width: 16px; - height: 20px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - /* Needed for Safari 5? */ - - text-indent: -9999px; -} -.ie .sceditor-button { - text-indent: 0; -} -.ie6 .sceditor-button, -.ie7 .sceditor-button { - float: none !important; - display: inline; - zoom: 1; -} -.ie6 .sceditor-button { - padding: 0; -} -.ie6 .sceditor-button div { - margin: 5px; -} -.ie7 .sceditor-button div { - margin: 5px 0; -} -.sceditor-button:hover, -.sceditor-button:active, -.sceditor-button.active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); -} -.sceditor-button:active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); -} -.sceditor-button.disabled:hover { - background: inherit; - cursor: default; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.sceditor-button, -.sceditor-button div { - display: block; -} -.sceditor-button div { - margin: 2px 0; - padding: 0; - overflow: hidden; - line-height: 0; - font-size: 0; - color: transparent; -} -.sceditor-button.disabled div { - filter: alpha(opacity=30); - opacity: 0.3; -} -.text .sceditor-button, -.text .sceditor-button div, -.sceditor-button.text, -.sceditor-button.text div, -.text-icon .sceditor-button, -.text-icon .sceditor-button div, -.sceditor-button.text-icon, -.sceditor-button.text-icon div { - width: auto; - overflow: visible; - line-height: 16px; - font-size: 1em; - color: inherit; - text-indent: 0; -} -.text .sceditor-button div, -.sceditor-button.text div { - padding: 0 2px; - background: none; -} -.text-icon .sceditor-button div, -.sceditor-button.text-icon div { - padding: 0 2px 0 20px; -} -.rtl div.sceditor-toolbar { - text-align: right; -} -.rtl .sceditor-button { - float: right; -} -.rtl div.sceditor-grip { - right: auto; - left: 0; -} -.sceditor-container { - border: 1px solid #999; -} -.sceditor-container textarea { - font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace; - background: #2e3436; - color: #fff; - margin: 0; - padding: 5px; -} -div.sceditor-toolbar { - background: #ccc; - background: -moz-linear-gradient(top, #cccccc 0%, #b2b2b2 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #cccccc), color-stop(100%, #b2b2b2)); - background: -webkit-linear-gradient(top, #cccccc 0%, #b2b2b2 100%); - background: -o-linear-gradient(top, #cccccc 0%, #b2b2b2 100%); - background: -ms-linear-gradient(top, #cccccc 0%, #b2b2b2 100%); - background: linear-gradient(to bottom, #cccccc 0%, #b2b2b2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#b2b2b2', GradientType=0); -} -.ie9 div.sceditor-toolbar { - filter: none; - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2NjY2NjYyIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNiMmIyYjIiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); -} -div.sceditor-group { - display: inline; - background: transparent; - margin: 0; - padding: 0; - border: 0; -} -.sceditor-button { - padding: 4px; - margin: 2px 1px 2px 3px; - height: 16px; - -webkit-border-radius: 12px; - -moz-border-radius: 12px; - border-radius: 12px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.sceditor-button:hover, -.sceditor-button.active, -.sceditor-button.active:hover { - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.sceditor-button:hover { - background: #fff; - background: rgba(255, 255, 255, 0.75); - margin: 1px 0 1px 2px; - border: 1px solid #eee; -} -.sceditor-button.disabled:hover { - margin: 2px 1px 2px 3px; - border: 0; -} -.sceditor-button.active { - background: #b1b1b1; - background: rgba(0, 0, 0, 0.1); - margin: 1px 0 1px 2px; - border: 1px solid #999; -} -.sceditor-button.active:hover { - background: #fff; - background: rgba(255, 255, 255, 0.25); -} -.sceditor-button:active, -.sceditor-button.active:active { - margin: 1px 0 1px 2px; - border: 1px solid #999; - -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.5); - -moz-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.5); - box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.5); -} -.sceditor-button div { - margin: 0; -} - -/* Additional buttons (for MyBB) */ -.sceditor-button-video div { - - background-image: url(video.png); - -} -.sceditor-button-php div { - - background-image: url(php.png); - -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/monocons.css b/html/forums/jscripts/sceditor/editor_themes/monocons.css deleted file mode 100644 index 8abcf95..0000000 --- a/html/forums/jscripts/sceditor/editor_themes/monocons.css +++ /dev/null @@ -1,719 +0,0 @@ -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -@font-face { - font-family: 'Monocons'; - src: url('monocons/monocons.eot'); - src: url('monocons/monocons.eot?#iefix') format('embedded-opentype'), url('monocons/monocons.ttf') format('truetype'); - font-weight: normal; - font-style: normal; -} -.sceditor-button div:before, -div.sceditor-grip { - font-family: 'Monocons'; - font-size: 16px; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; -} -.sceditor-button-youtube div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e000'); -} -.sceditor-button-unlink div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e001'); -} -.sceditor-button-underline div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e002'); -} -.sceditor-button-time div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e003'); -} -.sceditor-button-table div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e004'); -} -.sceditor-button-superscript div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e005'); -} -.sceditor-button-subscript div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e006'); -} -.sceditor-button-strike div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e007'); -} -.sceditor-button-source div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e008'); -} -.sceditor-button-size div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e009'); -} -.sceditor-button-rtl div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00a'); -} -.sceditor-button-right div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00b'); -} -.sceditor-button-removeformat div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00c'); -} -.sceditor-button-quote div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00d'); -} -.sceditor-button-print div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00e'); -} -.sceditor-button-pastetext div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e00f'); -} -.sceditor-button-paste div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e010'); -} -.sceditor-button-orderedlist div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e011'); -} -.sceditor-button-maximize div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e012'); -} -.sceditor-button-ltr div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e013'); -} -.sceditor-button-link div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e014'); -} -.sceditor-button-left div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e015'); -} -.sceditor-button-justify div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e016'); -} -.sceditor-button-italic div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e017'); -} -.sceditor-button-image div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e018'); -} -.sceditor-button-horizontalrule div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e019'); -} -.sceditor-button-format div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01c'); -} -.sceditor-button-font div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01d'); -} -.sceditor-button-emoticon div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01e'); -} -.sceditor-button-email div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01f'); -} -.sceditor-button-bold div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e020'); -} -.sceditor-button-date div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e021'); -} -.sceditor-button-cut div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e022'); -} -.sceditor-button-copy div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e023'); -} -.sceditor-button-color div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e024'); -} -.sceditor-button-code div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e025'); -} -.sceditor-button-center div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e026'); -} -.sceditor-button-bulletlist div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e027'); -} -div.sceditor-grip { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01b'); -} -.rtl div.sceditor-grip { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e01a'); -} -.sceditor-button-youtube div:before { - content: "\e000"; -} -.sceditor-button-unlink div:before { - content: "\e001"; -} -.sceditor-button-underline div:before { - content: "\e002"; -} -.sceditor-button-time div:before { - content: "\e003"; -} -.sceditor-button-table div:before { - content: "\e004"; -} -.sceditor-button-superscript div:before { - content: "\e005"; -} -.sceditor-button-subscript div:before { - content: "\e006"; -} -.sceditor-button-strike div:before { - content: "\e007"; -} -.sceditor-button-source div:before { - content: "\e008"; -} -.sceditor-button-size div:before { - content: "\e009"; -} -.sceditor-button-rtl div:before { - content: "\e00a"; -} -.sceditor-button-right div:before { - content: "\e00b"; -} -.sceditor-button-removeformat div:before { - content: "\e00c"; -} -.sceditor-button-quote div:before { - content: "\e00d"; -} -.sceditor-button-print div:before { - content: "\e00e"; -} -.sceditor-button-pastetext div:before { - content: "\e00f"; -} -.sceditor-button-paste div:before { - content: "\e010"; -} -.sceditor-button-orderedlist div:before { - content: "\e011"; -} -.sceditor-button-maximize div:before { - content: "\e012"; -} -.sceditor-button-ltr div:before { - content: "\e013"; -} -.sceditor-button-link div:before { - content: "\e014"; -} -.sceditor-button-left div:before { - content: "\e015"; -} -.sceditor-button-justify div:before { - content: "\e016"; -} -.sceditor-button-italic div:before { - content: "\e017"; -} -.sceditor-button-image div:before { - content: "\e018"; -} -.sceditor-button-horizontalrule div:before { - content: "\e019"; -} -.sceditor-button-format div:before { - content: "\e01c"; -} -.sceditor-button-font div:before { - content: "\e01d"; -} -.sceditor-button-emoticon div:before { - content: "\e01e"; -} -.sceditor-button-email div:before { - content: "\e01f"; -} -.sceditor-button-bold div:before { - content: "\e020"; -} -.sceditor-button-date div:before { - content: "\e021"; -} -.sceditor-button-cut div:before { - content: "\e022"; -} -.sceditor-button-copy div:before { - content: "\e023"; -} -.sceditor-button-color div:before { - content: "\e024"; -} -.sceditor-button-code div:before { - content: "\e025"; -} -.sceditor-button-center div:before { - content: "\e026"; -} -.sceditor-button-bulletlist div:before { - content: "\e027"; -} -div.sceditor-grip:before { - content: "\e01b"; -} -.rtl div.sceditor-grip:before { - content: "\e01a"; -} -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -/*--------------------------------------------------- - LESS Elements 0.7 - --------------------------------------------------- - A set of useful LESS mixins - More info at: http://lesselements.com - ---------------------------------------------------*/ -.sceditor-container { - position: relative; - background: #fff; - border: 1px solid #d9d9d9; - font-size: 13px; - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - color: #222; - line-height: 1; - font-weight: bold; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 100% !important; -} -.sceditor-container, -.sceditor-container div, -div.sceditor-dropdown, -div.sceditor-dropdown div { - padding: 0; - margin: 0; - z-index: 3; -} -.sceditor-container iframe, -.sceditor-container textarea { - line-height: 1; - border: 0; - outline: none; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 13px; - color: #111; - padding: 0; - margin: 5px; - resize: none; - background: #fff; - display: block; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 99% !important; -} -div.sceditor-resize-cover { - position: absolute; - top: 0; - left: 0; - background: #000; - width: 100%; - height: 100%; - z-index: 10; - opacity: 0.3; -} -.ie6 div.sceditor-resize-cover, -.ie7 div.sceditor-resize-cover, -.ie8 div.sceditor-resize-cover { - background: #efefef; -} -.sceditor-container.ie6 { - overflow: hidden; -} -div.sceditor-grip { - overflow: hidden; - width: 10px; - height: 10px; - cursor: pointer; - position: absolute; - bottom: 0; - right: 0; - z-index: 3; -} -.sceditor-maximize { - position: fixed; - top: 0; - left: 0; - height: 100% !important; - width: 100% !important; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - z-index: 2000; -} -html.sceditor-maximize, -body.sceditor-maximize { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - overflow: hidden; -} -.ie6.sceditor-maximize { - position: absolute; -} -.sceditor-maximize div.sceditor-grip { - display: none; -} -.sceditor-maximize div.sceditor-toolbar { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -/** - * Dropdown styleing - */ -div.sceditor-dropdown { - position: absolute; - border: 1px solid #ccc; - background: #fff; - color: #333; - z-index: 4000; - padding: 10px; - line-height: 1; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); -} -div.sceditor-dropdown a, -div.sceditor-dropdown a:link { - color: #333; -} -div.sceditor-dropdown form { - margin: 0; -} -div.sceditor-dropdown label { - display: block; - font-weight: bold; - color: #3c3c3c; - padding: 4px 0; -} -div.sceditor-dropdown input, -div.sceditor-dropdown textarea { - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - outline: 0; - padding: 4px; - border: 1px solid #ccc; - border-top-color: #888; - margin: 0 0 .75em; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-dropdown textarea { - padding: 6px; -} -div.sceditor-dropdown input:focus, -div.sceditor-dropdown textarea:focus { - border-color: #aaa; - border-top-color: #666; - -webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); -} -div.sceditor-dropdown .button { - font-weight: bold; - color: #444; - padding: 6px 12px; - background: #ececec; - border: solid 1px #ccc; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - cursor: pointer; - margin: .3em 0 0; -} -div.sceditor-dropdown .button:hover { - background: #f3f3f3; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); -} -div.sceditor-font-picker, -div.sceditor-fontsize-picker, -div.sceditor-format { - padding: 6px 0; -} -div.sceditor-emoticons, -div.sceditor-more-emoticons, -div.sceditor-color-picker { - padding: 0; -} -.sceditor-pastetext textarea { - border: 1px solid #bbb; - width: 20em; -} -.sceditor-emoticons img, -.sceditor-more-emoticons img { - padding: 0; - cursor: pointer; - margin: 2px; -} -.sceditor-more { - border-top: 1px solid #bbb; - display: block; - text-align: center; - cursor: pointer; - font-weight: bold; - padding: 6px 0; -} -.sceditor-dropdown a:hover { - background: #eee; -} -.sceditor-fontsize-option, -.sceditor-font-option, -.sceditor-format a { - display: block; - padding: 7px 10px; - cursor: pointer; - text-decoration: none; - color: #222; -} -.sceditor-fontsize-option { - padding: 7px 13px; -} -.sceditor-color-column { - float: left; -} -.sceditor-color-option { - display: block; - border: 1px solid #fff; - height: 10px; - width: 10px; - overflow: hidden; -} -.sceditor-color-option:hover { - border: 1px solid #333; -} -/** - * Toolbar styleing - */ -div.sceditor-toolbar { - overflow: hidden; - padding: 3px 5px 2px; - background: #f7f7f7; - border-bottom: 1px solid #c0c0c0; - line-height: 0; - text-align: left; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-group { - display: inline-block; - background: #ddd; - margin: 1px 5px 1px 0; - padding: 1px; - border-bottom: 1px solid #aaa; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.ie6 div.sceditor-group, -.ie7 div.sceditor-group { - display: inline; - zoom: 1; -} -.sceditor-button { - float: left; - cursor: pointer; - padding: 3px 5px; - width: 16px; - height: 20px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - /* Needed for Safari 5? */ - - text-indent: -9999px; -} -.ie .sceditor-button { - text-indent: 0; -} -.ie6 .sceditor-button, -.ie7 .sceditor-button { - float: none !important; - display: inline; - zoom: 1; -} -.ie6 .sceditor-button { - padding: 0; -} -.ie6 .sceditor-button div { - margin: 5px; -} -.ie7 .sceditor-button div { - margin: 5px 0; -} -.sceditor-button:hover, -.sceditor-button:active, -.sceditor-button.active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); -} -.sceditor-button:active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); -} -.sceditor-button.disabled:hover { - background: inherit; - cursor: default; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.sceditor-button, -.sceditor-button div { - display: block; -} -.sceditor-button div { - margin: 2px 0; - padding: 0; - overflow: hidden; - line-height: 0; - font-size: 0; - color: transparent; -} -.sceditor-button.disabled div { - filter: alpha(opacity=30); - opacity: 0.3; -} -.text .sceditor-button, -.text .sceditor-button div, -.sceditor-button.text, -.sceditor-button.text div, -.text-icon .sceditor-button, -.text-icon .sceditor-button div, -.sceditor-button.text-icon, -.sceditor-button.text-icon div { - width: auto; - overflow: visible; - line-height: 16px; - font-size: 1em; - color: inherit; - text-indent: 0; -} -.text .sceditor-button div, -.sceditor-button.text div { - padding: 0 2px; - background: none; -} -.text-icon .sceditor-button div, -.sceditor-button.text-icon div { - padding: 0 2px 0 20px; -} -.rtl div.sceditor-toolbar { - text-align: right; -} -.rtl .sceditor-button { - float: right; -} -.rtl div.sceditor-grip { - right: auto; - left: 0; -} -.ie7 .sceditor-button div, -.ie6 .sceditor-button div { - font-family: 'Monocons'; - overflow: visible; - font-size: 16px; - line-height: 1; - text-indent: 0; -} -div.sceditor-grip { - height: 16px; - width: 16px; -} -.sceditor-button div:before, -div.sceditor-grip:before { - text-indent: 0; - line-height: 17px; - width: 16px; - height: 16px; - display: block; - color: #333; - text-shadow: 0 1px #fff; -} - -/* Additonal buttons (for MyBB) */ -.sceditor-button-video div { - *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '\e000'); -} - -.sceditor-button-video div:before { - content: "\e000"; -} - -.sceditor-button-php div { - *zoom: expression(this.runtimeStyle['zoom'] = '0', this.innerHTML = '\24C5'); -} - -.sceditor-button-php div:before { - content: "\24C5"; - font-size: 17px; - line-height: 0.85; -} - -.sceditor-button-php:hover { - text-decoration: none; -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/monocons/monocons.eot b/html/forums/jscripts/sceditor/editor_themes/monocons/monocons.eot deleted file mode 100644 index 1db6547..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/monocons/monocons.eot and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/monocons/monocons.ttf b/html/forums/jscripts/sceditor/editor_themes/monocons/monocons.ttf deleted file mode 100644 index d100abd..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/monocons/monocons.ttf and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/mybb.css b/html/forums/jscripts/sceditor/editor_themes/mybb.css deleted file mode 100644 index e6c5f23..0000000 --- a/html/forums/jscripts/sceditor/editor_themes/mybb.css +++ /dev/null @@ -1,585 +0,0 @@ -html { - font-family: Tahoma, Verdana, Arial, Sans-Serif; - font-size: 0.9em; -} - -.sceditor-button div, div.sceditor-grip { - background-image: url(famfamfam.png); - width: 16px; - height: 16px; - background-repeat: no-repeat; -} -.sceditor-button-youtube div { - - background-position: 0px 0px; - -} -.sceditor-button-link div { - - background-position: 0px -16px; - -} -.sceditor-button-unlink div { - - background-position: 0px -32px; - -} -.sceditor-button-underline div { - - background-position: 0px -48px; - -} -.sceditor-button-time div { - - background-position: 0px -64px; - -} -.sceditor-button-table div { - - background-position: 0px -80px; - -} -.sceditor-button-superscript div { - - background-position: 0px -96px; - -} -.sceditor-button-subscript div { - - background-position: 0px -112px; - -} -.sceditor-button-strike div { - - background-position: 0px -128px; - -} -.sceditor-button-source div { - - background-position: 0px -144px; - -} -.sceditor-button-size div { - - background-position: 0px -160px; - -} -.sceditor-button-rtl div { - - background-position: 0px -176px; - -} -.sceditor-button-right div { - - background-position: 0px -192px; - -} -.sceditor-button-removeformat div { - - background-position: 0px -208px; - -} -.sceditor-button-quote div { - - background-position: 0px -224px; - -} -.sceditor-button-print div { - - background-position: 0px -240px; - -} -.sceditor-button-pastetext div { - - background-position: 0px -256px; - -} -.sceditor-button-paste div { - - background-position: 0px -272px; - -} -.sceditor-button-orderedlist div { - - background-position: 0px -288px; - -} -.sceditor-button-maximize div { - - background-position: 0px -304px; - -} -.sceditor-button-ltr div { - - background-position: 0px -320px; - -} -.sceditor-button-left div { - - background-position: 0px -336px; - -} -.sceditor-button-justify div { - - background-position: 0px -352px; - -} -.sceditor-button-italic div { - - background-position: 0px -368px; - -} -.sceditor-button-image div { - - background-position: 0px -384px; - -} -.sceditor-button-horizontalrule div { - - background-position: 0px -400px; - -} -.sceditor-button-format div { - - background-position: 0px -416px; - -} -.sceditor-button-font div { - - background-position: 0px -432px; - -} -.sceditor-button-emoticon div { - - background-position: 0px -448px; - -} -.sceditor-emoticons img { - cursor: pointer; -} -.sceditor-button-email div { - - background-position: 0px -464px; - -} -.sceditor-button-date div { - - background-position: 0px -480px; - -} -.sceditor-button-cut div { - - background-position: 0px -496px; - -} -.sceditor-button-copy div { - - background-position: 0px -512px; - -} -.sceditor-button-color div { - - background-position: 0px -528px; - -} -.sceditor-button-code div { - - background-position: 0px -544px; - -} -.sceditor-button-center div { - - background-position: 0px -560px; - -} -.sceditor-button-bulletlist div { - - background-position: 0px -576px; - -} -.sceditor-button-bold div { - - background-position: 0px -592px; - -} -div.sceditor-grip { - - background-position: 0px -608px; - - width: 10px; - - height: 10px; - -} -.rtl div.sceditor-grip { - - background-position: 0px -618px; - - width: 10px; - - height: 10px; - -} -.sceditor-container { - position: relative; - background: #fff; - border: 1px solid #d9d9d9; - padding: 0 4px; - font-size: 13px; - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - color: #222; - line-height: 1; - font-weight: bold; - z-index: 1001; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 100% !important; -} -.sceditor-container, .sceditor-container div, div.sceditor-dropdown, div.sceditor-dropdown div { - padding: 0; - margin: 0; - z-index: 3; -} -.sceditor-container iframe, .sceditor-container textarea { - border: 0; - outline: 0; - font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif; - font-size: 13px; - color: #111; - padding: 4px; - margin: 5px; - resize: none; - background: #fff; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 99% !important; -} -div.sceditor-resize-cover { - position: absolute; - top: 0; - left: 0; - background: #000; - width: 100%; - height: 100%; - z-index: 2; - opacity: .3; -} -.ie6 div.sceditor-resize-cover, .ie7 div.sceditor-resize-cover, .ie8 div.sceditor-resize-cover { - background: #efefef; -} -.sceditor-container.ie6 { - overflow: hidden; -} -div.sceditor-grip { - overflow: hidden; - width: 10px; - height: 10px; - cursor: pointer; - position: absolute; - bottom: 0; - right: 0; - z-index: 3; -} -.sceditor-maximize { - position: fixed; - top: 0; - left: 0; - height: 100%!important; - width: 100%!important; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -html.sceditor-maximize, body.sceditor-maximize { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - overflow: hidden; -} -.ie6.sceditor-maximize { - position: absolute; -} -.sceditor-maximize div.sceditor-grip { - display: none; -} -.sceditor-maximize div.sceditor-toolbar { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-dropdown { - position: absolute; - border: 1px solid #ccc; - background: #fff; - color: #333; - z-index: 6; - padding: 10px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); -} -div.sceditor-dropdown a, div.sceditor-dropdown a:link { - color: #333; -} -div.sceditor-dropdown form { - margin: 0; -} -div.sceditor-dropdown label { - display: block; - font-weight: bold; - color: #3c3c3c; - padding: 4px 0; -} -div.sceditor-dropdown input, div.sceditor-dropdown textarea { - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - outline: 0; - padding: 4px; - border: 1px solid #ccc; - border-top-color: #888; - margin: 0 0 .75em; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-dropdown textarea { - padding: 6px; -} -div.sceditor-dropdown input:focus, div.sceditor-dropdown textarea:focus { - border-color: #aaa; - border-top-color: #666; - -webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); -} -div.sceditor-dropdown .button { - font-weight: bold; - color: #444; - padding: 6px 12px; - background: #ececec; - border: solid 1px #ccc; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - cursor: pointer; - margin: .3em 0 0; -} -div.sceditor-dropdown .button:hover { - background: #f3f3f3; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); -} -div.sceditor-font-picker, div.sceditor-fontsize-picker { - padding: 6px 0; -} -div.sceditor-insertemoticon, div.sceditor-color-picker { - padding: 0; -} -.sceditor-pastetext textarea { - border: 1px solid #bbb; - width: 20em; -} -.sceditor-insertemoticon img, .sceditor-more-emoticons img { - cursor: pointer; - margin: 2px; -} -.sceditor-more { - border-top: 1px solid #bbb; - display: block; - text-align: center; - cursor: pointer; - font-weight: bold; - padding: 6px 0; -} -.sceditor-more:hover { - background: #eee; -} -.sceditor-fontsize-option, .sceditor-font-option { - display: block; - padding: 4px 10px; - cursor: pointer; - text-decoration: none; - color: #222; -} -.sceditor-fontsize-option { - padding: 4px 13px; -} -.sceditor-fontsize-option:hover, .sceditor-font-option:hover { - background: #eee; -} -.sceditor-color-column { - float: left; -} -.sceditor-color-option { - display: block; - border: 1px solid #fff; - height: 10px; - width: 10px; - overflow: hidden; -} -.sceditor-color-option:hover { - border: 1px solid #333; -} -div.sceditor-toolbar { - overflow: hidden; - padding: 2px 2px 1px; - background: #f7f7f7; - border-bottom: 1px solid #c0c0c0; - line-height: 0; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-group { - display: inline-block; - background: #eee; - margin: 1px 5px 1px 0; - padding: 1px; - border-bottom: 1px solid #ccc; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.ie6 div.sceditor-group, .ie7 div.sceditor-group { - display: inline; - zoom: 1; -} -.sceditor-button { - float: left; - cursor: pointer; - padding: 3px 5px; - width: 16px; - height: 20px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - border: 1px solid #eee; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.ie6 .sceditor-button, .ie7 .sceditor-button { - float: none!important; - display: inline; - zoom: 1; -} -.ie6 .sceditor-button { - padding: 0; -} -.ie6 .sceditor-button div { - margin: 5px; -} -.ie7 .sceditor-button div { - margin: 5px 0; -} -.sceditor-button:hover, .sceditor-button:active, .sceditor-button.active { - background: #fff; - /*-webkit-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.3), inset -1px 0 rgba(0, 0, 0, 0.3), inset 0 -1px 0 rgba(0, 0, 0, 0.2); - -moz-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.3), inset -1px 0 rgba(0, 0, 0, 0.3), inset 0 -1px 0 rgba(0, 0, 0, 0.2); - box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.3), inset -1px 0 rgba(0, 0, 0, 0.3), inset 0 -1px 0 rgba(0, 0, 0, 0.2)*/border: 1px solid #ddd; -} -.sceditor-button:active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.3), inset -1px 0 rgba(0, 0, 0, 0.3), inset 0 -1px 0 rgba(0, 0, 0, 0.2), inset 0 0 8px rgba(0, 0, 0, 0.3); - -moz-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.3), inset -1px 0 rgba(0, 0, 0, 0.3), inset 0 -1px 0 rgba(0, 0, 0, 0.2), inset 0 0 8px rgba(0, 0, 0, 0.3); - box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.3), inset -1px 0 rgba(0, 0, 0, 0.3), inset 0 -1px 0 rgba(0, 0, 0, 0.2), inset 0 0 8px rgba(0, 0, 0, 0.3); -} -.sceditor-button.disabled:hover { - background: inherit; - cursor: default; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.sceditor-button, .sceditor-button div { - display: block; -} -.sceditor-button div { - margin: 2px 0; - padding: 0; - overflow: hidden; - line-height: 0; - font-size: 0; - color: transparent; -} -.sceditor-button.disabled div { - filter: alpha(opacity=30); - opacity: .3; -} -.text .sceditor-button, .text .sceditor-button div, .sceditor-button.text, .sceditor-button.text div, .text-icon .sceditor-button, .text-icon .sceditor-button div, .sceditor-button.text-icon, .sceditor-button.text-icon div { - width: auto; - overflow: visible; - line-height: 16px; - font-size: 1em; - color: inherit; -} -.text .sceditor-button div, .sceditor-button.text div { - padding: 0 2px; - background: 0; -} -.text-icon .sceditor-button div, .sceditor-button.text-icon div { - padding: 0 2px 0 20px; -} -.rtl .sceditor-button { - float: right; -} -.rtl div.sceditor-grip { - right: auto; - left: 0; -} -.sceditor-container { - padding: 0 4px; - overflow: hidden; -} -.sceditor-container .sceditor-toolbar, .sceditor-container iframe, .sceditor-container textarea { - margin: 0 -4px; -} - -/* Additional buttons (for MyBB) */ -.sceditor-button-video div { - - background-image: url(video.png); - -} -.sceditor-button-php div { - - background-image: url(php.png); - -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/office-toolbar.css b/html/forums/jscripts/sceditor/editor_themes/office-toolbar.css deleted file mode 100644 index 5abf97f..0000000 --- a/html/forums/jscripts/sceditor/editor_themes/office-toolbar.css +++ /dev/null @@ -1,705 +0,0 @@ -/** - * Copyright (C) 2012, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * Icons by Mark James (http://www.famfamfam.com/lab/icons/silk/) - * Licensed under the Creative Commons CC-BY license (http://creativecommons.org/licenses/by/3.0/) - */ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -div.sceditor-grip, -.sceditor-button div { - background-image: url('famfamfam.png'); - background-repeat: no-repeat; - width: 16px; - height: 16px; -} -.sceditor-button-youtube div { - background-position: 0px 0px; -} -.sceditor-button-link div { - background-position: 0px -16px; -} -.sceditor-button-unlink div { - background-position: 0px -32px; -} -.sceditor-button-underline div { - background-position: 0px -48px; -} -.sceditor-button-time div { - background-position: 0px -64px; -} -.sceditor-button-table div { - background-position: 0px -80px; -} -.sceditor-button-superscript div { - background-position: 0px -96px; -} -.sceditor-button-subscript div { - background-position: 0px -112px; -} -.sceditor-button-strike div { - background-position: 0px -128px; -} -.sceditor-button-source div { - background-position: 0px -144px; -} -.sceditor-button-size div { - background-position: 0px -160px; -} -.sceditor-button-rtl div { - background-position: 0px -176px; -} -.sceditor-button-right div { - background-position: 0px -192px; -} -.sceditor-button-removeformat div { - background-position: 0px -208px; -} -.sceditor-button-quote div { - background-position: 0px -224px; -} -.sceditor-button-print div { - background-position: 0px -240px; -} -.sceditor-button-pastetext div { - background-position: 0px -256px; -} -.sceditor-button-paste div { - background-position: 0px -272px; -} -.sceditor-button-orderedlist div { - background-position: 0px -288px; -} -.sceditor-button-maximize div { - background-position: 0px -304px; -} -.sceditor-button-ltr div { - background-position: 0px -320px; -} -.sceditor-button-left div { - background-position: 0px -336px; -} -.sceditor-button-justify div { - background-position: 0px -352px; -} -.sceditor-button-italic div { - background-position: 0px -368px; -} -.sceditor-button-image div { - background-position: 0px -384px; -} -.sceditor-button-horizontalrule div { - background-position: 0px -400px; -} -.sceditor-button-format div { - background-position: 0px -416px; -} -.sceditor-button-font div { - background-position: 0px -432px; -} -.sceditor-button-emoticon div { - background-position: 0px -448px; -} -.sceditor-button-email div { - background-position: 0px -464px; -} -.sceditor-button-date div { - background-position: 0px -480px; -} -.sceditor-button-cut div { - background-position: 0px -496px; -} -.sceditor-button-copy div { - background-position: 0px -512px; -} -.sceditor-button-color div { - background-position: 0px -528px; -} -.sceditor-button-code div { - background-position: 0px -544px; -} -.sceditor-button-center div { - background-position: 0px -560px; -} -.sceditor-button-bulletlist div { - background-position: 0px -576px; -} -.sceditor-button-bold div { - background-position: 0px -592px; -} -div.sceditor-grip { - background-position: 0px -608px; - width: 10px; - height: 10px; -} -.rtl div.sceditor-grip { - background-position: 0px -618px; - width: 10px; - height: 10px; -} -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -/*--------------------------------------------------- - LESS Elements 0.7 - --------------------------------------------------- - A set of useful LESS mixins - More info at: http://lesselements.com - ---------------------------------------------------*/ -.sceditor-container { - position: relative; - background: #fff; - border: 1px solid #d9d9d9; - font-size: 13px; - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - color: #222; - line-height: 1; - font-weight: bold; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 100% !important; -} -.sceditor-container, -.sceditor-container div, -div.sceditor-dropdown, -div.sceditor-dropdown div { - padding: 0; - margin: 0; - z-index: 3; -} -.sceditor-container iframe, -.sceditor-container textarea { - line-height: 1; - border: 0; - outline: none; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 13px; - color: #111; - padding: 0; - margin: 5px; - resize: none; - background: #fff; - display: block; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 99% !important; -} -div.sceditor-resize-cover { - position: absolute; - top: 0; - left: 0; - background: #000; - width: 100%; - height: 100%; - z-index: 10; - opacity: 0.3; -} -.ie6 div.sceditor-resize-cover, -.ie7 div.sceditor-resize-cover, -.ie8 div.sceditor-resize-cover { - background: #efefef; -} -.sceditor-container.ie6 { - overflow: hidden; -} -div.sceditor-grip { - overflow: hidden; - width: 10px; - height: 10px; - cursor: pointer; - position: absolute; - bottom: 0; - right: 0; - z-index: 3; -} -.sceditor-maximize { - position: fixed; - top: 0; - left: 0; - height: 100% !important; - width: 100% !important; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - z-index: 2000; -} -html.sceditor-maximize, -body.sceditor-maximize { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - overflow: hidden; -} -.ie6.sceditor-maximize { - position: absolute; -} -.sceditor-maximize div.sceditor-grip { - display: none; -} -.sceditor-maximize div.sceditor-toolbar { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -/** - * Dropdown styleing - */ -div.sceditor-dropdown { - position: absolute; - border: 1px solid #ccc; - background: #fff; - color: #333; - z-index: 4000; - padding: 10px; - line-height: 1; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); -} -div.sceditor-dropdown a, -div.sceditor-dropdown a:link { - color: #333; -} -div.sceditor-dropdown form { - margin: 0; -} -div.sceditor-dropdown label { - display: block; - font-weight: bold; - color: #3c3c3c; - padding: 4px 0; -} -div.sceditor-dropdown input, -div.sceditor-dropdown textarea { - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - outline: 0; - padding: 4px; - border: 1px solid #ccc; - border-top-color: #888; - margin: 0 0 .75em; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-dropdown textarea { - padding: 6px; -} -div.sceditor-dropdown input:focus, -div.sceditor-dropdown textarea:focus { - border-color: #aaa; - border-top-color: #666; - -webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); -} -div.sceditor-dropdown .button { - font-weight: bold; - color: #444; - padding: 6px 12px; - background: #ececec; - border: solid 1px #ccc; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - cursor: pointer; - margin: .3em 0 0; -} -div.sceditor-dropdown .button:hover { - background: #f3f3f3; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); -} -div.sceditor-font-picker, -div.sceditor-fontsize-picker, -div.sceditor-format { - padding: 6px 0; -} -div.sceditor-emoticons, -div.sceditor-more-emoticons, -div.sceditor-color-picker { - padding: 0; -} -.sceditor-pastetext textarea { - border: 1px solid #bbb; - width: 20em; -} -.sceditor-emoticons img, -.sceditor-more-emoticons img { - padding: 0; - cursor: pointer; - margin: 2px; -} -.sceditor-more { - border-top: 1px solid #bbb; - display: block; - text-align: center; - cursor: pointer; - font-weight: bold; - padding: 6px 0; -} -.sceditor-dropdown a:hover { - background: #eee; -} -.sceditor-fontsize-option, -.sceditor-font-option, -.sceditor-format a { - display: block; - padding: 7px 10px; - cursor: pointer; - text-decoration: none; - color: #222; -} -.sceditor-fontsize-option { - padding: 7px 13px; -} -.sceditor-color-column { - float: left; -} -.sceditor-color-option { - display: block; - border: 1px solid #fff; - height: 10px; - width: 10px; - overflow: hidden; -} -.sceditor-color-option:hover { - border: 1px solid #333; -} -/** - * Toolbar styleing - */ -div.sceditor-toolbar { - overflow: hidden; - padding: 3px 5px 2px; - background: #f7f7f7; - border-bottom: 1px solid #c0c0c0; - line-height: 0; - text-align: left; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-group { - display: inline-block; - background: #ddd; - margin: 1px 5px 1px 0; - padding: 1px; - border-bottom: 1px solid #aaa; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.ie6 div.sceditor-group, -.ie7 div.sceditor-group { - display: inline; - zoom: 1; -} -.sceditor-button { - float: left; - cursor: pointer; - padding: 3px 5px; - width: 16px; - height: 20px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - /* Needed for Safari 5? */ - - text-indent: -9999px; -} -.ie .sceditor-button { - text-indent: 0; -} -.ie6 .sceditor-button, -.ie7 .sceditor-button { - float: none !important; - display: inline; - zoom: 1; -} -.ie6 .sceditor-button { - padding: 0; -} -.ie6 .sceditor-button div { - margin: 5px; -} -.ie7 .sceditor-button div { - margin: 5px 0; -} -.sceditor-button:hover, -.sceditor-button:active, -.sceditor-button.active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); -} -.sceditor-button:active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); -} -.sceditor-button.disabled:hover { - background: inherit; - cursor: default; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.sceditor-button, -.sceditor-button div { - display: block; -} -.sceditor-button div { - margin: 2px 0; - padding: 0; - overflow: hidden; - line-height: 0; - font-size: 0; - color: transparent; -} -.sceditor-button.disabled div { - filter: alpha(opacity=30); - opacity: 0.3; -} -.text .sceditor-button, -.text .sceditor-button div, -.sceditor-button.text, -.sceditor-button.text div, -.text-icon .sceditor-button, -.text-icon .sceditor-button div, -.sceditor-button.text-icon, -.sceditor-button.text-icon div { - width: auto; - overflow: visible; - line-height: 16px; - font-size: 1em; - color: inherit; - text-indent: 0; -} -.text .sceditor-button div, -.sceditor-button.text div { - padding: 0 2px; - background: none; -} -.text-icon .sceditor-button div, -.sceditor-button.text-icon div { - padding: 0 2px 0 20px; -} -.rtl div.sceditor-toolbar { - text-align: right; -} -.rtl .sceditor-button { - float: right; -} -.rtl div.sceditor-grip { - right: auto; - left: 0; -} -.sceditor-container { - border: 1px solid #8db2e3; -} -.sceditor-container textarea { - font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace; -} -div.sceditor-toolbar { - border-bottom: 1px solid #95a9c3; - background: #dee8f5; - background: -moz-linear-gradient(top, #dee8f5 0%, #c7d8ed 29%, #ccdcee 61%, #c0d8ef 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dee8f5), color-stop(29%, #c7d8ed), color-stop(61%, #ccdcee), color-stop(100%, #c0d8ef)); - background: -webkit-linear-gradient(top, #dee8f5 0%, #c7d8ed 29%, #ccdcee 61%, #c0d8ef 100%); - background: -o-linear-gradient(top, #dee8f5 0%, #c7d8ed 29%, #ccdcee 61%, #c0d8ef 100%); - background: -ms-linear-gradient(top, #dee8f5 0%, #c7d8ed 29%, #ccdcee 61%, #c0d8ef 100%); - background: linear-gradient(to bottom, #dee8f5 0%, #c7d8ed 29%, #ccdcee 61%, #c0d8ef 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dee8f5', endColorstr='#c0d8ef', GradientType=0); -} -.ie9 div.sceditor-toolbar { - filter: none; - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RlZThmNSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjI5JSIgc3RvcC1jb2xvcj0iI2M3ZDhlZCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjYxJSIgc3RvcC1jb2xvcj0iI2NjZGNlZSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNjMGQ4ZWYiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); -} -div.sceditor-group { - border: 1px solid #7596bf; - background: transparent; - padding: 0; - background: #cadcf0; - background: -moz-linear-gradient(top, #cadcf0 24%, #bcd0e9 38%, #d0e1f7 99%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(24%, #cadcf0), color-stop(38%, #bcd0e9), color-stop(99%, #d0e1f7)); - background: -webkit-linear-gradient(top, #cadcf0 24%, #bcd0e9 38%, #d0e1f7 99%); - background: -o-linear-gradient(top, #cadcf0 24%, #bcd0e9 38%, #d0e1f7 99%); - background: -ms-linear-gradient(top, #cadcf0 24%, #bcd0e9 38%, #d0e1f7 99%); - background: linear-gradient(to bottom, #cadcf0 24%, #bcd0e9 38%, #d0e1f7 99%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cadcf0', endColorstr='#d0e1f7', GradientType=0); -} -.ie9 div.sceditor-group { - filter: none; - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIyNCUiIHN0b3AtY29sb3I9IiNjYWRjZjAiIHN0b3Atb3BhY2l0eT0iMSIvPgogICAgPHN0b3Agb2Zmc2V0PSIzOCUiIHN0b3AtY29sb3I9IiNiY2QwZTkiIHN0b3Atb3BhY2l0eT0iMSIvPgogICAgPHN0b3Agb2Zmc2V0PSI5OSUiIHN0b3AtY29sb3I9IiNkMGUxZjciIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); -} -.sceditor-button { - height: 16px; - padding: 3px 4px; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-shadow: inset 0 1px #d5e3f1, inset 0 -1px #e3edfb, inset 1px 0 #cddcef, inset -1px 0 #b8ceea; - -moz-box-shadow: inset 0 1px #d5e3f1, inset 0 -1px #e3edfb, inset 1px 0 #cddcef, inset -1px 0 #b8ceea; - box-shadow: inset 0 1px #d5e3f1, inset 0 -1px #e3edfb, inset 1px 0 #cddcef, inset -1px 0 #b8ceea; -} -.sceditor-button:first-child { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.sceditor-button:last-child { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.sceditor-button div { - margin: 0; -} -.ie9 .sceditor-button { - filter: none !important; -} -.sceditor-button.active { - background: #fbdbb5; - background: -moz-linear-gradient(top, #fbdbb5 11%, #feb456 29%, #fdeb9f 99%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(11%, #fbdbb5), color-stop(29%, #feb456), color-stop(99%, #fdeb9f)); - background: -webkit-linear-gradient(top, #fbdbb5 11%, #feb456 29%, #fdeb9f 99%); - background: -o-linear-gradient(top, #fbdbb5 11%, #feb456 29%, #fdeb9f 99%); - background: -ms-linear-gradient(top, #fbdbb5 11%, #feb456 29%, #fdeb9f 99%); - background: linear-gradient(top, #fbdbb5 11%, #feb456 29%, #fdeb9f 99%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbdbb5', endColorstr='#fdeb9f', GradientType=0); - -webkit-box-shadow: inset 0 1px #ebd1b4, inset 0 -1px #ffe47f, inset -1px 0 #b8ceea; - -moz-box-shadow: inset 0 1px #ebd1b4, inset 0 -1px #ffe47f, inset -1px 0 #b8ceea; - box-shadow: inset 0 1px #ebd1b4, inset 0 -1px #ffe47f, inset -1px 0 #b8ceea; -} -.ie9 .sceditor-button.active { - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIxMSUiIHN0b3AtY29sb3I9IiNmYmRiYjUiIHN0b3Atb3BhY2l0eT0iMSIvPgogICAgPHN0b3Agb2Zmc2V0PSIyOSUiIHN0b3AtY29sb3I9IiNmZWI0NTYiIHN0b3Atb3BhY2l0eT0iMSIvPgogICAgPHN0b3Agb2Zmc2V0PSI5OSUiIHN0b3AtY29sb3I9IiNmZGZkOWYiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); -} -.sceditor-button:hover { - background: #fef7d5; - background: -moz-linear-gradient(top, #fef7d5 0%, #fae5a9 42%, #ffd048 42%, #ffe59f 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fef7d5), color-stop(42%, #fae5a9), color-stop(42%, #ffd048), color-stop(100%, #ffe59f)); - background: -webkit-linear-gradient(top, #fef7d5 0%, #fae5a9 42%, #ffd048 42%, #ffe59f 100%); - background: -o-linear-gradient(top, #fef7d5 0%, #fae5a9 42%, #ffd048 42%, #ffe59f 100%); - background: -ms-linear-gradient(top, #fef7d5 0%, #fae5a9 42%, #ffd048 42%, #ffe59f 100%); - background: linear-gradient(to bottom, #fef7d5 0%, #fae5a9 42%, #ffd048 42%, #ffe59f 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fef7d5', endColorstr='#ffe59f', GradientType=0); - -webkit-box-shadow: inset 0 1px #fffbe8, inset -1px 0 #ffefc4, inset 0 -1px #fff9cc; - -moz-box-shadow: inset 0 1px #fffbe8, inset -1px 0 #ffefc4, inset 0 -1px #fff9cc; - box-shadow: inset 0 1px #fffbe8, inset -1px 0 #ffefc4, inset 0 -1px #fff9cc; -} -.ie9 .sceditor-button:hover { - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZlZjdkNSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjQyJSIgc3RvcC1jb2xvcj0iI2ZhZTVhOSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjQyJSIgc3RvcC1jb2xvcj0iI2ZmZDA0OCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmU1OWYiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); -} -.sceditor-button:active { - background: #e7a66d; - background: -moz-linear-gradient(top, #e7a66d 0%, #fcb16d 1%, #ff8d05 42%, #ffc450 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #e7a66d), color-stop(1%, #fcb16d), color-stop(42%, #ff8d05), color-stop(100%, #ffc450)); - background: -webkit-linear-gradient(top, #e7a66d 0%, #fcb16d 1%, #ff8d05 42%, #ffc450 100%); - background: -o-linear-gradient(top, #e7a66d 0%, #fcb16d 1%, #ff8d05 42%, #ffc450 100%); - background: -ms-linear-gradient(top, #e7a66d 0%, #fcb16d 1%, #ff8d05 42%, #ffc450 100%); - background: linear-gradient(to bottom, #e7a66d 0%, #fcb16d 1%, #ff8d05 42%, #ffc450 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e7a66d', endColorstr='#ffc450', GradientType=0); - -webkit-box-shadow: inset 0 1px 1px #7b6645, inset 0 -1px #d19c33; - -moz-box-shadow: inset 0 1px 1px #7b6645, inset 0 -1px #d19c33; - box-shadow: inset 0 1px 1px #7b6645, inset 0 -1px #d19c33; -} -.ie9 .sceditor-button:active { - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2U3YTY2ZCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjElIiBzdG9wLWNvbG9yPSIjZmNiMTZkIiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iNDIlIiBzdG9wLWNvbG9yPSIjZmY4ZDA1IiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZmYzQ1MCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgPC9saW5lYXJHcmFkaWVudD4KICA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2dyYWQtdWNnZy1nZW5lcmF0ZWQpIiAvPgo8L3N2Zz4=); -} -.sceditor-button.active:hover { - background: #dba368; - background: -moz-linear-gradient(top, #dba368 0%, #ffbd79 4%, #fea335 34%, #ffc64c 66%, #fee069 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dba368), color-stop(4%, #ffbd79), color-stop(34%, #fea335), color-stop(66%, #ffc64c), color-stop(100%, #fee069)); - background: -webkit-linear-gradient(top, #dba368 0%, #ffbd79 4%, #fea335 34%, #ffc64c 66%, #fee069 100%); - background: -o-linear-gradient(top, #dba368 0%, #ffbd79 4%, #fea335 34%, #ffc64c 66%, #fee069 100%); - background: -ms-linear-gradient(top, #dba368 0%, #ffbd79 4%, #fea335 34%, #ffc64c 66%, #fee069 100%); - background: linear-gradient(to bottom, #dba368 0%, #ffbd79 4%, #fea335 34%, #ffc64c 66%, #fee069 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dba368', endColorstr='#fee069', GradientType=0); - -webkit-box-shadow: inset 0 1px 1px #9e8255, inset 0 -1px #fcce6b; - -moz-box-shadow: inset 0 1px 1px #9e8255, inset 0 -1px #fcce6b; - box-shadow: inset 0 1px 1px #9e8255, inset 0 -1px #fcce6b; -} -.ie9 .sceditor-button.active:hover { - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RiYTM2OCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjQlIiBzdG9wLWNvbG9yPSIjZmZiZDc5IiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iMzQlIiBzdG9wLWNvbG9yPSIjZmVhMzM1IiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iNjYlIiBzdG9wLWNvbG9yPSIjZmZjNjRjIiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZlZTA2OSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgPC9saW5lYXJHcmFkaWVudD4KICA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2dyYWQtdWNnZy1nZW5lcmF0ZWQpIiAvPgo8L3N2Zz4=); -} - -/* Additional buttons (for MyBB) */ -.sceditor-button-video div { - - background-image: url(video.png); - -} -.sceditor-button-php div { - - background-image: url(php.png); - -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/office.css b/html/forums/jscripts/sceditor/editor_themes/office.css deleted file mode 100644 index 1a79c41..0000000 --- a/html/forums/jscripts/sceditor/editor_themes/office.css +++ /dev/null @@ -1,734 +0,0 @@ -/** - * Copyright (C) 2012, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * Icons by Mark James (http://www.famfamfam.com/lab/icons/silk/) - * Licensed under the Creative Commons CC-BY license (http://creativecommons.org/licenses/by/3.0/) - */ -/** - * Copyright (C) 2012, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * Icons by Mark James (http://www.famfamfam.com/lab/icons/silk/) - * Licensed under the Creative Commons CC-BY license (http://creativecommons.org/licenses/by/3.0/) - */ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -div.sceditor-grip, -.sceditor-button div { - background-image: url('famfamfam.png'); - background-repeat: no-repeat; - width: 16px; - height: 16px; -} -.sceditor-button-youtube div { - background-position: 0px 0px; -} -.sceditor-button-link div { - background-position: 0px -16px; -} -.sceditor-button-unlink div { - background-position: 0px -32px; -} -.sceditor-button-underline div { - background-position: 0px -48px; -} -.sceditor-button-time div { - background-position: 0px -64px; -} -.sceditor-button-table div { - background-position: 0px -80px; -} -.sceditor-button-superscript div { - background-position: 0px -96px; -} -.sceditor-button-subscript div { - background-position: 0px -112px; -} -.sceditor-button-strike div { - background-position: 0px -128px; -} -.sceditor-button-source div { - background-position: 0px -144px; -} -.sceditor-button-size div { - background-position: 0px -160px; -} -.sceditor-button-rtl div { - background-position: 0px -176px; -} -.sceditor-button-right div { - background-position: 0px -192px; -} -.sceditor-button-removeformat div { - background-position: 0px -208px; -} -.sceditor-button-quote div { - background-position: 0px -224px; -} -.sceditor-button-print div { - background-position: 0px -240px; -} -.sceditor-button-pastetext div { - background-position: 0px -256px; -} -.sceditor-button-paste div { - background-position: 0px -272px; -} -.sceditor-button-orderedlist div { - background-position: 0px -288px; -} -.sceditor-button-maximize div { - background-position: 0px -304px; -} -.sceditor-button-ltr div { - background-position: 0px -320px; -} -.sceditor-button-left div { - background-position: 0px -336px; -} -.sceditor-button-justify div { - background-position: 0px -352px; -} -.sceditor-button-italic div { - background-position: 0px -368px; -} -.sceditor-button-image div { - background-position: 0px -384px; -} -.sceditor-button-horizontalrule div { - background-position: 0px -400px; -} -.sceditor-button-format div { - background-position: 0px -416px; -} -.sceditor-button-font div { - background-position: 0px -432px; -} -.sceditor-button-emoticon div { - background-position: 0px -448px; -} -.sceditor-button-email div { - background-position: 0px -464px; -} -.sceditor-button-date div { - background-position: 0px -480px; -} -.sceditor-button-cut div { - background-position: 0px -496px; -} -.sceditor-button-copy div { - background-position: 0px -512px; -} -.sceditor-button-color div { - background-position: 0px -528px; -} -.sceditor-button-code div { - background-position: 0px -544px; -} -.sceditor-button-center div { - background-position: 0px -560px; -} -.sceditor-button-bulletlist div { - background-position: 0px -576px; -} -.sceditor-button-bold div { - background-position: 0px -592px; -} -div.sceditor-grip { - background-position: 0px -608px; - width: 10px; - height: 10px; -} -.rtl div.sceditor-grip { - background-position: 0px -618px; - width: 10px; - height: 10px; -} -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -/*--------------------------------------------------- - LESS Elements 0.7 - --------------------------------------------------- - A set of useful LESS mixins - More info at: http://lesselements.com - ---------------------------------------------------*/ -.sceditor-container { - position: relative; - background: #fff; - border: 1px solid #d9d9d9; - font-size: 13px; - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - color: #222; - line-height: 1; - font-weight: bold; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 100% !important; -} -.sceditor-container, -.sceditor-container div, -div.sceditor-dropdown, -div.sceditor-dropdown div { - padding: 0; - margin: 0; - z-index: 3; -} -.sceditor-container iframe, -.sceditor-container textarea { - line-height: 1; - border: 0; - outline: none; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 13px; - color: #111; - padding: 0; - margin: 5px; - resize: none; - background: #fff; - display: block; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 90% !important; -} -div.sceditor-resize-cover { - position: absolute; - top: 0; - left: 0; - background: #000; - width: 100%; - height: 100%; - z-index: 10; - opacity: 0.3; -} -.ie6 div.sceditor-resize-cover, -.ie7 div.sceditor-resize-cover, -.ie8 div.sceditor-resize-cover { - background: #efefef; -} -.sceditor-container.ie6 { - overflow: hidden; -} -div.sceditor-grip { - overflow: hidden; - width: 10px; - height: 10px; - cursor: pointer; - position: absolute; - bottom: 0; - right: 0; - z-index: 3; -} -.sceditor-maximize { - position: fixed; - top: 0; - left: 0; - height: 100% !important; - width: 100% !important; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - z-index: 2000; -} -html.sceditor-maximize, -body.sceditor-maximize { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - overflow: hidden; -} -.ie6.sceditor-maximize { - position: absolute; -} -.sceditor-maximize div.sceditor-grip { - display: none; -} -.sceditor-maximize div.sceditor-toolbar { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -/** - * Dropdown styleing - */ -div.sceditor-dropdown { - position: absolute; - border: 1px solid #ccc; - background: #fff; - color: #333; - z-index: 4000; - padding: 10px; - line-height: 1; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); -} -div.sceditor-dropdown a, -div.sceditor-dropdown a:link { - color: #333; -} -div.sceditor-dropdown form { - margin: 0; -} -div.sceditor-dropdown label { - display: block; - font-weight: bold; - color: #3c3c3c; - padding: 4px 0; -} -div.sceditor-dropdown input, -div.sceditor-dropdown textarea { - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - outline: 0; - padding: 4px; - border: 1px solid #ccc; - border-top-color: #888; - margin: 0 0 .75em; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-dropdown textarea { - padding: 6px; -} -div.sceditor-dropdown input:focus, -div.sceditor-dropdown textarea:focus { - border-color: #aaa; - border-top-color: #666; - -webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); -} -div.sceditor-dropdown .button { - font-weight: bold; - color: #444; - padding: 6px 12px; - background: #ececec; - border: solid 1px #ccc; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - cursor: pointer; - margin: .3em 0 0; -} -div.sceditor-dropdown .button:hover { - background: #f3f3f3; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); -} -div.sceditor-font-picker, -div.sceditor-fontsize-picker, -div.sceditor-format { - padding: 6px 0; -} -div.sceditor-emoticons, -div.sceditor-more-emoticons, -div.sceditor-color-picker { - padding: 0; -} -.sceditor-pastetext textarea { - border: 1px solid #bbb; - width: 20em; -} -.sceditor-emoticons img, -.sceditor-more-emoticons img { - padding: 0; - cursor: pointer; - margin: 2px; -} -.sceditor-more { - border-top: 1px solid #bbb; - display: block; - text-align: center; - cursor: pointer; - font-weight: bold; - padding: 6px 0; -} -.sceditor-dropdown a:hover { - background: #eee; -} -.sceditor-fontsize-option, -.sceditor-font-option, -.sceditor-format a { - display: block; - padding: 7px 10px; - cursor: pointer; - text-decoration: none; - color: #222; -} -.sceditor-fontsize-option { - padding: 7px 13px; -} -.sceditor-color-column { - float: left; -} -.sceditor-color-option { - display: block; - border: 1px solid #fff; - height: 10px; - width: 10px; - overflow: hidden; -} -.sceditor-color-option:hover { - border: 1px solid #333; -} -/** - * Toolbar styleing - */ -div.sceditor-toolbar { - overflow: hidden; - padding: 3px 5px 2px; - background: #f7f7f7; - border-bottom: 1px solid #c0c0c0; - line-height: 0; - text-align: left; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-group { - display: inline-block; - background: #ddd; - margin: 1px 5px 1px 0; - padding: 1px; - border-bottom: 1px solid #aaa; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.ie6 div.sceditor-group, -.ie7 div.sceditor-group { - display: inline; - zoom: 1; -} -.sceditor-button { - float: left; - cursor: pointer; - padding: 3px 5px; - width: 16px; - height: 20px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - /* Needed for Safari 5? */ - - text-indent: -9999px; -} -.ie .sceditor-button { - text-indent: 0; -} -.ie6 .sceditor-button, -.ie7 .sceditor-button { - float: none !important; - display: inline; - zoom: 1; -} -.ie6 .sceditor-button { - padding: 0; -} -.ie6 .sceditor-button div { - margin: 5px; -} -.ie7 .sceditor-button div { - margin: 5px 0; -} -.sceditor-button:hover, -.sceditor-button:active, -.sceditor-button.active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); -} -.sceditor-button:active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); -} -.sceditor-button.disabled:hover { - background: inherit; - cursor: default; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.sceditor-button, -.sceditor-button div { - display: block; -} -.sceditor-button div { - margin: 2px 0; - padding: 0; - overflow: hidden; - line-height: 0; - font-size: 0; - color: transparent; -} -.sceditor-button.disabled div { - filter: alpha(opacity=30); - opacity: 0.3; -} -.text .sceditor-button, -.text .sceditor-button div, -.sceditor-button.text, -.sceditor-button.text div, -.text-icon .sceditor-button, -.text-icon .sceditor-button div, -.sceditor-button.text-icon, -.sceditor-button.text-icon div { - width: auto; - overflow: visible; - line-height: 16px; - font-size: 1em; - color: inherit; - text-indent: 0; -} -.text .sceditor-button div, -.sceditor-button.text div { - padding: 0 2px; - background: none; -} -.text-icon .sceditor-button div, -.sceditor-button.text-icon div { - padding: 0 2px 0 20px; -} -.rtl div.sceditor-toolbar { - text-align: right; -} -.rtl .sceditor-button { - float: right; -} -.rtl div.sceditor-grip { - right: auto; - left: 0; -} -.sceditor-container { - border: 1px solid #8db2e3; -} -.sceditor-container textarea { - font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace; -} -div.sceditor-toolbar { - border-bottom: 1px solid #95a9c3; - background: #dee8f5; - background: -moz-linear-gradient(top, #dee8f5 0%, #c7d8ed 29%, #ccdcee 61%, #c0d8ef 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dee8f5), color-stop(29%, #c7d8ed), color-stop(61%, #ccdcee), color-stop(100%, #c0d8ef)); - background: -webkit-linear-gradient(top, #dee8f5 0%, #c7d8ed 29%, #ccdcee 61%, #c0d8ef 100%); - background: -o-linear-gradient(top, #dee8f5 0%, #c7d8ed 29%, #ccdcee 61%, #c0d8ef 100%); - background: -ms-linear-gradient(top, #dee8f5 0%, #c7d8ed 29%, #ccdcee 61%, #c0d8ef 100%); - background: linear-gradient(to bottom, #dee8f5 0%, #c7d8ed 29%, #ccdcee 61%, #c0d8ef 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dee8f5', endColorstr='#c0d8ef', GradientType=0); -} -.ie9 div.sceditor-toolbar { - filter: none; - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RlZThmNSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjI5JSIgc3RvcC1jb2xvcj0iI2M3ZDhlZCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjYxJSIgc3RvcC1jb2xvcj0iI2NjZGNlZSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNjMGQ4ZWYiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); -} -div.sceditor-group { - border: 1px solid #7596bf; - background: transparent; - padding: 0; - background: #cadcf0; - background: -moz-linear-gradient(top, #cadcf0 24%, #bcd0e9 38%, #d0e1f7 99%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(24%, #cadcf0), color-stop(38%, #bcd0e9), color-stop(99%, #d0e1f7)); - background: -webkit-linear-gradient(top, #cadcf0 24%, #bcd0e9 38%, #d0e1f7 99%); - background: -o-linear-gradient(top, #cadcf0 24%, #bcd0e9 38%, #d0e1f7 99%); - background: -ms-linear-gradient(top, #cadcf0 24%, #bcd0e9 38%, #d0e1f7 99%); - background: linear-gradient(to bottom, #cadcf0 24%, #bcd0e9 38%, #d0e1f7 99%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cadcf0', endColorstr='#d0e1f7', GradientType=0); -} -.ie9 div.sceditor-group { - filter: none; - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIyNCUiIHN0b3AtY29sb3I9IiNjYWRjZjAiIHN0b3Atb3BhY2l0eT0iMSIvPgogICAgPHN0b3Agb2Zmc2V0PSIzOCUiIHN0b3AtY29sb3I9IiNiY2QwZTkiIHN0b3Atb3BhY2l0eT0iMSIvPgogICAgPHN0b3Agb2Zmc2V0PSI5OSUiIHN0b3AtY29sb3I9IiNkMGUxZjciIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); -} -.sceditor-button { - height: 16px; - padding: 3px 4px; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-shadow: inset 0 1px #d5e3f1, inset 0 -1px #e3edfb, inset 1px 0 #cddcef, inset -1px 0 #b8ceea; - -moz-box-shadow: inset 0 1px #d5e3f1, inset 0 -1px #e3edfb, inset 1px 0 #cddcef, inset -1px 0 #b8ceea; - box-shadow: inset 0 1px #d5e3f1, inset 0 -1px #e3edfb, inset 1px 0 #cddcef, inset -1px 0 #b8ceea; -} -.sceditor-button:first-child { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.sceditor-button:last-child { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.sceditor-button div { - margin: 0; -} -.ie9 .sceditor-button { - filter: none !important; -} -.sceditor-button.active { - background: #fbdbb5; - background: -moz-linear-gradient(top, #fbdbb5 11%, #feb456 29%, #fdeb9f 99%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(11%, #fbdbb5), color-stop(29%, #feb456), color-stop(99%, #fdeb9f)); - background: -webkit-linear-gradient(top, #fbdbb5 11%, #feb456 29%, #fdeb9f 99%); - background: -o-linear-gradient(top, #fbdbb5 11%, #feb456 29%, #fdeb9f 99%); - background: -ms-linear-gradient(top, #fbdbb5 11%, #feb456 29%, #fdeb9f 99%); - background: linear-gradient(top, #fbdbb5 11%, #feb456 29%, #fdeb9f 99%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbdbb5', endColorstr='#fdeb9f', GradientType=0); - -webkit-box-shadow: inset 0 1px #ebd1b4, inset 0 -1px #ffe47f, inset -1px 0 #b8ceea; - -moz-box-shadow: inset 0 1px #ebd1b4, inset 0 -1px #ffe47f, inset -1px 0 #b8ceea; - box-shadow: inset 0 1px #ebd1b4, inset 0 -1px #ffe47f, inset -1px 0 #b8ceea; -} -.ie9 .sceditor-button.active { - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIxMSUiIHN0b3AtY29sb3I9IiNmYmRiYjUiIHN0b3Atb3BhY2l0eT0iMSIvPgogICAgPHN0b3Agb2Zmc2V0PSIyOSUiIHN0b3AtY29sb3I9IiNmZWI0NTYiIHN0b3Atb3BhY2l0eT0iMSIvPgogICAgPHN0b3Agb2Zmc2V0PSI5OSUiIHN0b3AtY29sb3I9IiNmZGZkOWYiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); -} -.sceditor-button:hover { - background: #fef7d5; - background: -moz-linear-gradient(top, #fef7d5 0%, #fae5a9 42%, #ffd048 42%, #ffe59f 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fef7d5), color-stop(42%, #fae5a9), color-stop(42%, #ffd048), color-stop(100%, #ffe59f)); - background: -webkit-linear-gradient(top, #fef7d5 0%, #fae5a9 42%, #ffd048 42%, #ffe59f 100%); - background: -o-linear-gradient(top, #fef7d5 0%, #fae5a9 42%, #ffd048 42%, #ffe59f 100%); - background: -ms-linear-gradient(top, #fef7d5 0%, #fae5a9 42%, #ffd048 42%, #ffe59f 100%); - background: linear-gradient(to bottom, #fef7d5 0%, #fae5a9 42%, #ffd048 42%, #ffe59f 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fef7d5', endColorstr='#ffe59f', GradientType=0); - -webkit-box-shadow: inset 0 1px #fffbe8, inset -1px 0 #ffefc4, inset 0 -1px #fff9cc; - -moz-box-shadow: inset 0 1px #fffbe8, inset -1px 0 #ffefc4, inset 0 -1px #fff9cc; - box-shadow: inset 0 1px #fffbe8, inset -1px 0 #ffefc4, inset 0 -1px #fff9cc; -} -.ie9 .sceditor-button:hover { - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZlZjdkNSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjQyJSIgc3RvcC1jb2xvcj0iI2ZhZTVhOSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjQyJSIgc3RvcC1jb2xvcj0iI2ZmZDA0OCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmU1OWYiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); -} -.sceditor-button:active { - background: #e7a66d; - background: -moz-linear-gradient(top, #e7a66d 0%, #fcb16d 1%, #ff8d05 42%, #ffc450 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #e7a66d), color-stop(1%, #fcb16d), color-stop(42%, #ff8d05), color-stop(100%, #ffc450)); - background: -webkit-linear-gradient(top, #e7a66d 0%, #fcb16d 1%, #ff8d05 42%, #ffc450 100%); - background: -o-linear-gradient(top, #e7a66d 0%, #fcb16d 1%, #ff8d05 42%, #ffc450 100%); - background: -ms-linear-gradient(top, #e7a66d 0%, #fcb16d 1%, #ff8d05 42%, #ffc450 100%); - background: linear-gradient(to bottom, #e7a66d 0%, #fcb16d 1%, #ff8d05 42%, #ffc450 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e7a66d', endColorstr='#ffc450', GradientType=0); - -webkit-box-shadow: inset 0 1px 1px #7b6645, inset 0 -1px #d19c33; - -moz-box-shadow: inset 0 1px 1px #7b6645, inset 0 -1px #d19c33; - box-shadow: inset 0 1px 1px #7b6645, inset 0 -1px #d19c33; -} -.ie9 .sceditor-button:active { - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2U3YTY2ZCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjElIiBzdG9wLWNvbG9yPSIjZmNiMTZkIiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iNDIlIiBzdG9wLWNvbG9yPSIjZmY4ZDA1IiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZmYzQ1MCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgPC9saW5lYXJHcmFkaWVudD4KICA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2dyYWQtdWNnZy1nZW5lcmF0ZWQpIiAvPgo8L3N2Zz4=); -} -.sceditor-button.active:hover { - background: #dba368; - background: -moz-linear-gradient(top, #dba368 0%, #ffbd79 4%, #fea335 34%, #ffc64c 66%, #fee069 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dba368), color-stop(4%, #ffbd79), color-stop(34%, #fea335), color-stop(66%, #ffc64c), color-stop(100%, #fee069)); - background: -webkit-linear-gradient(top, #dba368 0%, #ffbd79 4%, #fea335 34%, #ffc64c 66%, #fee069 100%); - background: -o-linear-gradient(top, #dba368 0%, #ffbd79 4%, #fea335 34%, #ffc64c 66%, #fee069 100%); - background: -ms-linear-gradient(top, #dba368 0%, #ffbd79 4%, #fea335 34%, #ffc64c 66%, #fee069 100%); - background: linear-gradient(to bottom, #dba368 0%, #ffbd79 4%, #fea335 34%, #ffc64c 66%, #fee069 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dba368', endColorstr='#fee069', GradientType=0); - -webkit-box-shadow: inset 0 1px 1px #9e8255, inset 0 -1px #fcce6b; - -moz-box-shadow: inset 0 1px 1px #9e8255, inset 0 -1px #fcce6b; - box-shadow: inset 0 1px 1px #9e8255, inset 0 -1px #fcce6b; -} -.ie9 .sceditor-button.active:hover { - background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RiYTM2OCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjQlIiBzdG9wLWNvbG9yPSIjZmZiZDc5IiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iMzQlIiBzdG9wLWNvbG9yPSIjZmVhMzM1IiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iNjYlIiBzdG9wLWNvbG9yPSIjZmZjNjRjIiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZlZTA2OSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgPC9saW5lYXJHcmFkaWVudD4KICA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2dyYWQtdWNnZy1nZW5lcmF0ZWQpIiAvPgo8L3N2Zz4=); -} -.sceditor-container { - background: #a3c2ea; - background: -moz-linear-gradient(top, #a3c2ea 0%, #6d92c1 39%, #577fb3 64%, #6591cc 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #a3c2ea), color-stop(39%, #6d92c1), color-stop(64%, #577fb3), color-stop(100%, #6591cc)); - background: -webkit-linear-gradient(top, #a3c2ea 0%, #6d92c1 39%, #577fb3 64%, #6591cc 100%); - background: -o-linear-gradient(top, #a3c2ea 0%, #6d92c1 39%, #577fb3 64%, #6591cc 100%); - background: -ms-linear-gradient(top, #a3c2ea 0%, #6d92c1 39%, #577fb3 64%, #6591cc 100%); - background: linear-gradient(top, #a3c2ea 0%, #6d92c1 39%, #577fb3 64%, #6591cc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#a3c2ea', endColorstr='#6591cc', GradientType=0); -} -.sceditor-container iframe, -.sceditor-container textarea { - border: 1px solid #646464; - background: #fff; - margin: 7px 4.5%; - padding: 20px; - -webkit-box-shadow: 1px 1px 5px #293a52; - -moz-box-shadow: 1px 1px 5px #293a52; - box-shadow: 1px 1px 5px #293a52; -} - -/* Additional buttons (for MyBB) */ -.sceditor-button-video div { - - background-image: url(video.png); - -} -.sceditor-button-php div { - - background-image: url(php.png); - -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/php.png b/html/forums/jscripts/sceditor/editor_themes/php.png deleted file mode 100644 index 2cec03c..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/php.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/editor_themes/square.css b/html/forums/jscripts/sceditor/editor_themes/square.css deleted file mode 100644 index 2bda9c6..0000000 --- a/html/forums/jscripts/sceditor/editor_themes/square.css +++ /dev/null @@ -1,668 +0,0 @@ -/** - * Square theme - * - * This theme is best suited to short toolbars that - * don't span multiple lines. - * - * Copyright (C) 2012, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * Icons by Mark James (http://www.famfamfam.com/lab/icons/silk/) - * Licensed under the Creative Commons CC-BY license (http://creativecommons.org/licenses/by/3.0/) - */ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -div.sceditor-grip, -.sceditor-button div { - background-image: url('famfamfam.png'); - background-repeat: no-repeat; - width: 16px; - height: 16px; -} -.sceditor-button-youtube div { - background-position: 0px 0px; -} -.sceditor-button-link div { - background-position: 0px -16px; -} -.sceditor-button-unlink div { - background-position: 0px -32px; -} -.sceditor-button-underline div { - background-position: 0px -48px; -} -.sceditor-button-time div { - background-position: 0px -64px; -} -.sceditor-button-table div { - background-position: 0px -80px; -} -.sceditor-button-superscript div { - background-position: 0px -96px; -} -.sceditor-button-subscript div { - background-position: 0px -112px; -} -.sceditor-button-strike div { - background-position: 0px -128px; -} -.sceditor-button-source div { - background-position: 0px -144px; -} -.sceditor-button-size div { - background-position: 0px -160px; -} -.sceditor-button-rtl div { - background-position: 0px -176px; -} -.sceditor-button-right div { - background-position: 0px -192px; -} -.sceditor-button-removeformat div { - background-position: 0px -208px; -} -.sceditor-button-quote div { - background-position: 0px -224px; -} -.sceditor-button-print div { - background-position: 0px -240px; -} -.sceditor-button-pastetext div { - background-position: 0px -256px; -} -.sceditor-button-paste div { - background-position: 0px -272px; -} -.sceditor-button-orderedlist div { - background-position: 0px -288px; -} -.sceditor-button-maximize div { - background-position: 0px -304px; -} -.sceditor-button-ltr div { - background-position: 0px -320px; -} -.sceditor-button-left div { - background-position: 0px -336px; -} -.sceditor-button-justify div { - background-position: 0px -352px; -} -.sceditor-button-italic div { - background-position: 0px -368px; -} -.sceditor-button-image div { - background-position: 0px -384px; -} -.sceditor-button-horizontalrule div { - background-position: 0px -400px; -} -.sceditor-button-format div { - background-position: 0px -416px; -} -.sceditor-button-font div { - background-position: 0px -432px; -} -.sceditor-button-emoticon div { - background-position: 0px -448px; -} -.sceditor-button-email div { - background-position: 0px -464px; -} -.sceditor-button-date div { - background-position: 0px -480px; -} -.sceditor-button-cut div { - background-position: 0px -496px; -} -.sceditor-button-copy div { - background-position: 0px -512px; -} -.sceditor-button-color div { - background-position: 0px -528px; -} -.sceditor-button-code div { - background-position: 0px -544px; -} -.sceditor-button-center div { - background-position: 0px -560px; -} -.sceditor-button-bulletlist div { - background-position: 0px -576px; -} -.sceditor-button-bold div { - background-position: 0px -592px; -} -div.sceditor-grip { - background-position: 0px -608px; - width: 10px; - height: 10px; -} -.rtl div.sceditor-grip { - background-position: 0px -618px; - width: 10px; - height: 10px; -} -/** - * SCEditor - * http://www.ssceditor.com/ - * - * Copyright (C) 2011-12, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ -/*--------------------------------------------------- - LESS Elements 0.7 - --------------------------------------------------- - A set of useful LESS mixins - More info at: http://lesselements.com - ---------------------------------------------------*/ -.sceditor-container { - position: relative; - background: #fff; - border: 1px solid #d9d9d9; - font-size: 13px; - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - color: #222; - line-height: 1; - font-weight: bold; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 100% !important; -} -.sceditor-container, -.sceditor-container div, -div.sceditor-dropdown, -div.sceditor-dropdown div { - padding: 0; - margin: 0; - z-index: 3; -} -.sceditor-container iframe, -.sceditor-container textarea { - line-height: 1; - border: 0; - outline: none; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 13px; - color: #111; - padding: 0; - margin: 5px; - resize: none; - background: #fff; - display: block; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width: 99% !important; -} -div.sceditor-resize-cover { - position: absolute; - top: 0; - left: 0; - background: #000; - width: 100%; - height: 100%; - z-index: 10; - opacity: 0.3; -} -.ie6 div.sceditor-resize-cover, -.ie7 div.sceditor-resize-cover, -.ie8 div.sceditor-resize-cover { - background: #efefef; -} -.sceditor-container.ie6 { - overflow: hidden; -} -div.sceditor-grip { - overflow: hidden; - width: 10px; - height: 10px; - cursor: pointer; - position: absolute; - bottom: 0; - right: 0; - z-index: 3; -} -.sceditor-maximize { - position: fixed; - top: 0; - left: 0; - height: 100% !important; - width: 100% !important; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - z-index: 2000; -} -html.sceditor-maximize, -body.sceditor-maximize { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - overflow: hidden; -} -.ie6.sceditor-maximize { - position: absolute; -} -.sceditor-maximize div.sceditor-grip { - display: none; -} -.sceditor-maximize div.sceditor-toolbar { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -/** - * Dropdown styleing - */ -div.sceditor-dropdown { - position: absolute; - border: 1px solid #ccc; - background: #fff; - color: #333; - z-index: 4000; - padding: 10px; - line-height: 1; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2); -} -div.sceditor-dropdown a, -div.sceditor-dropdown a:link { - color: #333; -} -div.sceditor-dropdown form { - margin: 0; -} -div.sceditor-dropdown label { - display: block; - font-weight: bold; - color: #3c3c3c; - padding: 4px 0; -} -div.sceditor-dropdown input, -div.sceditor-dropdown textarea { - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - outline: 0; - padding: 4px; - border: 1px solid #ccc; - border-top-color: #888; - margin: 0 0 .75em; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-dropdown textarea { - padding: 6px; -} -div.sceditor-dropdown input:focus, -div.sceditor-dropdown textarea:focus { - border-color: #aaa; - border-top-color: #666; - -webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); -} -div.sceditor-dropdown .button { - font-weight: bold; - color: #444; - padding: 6px 12px; - background: #ececec; - border: solid 1px #ccc; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - cursor: pointer; - margin: .3em 0 0; -} -div.sceditor-dropdown .button:hover { - background: #f3f3f3; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); -} -div.sceditor-font-picker, -div.sceditor-fontsize-picker, -div.sceditor-format { - padding: 6px 0; -} -div.sceditor-emoticons, -div.sceditor-more-emoticons, -div.sceditor-color-picker { - padding: 0; -} -.sceditor-pastetext textarea { - border: 1px solid #bbb; - width: 20em; -} -.sceditor-emoticons img, -.sceditor-more-emoticons img { - padding: 0; - cursor: pointer; - margin: 2px; -} -.sceditor-more { - border-top: 1px solid #bbb; - display: block; - text-align: center; - cursor: pointer; - font-weight: bold; - padding: 6px 0; -} -.sceditor-dropdown a:hover { - background: #eee; -} -.sceditor-fontsize-option, -.sceditor-font-option, -.sceditor-format a { - display: block; - padding: 7px 10px; - cursor: pointer; - text-decoration: none; - color: #222; -} -.sceditor-fontsize-option { - padding: 7px 13px; -} -.sceditor-color-column { - float: left; -} -.sceditor-color-option { - display: block; - border: 1px solid #fff; - height: 10px; - width: 10px; - overflow: hidden; -} -.sceditor-color-option:hover { - border: 1px solid #333; -} -/** - * Toolbar styleing - */ -div.sceditor-toolbar { - overflow: hidden; - padding: 3px 5px 2px; - background: #f7f7f7; - border-bottom: 1px solid #c0c0c0; - line-height: 0; - text-align: left; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-group { - display: inline-block; - background: #ddd; - margin: 1px 5px 1px 0; - padding: 1px; - border-bottom: 1px solid #aaa; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.ie6 div.sceditor-group, -.ie7 div.sceditor-group { - display: inline; - zoom: 1; -} -.sceditor-button { - float: left; - cursor: pointer; - padding: 3px 5px; - width: 16px; - height: 20px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - /* Needed for Safari 5? */ - - text-indent: -9999px; -} -.ie .sceditor-button { - text-indent: 0; -} -.ie6 .sceditor-button, -.ie7 .sceditor-button { - float: none !important; - display: inline; - zoom: 1; -} -.ie6 .sceditor-button { - padding: 0; -} -.ie6 .sceditor-button div { - margin: 5px; -} -.ie7 .sceditor-button div { - margin: 5px 0; -} -.sceditor-button:hover, -.sceditor-button:active, -.sceditor-button.active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2); -} -.sceditor-button:active { - background: #fff; - -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); - box-shadow: inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3); -} -.sceditor-button.disabled:hover { - background: inherit; - cursor: default; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.sceditor-button, -.sceditor-button div { - display: block; -} -.sceditor-button div { - margin: 2px 0; - padding: 0; - overflow: hidden; - line-height: 0; - font-size: 0; - color: transparent; -} -.sceditor-button.disabled div { - filter: alpha(opacity=30); - opacity: 0.3; -} -.text .sceditor-button, -.text .sceditor-button div, -.sceditor-button.text, -.sceditor-button.text div, -.text-icon .sceditor-button, -.text-icon .sceditor-button div, -.sceditor-button.text-icon, -.sceditor-button.text-icon div { - width: auto; - overflow: visible; - line-height: 16px; - font-size: 1em; - color: inherit; - text-indent: 0; -} -.text .sceditor-button div, -.sceditor-button.text div { - padding: 0 2px; - background: none; -} -.text-icon .sceditor-button div, -.sceditor-button.text-icon div { - padding: 0 2px 0 20px; -} -.rtl div.sceditor-toolbar { - text-align: right; -} -.rtl .sceditor-button { - float: right; -} -.rtl div.sceditor-grip { - right: auto; - left: 0; -} -.sceditor-container { - border: 1px solid #d6d6d6; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.sceditor-container textarea { - font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace; - background: #2e3436; - color: #fff; - margin: 0; - padding: 5px; -} -div.sceditor-toolbar, -div.sceditor-group { - background: #f2f2f2; - background: -moz-linear-gradient(top, #f2f2f2 0%, #dddddd 89%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f2f2f2), color-stop(89%, #dddddd)); - background: -webkit-linear-gradient(top, #f2f2f2 0%, #dddddd 89%); - background: -o-linear-gradient(top, #f2f2f2 0%, #dddddd 89%); - background: -ms-linear-gradient(top, #f2f2f2 0%, #dddddd 89%); - background: linear-gradient(to bottom, #f2f2f2 0%, #dddddd 89%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f2f2', endColorstr='#dddddd', GradientType=0); -} -div.sceditor-toolbar { - padding: 0; - border-bottom: 1px solid #bbb; - -moz-background-size: 100% 32px; - -o-background-size: 100% 32px; - -webkit-background-size: 100% 32px; - background-size: 100% 32px; -} -div.sceditor-group { - margin: 0; - padding: 2px 4px; - border: 0; - border-right: 1px solid #ccc; - border-left: 1px solid #eaeaea; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -div.sceditor-group:last-child { - border-right: 0; -} -div.sceditor-group:first-child { - border-left: 0; -} -.sceditor-button { - height: 16px; - padding: 5px; - margin: 1px; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; -} -.sceditor-button div { - margin: 0; -} -.sceditor-button.active, -.sceditor-button:hover, -.sceditor-button:active, -.sceditor-button.active:hover { - margin: 0; - box-shadow: none; -} -.sceditor-button.active { - background: #f4f4f4; - border: 1px solid #ccc; -} -.sceditor-button:hover { - background: #fefefe; - border: 1px solid #ddd; -} -.sceditor-button.disabled:hover { - margin: 1px; - border: 0; -} -.sceditor-button:active { - background: #eee; - border: 1px solid #ccc; -} -.sceditor-button.active:hover { - background: #f8f8f8; - border: 1px solid #ddd; -} - -/* Additional buttons (for MyBB) */ -.sceditor-button-video div { - - background-image: url(video.png); - -} -.sceditor-button-php div { - - background-image: url(php.png); - -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/editor_themes/video.png b/html/forums/jscripts/sceditor/editor_themes/video.png deleted file mode 100644 index d230cd4..0000000 Binary files a/html/forums/jscripts/sceditor/editor_themes/video.png and /dev/null differ diff --git a/html/forums/jscripts/sceditor/jquery.sceditor.bbcode.min.js b/html/forums/jscripts/sceditor/jquery.sceditor.bbcode.min.js deleted file mode 100644 index ca09744..0000000 --- a/html/forums/jscripts/sceditor/jquery.sceditor.bbcode.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/* SCEditor v1.4.7 | (C) 2015, Sam Clarke | sceditor.com/license */ -!function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){var d;d=function(){"use strict";var a=c(1),b=c(2),d=c(3),e=c(4),f=c(5);a.sceditor=b,b.commands=c(6),b.defaultOptions=c(7),b.RangeHelper=c(8),b.dom=c(9),b.ie=e.ie,b.ios=e.ios,b.isWysiwygSupported=e.isWysiwygSupported,b.regexEscape=f.regex,b.escapeEntities=f.entities,b.escapeUriScheme=f.uriScheme,b.PluginManager=d,b.plugins=d.plugins,a.fn.sceditor=function(c){var d,f,g=[];return c=c||{},c.runWithoutWysiwygSupport||e.isWysiwygSupported?(this.each(function(){d=this.jquery?this:a(this),f=d.data("sceditor"),d.parents(".sceditor-container").length>0||("state"===c?g.push(!!f):"instance"===c?g.push(f):f||new b(this,c))}),g.length?1===g.length?g[0]:a(g):this):void 0}}.call(b,c,b,a),!(void 0!==d&&(a.exports=d))},function(a){a.exports=jQuery},function(a,b,c){var d;d=function(){"use strict";var a=c(1),b=c(3),d=c(8),e=c(9),f=c(5),g=c(4),h=c(10),i=window,j=document,k=a(i),l=a(j),m=g.ie,n=m&&11>m,o=function(c,p){var q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,_,ab,bb,cb,db,eb,fb,gb,hb,ib,jb,kb,lb,mb,nb,ob,pb,qb,rb,sb,tb,ub=this,vb=c.get?c.get(0):c,wb=a(vb),xb=[],yb=[],zb=[],Ab={},Bb=[],Cb={};ub.commands=a.extend(!0,{},p.commands||o.commands),ub.opts=p=a.extend({},o.defaultOptions,p),K=function(){wb.data("sceditor",ub),a.each(p,function(b,c){a.isPlainObject(c)&&(p[b]=a.extend(!0,{},c))}),p.locale&&"en"!==p.locale&&Q(),q=a('

    ').insertAfter(wb).css("z-index",p.zIndex),m&&q.addClass("ie ie"+m),H=!!wb.attr("required"),wb.removeAttr("required"),P(),W(),R(),O(),U(),S(),T(),g.isWysiwygSupported||ub.toggleSourceMode(),hb();var b=function(){k.unbind("load",b),p.autofocus&&mb(),p.autoExpand&&ub.expandToContent(),fb(),C.call("ready")};k.load(b),j.readyState&&"complete"===j.readyState&&b()},P=function(){var c=p.plugins;c=c?c.toString().split(","):[],C=new b(ub),a.each(c,function(b,c){C.register(a.trim(c))})},Q=function(){var a;A=o.locale[p.locale],A||(a=p.locale.split("-"),A=o.locale[a[0]]),A&&A.dateFormat&&(p.dateFormat=A.dateFormat)},O=function(){var b,c;w=a("").hide(),s=a(''),p.spellcheck||w.attr("spellcheck","false"),"https:"===i.location.protocol&&s.attr("src","javascript:false"),q.append(s).append(w),t=s[0],x=w[0],ub.dimensions(p.width||wb.width(),p.height||wb.height()),b=X(),b.open(),b.write(h("html",{attrs:m?' class="ie ie"'+m:"",spellcheck:p.spellcheck?"":'spellcheck="false"',charset:p.charset,style:p.style})),b.close(),v=a(b),u=a(b.body),ub.readOnly(!!p.readOnly),(g.ios||m)&&(u.height("100%"),m||u.bind("touchend",ub.focus)),c=wb.attr("tabindex"),w.attr("tabindex",c),s.attr("tabindex",c),B=new d(t.contentWindow),ub.val(wb.hide().val())},S=function(){p.autoUpdate&&(u.bind("blur",tb),w.bind("blur",tb)),null===p.rtl&&(p.rtl="rtl"===w.css("direction")),ub.rtl(!!p.rtl),p.autoExpand&&v.bind("keyup",ub.expandToContent),p.resizeEnabled&&V(),q.attr("id",p.id),ub.emoticons(p.emoticonsEnabled)},T=function(){var b=m?"selectionchange":"keyup focus blur contextmenu mouseup touchend click",c="keydown keyup keypress focus blur contextmenu";l.click(eb),a(vb.form).bind("reset",bb).submit(ub.updateOriginal),k.bind("resize orientationChanged",fb),u.keypress(ab).keydown($).keydown(_).keyup(jb).blur(rb).keyup(sb).bind("paste",Y).bind(b,kb).bind(c,db),p.emoticonsCompat&&i.getSelection&&u.keyup(ob),w.blur(rb).keyup(sb).keydown($).bind(c,db),v.mousedown(cb).blur(rb).bind(b,kb).bind("beforedeactivate keyup mouseup",N).keyup(jb).focus(function(){z=null}),q.bind("selectionchanged",lb).bind("selectionchanged",hb).bind("selectionchanged valuechanged nodechanged",db)},R=function(){var b,c=ub.commands,d=(p.toolbarExclude||"").split(","),e=p.toolbar.split("|");r=a('
    '),a.each(e,function(e,f){b=a('
    '),a.each(f.split(","),function(e,f){var g,i,j=c[f];!j||a.inArray(f,d)>-1||(i=j.shortcut,g=h("toolbarButton",{name:f,dispName:ub._(j.tooltip||f)},!0),g.data("sceditor-txtmode",!!j.txtExec).data("sceditor-wysiwygmode",!!j.exec).toggleClass("disabled",!j.exec).mousedown(function(){(!m||9>m)&&(J=!0)}).click(function(){var b=a(this);return b.hasClass("disabled")||M(b,j),hb(),!1}),j.tooltip&&g.attr("title",ub._(j.tooltip)+(i?"("+i+")":"")),i&&ub.addShortcut(i,f),j.state?zb.push({name:f,state:j.state}):"string"==typeof j.exec&&zb.push({name:f,state:j.exec}),b.append(g),Cb[f]=g)}),b[0].firstChild&&r.append(b)}),a(p.toolbarContainer||q).append(r)},U=function(){a.each(ub.commands,function(b,c){c.forceNewLineAfter&&a.isArray(c.forceNewLineAfter)&&(yb=a.merge(yb,c.forceNewLineAfter))}),jb()},V=function(){var b,c,d,e,f,g,h=a('
    '),j=a('
    '),k="touchmove mousemove",n="touchcancel touchend mouseup",o=0,r=0,s=0,t=0,u=0,v=0,w=q.width(),x=q.height(),y=!1,z=ub.rtl();b=p.resizeMinHeight||x/1.5,c=p.resizeMaxHeight||2.5*x,d=p.resizeMinWidth||w/1.25,e=p.resizeMaxWidth||1.25*w,f=function(a){"touchmove"===a.type?(a=i.event,s=a.changedTouches[0].pageX,t=a.changedTouches[0].pageY):(s=a.pageX,t=a.pageY);var f=v+(t-r),g=z?u-(s-o):u+(s-o);e>0&&g>e&&(g=e),d>0&&d>g&&(g=d),p.resizeWidth||(g=!1),c>0&&f>c&&(f=c),b>0&&b>f&&(f=b),p.resizeHeight||(f=!1),(g||f)&&(ub.dimensions(g,f),7>m&&q.height(f)),a.preventDefault()},g=function(a){y&&(y=!1,j.hide(),q.removeClass("resizing").height("auto"),l.unbind(k,f),l.unbind(n,g),a.preventDefault())},q.append(h),q.append(j.hide()),h.bind("touchstart mousedown",function(a){"touchstart"===a.type?(a=i.event,o=a.touches[0].pageX,r=a.touches[0].pageY):(o=a.pageX,r=a.pageY),u=q.width(),v=q.height(),y=!0,q.addClass("resizing"),j.show(),l.bind(k,f),l.bind(n,g),7>m&&q.height(v),a.preventDefault()})},W=function(){var b,c=p.emoticons,d=p.emoticonsRoot;a.isPlainObject(c)&&p.emoticonsEnabled&&a.each(c,function(e,f){a.each(f,function(a,f){d&&(f={url:d+(f.url||f),tooltip:f.tooltip||a},c[e][a]=f),b=j.createElement("img"),b.src=f.url||f,xb.push(b)})})},mb=function(){var b,c,d=v[0],f=u[0],g=f.firstChild,h=!!p.autofocusEnd;if(q.is(":visible")){if(ub.sourceMode())return c=h?x.value.length:0,void(x.setSelectionRange?x.setSelectionRange(c,c):(b=x.createTextRange(),b.moveEnd("character",c),b.collapse(!1),b.select()));if(e.removeWhiteSpace(f),h)for((g=f.lastChild)||(g=d.createElement("p"),u.append(g));g.lastChild;)g=g.lastChild,!n&&a(g).is("br")&&g.previousSibling&&(g=g.previousSibling);d.createRange?(b=d.createRange(),e.canHaveChildren(g)?b.selectNodeContents(g):(b.setStartBefore(g),h&&b.setStartAfter(g))):(b=f.createTextRange(),b.moveToElementText(3!==g.nodeType?g:g.parentNode)),b.collapse(!h),B.selectRange(b),F=b,h&&(v.scrollTop(f.scrollHeight),u.scrollTop(f.scrollHeight)),ub.focus()}},ub.readOnly=function(a){return"boolean"!=typeof a?"readonly"===w.attr("readonly"):(u[0].contentEditable=!a,a?w.attr("readonly","readonly"):w.removeAttr("readonly"),gb(a),ub)},ub.rtl=function(a){var b=a?"rtl":"ltr";return"boolean"!=typeof a?"rtl"===w.attr("dir"):(u.attr("dir",b),w.attr("dir",b),q.removeClass("rtl").removeClass("ltr").addClass(b),ub)},gb=function(b){var c=ub.inSourceMode()?"txtmode":"wysiwygmode";a.each(Cb,function(a,d){b!==!0&&d.data("sceditor-"+c)?d.removeClass("disabled"):d.addClass("disabled")})},ub.width=function(a,b){return a||0===a?(ub.dimensions(a,null,b),ub):q.width()},ub.dimensions=function(a,b,c){var d,e=8>m||j.documentMode<8?2:0;return a=a||0===a?a:!1,b=b||0===b?b:!1,a===!1&&b===!1?{width:ub.width(),height:ub.height()}:(s.data("outerWidthOffset")===d&&ub.updateStyleCache(),a!==!1&&(c!==!1&&(p.width=a),b===!1&&(b=q.height(),c=!1),q.width(a),a&&a.toString().indexOf("%")>-1&&(a=q.width()),s.width(a-s.data("outerWidthOffset")),w.width(a-w.data("outerWidthOffset")),g.ios&&u&&u.width(a-s.data("outerWidthOffset")-(u.outerWidth(!0)-u.width()))),b!==!1&&(c!==!1&&(p.height=b),b&&b.toString().indexOf("%")>-1&&(b=q.height(b).height(),q.height("auto")),b-=p.toolbarContainer?0:r.outerHeight(!0),s.height(b-s.data("outerHeightOffset")),w.height(b-e-w.data("outerHeightOffset"))),ub)},ub.updateStyleCache=function(){s.data("outerWidthOffset",s.outerWidth(!0)-s.width()),w.data("outerWidthOffset",w.outerWidth(!0)-w.width()),s.data("outerHeightOffset",s.outerHeight(!0)-s.height()),w.data("outerHeightOffset",w.outerHeight(!0)-w.height())},ub.height=function(a,b){return a||0===a?(ub.dimensions(null,a,b),ub):q.height()},ub.maximize=function(b){return"undefined"==typeof b?q.is(".sceditor-maximize"):(b=!!b,7>m&&a("html, body").toggleClass("sceditor-maximize",b),q.toggleClass("sceditor-maximize",b),ub.width(b?"100%":p.width,!1),ub.height(b?"100%":p.height,!1),ub)},ub.expandToContent=function(a){var b=q.height(),c=b-s.height(),d=u[0].scrollHeight||v[0].documentElement.scrollHeight,e=p.resizeMaxHeight||2*(p.height||wb.height());d+=c,(a===!0||e>=d)&&d>b&&ub.height(d)},ub.destroy=function(){C&&(C.destroy(),B=null,z=null,C=null,l.unbind("click",eb),k.unbind("resize orientationChanged",fb),a(vb.form).unbind("reset",bb).unbind("submit",ub.updateOriginal),u.unbind(),v.unbind().find("*").remove(),w.unbind().remove(),r.remove(),q.unbind().find("*").unbind().remove(),q.remove(),wb.removeData("sceditor").removeData("sceditorbbcode").show(),H&&wb.attr("required","required"))},ub.createDropDown=function(b,c,d,e){var f,g="sceditor-"+c,h=y&&y.is("."+g);ub.closeDropDown(),h||(e!==!1&&a(d).find(":not(input,textarea)").filter(function(){return 1===this.nodeType}).attr("unselectable","on"),f={top:b.offset().top,left:b.offset().left,marginTop:b.outerHeight()},a.extend(f,p.dropDownCss),y=a('
    ').css(f).append(d).appendTo(a("body")).on("click focusin",function(a){a.stopPropagation()}),setTimeout(function(){y.find("input,textarea").first().focus()}))},eb=function(a){3!==a.which&&y&&(tb(),ub.closeDropDown())},Y=function(a){var b,c,d,e=u[0],f=v[0],g=0,h=j.createElement("div"),i=f.createDocumentFragment(),k=a?a.clipboardData:!1;if(p.disablePasting)return!1;if(p.enablePasteFiltering){if(B.saveRange(),j.body.appendChild(h),k&&k.getData&&((b=k.getData("text/html"))||(b=k.getData("text/plain"))))return h.innerHTML=b,Z(e,h),!1;for(d=u.scrollTop()||v.scrollTop();e.firstChild;)i.appendChild(e.firstChild);return c=function(a,b){if(a.childNodes.length>0||g>25){for(;a.firstChild;)b.appendChild(a.firstChild);for(;i.firstChild;)a.appendChild(i.firstChild);u.scrollTop(d),v.scrollTop(d),b.childNodes.length>0?Z(a,b):B.restoreRange()}else g++,setTimeout(function(){c(a,b)},20)},c(e,h),ub.focus(),!0}},Z=function(b,c){e.fixNesting(c);var d=c.innerHTML;C.hasHandler("toSource")&&(d=C.callOnlyFirst("toSource",d,a(c))),c.parentNode.removeChild(c),C.hasHandler("toWysiwyg")&&(d=C.callOnlyFirst("toWysiwyg",d,!0)),B.restoreRange(),ub.wysiwygEditorInsertHtml(d,null,!0)},ub.closeDropDown=function(a){y&&(y.unbind().remove(),y=null),a===!0&&ub.focus()},X=function(){return t.contentDocument?t.contentDocument:t.contentWindow&&t.contentWindow.document?t.contentWindow.document:t.document},ub.wysiwygEditorInsertHtml=function(b,c,d){var f,g,h,i=s.height();ub.focus(),(d||!a(E).is("code")&&0===a(E).parents("code").length)&&(B.insertHTML(b,c),B.saveRange(),L(u[0]),f=u.find("#sceditor-end-marker").show(),g=u.scrollTop()||v.scrollTop(),h=e.getOffset(f[0]).top+1.5*f.outerHeight(!0)-i,f.hide(),(h>g||g>h+i)&&(u.scrollTop(h),v.scrollTop(h)),qb(!1),B.restoreRange(),jb())},ub.wysiwygEditorInsertText=function(a,b){ub.wysiwygEditorInsertHtml(f.entities(a),f.entities(b))},ub.insertText=function(a,b){return ub.inSourceMode()?ub.sourceEditorInsertText(a,b):ub.wysiwygEditorInsertText(a,b),ub},ub.sourceEditorInsertText=function(a,b){var c,d,e,f=x.selectionStart,g=x.selectionEnd;d=x.scrollTop,x.focus(),"undefined"!=typeof f?(e=x.value,b&&(a+=e.substring(f,g)+b),x.value=e.substring(0,f)+a+e.substring(g,e.length),x.selectionStart=f+a.length-(b?b.length:0),x.selectionEnd=x.selectionStart):(c=j.selection.createRange(),b&&(a+=c.text+b),c.text=a,b&&c.moveEnd("character",0-b.length),c.moveStart("character",c.End-c.Start),c.select()),x.scrollTop=d,x.focus(),qb()},ub.getRangeHelper=function(){return B},ub.sourceEditorCaret=function(a){var b,c={};return x.focus(),"undefined"!=typeof x.selectionStart?a?(x.selectionStart=a.start,x.selectionEnd=a.end):(c.start=x.selectionStart,c.end=x.selectionEnd):(b=j.selection.createRange(),a?(b.moveEnd("character",a.end),b.moveStart("character",a.start),b.select()):(c.start=b.Start,c.end=b.End)),a?this:c},ub.val=function(a,b){return"string"!=typeof a?ub.inSourceMode()?ub.getSourceEditorValue(!1):ub.getWysiwygEditorValue(b):(ub.inSourceMode()?ub.setSourceEditorValue(a):(b!==!1&&C.hasHandler("toWysiwyg")&&(a=C.callOnlyFirst("toWysiwyg",a)),ub.setWysiwygEditorValue(a)),ub)},ub.insert=function(b,c,d,e,f){if(ub.inSourceMode())return ub.sourceEditorInsertText(b,c),ub;if(c){var g=B.selectedHtml(),h=a("
    ").appendTo(a("body")).hide().html(g);d!==!1&&C.hasHandler("toSource")&&(g=C.callOnlyFirst("toSource",g,h)),h.remove(),b+=g+c}return d!==!1&&C.hasHandler("toWysiwyg")&&(b=C.callOnlyFirst("toWysiwyg",b,!0)),d!==!1&&f===!0&&(b=b.replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&")),ub.wysiwygEditorInsertHtml(b),ub},ub.getWysiwygEditorValue=function(a){var b,c,d=B.hasSelection();return d?B.saveRange():z&&z.getBookmark&&(c=z.getBookmark()),e.fixNesting(u[0]),b=u.html(),a!==!1&&C.hasHandler("toSource")&&(b=C.callOnlyFirst("toSource",b,u)),d?(B.restoreRange(),z=null):c&&(z.moveToBookmark(c),z=null),b},ub.getBody=function(){return u},ub.getContentAreaContainer=function(){return s},ub.getSourceEditorValue=function(a){var b=w.val();return a!==!1&&C.hasHandler("toWysiwyg")&&(b=C.callOnlyFirst("toWysiwyg",b)),b},ub.setWysiwygEditorValue=function(a){a||(a="

    "+(m?"":"
    ")+"

    "),u[0].innerHTML=a,L(u[0]),jb(),qb()},ub.setSourceEditorValue=function(a){w.val(a),qb()},ub.updateOriginal=function(){wb.val(ub.val())},L=function(b){if(p.emoticonsEnabled&&!a(b).parents("code").length){var c=b.ownerDocument,d="\\s| | | | | ",g=[],i=[],j=a.extend({},p.emoticons.more,p.emoticons.dropdown,p.emoticons.hidden);a.each(j,function(a){p.emoticonsCompat&&(i[a]=new RegExp("(>|^|"+d+")"+f.regex(a)+"($|<|"+d+")")),g.push(a)});var k=function(b){for(b=b.firstChild;b;){var d,f,l,m,n,o,q,r=b.parentNode,s=b.nodeValue;if(3!==b.nodeType)a(b).is("code")||k(b);else if(s)for(n=g.length;n--;)f=g[n],q=p.emoticonsCompat?s.search(i[f]):s.indexOf(f),q>-1&&(o=b.nextSibling,l=j[f],d=s.substr(q).split(f),s=s.substr(0,q)+d.shift(),b.nodeValue=s,m=e.parseHTML(h("emoticon",{key:f,url:l.url||l,tooltip:l.tooltip||f}),c),r.insertBefore(m[0],o),r.insertBefore(c.createTextNode(d.join(f)),o));b=b.nextSibling}};k(b),p.emoticonsCompat&&(Bb=u.find("img[data-sceditor-emoticon]"))}},ub.inSourceMode=function(){return q.hasClass("sourceMode")},ub.sourceMode=function(a){var b=ub.inSourceMode();return"boolean"!=typeof a?b:((b&&!a||!b&&a)&&ub.toggleSourceMode(),ub)},ub.toggleSourceMode=function(){var a=ub.inSourceMode();(g.isWysiwygSupported||!a)&&(a||(B.saveRange(),B.clear()),ub.blur(),a?ub.setWysiwygEditorValue(ub.getSourceEditorValue()):ub.setSourceEditorValue(ub.getWysiwygEditorValue()),z=null,w.toggle(),s.toggle(),q.toggleClass("wysiwygMode",a).toggleClass("sourceMode",!a),gb(),hb())},ib=function(){return x.focus(),"undefined"!=typeof x.selectionStart?x.value.substring(x.selectionStart,x.selectionEnd):j.selection.createRange().text},M=function(b,c){ub.inSourceMode()?c.txtExec&&(a.isArray(c.txtExec)?ub.sourceEditorInsertText.apply(ub,c.txtExec):c.txtExec.call(ub,b,ib())):c.exec&&(a.isFunction(c.exec)?c.exec.call(ub,b):ub.execCommand(c.exec,c.hasOwnProperty("execParam")?c.execParam:null))},N=function(){m&&(z=B.selectedRange())},ub.execCommand=function(b,c){var d=!1,e=ub.commands[b],f=a(B.parentNode());if(ub.focus(),!f.is("code")&&0===f.parents("code").length){try{d=v[0].execCommand(b,!1,c)}catch(g){}!d&&e&&e.errorMessage&&alert(ub._(e.errorMessage)),hb()}},kb=function(){function b(){B&&!B.compare(F)&&(F=B.cloneSelected(),q.trigger(a.Event("selectionchanged"))),G=!1}G||(G=!0,m?b():setTimeout(b,100))},lb=function(){var b,c=B.parentNode();D!==c&&(b=D,D=c,E=B.getFirstBlockParent(c),q.trigger(a.Event("nodechanged",{oldNode:b,newNode:D})))},ub.currentNode=function(){return D},ub.currentBlockNode=function(){return E},hb=function(a){var b,c,d="active",e=v[0],f=ub.sourceMode();if(ub.readOnly())return void r.find(d).removeClass(d);f||(c=a?a.newNode:B.parentNode(),b=B.getFirstBlockParent(c));for(var g=0;g-1&&(h=e.queryCommandState(j)?1:0)}catch(l){}}else k||(h=j.call(ub,c,b));i.toggleClass("disabled",k||0>h).toggleClass(d,h>0)}},ab=function(b){var c,d,f,g,h="code,blockquote,pre",i="li,ul,ol";return b.originalEvent.defaultPrevented?void 0:(ub.closeDropDown(),c=a(E).closest(h+","+i).first(),13===b.which&&c.length&&!c.is(i)?(z=null,d=v[0].createElement("br"),B.insertNode(d),n||(f=d.parentNode,g=f.lastChild,g&&3===g.nodeType&&""===g.nodeValue&&(f.removeChild(g),g=f.lastChild),!e.isInline(f,!0)&&g===d&&e.isInline(d.previousSibling)&&B.insertHTML("
    ")),!1):void 0)},jb=function(){var b,c,d,f=u[0];e.rTraverse(f,function(g){return b=g.nodeName.toLowerCase(),a.inArray(b,yb)>-1&&(c=!0),3===g.nodeType&&!/^\s*$/.test(g.nodeValue)||"br"===b||n&&!g.firstChild&&!e.isInline(g,!1)?(c&&(d=v[0].createElement("p"),d.className="sceditor-nlf",d.innerHTML=n?"":"
    ",f.appendChild(d)),!1):void 0})},bb=function(){ub.val(wb.val())},cb=function(){ub.closeDropDown(),z=null},fb=function(){var a=p.height,b=p.width;ub.maximize()?ub.dimensions("100%","100%",!1):(a&&a.toString().indexOf("%")>-1||b&&b.toString().indexOf("%")>-1)&&ub.dimensions(b,a)},ub._=function(){var a,b=arguments;return A&&A[b[0]]&&(b[0]=A[b[0]]),b[0].replace(/\{(\d+)\}/g,function(c,d){return b[d-0+1]!==a?b[d-0+1]:"{"+d+"}"})},db=function(b){C.call(b.type+"Event",b,ub);var c=b.target===x?"scesrc":"scewys",d=a.Event(b);d.type=c+b.type,q.trigger(d,ub)},ub.bind=function(b,c,d,e){b=b.split(" ");for(var f=b.length;f--;)a.isFunction(c)&&(d||q.bind("scewys"+b[f],c),e||q.bind("scesrc"+b[f],c),"valuechanged"===b[f]&&(qb.hasHandler=!0));return ub},ub.unbind=function(b,c,d,e){b=b.split(" ");for(var f=b.length;f--;)a.isFunction(c)&&(d||q.unbind("scewys"+b[f],c),e||q.unbind("scesrc"+b[f],c));return ub},ub.blur=function(b,c,d){return a.isFunction(b)?ub.bind("blur",b,c,d):ub.sourceMode()?w.blur():u.blur(),ub},ub.focus=function(b,c,d){if(a.isFunction(b))ub.bind("focus",b,c,d);else if(ub.inSourceMode())x.focus();else{var e,f=B.selectedRange();F||B.hasSelection()||mb(),!n&&f&&1===f.endOffset&&f.collapsed&&(e=f.endContainer,e&&1===e.childNodes.length&&a(e.firstChild).is("br")&&(f.setStartBefore(e.firstChild),f.collapse(!0),B.selectRange(f))),t.contentWindow.focus(),u[0].focus(),z&&(B.selectRange(z),z=null)}return ub},ub.keyDown=function(a,b,c){return ub.bind("keydown",a,b,c)},ub.keyPress=function(a,b,c){return ub.bind("keypress",a,b,c)},ub.keyUp=function(a,b,c){return ub.bind("keyup",a,b,c)},ub.nodeChanged=function(a){return ub.bind("nodechanged",a,!1,!0)},ub.selectionChanged=function(a){return ub.bind("selectionchanged",a,!1,!0)},ub.valueChanged=function(a,b,c){return ub.bind("valuechanged",a,b,c)},nb=function(b){var c,d=0,e=ub.emoticonsCache,f=String.fromCharCode(b.which);return a(E).is("code")||a(E).parents("code").length?void 0:(e||(e=[],a.each(a.extend({},p.emoticons.more,p.emoticons.dropdown,p.emoticons.hidden),function(a,b){e[d++]=[a,h("emoticon",{key:a,url:b.url||b,tooltip:b.tooltip||a})]}),e.sort(function(a,b){return a[0].length-b[0].length}),ub.emoticonsCache=e,ub.longestEmoticonCode=e[e.length-1][0].length),c=B.raplaceKeyword(ub.emoticonsCache,!0,!0,ub.longestEmoticonCode,p.emoticonsCompat,f),c&&p.emoticonsCompat?(Bb=u.find("img[data-sceditor-emoticon]"),/^\s$/.test(f)):!c)},ob=function(){if(Bb.length){var b,c,d,e,f,g,h=ub.currentBlockNode(),i=!1,j=/[^\s\xA0\u2002\u2003\u2009\u00a0]+/;Bb=a.map(Bb,function(k){return k&&k.parentNode?a.contains(h,k)?(b=k.previousSibling,c=k.nextSibling,f=b.nodeValue,null===f&&(f=b.innerText||""),b&&j.test(b.nodeValue.slice(-1))||c&&j.test((c.nodeValue||"")[0])?(d=k.parentNode,e=B.cloneSelected(),g=e.startContainer,f+=a(k).data("sceditor-emoticon"),g===c?i=f.length+e.startOffset:g===h&&h.childNodes[e.startOffset]===c?i=f.length:g===b&&(i=e.startOffset),c&&3===c.nodeType||(c=d.insertBefore(d.ownerDocument.createTextNode(""),c)),c.insertData(0,f),d.removeChild(b),d.removeChild(k),i!==!1&&(e.setStart(c,i),e.collapse(!0),B.selectRange(e)),null):k):k:null})}},ub.emoticons=function(b){return b||b===!1?(p.emoticonsEnabled=b,b?(u.keypress(nb),ub.sourceMode()||(B.saveRange(),L(u[0]),Bb=u.find("img[data-sceditor-emoticon]"),qb(!1),B.restoreRange())):(u.find("img[data-sceditor-emoticon]").replaceWith(function(){return a(this).data("sceditor-emoticon")}),Bb=[],u.unbind("keypress",nb),qb()),ub):p.emoticonsEnabled},ub.css=function(b){return I||(I=a('

    ',toolbarButton:'
    {dispName}
    ',emoticon:'{key}',fontOpt:'{font}',sizeOpt:'{size}',pastetext:'
    ',table:'
    ',image:'
    ',email:'
    ',link:'
    ',youtubeMenu:'
    ',youtube:''};return function(b,c,d){var e=a[b];return $.each(c,function(a,b){e=e.replace(new RegExp("\\{"+a+"\\}","g"),b)}),d&&(e=$(e)),e}}.call(b,c,b,a),!(void 0!==d&&(a.exports=d))}]),function(a,b,c){"use strict";var d=a.sceditor,e=d.plugins,f=d.escapeEntities,g=d.escapeUriScheme,h=d.ie,i=h&&11>h,j=d.command.get,k={bold:{txtExec:["[b]","[/b]"]},italic:{txtExec:["[i]","[/i]"]},underline:{txtExec:["[u]","[/u]"]},strike:{txtExec:["[s]","[/s]"]},subscript:{txtExec:["[sub]","[/sub]"]},superscript:{txtExec:["[sup]","[/sup]"]},left:{txtExec:["[left]","[/left]"]},center:{txtExec:["[center]","[/center]"]},right:{txtExec:["[right]","[/right]"]},justify:{txtExec:["[justify]","[/justify]"]},font:{txtExec:function(a){var b=this;j("font")._dropDown(b,a,function(a){b.insertText("[font="+a+"]","[/font]")})}},size:{txtExec:function(a){var b=this;j("size")._dropDown(b,a,function(a){b.insertText("[size="+a+"]","[/size]")})}},color:{txtExec:function(a){var b=this;j("color")._dropDown(b,a,function(a){b.insertText("[color="+a+"]","[/color]")})}},bulletlist:{txtExec:function(b,c){var d="";a.each(c.split(/\r?\n/),function(){d+=(d?"\n":"")+"[li]"+this+"[/li]"}),this.insertText("[ul]\n"+d+"\n[/ul]")}},orderedlist:{txtExec:function(b,c){var d="";a.each(c.split(/\r?\n/),function(){d+=(d?"\n":"")+"[li]"+this+"[/li]"}),e.bbcode.bbcode.get(""),this.insertText("[ol]\n"+d+"\n[/ol]")}},table:{txtExec:["[table][tr][td]","[/td][/tr][/table]"]},horizontalrule:{txtExec:["[hr]"]},code:{txtExec:["[code]","[/code]"]},image:{txtExec:function(a,b){var c=this,d=prompt(c._("Enter the image URL:"),b);d&&c.insertText("[img]"+d+"[/img]")}},email:{txtExec:function(a,b){var c=this,d=b&&b.indexOf("@")>-1?null:b,e=prompt(c._("Enter the e-mail address:"),d?"":b),f=prompt(c._("Enter the displayed text:"),d||e)||e;e&&c.insertText("[email="+e+"]"+f+"[/email]")}},link:{txtExec:function(b,c){var d=this,e=/^[a-z]+:\/\//i.test(a.trim(c))?null:c,f=prompt(d._("Enter URL:"),e?"http://":a.trim(c)),g=prompt(d._("Enter the displayed text:"),e||f)||f;f&&d.insertText("[url="+f+"]"+g+"[/url]")}},quote:{txtExec:["[quote]","[/quote]"]},youtube:{txtExec:function(a){var b=this;j("youtube")._dropDown(b,a,function(a){b.insertText("[youtube]"+a+"[/youtube]")})}},rtl:{txtExec:["[rtl]","[/rtl]"]},ltr:{txtExec:["[ltr]","[/ltr]"]}},l=function(a){return a?a.replace(/\\(.)/g,"$1").replace(/^(["'])(.*?)\1$/,"$2"):a},m=function(){var a,b=arguments;return b[0].replace(/\{(\d+)\}/g,function(c,d){return b[d-0+1]!==a?b[d-0+1]:"{"+d+"}"})},n={OPEN:"open",CONTENT:"content",NEWLINE:"newline",CLOSE:"close"},o=function(a,b,c,d,e,f){var g=this;g.type=a,g.name=b,g.val=c,g.attrs=d||{},g.children=e||[],g.closing=f||null};o.prototype={clone:function(a){var b=this;return new o(b.type,b.name,b.val,b.attrs,a?b.children:[],b.closing?b.closing.clone():null)},splitAt:function(b){var c,d=this,e=0,f=d.children.length;if("number"!=typeof b&&(b=a.inArray(b,d.children)),0>b||b>f)return null;for(;f--;)f>=b?e++:f=0;return c=d.clone(),c.children=d.children.splice(b,e),c}};var p=function(b){if(!(this instanceof p))return new p(b);var d,g,j,k,m,q,r,s,t,u,v,w,x,y,z,A=this;d=function(){A.bbcodes=e.bbcode.bbcodes,A.opts=a.extend({},p.defaults,b)},A.tokenize=function(a){var b,c,d,e=[],f=[{type:n.CLOSE,regex:/^\[\/[^\[\]]+\]/},{type:n.OPEN,regex:/^\[[^\[\]]+\]/},{type:n.NEWLINE,regex:/^(\r\n|\r|\n)/},{type:n.CONTENT,regex:/^([^\[\r\n]+|\[)/}];f.reverse();a:for(;a.length;){for(d=f.length;d--;)if(c=f[d].type,(b=a.match(f[d].regex))&&b[0]){e.push(g(c,b[0])),a=a.substr(b[0].length);continue a}a.length&&e.push(g(n.CONTENT,a)),a=""}return e},g=function(b,c){var d,f,g,h=/\[([^\]\s=]+)(?:([^\]]+))?\]/,i=/\[\/([^\[\]]+)\]/;return b===n.OPEN&&(d=c.match(h))&&(g=y(d[1]),d[2]&&(d[2]=a.trim(d[2]))&&(f=j(d[2]))),b===n.CLOSE&&(d=c.match(i))&&(g=y(d[1])),b===n.NEWLINE&&(g="#newline"),g&&(b!==n.OPEN&&b!==n.CLOSE||e.bbcode.bbcodes[g])||(b=n.CONTENT,g="#"),new o(b,g,c,f)},j=function(a){var b,c=/([^\s=]+)=(?:(?:(["'])((?:\\\2|[^\2])*?)\2)|((?:.(?!\s\S+=))*.))/g,d={};if("="===a.charAt(0)&&a.indexOf("=",1)<0)d.defaultattr=l(a.substr(1));else for("="===a.charAt(0)&&(a="defaultattr"+a);b=c.exec(a);)d[y(b[1])]=l(b[3])||b[4];return d},A.parse=function(a,b){var c=k(A.tokenize(a)),d=A.opts;return d.fixInvalidChildren&&t(c),d.removeEmptyTags&&s(c),d.fixInvalidNesting&&q(c),m(c,null,b),d.removeEmptyTags&&s(c),c},w=function(a,b,c){for(var d=c.length;d--;)if(c[d].type===b&&c[d].name===a)return!0;return!1},r=function(b,c){var d=b?A.bbcodes[b.name]:{},e=d.allowedChildren;return A.opts.fixInvalidChildren&&e?a.inArray(c.name||"#",e)>-1:!0},k=function(b){for(var c,d,e,f,g,h,i,j=[],k=[],l=[],m=function(){return z(l)},o=function(a){m()?m().children.push(a):k.push(a)},p=function(b){return m()&&(d=A.bbcodes[m().name])&&d.closedBy&&a.inArray(b,d.closedBy)>-1};c=b.shift();){switch(i=b[0],c.type){case n.OPEN:p(c.name)&&l.pop(),o(c),d=A.bbcodes[c.name],d&&d.isSelfClosing||!d.closedBy&&!w(c.name,n.CLOSE,b)?d&&d.isSelfClosing||(c.type=n.CONTENT):l.push(c);break;case n.CLOSE:if(m()&&c.name!==m().name&&p("/"+c.name)&&l.pop(),m()&&c.name===m().name)m().closing=c,l.pop();else if(w(c.name,n.OPEN,l)){for(;e=l.pop();){if(e.name===c.name){e.closing=c;break}f=e.clone(),j.length>1&&f.children.push(z(j)),j.push(f)}for(o(z(j)),g=j.length;g--;)l.push(j[g]);j.length=0}else c.type=n.CONTENT,o(c);break;case n.NEWLINE:m()&&i&&p((i.type===n.CLOSE?"/":"")+i.name)&&(i.type!==n.CLOSE||i.name!==m().name)&&(d=A.bbcodes[m().name],d&&d.breakAfter?l.pop():d&&d.isInline===!1&&A.opts.breakAfterBlock&&d.breakAfter!==!1&&l.pop()),o(c);break;default:o(c)}h=c}return k},m=function(a,b,c){var d,e,f,g,h,i,j,k,l=a.length;b&&(g=A.bbcodes[b.name]);for(var o=l;o--;)if(d=a[o])if(d.type===n.NEWLINE){if(e=o>0?a[o-1]:null,f=l-1>o?a[o+1]:null,k=!1,!c&&g&&g.isSelfClosing!==!0&&(e?i||f||(g.isInline===!1&&A.opts.breakEndBlock&&g.breakEnd!==!1&&(k=!0),g.breakEnd&&(k=!0),i=k):(g.isInline===!1&&A.opts.breakStartBlock&&g.breakStart!==!1&&(k=!0),g.breakStart&&(k=!0))),e&&e.type===n.OPEN&&(h=A.bbcodes[e.name])&&(c?h.isInline===!1&&(k=!0):(h.isInline===!1&&A.opts.breakAfterBlock&&h.breakAfter!==!1&&(k=!0),h.breakAfter&&(k=!0))),!c&&!j&&f&&f.type===n.OPEN&&(h=A.bbcodes[f.name])&&(h.isInline===!1&&A.opts.breakBeforeBlock&&h.breakBefore!==!1&&(k=!0),h.breakBefore&&(k=!0),j=k,k)){a.splice(o,1);continue}k&&a.splice(o,1),j=!1}else d.type===n.OPEN&&m(d.children,d,c)},q=function(b,c,d,e){var f,g,h,i,j,k,l=function(a){var b=A.bbcodes[a.name];return!b||b.isInline!==!1};for(c=c||[],e=e||b,g=0;g1?c[c.length-2].children:e,i=a.inArray(h,j),i>-1))return k.children.splice(a.inArray(f,k.children),1),void j.splice(i+1,0,f,k);c.push(f),q(f.children,c,d||l(f),e),c.pop(f)}},t=function(a,b){for(var c,d,e=a.length;e--;)(c=a[e])&&(r(b,c)||(c.name=null,c.type=n.CONTENT,r(b,c)?(d=[e+1,0].concat(c.children),c.closing&&(c.closing.name=null,c.closing.type=n.CONTENT,d.push(c.closing)),e+=d.length-1,Array.prototype.splice.apply(a,d)):b.children.splice(e,1)),c.type===n.OPEN&&t(c.children,c))},s=function(b){for(var c,d,e=function(a){for(var b=a.length;b--;){var c=a[b].type;if(c===n.OPEN||c===n.CLOSE)return!1;if(c===n.CONTENT&&/\S|\u00A0/.test(a[b].val))return!1}return!0},f=b.length;f--;)(c=b[f])&&c.type===n.OPEN&&(d=A.bbcodes[c.name],s(c.children),e(c.children)&&d&&!d.isSelfClosing&&!d.allowsEmpty&&b.splice.apply(b,a.merge([f,1],c.children)))},A.toHTML=function(a,b){return u(A.parse(a,b),!0)},u=function(b,d){var g,j,k,l,m,o,p,q,r,s=[];for(q=function(a){return(!a||(a.isHtmlInline!==g?a.isHtmlInline:a.isInline))!==!1};b.length>0;)if(j=b.shift()){if(j.type===n.OPEN)r=j.children[j.children.length-1]||{},k=A.bbcodes[j.name],o=d&&q(k),l=u(j.children,!1),k&&k.html?(q(k)||!q(A.bbcodes[r.name])||k.isPreFormatted||k.skipLastLineBreak||i||(l+="
    "),a.isFunction(k.html)?m=k.html.call(A,j,j.attrs,l):(j.attrs[0]=l,m=e.bbcode.formatBBCodeString(k.html,j.attrs))):m=j.val+l+(j.closing?j.closing.val:"");else{if(j.type===n.NEWLINE){if(!d){s.push("
    ");continue}p||(s.push("
    "),(8>h||c.documentMode&&c.documentMode<8)&&s.push(" ")),i||s.push("
    "),b.length||s.push("
    "),s.push("
    \n"),p=!1;continue}o=d,m=f(j.val,!0)}o&&!p?(s.push("
    "),p=!0):!o&&p&&(s.push("
    \n"),p=!1),s.push(m)}return p&&s.push("
    \n"),s.join("")},A.toBBCode=function(a,b){return v(A.parse(a,b))},v=function(a){for(var b,c,d,e,f,g,h,i,j,k,l=[];a.length>0;)if(b=a.shift())if(d=A.bbcodes[b.name],e=!(!d||d.isInline!==!1),f=d&&d.isSelfClosing,h=e&&A.opts.breakBeforeBlock&&d.breakBefore!==!1||d&&d.breakBefore,i=e&&!f&&A.opts.breakStartBlock&&d.breakStart!==!1||d&&d.breakStart,j=e&&A.opts.breakEndBlock&&d.breakEnd!==!1||d&&d.breakEnd,k=e&&A.opts.breakAfterBlock&&d.breakAfter!==!1||d&&d.breakAfter,g=(d?d.quoteType:null)||A.opts.quoteType||p.QuoteType.auto,d||b.type!==n.OPEN)if(b.type===n.OPEN){if(h&&l.push("\n"),l.push("["+b.name),b.attrs){b.attrs.defaultattr&&(l.push("=",x(b.attrs.defaultattr,g,"defaultattr")),delete b.attrs.defaultattr);for(c in b.attrs)b.attrs.hasOwnProperty(c)&&l.push(" ",c,"=",x(b.attrs[c],g,c))}l.push("]"),i&&l.push("\n"),b.children&&l.push(v(b.children)),f||d.excludeClosing||(j&&l.push("\n"),l.push("[/"+b.name+"]")),k&&l.push("\n"),b.closing&&f&&l.push(b.closing.val)}else l.push(b.val);else l.push(b.val),b.children&&l.push(v(b.children)),b.closing&&l.push(b.closing.val);return l.join("")},x=function(b,c,d){var e=p.QuoteType,f=/\s|=/.test(b);return a.isFunction(c)?c(b,d):c===e.never||c===e.auto&&!f?b:'"'+b.replace("\\","\\\\").replace('"','\\"')+'"'},z=function(a){return a.length?a[a.length-1]:null},y=function(a){return a.toLowerCase()},d()};p.QuoteType={always:1,never:2,auto:3},p.defaults={breakBeforeBlock:!1,breakStartBlock:!1,breakEndBlock:!1,breakAfterBlock:!0,removeEmptyTags:!0,fixInvalidNesting:!0,fixInvalidChildren:!0,quoteType:p.QuoteType.auto},a.sceditorBBCodePlugin=e.bbcode=function(){var b,f,g,h,j=this;j.bbcodes=e.bbcode.bbcodes,j.stripQuotes=l;var n={},o={},q={ul:["li","ol","ul"],ol:["li","ol","ul"],table:["tr"],tr:["td","th"],code:["br","p","div"]};j.init=function(){j.opts=this.opts,b(),this.commands=a.extend(!0,{},k,this.commands),this.toBBCode=j.signalToSource,this.fromBBCode=j.signalToWysiwyg},b=function(){a.each(j.bbcodes,function(b){var c,d=j.bbcodes[b].tags,e=j.bbcodes[b].styles;d&&a.each(d,function(a,d){c=j.bbcodes[b].isInline===!1,n[a]=n[a]||{},n[a][c]=n[a][c]||{},n[a][c][b]=d}),e&&a.each(e,function(a,d){c=j.bbcodes[b].isInline===!1,o[c]=o[c]||{},o[c][a]=o[c][a]||{},o[c][a][b]=d})})},f=function(b,c,e){var f,g,h=d.dom.getStyle;return e=!!e,o[e]?(a.each(o[e],function(d,e){f=h(b[0],d),f&&h(b.parent()[0],d)!==f&&a.each(e,function(d,e){(!e||a.inArray(f.toString(),e)>-1)&&(g=j.bbcodes[d].format,c=a.isFunction(g)?g.call(j,b,c):m(g,c))})}),c):c},g=function(b,c,e){var f,g,h=b[0],k=h.nodeName.toLowerCase();e=!!e,n[k]&&n[k][e]&&a.each(n[k][e],function(d,e){(!e||(f=!1,a.each(e,function(c,d){return!b.attr(c)||d&&a.inArray(b.attr(c),d)<0?void 0:(f=!0,!1)}),f))&&(g=j.bbcodes[d].format,c=a.isFunction(g)?g.call(j,b,c):m(g,c))});var l=d.dom.isInline;if(e&&(!l(h,!0)||"br"===k)){for(var o,p,q,r=h.previousSibling;r&&(a(r).hasClass("sceditor-ignore")||1===r.nodeType&&!a(r).is("br")&&l(r,!0)&&!r.firstChild);)r=r.previousSibling;do{for(p=h.parentNode,q=p.lastChild;a(q).hasClass("sceditor-ignore");)q=q.previousSibling;o=q===h,h=p}while(p&&o&&l(p,!0));(!o||"li"===k||"br"===k&&i)&&(c+="\n"),"br"!==k&&r&&!a(r).is("br")&&l(r,!0)&&(c="\n"+c)}return c},j.signalToSource=function(b,e){var f,g,h=new p(j.opts.parserOptions);return e||("string"==typeof b?(f=a("
    ").css("visibility","hidden").appendTo(c.body).html(b),e=f):e=a(b)),e&&e.jquery?(d.dom.removeWhiteSpace(e[0]),g=j.elementToBbcode(e),f&&f.remove(),g=h.toBBCode(g,!0),j.opts.bbcodeTrim&&(g=a.trim(g)),g):""},j.elementToBbcode=function(b){var c=function(b,e){var h="";return d.dom.traverse(b,function(b){var d=a(b),j="",k=b.nodeType,l=b.nodeName.toLowerCase(),m=q[l],n=b.firstChild,o=!0;if("object"==typeof e&&(o=a.inArray(l,e)>-1,d.is("img")&&d.data("sceditor-emoticon")&&(o=!0),o||(m=e)),3===k||1===k)if(1===k){if(d.hasClass("sceditor-ignore"))return;if(d.hasClass("sceditor-nlf")&&(!n||!i&&1===b.childNodes.length&&/br/i.test(n.nodeName)))return;"iframe"!==l&&(j=c(b,m)),o?("code"!==l&&(j=f(d,j),j=g(d,j),j=f(d,j,!0)),h+=g(d,j,!0)):h+=j}else h+=b.nodeValue},!1,!0),h};return c(b[0])},j.signalToWysiwyg=function(b,c){var d=new p(j.opts.parserOptions),e=d.toHTML(j.opts.bbcodeTrim?a.trim(b):b);return c?h(e):e},h=function(b){var e,f,g,h=a("
    ").hide().appendTo(c.body),j=h[0];return g=function(b,e){if(!d.dom.hasStyling(b)){if(i||1!==b.childNodes.length||!a(b.firstChild).is("br"))for(;f=b.firstChild;)j.insertBefore(f,b);if(e){var g=j.lastChild;b!==g&&a(g).is("div")&&b.nextSibling===g&&j.insertBefore(c.createElement("br"),b)}j.removeChild(b)}},j.innerHTML=b.replace(/<\/div>\n/g,"
    "),(e=j.firstChild)&&a(e).is("div")&&g(e,!0),(e=j.lastChild)&&a(e).is("div")&&g(e),j=j.innerHTML,h.remove(),j}},e.bbcode.formatBBCodeString=function(a,b){return a.replace(/\{([^}]+)\}/g,function(a,c){var d,e=!0;return"!"===c.charAt(0)&&(e=!1,c=c.substring(1)),"0"===c&&(e=!1),b[c]===d?a:e?f(b[c],!0):b[c]})};var q=function(a){return a=parseInt(a,10),isNaN(a)?"00":(a=Math.max(0,Math.min(a,255)).toString(16),a.length<2?"0"+a:a)},r=function(a){var b;return a=a||"#000",(b=a.match(/rgb\((\d{1,3}),\s*?(\d{1,3}),\s*?(\d{1,3})\)/i))?"#"+q(b[1])+q(b[2]-0)+q(b[3]-0):(b=a.match(/#([0-f])([0-f])([0-f])\s*?$/i))?"#"+b[1]+b[1]+b[2]+b[2]+b[3]+b[3]:a -},s={b:{tags:{b:null,strong:null},styles:{"font-weight":["bold","bolder","401","700","800","900"]},format:"[b]{0}[/b]",html:"{0}"},i:{tags:{i:null,em:null},styles:{"font-style":["italic","oblique"]},format:"[i]{0}[/i]",html:"{0}"},u:{tags:{u:null},styles:{"text-decoration":["underline"]},format:"[u]{0}[/u]",html:"{0}"},s:{tags:{s:null,strike:null},styles:{"text-decoration":["line-through"]},format:"[s]{0}[/s]",html:"{0}"},sub:{tags:{sub:null},format:"[sub]{0}[/sub]",html:"{0}"},sup:{tags:{sup:null},format:"[sup]{0}[/sup]",html:"{0}"},font:{tags:{font:{face:null}},styles:{"font-family":null},quoteType:p.QuoteType.never,format:function(a,b){var c;return a.is("font")&&(c=a.attr("face"))||(c=a.css("font-family")),"[font="+l(c)+"]"+b+"[/font]"},html:'{0}'},size:{tags:{font:{size:null}},styles:{"font-size":null},format:function(a,b){var c=a.attr("size"),d=2;return c||(c=a.css("fontSize")),c.indexOf("px")>-1?(c=c.replace("px","")-0,12>c&&(d=1),c>15&&(d=3),c>17&&(d=4),c>23&&(d=5),c>31&&(d=6),c>47&&(d=7)):d=c,"[size="+d+"]"+b+"[/size]"},html:'{!0}'},color:{tags:{font:{color:null}},styles:{color:null},quoteType:p.QuoteType.never,format:function(a,b){var c;return a.is("font")&&(c=a.attr("color"))||(c=a[0].style.color||a.css("color")),"[color="+r(c)+"]"+b+"[/color]"},html:function(a,b,c){return''+c+""}},ul:{tags:{ul:null},breakStart:!0,isInline:!1,skipLastLineBreak:!0,format:"[ul]{0}[/ul]",html:"
      {0}
    "},list:{breakStart:!0,isInline:!1,skipLastLineBreak:!0,html:"
      {0}
    "},ol:{tags:{ol:null},breakStart:!0,isInline:!1,skipLastLineBreak:!0,format:"[ol]{0}[/ol]",html:"
      {0}
    "},li:{tags:{li:null},isInline:!1,closedBy:["/ul","/ol","/list","*","li"],format:"[li]{0}[/li]",html:"
  • {0}
  • "},"*":{isInline:!1,closedBy:["/ul","/ol","/list","*","li"],html:"
  • {0}
  • "},table:{tags:{table:null},isInline:!1,isHtmlInline:!0,skipLastLineBreak:!0,format:"[table]{0}[/table]",html:"{0}
    "},tr:{tags:{tr:null},isInline:!1,skipLastLineBreak:!0,format:"[tr]{0}[/tr]",html:"{0}"},th:{tags:{th:null},allowsEmpty:!0,isInline:!1,format:"[th]{0}[/th]",html:"{0}"},td:{tags:{td:null},allowsEmpty:!0,isInline:!1,format:"[td]{0}[/td]",html:"{0}"},emoticon:{allowsEmpty:!0,tags:{img:{src:null,"data-sceditor-emoticon":null}},format:function(a,b){return a.data("sceditor-emoticon")+b},html:"{0}"},hr:{tags:{hr:null},allowsEmpty:!0,isSelfClosing:!0,isInline:!1,format:"[hr]{0}",html:"
    "},img:{allowsEmpty:!0,tags:{img:{src:null}},allowedChildren:["#"],quoteType:p.QuoteType.never,format:function(a,b){var c,d,e="",f=a[0],g=function(a){return f.style?f.style[a]:null};return a.attr("data-sceditor-emoticon")?b:(c=a.attr("width")||g("width"),d=a.attr("height")||g("height"),(f.complete&&(c||d)||c&&d)&&(e="="+a.width()+"x"+a.height()),"[img"+e+"]"+a.attr("src")+"[/img]")},html:function(a,b,c){var d,e,h,i,j="";return e=b.width,h=b.height,b.defaultattr&&(i=b.defaultattr.split(/x/i),e=i[0],h=2===i.length?i[1]:i[0]),e!==d&&(j+=' width="'+f(e,!0)+'"'),h!==d&&(j+=' height="'+f(h,!0)+'"'),"'}},url:{allowsEmpty:!0,tags:{a:{href:null}},quoteType:p.QuoteType.never,format:function(a,b){var c=a.attr("href");return"mailto:"===c.substr(0,7)?'[email="'+c.substr(7)+'"]'+b+"[/email]":"[url="+c+"]"+b+"[/url]"},html:function(a,b,c){return b.defaultattr=f(b.defaultattr,!0)||c,''+c+""}},email:{quoteType:p.QuoteType.never,html:function(a,b,c){return''+c+""}},quote:{tags:{blockquote:null},isInline:!1,quoteType:p.QuoteType.never,format:function(b,c){var d="",e=a(b),f=e.children("cite").first();return(1===f.length||e.data("author"))&&(d=f.text()||e.data("author"),e.data("author",d),f.remove(),c=this.elementToBbcode(a(b)),d="="+d.replace(/(^\s+|\s+$)/g,""),e.prepend(f)),"[quote"+d+"]"+c+"[/quote]"},html:function(a,b,c){return b.defaultattr&&(c=""+f(b.defaultattr)+""+c),"
    "+c+"
    "}},code:{tags:{code:null},isInline:!1,allowedChildren:["#","#newline"],format:"[code]{0}[/code]",html:"{0}"},left:{styles:{"text-align":["left","-webkit-left","-moz-left","-khtml-left"]},isInline:!1,format:"[left]{0}[/left]",html:'
    {0}
    '},center:{styles:{"text-align":["center","-webkit-center","-moz-center","-khtml-center"]},isInline:!1,format:"[center]{0}[/center]",html:'
    {0}
    '},right:{styles:{"text-align":["right","-webkit-right","-moz-right","-khtml-right"]},isInline:!1,format:"[right]{0}[/right]",html:'
    {0}
    '},justify:{styles:{"text-align":["justify","-webkit-justify","-moz-justify","-khtml-justify"]},isInline:!1,format:"[justify]{0}[/justify]",html:'
    {0}
    '},youtube:{allowsEmpty:!0,tags:{iframe:{"data-youtube-id":null}},format:function(a,b){return a=a.attr("data-youtube-id"),a?"[youtube]"+a+"[/youtube]":b},html:''},rtl:{styles:{direction:["rtl"]},format:"[rtl]{0}[/rtl]",html:'
    {0}
    '},ltr:{styles:{direction:["ltr"]},format:"[ltr]{0}[/ltr]",html:'
    {0}
    '},ignore:{}};e.bbcode.bbcode={get:function(a){return s[a]||null},set:function(b,c){return b&&c?(c=a.extend(s[b]||{},c),c.remove=function(){delete s[b]},s[b]=c,this):!1},rename:function(a,b){return a in s?(s[b]=s[a],delete s[a],this):!1},remove:function(a){return a in s&&delete s[a],this}},a.fn.sceditorBBCodePlugin=function(b){return b=b||{},a.isPlainObject(b)&&(b.plugins=(b.plugins||"")+"bbcode"),this.sceditor(b)},e.bbcode.normaliseColour=r,e.bbcode.formatString=m,e.bbcode.stripQuotes=l,e.bbcode.bbcodes=s,d.BBCodeParser=p}(jQuery,window,document); \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/jquery.sceditor.default.min.css b/html/forums/jscripts/sceditor/jquery.sceditor.default.min.css deleted file mode 100644 index 1fb79d7..0000000 --- a/html/forums/jscripts/sceditor/jquery.sceditor.default.min.css +++ /dev/null @@ -1 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */body,code:before,html,p,table{margin:0;padding:0;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:13px;color:#111}html{height:100%;overflow:auto;-webkit-overflow-scrolling:touch}body{position:relative;overflow:auto;min-height:100%;word-wrap:break-word}ol,ul{margin-top:0;margin-bottom:0;padding-top:0;padding-bottom:0}table,td{border:1px dotted #000;empty-cells:show}code:before{position:absolute;content:'Code:';top:-1.35em;left:0}code{margin-top:1.5em;position:relative;background:#eee;border:1px solid #aaa;white-space:pre;padding:.25em}.ie6 code,.ie7 code{margin-top:0}code,code:before{display:block;text-align:left}blockquote{position:relative;background:#fff6c7;margin:.25em 0;border:1px solid #aaa;padding:.25em}blockquote cite{font-weight:700;display:block;font-size:1em;border-bottom:1px solid #aaa}h1,h2,h3,h4,h5,h6{padding:0;margin:0}div,p{min-height:1.25em} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/jquery.sceditor.min.js b/html/forums/jscripts/sceditor/jquery.sceditor.min.js deleted file mode 100644 index 3e922ce..0000000 --- a/html/forums/jscripts/sceditor/jquery.sceditor.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/* SCEditor v1.4.7 | (C) 2015, Sam Clarke | sceditor.com/license */ -!function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){var d;d=function(){"use strict";var a=c(1),b=c(2),d=c(3),e=c(4),f=c(5);a.sceditor=b,b.commands=c(6),b.defaultOptions=c(7),b.RangeHelper=c(8),b.dom=c(9),b.ie=e.ie,b.ios=e.ios,b.isWysiwygSupported=e.isWysiwygSupported,b.regexEscape=f.regex,b.escapeEntities=f.entities,b.escapeUriScheme=f.uriScheme,b.PluginManager=d,b.plugins=d.plugins,a.fn.sceditor=function(c){var d,f,g=[];return c=c||{},c.runWithoutWysiwygSupport||e.isWysiwygSupported?(this.each(function(){d=this.jquery?this:a(this),f=d.data("sceditor"),d.parents(".sceditor-container").length>0||("state"===c?g.push(!!f):"instance"===c?g.push(f):f||new b(this,c))}),g.length?1===g.length?g[0]:a(g):this):void 0}}.call(b,c,b,a),!(void 0!==d&&(a.exports=d))},function(a){a.exports=jQuery},function(a,b,c){var d;d=function(){"use strict";var a=c(1),b=c(3),d=c(8),e=c(9),f=c(5),g=c(4),h=c(10),i=window,j=document,k=a(i),l=a(j),m=g.ie,n=m&&11>m,o=function(c,p){var q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,_,ab,bb,cb,db,eb,fb,gb,hb,ib,jb,kb,lb,mb,nb,ob,pb,qb,rb,sb,tb,ub=this,vb=c.get?c.get(0):c,wb=a(vb),xb=[],yb=[],zb=[],Ab={},Bb=[],Cb={};ub.commands=a.extend(!0,{},p.commands||o.commands),ub.opts=p=a.extend({},o.defaultOptions,p),K=function(){wb.data("sceditor",ub),a.each(p,function(b,c){a.isPlainObject(c)&&(p[b]=a.extend(!0,{},c))}),p.locale&&"en"!==p.locale&&Q(),q=a('
    ').insertAfter(wb).css("z-index",p.zIndex),m&&q.addClass("ie ie"+m),H=!!wb.attr("required"),wb.removeAttr("required"),P(),W(),R(),O(),U(),S(),T(),g.isWysiwygSupported||ub.toggleSourceMode(),hb();var b=function(){k.unbind("load",b),p.autofocus&&mb(),p.autoExpand&&ub.expandToContent(),fb(),C.call("ready")};k.load(b),j.readyState&&"complete"===j.readyState&&b()},P=function(){var c=p.plugins;c=c?c.toString().split(","):[],C=new b(ub),a.each(c,function(b,c){C.register(a.trim(c))})},Q=function(){var a;A=o.locale[p.locale],A||(a=p.locale.split("-"),A=o.locale[a[0]]),A&&A.dateFormat&&(p.dateFormat=A.dateFormat)},O=function(){var b,c;w=a("").hide(),s=a(''),p.spellcheck||w.attr("spellcheck","false"),"https:"===i.location.protocol&&s.attr("src","javascript:false"),q.append(s).append(w),t=s[0],x=w[0],ub.dimensions(p.width||wb.width(),p.height||wb.height()),b=X(),b.open(),b.write(h("html",{attrs:m?' class="ie ie"'+m:"",spellcheck:p.spellcheck?"":'spellcheck="false"',charset:p.charset,style:p.style})),b.close(),v=a(b),u=a(b.body),ub.readOnly(!!p.readOnly),(g.ios||m)&&(u.height("100%"),m||u.bind("touchend",ub.focus)),c=wb.attr("tabindex"),w.attr("tabindex",c),s.attr("tabindex",c),B=new d(t.contentWindow),ub.val(wb.hide().val())},S=function(){p.autoUpdate&&(u.bind("blur",tb),w.bind("blur",tb)),null===p.rtl&&(p.rtl="rtl"===w.css("direction")),ub.rtl(!!p.rtl),p.autoExpand&&v.bind("keyup",ub.expandToContent),p.resizeEnabled&&V(),q.attr("id",p.id),ub.emoticons(p.emoticonsEnabled)},T=function(){var b=m?"selectionchange":"keyup focus blur contextmenu mouseup touchend click",c="keydown keyup keypress focus blur contextmenu";l.click(eb),a(vb.form).bind("reset",bb).submit(ub.updateOriginal),k.bind("resize orientationChanged",fb),u.keypress(ab).keydown($).keydown(_).keyup(jb).blur(rb).keyup(sb).bind("paste",Y).bind(b,kb).bind(c,db),p.emoticonsCompat&&i.getSelection&&u.keyup(ob),w.blur(rb).keyup(sb).keydown($).bind(c,db),v.mousedown(cb).blur(rb).bind(b,kb).bind("beforedeactivate keyup mouseup",N).keyup(jb).focus(function(){z=null}),q.bind("selectionchanged",lb).bind("selectionchanged",hb).bind("selectionchanged valuechanged nodechanged",db)},R=function(){var b,c=ub.commands,d=(p.toolbarExclude||"").split(","),e=p.toolbar.split("|");r=a('
    '),a.each(e,function(e,f){b=a('
    '),a.each(f.split(","),function(e,f){var g,i,j=c[f];!j||a.inArray(f,d)>-1||(i=j.shortcut,g=h("toolbarButton",{name:f,dispName:ub._(j.tooltip||f)},!0),g.data("sceditor-txtmode",!!j.txtExec).data("sceditor-wysiwygmode",!!j.exec).toggleClass("disabled",!j.exec).mousedown(function(){(!m||9>m)&&(J=!0)}).click(function(){var b=a(this);return b.hasClass("disabled")||M(b,j),hb(),!1}),j.tooltip&&g.attr("title",ub._(j.tooltip)+(i?"("+i+")":"")),i&&ub.addShortcut(i,f),j.state?zb.push({name:f,state:j.state}):"string"==typeof j.exec&&zb.push({name:f,state:j.exec}),b.append(g),Cb[f]=g)}),b[0].firstChild&&r.append(b)}),a(p.toolbarContainer||q).append(r)},U=function(){a.each(ub.commands,function(b,c){c.forceNewLineAfter&&a.isArray(c.forceNewLineAfter)&&(yb=a.merge(yb,c.forceNewLineAfter))}),jb()},V=function(){var b,c,d,e,f,g,h=a('
    '),j=a('
    '),k="touchmove mousemove",n="touchcancel touchend mouseup",o=0,r=0,s=0,t=0,u=0,v=0,w=q.width(),x=q.height(),y=!1,z=ub.rtl();b=p.resizeMinHeight||x/1.5,c=p.resizeMaxHeight||2.5*x,d=p.resizeMinWidth||w/1.25,e=p.resizeMaxWidth||1.25*w,f=function(a){"touchmove"===a.type?(a=i.event,s=a.changedTouches[0].pageX,t=a.changedTouches[0].pageY):(s=a.pageX,t=a.pageY);var f=v+(t-r),g=z?u-(s-o):u+(s-o);e>0&&g>e&&(g=e),d>0&&d>g&&(g=d),p.resizeWidth||(g=!1),c>0&&f>c&&(f=c),b>0&&b>f&&(f=b),p.resizeHeight||(f=!1),(g||f)&&(ub.dimensions(g,f),7>m&&q.height(f)),a.preventDefault()},g=function(a){y&&(y=!1,j.hide(),q.removeClass("resizing").height("auto"),l.unbind(k,f),l.unbind(n,g),a.preventDefault())},q.append(h),q.append(j.hide()),h.bind("touchstart mousedown",function(a){"touchstart"===a.type?(a=i.event,o=a.touches[0].pageX,r=a.touches[0].pageY):(o=a.pageX,r=a.pageY),u=q.width(),v=q.height(),y=!0,q.addClass("resizing"),j.show(),l.bind(k,f),l.bind(n,g),7>m&&q.height(v),a.preventDefault()})},W=function(){var b,c=p.emoticons,d=p.emoticonsRoot;a.isPlainObject(c)&&p.emoticonsEnabled&&a.each(c,function(e,f){a.each(f,function(a,f){d&&(f={url:d+(f.url||f),tooltip:f.tooltip||a},c[e][a]=f),b=j.createElement("img"),b.src=f.url||f,xb.push(b)})})},mb=function(){var b,c,d=v[0],f=u[0],g=f.firstChild,h=!!p.autofocusEnd;if(q.is(":visible")){if(ub.sourceMode())return c=h?x.value.length:0,void(x.setSelectionRange?x.setSelectionRange(c,c):(b=x.createTextRange(),b.moveEnd("character",c),b.collapse(!1),b.select()));if(e.removeWhiteSpace(f),h)for((g=f.lastChild)||(g=d.createElement("p"),u.append(g));g.lastChild;)g=g.lastChild,!n&&a(g).is("br")&&g.previousSibling&&(g=g.previousSibling);d.createRange?(b=d.createRange(),e.canHaveChildren(g)?b.selectNodeContents(g):(b.setStartBefore(g),h&&b.setStartAfter(g))):(b=f.createTextRange(),b.moveToElementText(3!==g.nodeType?g:g.parentNode)),b.collapse(!h),B.selectRange(b),F=b,h&&(v.scrollTop(f.scrollHeight),u.scrollTop(f.scrollHeight)),ub.focus()}},ub.readOnly=function(a){return"boolean"!=typeof a?"readonly"===w.attr("readonly"):(u[0].contentEditable=!a,a?w.attr("readonly","readonly"):w.removeAttr("readonly"),gb(a),ub)},ub.rtl=function(a){var b=a?"rtl":"ltr";return"boolean"!=typeof a?"rtl"===w.attr("dir"):(u.attr("dir",b),w.attr("dir",b),q.removeClass("rtl").removeClass("ltr").addClass(b),ub)},gb=function(b){var c=ub.inSourceMode()?"txtmode":"wysiwygmode";a.each(Cb,function(a,d){b!==!0&&d.data("sceditor-"+c)?d.removeClass("disabled"):d.addClass("disabled")})},ub.width=function(a,b){return a||0===a?(ub.dimensions(a,null,b),ub):q.width()},ub.dimensions=function(a,b,c){var d,e=8>m||j.documentMode<8?2:0;return a=a||0===a?a:!1,b=b||0===b?b:!1,a===!1&&b===!1?{width:ub.width(),height:ub.height()}:(s.data("outerWidthOffset")===d&&ub.updateStyleCache(),a!==!1&&(c!==!1&&(p.width=a),b===!1&&(b=q.height(),c=!1),q.width(a),a&&a.toString().indexOf("%")>-1&&(a=q.width()),s.width(a-s.data("outerWidthOffset")),w.width(a-w.data("outerWidthOffset")),g.ios&&u&&u.width(a-s.data("outerWidthOffset")-(u.outerWidth(!0)-u.width()))),b!==!1&&(c!==!1&&(p.height=b),b&&b.toString().indexOf("%")>-1&&(b=q.height(b).height(),q.height("auto")),b-=p.toolbarContainer?0:r.outerHeight(!0),s.height(b-s.data("outerHeightOffset")),w.height(b-e-w.data("outerHeightOffset"))),ub)},ub.updateStyleCache=function(){s.data("outerWidthOffset",s.outerWidth(!0)-s.width()),w.data("outerWidthOffset",w.outerWidth(!0)-w.width()),s.data("outerHeightOffset",s.outerHeight(!0)-s.height()),w.data("outerHeightOffset",w.outerHeight(!0)-w.height())},ub.height=function(a,b){return a||0===a?(ub.dimensions(null,a,b),ub):q.height()},ub.maximize=function(b){return"undefined"==typeof b?q.is(".sceditor-maximize"):(b=!!b,7>m&&a("html, body").toggleClass("sceditor-maximize",b),q.toggleClass("sceditor-maximize",b),ub.width(b?"100%":p.width,!1),ub.height(b?"100%":p.height,!1),ub)},ub.expandToContent=function(a){var b=q.height(),c=b-s.height(),d=u[0].scrollHeight||v[0].documentElement.scrollHeight,e=p.resizeMaxHeight||2*(p.height||wb.height());d+=c,(a===!0||e>=d)&&d>b&&ub.height(d)},ub.destroy=function(){C&&(C.destroy(),B=null,z=null,C=null,l.unbind("click",eb),k.unbind("resize orientationChanged",fb),a(vb.form).unbind("reset",bb).unbind("submit",ub.updateOriginal),u.unbind(),v.unbind().find("*").remove(),w.unbind().remove(),r.remove(),q.unbind().find("*").unbind().remove(),q.remove(),wb.removeData("sceditor").removeData("sceditorbbcode").show(),H&&wb.attr("required","required"))},ub.createDropDown=function(b,c,d,e){var f,g="sceditor-"+c,h=y&&y.is("."+g);ub.closeDropDown(),h||(e!==!1&&a(d).find(":not(input,textarea)").filter(function(){return 1===this.nodeType}).attr("unselectable","on"),f={top:b.offset().top,left:b.offset().left,marginTop:b.outerHeight()},a.extend(f,p.dropDownCss),y=a('
    ').css(f).append(d).appendTo(a("body")).on("click focusin",function(a){a.stopPropagation()}),setTimeout(function(){y.find("input,textarea").first().focus()}))},eb=function(a){3!==a.which&&y&&(tb(),ub.closeDropDown())},Y=function(a){var b,c,d,e=u[0],f=v[0],g=0,h=j.createElement("div"),i=f.createDocumentFragment(),k=a?a.clipboardData:!1;if(p.disablePasting)return!1;if(p.enablePasteFiltering){if(B.saveRange(),j.body.appendChild(h),k&&k.getData&&((b=k.getData("text/html"))||(b=k.getData("text/plain"))))return h.innerHTML=b,Z(e,h),!1;for(d=u.scrollTop()||v.scrollTop();e.firstChild;)i.appendChild(e.firstChild);return c=function(a,b){if(a.childNodes.length>0||g>25){for(;a.firstChild;)b.appendChild(a.firstChild);for(;i.firstChild;)a.appendChild(i.firstChild);u.scrollTop(d),v.scrollTop(d),b.childNodes.length>0?Z(a,b):B.restoreRange()}else g++,setTimeout(function(){c(a,b)},20)},c(e,h),ub.focus(),!0}},Z=function(b,c){e.fixNesting(c);var d=c.innerHTML;C.hasHandler("toSource")&&(d=C.callOnlyFirst("toSource",d,a(c))),c.parentNode.removeChild(c),C.hasHandler("toWysiwyg")&&(d=C.callOnlyFirst("toWysiwyg",d,!0)),B.restoreRange(),ub.wysiwygEditorInsertHtml(d,null,!0)},ub.closeDropDown=function(a){y&&(y.unbind().remove(),y=null),a===!0&&ub.focus()},X=function(){return t.contentDocument?t.contentDocument:t.contentWindow&&t.contentWindow.document?t.contentWindow.document:t.document},ub.wysiwygEditorInsertHtml=function(b,c,d){var f,g,h,i=s.height();ub.focus(),(d||!a(E).is("code")&&0===a(E).parents("code").length)&&(B.insertHTML(b,c),B.saveRange(),L(u[0]),f=u.find("#sceditor-end-marker").show(),g=u.scrollTop()||v.scrollTop(),h=e.getOffset(f[0]).top+1.5*f.outerHeight(!0)-i,f.hide(),(h>g||g>h+i)&&(u.scrollTop(h),v.scrollTop(h)),qb(!1),B.restoreRange(),jb())},ub.wysiwygEditorInsertText=function(a,b){ub.wysiwygEditorInsertHtml(f.entities(a),f.entities(b))},ub.insertText=function(a,b){return ub.inSourceMode()?ub.sourceEditorInsertText(a,b):ub.wysiwygEditorInsertText(a,b),ub},ub.sourceEditorInsertText=function(a,b){var c,d,e,f=x.selectionStart,g=x.selectionEnd;d=x.scrollTop,x.focus(),"undefined"!=typeof f?(e=x.value,b&&(a+=e.substring(f,g)+b),x.value=e.substring(0,f)+a+e.substring(g,e.length),x.selectionStart=f+a.length-(b?b.length:0),x.selectionEnd=x.selectionStart):(c=j.selection.createRange(),b&&(a+=c.text+b),c.text=a,b&&c.moveEnd("character",0-b.length),c.moveStart("character",c.End-c.Start),c.select()),x.scrollTop=d,x.focus(),qb()},ub.getRangeHelper=function(){return B},ub.sourceEditorCaret=function(a){var b,c={};return x.focus(),"undefined"!=typeof x.selectionStart?a?(x.selectionStart=a.start,x.selectionEnd=a.end):(c.start=x.selectionStart,c.end=x.selectionEnd):(b=j.selection.createRange(),a?(b.moveEnd("character",a.end),b.moveStart("character",a.start),b.select()):(c.start=b.Start,c.end=b.End)),a?this:c},ub.val=function(a,b){return"string"!=typeof a?ub.inSourceMode()?ub.getSourceEditorValue(!1):ub.getWysiwygEditorValue(b):(ub.inSourceMode()?ub.setSourceEditorValue(a):(b!==!1&&C.hasHandler("toWysiwyg")&&(a=C.callOnlyFirst("toWysiwyg",a)),ub.setWysiwygEditorValue(a)),ub)},ub.insert=function(b,c,d,e,f){if(ub.inSourceMode())return ub.sourceEditorInsertText(b,c),ub;if(c){var g=B.selectedHtml(),h=a("
    ").appendTo(a("body")).hide().html(g);d!==!1&&C.hasHandler("toSource")&&(g=C.callOnlyFirst("toSource",g,h)),h.remove(),b+=g+c}return d!==!1&&C.hasHandler("toWysiwyg")&&(b=C.callOnlyFirst("toWysiwyg",b,!0)),d!==!1&&f===!0&&(b=b.replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&")),ub.wysiwygEditorInsertHtml(b),ub},ub.getWysiwygEditorValue=function(a){var b,c,d=B.hasSelection();return d?B.saveRange():z&&z.getBookmark&&(c=z.getBookmark()),e.fixNesting(u[0]),b=u.html(),a!==!1&&C.hasHandler("toSource")&&(b=C.callOnlyFirst("toSource",b,u)),d?(B.restoreRange(),z=null):c&&(z.moveToBookmark(c),z=null),b},ub.getBody=function(){return u},ub.getContentAreaContainer=function(){return s},ub.getSourceEditorValue=function(a){var b=w.val();return a!==!1&&C.hasHandler("toWysiwyg")&&(b=C.callOnlyFirst("toWysiwyg",b)),b},ub.setWysiwygEditorValue=function(a){a||(a="

    "+(m?"":"
    ")+"

    "),u[0].innerHTML=a,L(u[0]),jb(),qb()},ub.setSourceEditorValue=function(a){w.val(a),qb()},ub.updateOriginal=function(){wb.val(ub.val())},L=function(b){if(p.emoticonsEnabled&&!a(b).parents("code").length){var c=b.ownerDocument,d="\\s| | | | | ",g=[],i=[],j=a.extend({},p.emoticons.more,p.emoticons.dropdown,p.emoticons.hidden);a.each(j,function(a){p.emoticonsCompat&&(i[a]=new RegExp("(>|^|"+d+")"+f.regex(a)+"($|<|"+d+")")),g.push(a)});var k=function(b){for(b=b.firstChild;b;){var d,f,l,m,n,o,q,r=b.parentNode,s=b.nodeValue;if(3!==b.nodeType)a(b).is("code")||k(b);else if(s)for(n=g.length;n--;)f=g[n],q=p.emoticonsCompat?s.search(i[f]):s.indexOf(f),q>-1&&(o=b.nextSibling,l=j[f],d=s.substr(q).split(f),s=s.substr(0,q)+d.shift(),b.nodeValue=s,m=e.parseHTML(h("emoticon",{key:f,url:l.url||l,tooltip:l.tooltip||f}),c),r.insertBefore(m[0],o),r.insertBefore(c.createTextNode(d.join(f)),o));b=b.nextSibling}};k(b),p.emoticonsCompat&&(Bb=u.find("img[data-sceditor-emoticon]"))}},ub.inSourceMode=function(){return q.hasClass("sourceMode")},ub.sourceMode=function(a){var b=ub.inSourceMode();return"boolean"!=typeof a?b:((b&&!a||!b&&a)&&ub.toggleSourceMode(),ub)},ub.toggleSourceMode=function(){var a=ub.inSourceMode();(g.isWysiwygSupported||!a)&&(a||(B.saveRange(),B.clear()),ub.blur(),a?ub.setWysiwygEditorValue(ub.getSourceEditorValue()):ub.setSourceEditorValue(ub.getWysiwygEditorValue()),z=null,w.toggle(),s.toggle(),q.toggleClass("wysiwygMode",a).toggleClass("sourceMode",!a),gb(),hb())},ib=function(){return x.focus(),"undefined"!=typeof x.selectionStart?x.value.substring(x.selectionStart,x.selectionEnd):j.selection.createRange().text},M=function(b,c){ub.inSourceMode()?c.txtExec&&(a.isArray(c.txtExec)?ub.sourceEditorInsertText.apply(ub,c.txtExec):c.txtExec.call(ub,b,ib())):c.exec&&(a.isFunction(c.exec)?c.exec.call(ub,b):ub.execCommand(c.exec,c.hasOwnProperty("execParam")?c.execParam:null))},N=function(){m&&(z=B.selectedRange())},ub.execCommand=function(b,c){var d=!1,e=ub.commands[b],f=a(B.parentNode());if(ub.focus(),!f.is("code")&&0===f.parents("code").length){try{d=v[0].execCommand(b,!1,c)}catch(g){}!d&&e&&e.errorMessage&&alert(ub._(e.errorMessage)),hb()}},kb=function(){function b(){B&&!B.compare(F)&&(F=B.cloneSelected(),q.trigger(a.Event("selectionchanged"))),G=!1}G||(G=!0,m?b():setTimeout(b,100))},lb=function(){var b,c=B.parentNode();D!==c&&(b=D,D=c,E=B.getFirstBlockParent(c),q.trigger(a.Event("nodechanged",{oldNode:b,newNode:D})))},ub.currentNode=function(){return D},ub.currentBlockNode=function(){return E},hb=function(a){var b,c,d="active",e=v[0],f=ub.sourceMode();if(ub.readOnly())return void r.find(d).removeClass(d);f||(c=a?a.newNode:B.parentNode(),b=B.getFirstBlockParent(c));for(var g=0;g-1&&(h=e.queryCommandState(j)?1:0)}catch(l){}}else k||(h=j.call(ub,c,b));i.toggleClass("disabled",k||0>h).toggleClass(d,h>0)}},ab=function(b){var c,d,f,g,h="code,blockquote,pre",i="li,ul,ol";return b.originalEvent.defaultPrevented?void 0:(ub.closeDropDown(),c=a(E).closest(h+","+i).first(),13===b.which&&c.length&&!c.is(i)?(z=null,d=v[0].createElement("br"),B.insertNode(d),n||(f=d.parentNode,g=f.lastChild,g&&3===g.nodeType&&""===g.nodeValue&&(f.removeChild(g),g=f.lastChild),!e.isInline(f,!0)&&g===d&&e.isInline(d.previousSibling)&&B.insertHTML("
    ")),!1):void 0)},jb=function(){var b,c,d,f=u[0];e.rTraverse(f,function(g){return b=g.nodeName.toLowerCase(),a.inArray(b,yb)>-1&&(c=!0),3===g.nodeType&&!/^\s*$/.test(g.nodeValue)||"br"===b||n&&!g.firstChild&&!e.isInline(g,!1)?(c&&(d=v[0].createElement("p"),d.className="sceditor-nlf",d.innerHTML=n?"":"
    ",f.appendChild(d)),!1):void 0})},bb=function(){ub.val(wb.val())},cb=function(){ub.closeDropDown(),z=null},fb=function(){var a=p.height,b=p.width;ub.maximize()?ub.dimensions("100%","100%",!1):(a&&a.toString().indexOf("%")>-1||b&&b.toString().indexOf("%")>-1)&&ub.dimensions(b,a)},ub._=function(){var a,b=arguments;return A&&A[b[0]]&&(b[0]=A[b[0]]),b[0].replace(/\{(\d+)\}/g,function(c,d){return b[d-0+1]!==a?b[d-0+1]:"{"+d+"}"})},db=function(b){C.call(b.type+"Event",b,ub);var c=b.target===x?"scesrc":"scewys",d=a.Event(b);d.type=c+b.type,q.trigger(d,ub)},ub.bind=function(b,c,d,e){b=b.split(" ");for(var f=b.length;f--;)a.isFunction(c)&&(d||q.bind("scewys"+b[f],c),e||q.bind("scesrc"+b[f],c),"valuechanged"===b[f]&&(qb.hasHandler=!0));return ub},ub.unbind=function(b,c,d,e){b=b.split(" ");for(var f=b.length;f--;)a.isFunction(c)&&(d||q.unbind("scewys"+b[f],c),e||q.unbind("scesrc"+b[f],c));return ub},ub.blur=function(b,c,d){return a.isFunction(b)?ub.bind("blur",b,c,d):ub.sourceMode()?w.blur():u.blur(),ub},ub.focus=function(b,c,d){if(a.isFunction(b))ub.bind("focus",b,c,d);else if(ub.inSourceMode())x.focus();else{var e,f=B.selectedRange();F||B.hasSelection()||mb(),!n&&f&&1===f.endOffset&&f.collapsed&&(e=f.endContainer,e&&1===e.childNodes.length&&a(e.firstChild).is("br")&&(f.setStartBefore(e.firstChild),f.collapse(!0),B.selectRange(f))),t.contentWindow.focus(),u[0].focus(),z&&(B.selectRange(z),z=null)}return ub},ub.keyDown=function(a,b,c){return ub.bind("keydown",a,b,c)},ub.keyPress=function(a,b,c){return ub.bind("keypress",a,b,c)},ub.keyUp=function(a,b,c){return ub.bind("keyup",a,b,c)},ub.nodeChanged=function(a){return ub.bind("nodechanged",a,!1,!0)},ub.selectionChanged=function(a){return ub.bind("selectionchanged",a,!1,!0)},ub.valueChanged=function(a,b,c){return ub.bind("valuechanged",a,b,c)},nb=function(b){var c,d=0,e=ub.emoticonsCache,f=String.fromCharCode(b.which);if(!a(E).is("code")&&!a(E).parents("code").length)return e||(e=[],a.each(a.extend({},p.emoticons.more,p.emoticons.dropdown,p.emoticons.hidden),function(a,b){e[d++]=[a,h("emoticon",{key:a,url:b.url||b,tooltip:b.tooltip||a})]}),e.sort(function(a,b){return a[0].length-b[0].length}),ub.emoticonsCache=e,ub.longestEmoticonCode=e[e.length-1][0].length),c=B.raplaceKeyword(ub.emoticonsCache,!0,!0,ub.longestEmoticonCode,p.emoticonsCompat,f),c&&p.emoticonsCompat?(Bb=u.find("img[data-sceditor-emoticon]"),/^\s$/.test(f)):!c},ob=function(){if(Bb.length){var b,c,d,e,f,g,h=ub.currentBlockNode(),i=!1,j=/[^\s\xA0\u2002\u2003\u2009\u00a0]+/;Bb=a.map(Bb,function(k){return k&&k.parentNode?a.contains(h,k)?(b=k.previousSibling,c=k.nextSibling,f=b.nodeValue,null===f&&(f=b.innerText||""),b&&j.test(b.nodeValue.slice(-1))||c&&j.test((c.nodeValue||"")[0])?(d=k.parentNode,e=B.cloneSelected(),g=e.startContainer,f+=a(k).data("sceditor-emoticon"),g===c?i=f.length+e.startOffset:g===h&&h.childNodes[e.startOffset]===c?i=f.length:g===b&&(i=e.startOffset),c&&3===c.nodeType||(c=d.insertBefore(d.ownerDocument.createTextNode(""),c)),c.insertData(0,f),d.removeChild(b),d.removeChild(k),i!==!1&&(e.setStart(c,i),e.collapse(!0),B.selectRange(e)),null):k):k:null})}},ub.emoticons=function(b){return b||b===!1?(p.emoticonsEnabled=b,b?(u.keypress(nb),ub.sourceMode()||(B.saveRange(),L(u[0]),Bb=u.find("img[data-sceditor-emoticon]"),qb(!1),B.restoreRange())):(u.find("img[data-sceditor-emoticon]").replaceWith(function(){return a(this).data("sceditor-emoticon")}),Bb=[],u.unbind("keypress",nb),qb()),ub):p.emoticonsEnabled},ub.css=function(b){return I||(I=a('

    ',toolbarButton:'
    {dispName}
    ',emoticon:'{key}',fontOpt:'{font}',sizeOpt:'{size}',pastetext:'
    ',table:'
    ',image:'
    ',email:'
    ',link:'
    ',youtubeMenu:'
    ',youtube:''};return function(b,c,d){var e=a[b];return $.each(c,function(a,b){e=e.replace(new RegExp("\\{"+a+"\\}","g"),b)}),d&&(e=$(e)),e}}.call(b,c,b,a),!(void 0!==d&&(a.exports=d))}]); \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/jquery.sceditor.xhtml.min.js b/html/forums/jscripts/sceditor/jquery.sceditor.xhtml.min.js deleted file mode 100644 index 5d1da15..0000000 --- a/html/forums/jscripts/sceditor/jquery.sceditor.xhtml.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/* SCEditor v1.4.7 | (C) 2015, Sam Clarke | sceditor.com/license */ -!function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){var d;d=function(){"use strict";var a=c(1),b=c(2),d=c(3),e=c(4),f=c(5);a.sceditor=b,b.commands=c(6),b.defaultOptions=c(7),b.RangeHelper=c(8),b.dom=c(9),b.ie=e.ie,b.ios=e.ios,b.isWysiwygSupported=e.isWysiwygSupported,b.regexEscape=f.regex,b.escapeEntities=f.entities,b.escapeUriScheme=f.uriScheme,b.PluginManager=d,b.plugins=d.plugins,a.fn.sceditor=function(c){var d,f,g=[];return c=c||{},c.runWithoutWysiwygSupport||e.isWysiwygSupported?(this.each(function(){d=this.jquery?this:a(this),f=d.data("sceditor"),d.parents(".sceditor-container").length>0||("state"===c?g.push(!!f):"instance"===c?g.push(f):f||new b(this,c))}),g.length?1===g.length?g[0]:a(g):this):void 0}}.call(b,c,b,a),!(void 0!==d&&(a.exports=d))},function(a){a.exports=jQuery},function(a,b,c){var d;d=function(){"use strict";var a=c(1),b=c(3),d=c(8),e=c(9),f=c(5),g=c(4),h=c(10),i=window,j=document,k=a(i),l=a(j),m=g.ie,n=m&&11>m,o=function(c,p){var q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,_,ab,bb,cb,db,eb,fb,gb,hb,ib,jb,kb,lb,mb,nb,ob,pb,qb,rb,sb,tb,ub=this,vb=c.get?c.get(0):c,wb=a(vb),xb=[],yb=[],zb=[],Ab={},Bb=[],Cb={};ub.commands=a.extend(!0,{},p.commands||o.commands),ub.opts=p=a.extend({},o.defaultOptions,p),K=function(){wb.data("sceditor",ub),a.each(p,function(b,c){a.isPlainObject(c)&&(p[b]=a.extend(!0,{},c))}),p.locale&&"en"!==p.locale&&Q(),q=a('
    ').insertAfter(wb).css("z-index",p.zIndex),m&&q.addClass("ie ie"+m),H=!!wb.attr("required"),wb.removeAttr("required"),P(),W(),R(),O(),U(),S(),T(),g.isWysiwygSupported||ub.toggleSourceMode(),hb();var b=function(){k.unbind("load",b),p.autofocus&&mb(),p.autoExpand&&ub.expandToContent(),fb(),C.call("ready")};k.load(b),j.readyState&&"complete"===j.readyState&&b()},P=function(){var c=p.plugins;c=c?c.toString().split(","):[],C=new b(ub),a.each(c,function(b,c){C.register(a.trim(c))})},Q=function(){var a;A=o.locale[p.locale],A||(a=p.locale.split("-"),A=o.locale[a[0]]),A&&A.dateFormat&&(p.dateFormat=A.dateFormat)},O=function(){var b,c;w=a("").hide(),s=a(''),p.spellcheck||w.attr("spellcheck","false"),"https:"===i.location.protocol&&s.attr("src","javascript:false"),q.append(s).append(w),t=s[0],x=w[0],ub.dimensions(p.width||wb.width(),p.height||wb.height()),b=X(),b.open(),b.write(h("html",{attrs:m?' class="ie ie"'+m:"",spellcheck:p.spellcheck?"":'spellcheck="false"',charset:p.charset,style:p.style})),b.close(),v=a(b),u=a(b.body),ub.readOnly(!!p.readOnly),(g.ios||m)&&(u.height("100%"),m||u.bind("touchend",ub.focus)),c=wb.attr("tabindex"),w.attr("tabindex",c),s.attr("tabindex",c),B=new d(t.contentWindow),ub.val(wb.hide().val())},S=function(){p.autoUpdate&&(u.bind("blur",tb),w.bind("blur",tb)),null===p.rtl&&(p.rtl="rtl"===w.css("direction")),ub.rtl(!!p.rtl),p.autoExpand&&v.bind("keyup",ub.expandToContent),p.resizeEnabled&&V(),q.attr("id",p.id),ub.emoticons(p.emoticonsEnabled)},T=function(){var b=m?"selectionchange":"keyup focus blur contextmenu mouseup touchend click",c="keydown keyup keypress focus blur contextmenu";l.click(eb),a(vb.form).bind("reset",bb).submit(ub.updateOriginal),k.bind("resize orientationChanged",fb),u.keypress(ab).keydown($).keydown(_).keyup(jb).blur(rb).keyup(sb).bind("paste",Y).bind(b,kb).bind(c,db),p.emoticonsCompat&&i.getSelection&&u.keyup(ob),w.blur(rb).keyup(sb).keydown($).bind(c,db),v.mousedown(cb).blur(rb).bind(b,kb).bind("beforedeactivate keyup mouseup",N).keyup(jb).focus(function(){z=null}),q.bind("selectionchanged",lb).bind("selectionchanged",hb).bind("selectionchanged valuechanged nodechanged",db)},R=function(){var b,c=ub.commands,d=(p.toolbarExclude||"").split(","),e=p.toolbar.split("|");r=a('
    '),a.each(e,function(e,f){b=a('
    '),a.each(f.split(","),function(e,f){var g,i,j=c[f];!j||a.inArray(f,d)>-1||(i=j.shortcut,g=h("toolbarButton",{name:f,dispName:ub._(j.tooltip||f)},!0),g.data("sceditor-txtmode",!!j.txtExec).data("sceditor-wysiwygmode",!!j.exec).toggleClass("disabled",!j.exec).mousedown(function(){(!m||9>m)&&(J=!0)}).click(function(){var b=a(this);return b.hasClass("disabled")||M(b,j),hb(),!1}),j.tooltip&&g.attr("title",ub._(j.tooltip)+(i?"("+i+")":"")),i&&ub.addShortcut(i,f),j.state?zb.push({name:f,state:j.state}):"string"==typeof j.exec&&zb.push({name:f,state:j.exec}),b.append(g),Cb[f]=g)}),b[0].firstChild&&r.append(b)}),a(p.toolbarContainer||q).append(r)},U=function(){a.each(ub.commands,function(b,c){c.forceNewLineAfter&&a.isArray(c.forceNewLineAfter)&&(yb=a.merge(yb,c.forceNewLineAfter))}),jb()},V=function(){var b,c,d,e,f,g,h=a('
    '),j=a('
    '),k="touchmove mousemove",n="touchcancel touchend mouseup",o=0,r=0,s=0,t=0,u=0,v=0,w=q.width(),x=q.height(),y=!1,z=ub.rtl();b=p.resizeMinHeight||x/1.5,c=p.resizeMaxHeight||2.5*x,d=p.resizeMinWidth||w/1.25,e=p.resizeMaxWidth||1.25*w,f=function(a){"touchmove"===a.type?(a=i.event,s=a.changedTouches[0].pageX,t=a.changedTouches[0].pageY):(s=a.pageX,t=a.pageY);var f=v+(t-r),g=z?u-(s-o):u+(s-o);e>0&&g>e&&(g=e),d>0&&d>g&&(g=d),p.resizeWidth||(g=!1),c>0&&f>c&&(f=c),b>0&&b>f&&(f=b),p.resizeHeight||(f=!1),(g||f)&&(ub.dimensions(g,f),7>m&&q.height(f)),a.preventDefault()},g=function(a){y&&(y=!1,j.hide(),q.removeClass("resizing").height("auto"),l.unbind(k,f),l.unbind(n,g),a.preventDefault())},q.append(h),q.append(j.hide()),h.bind("touchstart mousedown",function(a){"touchstart"===a.type?(a=i.event,o=a.touches[0].pageX,r=a.touches[0].pageY):(o=a.pageX,r=a.pageY),u=q.width(),v=q.height(),y=!0,q.addClass("resizing"),j.show(),l.bind(k,f),l.bind(n,g),7>m&&q.height(v),a.preventDefault()})},W=function(){var b,c=p.emoticons,d=p.emoticonsRoot;a.isPlainObject(c)&&p.emoticonsEnabled&&a.each(c,function(e,f){a.each(f,function(a,f){d&&(f={url:d+(f.url||f),tooltip:f.tooltip||a},c[e][a]=f),b=j.createElement("img"),b.src=f.url||f,xb.push(b)})})},mb=function(){var b,c,d=v[0],f=u[0],g=f.firstChild,h=!!p.autofocusEnd;if(q.is(":visible")){if(ub.sourceMode())return c=h?x.value.length:0,void(x.setSelectionRange?x.setSelectionRange(c,c):(b=x.createTextRange(),b.moveEnd("character",c),b.collapse(!1),b.select()));if(e.removeWhiteSpace(f),h)for((g=f.lastChild)||(g=d.createElement("p"),u.append(g));g.lastChild;)g=g.lastChild,!n&&a(g).is("br")&&g.previousSibling&&(g=g.previousSibling);d.createRange?(b=d.createRange(),e.canHaveChildren(g)?b.selectNodeContents(g):(b.setStartBefore(g),h&&b.setStartAfter(g))):(b=f.createTextRange(),b.moveToElementText(3!==g.nodeType?g:g.parentNode)),b.collapse(!h),B.selectRange(b),F=b,h&&(v.scrollTop(f.scrollHeight),u.scrollTop(f.scrollHeight)),ub.focus()}},ub.readOnly=function(a){return"boolean"!=typeof a?"readonly"===w.attr("readonly"):(u[0].contentEditable=!a,a?w.attr("readonly","readonly"):w.removeAttr("readonly"),gb(a),ub)},ub.rtl=function(a){var b=a?"rtl":"ltr";return"boolean"!=typeof a?"rtl"===w.attr("dir"):(u.attr("dir",b),w.attr("dir",b),q.removeClass("rtl").removeClass("ltr").addClass(b),ub)},gb=function(b){var c=ub.inSourceMode()?"txtmode":"wysiwygmode";a.each(Cb,function(a,d){b!==!0&&d.data("sceditor-"+c)?d.removeClass("disabled"):d.addClass("disabled")})},ub.width=function(a,b){return a||0===a?(ub.dimensions(a,null,b),ub):q.width()},ub.dimensions=function(a,b,c){var d,e=8>m||j.documentMode<8?2:0;return a=a||0===a?a:!1,b=b||0===b?b:!1,a===!1&&b===!1?{width:ub.width(),height:ub.height()}:(s.data("outerWidthOffset")===d&&ub.updateStyleCache(),a!==!1&&(c!==!1&&(p.width=a),b===!1&&(b=q.height(),c=!1),q.width(a),a&&a.toString().indexOf("%")>-1&&(a=q.width()),s.width(a-s.data("outerWidthOffset")),w.width(a-w.data("outerWidthOffset")),g.ios&&u&&u.width(a-s.data("outerWidthOffset")-(u.outerWidth(!0)-u.width()))),b!==!1&&(c!==!1&&(p.height=b),b&&b.toString().indexOf("%")>-1&&(b=q.height(b).height(),q.height("auto")),b-=p.toolbarContainer?0:r.outerHeight(!0),s.height(b-s.data("outerHeightOffset")),w.height(b-e-w.data("outerHeightOffset"))),ub)},ub.updateStyleCache=function(){s.data("outerWidthOffset",s.outerWidth(!0)-s.width()),w.data("outerWidthOffset",w.outerWidth(!0)-w.width()),s.data("outerHeightOffset",s.outerHeight(!0)-s.height()),w.data("outerHeightOffset",w.outerHeight(!0)-w.height())},ub.height=function(a,b){return a||0===a?(ub.dimensions(null,a,b),ub):q.height()},ub.maximize=function(b){return"undefined"==typeof b?q.is(".sceditor-maximize"):(b=!!b,7>m&&a("html, body").toggleClass("sceditor-maximize",b),q.toggleClass("sceditor-maximize",b),ub.width(b?"100%":p.width,!1),ub.height(b?"100%":p.height,!1),ub)},ub.expandToContent=function(a){var b=q.height(),c=b-s.height(),d=u[0].scrollHeight||v[0].documentElement.scrollHeight,e=p.resizeMaxHeight||2*(p.height||wb.height());d+=c,(a===!0||e>=d)&&d>b&&ub.height(d)},ub.destroy=function(){C&&(C.destroy(),B=null,z=null,C=null,l.unbind("click",eb),k.unbind("resize orientationChanged",fb),a(vb.form).unbind("reset",bb).unbind("submit",ub.updateOriginal),u.unbind(),v.unbind().find("*").remove(),w.unbind().remove(),r.remove(),q.unbind().find("*").unbind().remove(),q.remove(),wb.removeData("sceditor").removeData("sceditorbbcode").show(),H&&wb.attr("required","required"))},ub.createDropDown=function(b,c,d,e){var f,g="sceditor-"+c,h=y&&y.is("."+g);ub.closeDropDown(),h||(e!==!1&&a(d).find(":not(input,textarea)").filter(function(){return 1===this.nodeType}).attr("unselectable","on"),f={top:b.offset().top,left:b.offset().left,marginTop:b.outerHeight()},a.extend(f,p.dropDownCss),y=a('
    ').css(f).append(d).appendTo(a("body")).on("click focusin",function(a){a.stopPropagation()}),setTimeout(function(){y.find("input,textarea").first().focus()}))},eb=function(a){3!==a.which&&y&&(tb(),ub.closeDropDown())},Y=function(a){var b,c,d,e=u[0],f=v[0],g=0,h=j.createElement("div"),i=f.createDocumentFragment(),k=a?a.clipboardData:!1;if(p.disablePasting)return!1;if(p.enablePasteFiltering){if(B.saveRange(),j.body.appendChild(h),k&&k.getData&&((b=k.getData("text/html"))||(b=k.getData("text/plain"))))return h.innerHTML=b,Z(e,h),!1;for(d=u.scrollTop()||v.scrollTop();e.firstChild;)i.appendChild(e.firstChild);return c=function(a,b){if(a.childNodes.length>0||g>25){for(;a.firstChild;)b.appendChild(a.firstChild);for(;i.firstChild;)a.appendChild(i.firstChild);u.scrollTop(d),v.scrollTop(d),b.childNodes.length>0?Z(a,b):B.restoreRange()}else g++,setTimeout(function(){c(a,b)},20)},c(e,h),ub.focus(),!0}},Z=function(b,c){e.fixNesting(c);var d=c.innerHTML;C.hasHandler("toSource")&&(d=C.callOnlyFirst("toSource",d,a(c))),c.parentNode.removeChild(c),C.hasHandler("toWysiwyg")&&(d=C.callOnlyFirst("toWysiwyg",d,!0)),B.restoreRange(),ub.wysiwygEditorInsertHtml(d,null,!0)},ub.closeDropDown=function(a){y&&(y.unbind().remove(),y=null),a===!0&&ub.focus()},X=function(){return t.contentDocument?t.contentDocument:t.contentWindow&&t.contentWindow.document?t.contentWindow.document:t.document},ub.wysiwygEditorInsertHtml=function(b,c,d){var f,g,h,i=s.height();ub.focus(),(d||!a(E).is("code")&&0===a(E).parents("code").length)&&(B.insertHTML(b,c),B.saveRange(),L(u[0]),f=u.find("#sceditor-end-marker").show(),g=u.scrollTop()||v.scrollTop(),h=e.getOffset(f[0]).top+1.5*f.outerHeight(!0)-i,f.hide(),(h>g||g>h+i)&&(u.scrollTop(h),v.scrollTop(h)),qb(!1),B.restoreRange(),jb())},ub.wysiwygEditorInsertText=function(a,b){ub.wysiwygEditorInsertHtml(f.entities(a),f.entities(b))},ub.insertText=function(a,b){return ub.inSourceMode()?ub.sourceEditorInsertText(a,b):ub.wysiwygEditorInsertText(a,b),ub},ub.sourceEditorInsertText=function(a,b){var c,d,e,f=x.selectionStart,g=x.selectionEnd;d=x.scrollTop,x.focus(),"undefined"!=typeof f?(e=x.value,b&&(a+=e.substring(f,g)+b),x.value=e.substring(0,f)+a+e.substring(g,e.length),x.selectionStart=f+a.length-(b?b.length:0),x.selectionEnd=x.selectionStart):(c=j.selection.createRange(),b&&(a+=c.text+b),c.text=a,b&&c.moveEnd("character",0-b.length),c.moveStart("character",c.End-c.Start),c.select()),x.scrollTop=d,x.focus(),qb()},ub.getRangeHelper=function(){return B},ub.sourceEditorCaret=function(a){var b,c={};return x.focus(),"undefined"!=typeof x.selectionStart?a?(x.selectionStart=a.start,x.selectionEnd=a.end):(c.start=x.selectionStart,c.end=x.selectionEnd):(b=j.selection.createRange(),a?(b.moveEnd("character",a.end),b.moveStart("character",a.start),b.select()):(c.start=b.Start,c.end=b.End)),a?this:c},ub.val=function(a,b){return"string"!=typeof a?ub.inSourceMode()?ub.getSourceEditorValue(!1):ub.getWysiwygEditorValue(b):(ub.inSourceMode()?ub.setSourceEditorValue(a):(b!==!1&&C.hasHandler("toWysiwyg")&&(a=C.callOnlyFirst("toWysiwyg",a)),ub.setWysiwygEditorValue(a)),ub)},ub.insert=function(b,c,d,e,f){if(ub.inSourceMode())return ub.sourceEditorInsertText(b,c),ub;if(c){var g=B.selectedHtml(),h=a("
    ").appendTo(a("body")).hide().html(g);d!==!1&&C.hasHandler("toSource")&&(g=C.callOnlyFirst("toSource",g,h)),h.remove(),b+=g+c}return d!==!1&&C.hasHandler("toWysiwyg")&&(b=C.callOnlyFirst("toWysiwyg",b,!0)),d!==!1&&f===!0&&(b=b.replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&")),ub.wysiwygEditorInsertHtml(b),ub},ub.getWysiwygEditorValue=function(a){var b,c,d=B.hasSelection();return d?B.saveRange():z&&z.getBookmark&&(c=z.getBookmark()),e.fixNesting(u[0]),b=u.html(),a!==!1&&C.hasHandler("toSource")&&(b=C.callOnlyFirst("toSource",b,u)),d?(B.restoreRange(),z=null):c&&(z.moveToBookmark(c),z=null),b},ub.getBody=function(){return u},ub.getContentAreaContainer=function(){return s},ub.getSourceEditorValue=function(a){var b=w.val();return a!==!1&&C.hasHandler("toWysiwyg")&&(b=C.callOnlyFirst("toWysiwyg",b)),b},ub.setWysiwygEditorValue=function(a){a||(a="

    "+(m?"":"
    ")+"

    "),u[0].innerHTML=a,L(u[0]),jb(),qb()},ub.setSourceEditorValue=function(a){w.val(a),qb()},ub.updateOriginal=function(){wb.val(ub.val())},L=function(b){if(p.emoticonsEnabled&&!a(b).parents("code").length){var c=b.ownerDocument,d="\\s| | | | | ",g=[],i=[],j=a.extend({},p.emoticons.more,p.emoticons.dropdown,p.emoticons.hidden);a.each(j,function(a){p.emoticonsCompat&&(i[a]=new RegExp("(>|^|"+d+")"+f.regex(a)+"($|<|"+d+")")),g.push(a)});var k=function(b){for(b=b.firstChild;b;){var d,f,l,m,n,o,q,r=b.parentNode,s=b.nodeValue;if(3!==b.nodeType)a(b).is("code")||k(b);else if(s)for(n=g.length;n--;)f=g[n],q=p.emoticonsCompat?s.search(i[f]):s.indexOf(f),q>-1&&(o=b.nextSibling,l=j[f],d=s.substr(q).split(f),s=s.substr(0,q)+d.shift(),b.nodeValue=s,m=e.parseHTML(h("emoticon",{key:f,url:l.url||l,tooltip:l.tooltip||f}),c),r.insertBefore(m[0],o),r.insertBefore(c.createTextNode(d.join(f)),o));b=b.nextSibling}};k(b),p.emoticonsCompat&&(Bb=u.find("img[data-sceditor-emoticon]"))}},ub.inSourceMode=function(){return q.hasClass("sourceMode")},ub.sourceMode=function(a){var b=ub.inSourceMode();return"boolean"!=typeof a?b:((b&&!a||!b&&a)&&ub.toggleSourceMode(),ub)},ub.toggleSourceMode=function(){var a=ub.inSourceMode();(g.isWysiwygSupported||!a)&&(a||(B.saveRange(),B.clear()),ub.blur(),a?ub.setWysiwygEditorValue(ub.getSourceEditorValue()):ub.setSourceEditorValue(ub.getWysiwygEditorValue()),z=null,w.toggle(),s.toggle(),q.toggleClass("wysiwygMode",a).toggleClass("sourceMode",!a),gb(),hb())},ib=function(){return x.focus(),"undefined"!=typeof x.selectionStart?x.value.substring(x.selectionStart,x.selectionEnd):j.selection.createRange().text},M=function(b,c){ub.inSourceMode()?c.txtExec&&(a.isArray(c.txtExec)?ub.sourceEditorInsertText.apply(ub,c.txtExec):c.txtExec.call(ub,b,ib())):c.exec&&(a.isFunction(c.exec)?c.exec.call(ub,b):ub.execCommand(c.exec,c.hasOwnProperty("execParam")?c.execParam:null))},N=function(){m&&(z=B.selectedRange())},ub.execCommand=function(b,c){var d=!1,e=ub.commands[b],f=a(B.parentNode());if(ub.focus(),!f.is("code")&&0===f.parents("code").length){try{d=v[0].execCommand(b,!1,c)}catch(g){}!d&&e&&e.errorMessage&&alert(ub._(e.errorMessage)),hb()}},kb=function(){function b(){B&&!B.compare(F)&&(F=B.cloneSelected(),q.trigger(a.Event("selectionchanged"))),G=!1}G||(G=!0,m?b():setTimeout(b,100))},lb=function(){var b,c=B.parentNode();D!==c&&(b=D,D=c,E=B.getFirstBlockParent(c),q.trigger(a.Event("nodechanged",{oldNode:b,newNode:D})))},ub.currentNode=function(){return D},ub.currentBlockNode=function(){return E},hb=function(a){var b,c,d="active",e=v[0],f=ub.sourceMode();if(ub.readOnly())return void r.find(d).removeClass(d);f||(c=a?a.newNode:B.parentNode(),b=B.getFirstBlockParent(c));for(var g=0;g-1&&(h=e.queryCommandState(j)?1:0)}catch(l){}}else k||(h=j.call(ub,c,b));i.toggleClass("disabled",k||0>h).toggleClass(d,h>0)}},ab=function(b){var c,d,f,g,h="code,blockquote,pre",i="li,ul,ol";return b.originalEvent.defaultPrevented?void 0:(ub.closeDropDown(),c=a(E).closest(h+","+i).first(),13===b.which&&c.length&&!c.is(i)?(z=null,d=v[0].createElement("br"),B.insertNode(d),n||(f=d.parentNode,g=f.lastChild,g&&3===g.nodeType&&""===g.nodeValue&&(f.removeChild(g),g=f.lastChild),!e.isInline(f,!0)&&g===d&&e.isInline(d.previousSibling)&&B.insertHTML("
    ")),!1):void 0)},jb=function(){var b,c,d,f=u[0];e.rTraverse(f,function(g){return b=g.nodeName.toLowerCase(),a.inArray(b,yb)>-1&&(c=!0),3===g.nodeType&&!/^\s*$/.test(g.nodeValue)||"br"===b||n&&!g.firstChild&&!e.isInline(g,!1)?(c&&(d=v[0].createElement("p"),d.className="sceditor-nlf",d.innerHTML=n?"":"
    ",f.appendChild(d)),!1):void 0})},bb=function(){ub.val(wb.val())},cb=function(){ub.closeDropDown(),z=null},fb=function(){var a=p.height,b=p.width;ub.maximize()?ub.dimensions("100%","100%",!1):(a&&a.toString().indexOf("%")>-1||b&&b.toString().indexOf("%")>-1)&&ub.dimensions(b,a)},ub._=function(){var a,b=arguments;return A&&A[b[0]]&&(b[0]=A[b[0]]),b[0].replace(/\{(\d+)\}/g,function(c,d){return b[d-0+1]!==a?b[d-0+1]:"{"+d+"}"})},db=function(b){C.call(b.type+"Event",b,ub);var c=b.target===x?"scesrc":"scewys",d=a.Event(b);d.type=c+b.type,q.trigger(d,ub)},ub.bind=function(b,c,d,e){b=b.split(" ");for(var f=b.length;f--;)a.isFunction(c)&&(d||q.bind("scewys"+b[f],c),e||q.bind("scesrc"+b[f],c),"valuechanged"===b[f]&&(qb.hasHandler=!0));return ub},ub.unbind=function(b,c,d,e){b=b.split(" ");for(var f=b.length;f--;)a.isFunction(c)&&(d||q.unbind("scewys"+b[f],c),e||q.unbind("scesrc"+b[f],c));return ub},ub.blur=function(b,c,d){return a.isFunction(b)?ub.bind("blur",b,c,d):ub.sourceMode()?w.blur():u.blur(),ub},ub.focus=function(b,c,d){if(a.isFunction(b))ub.bind("focus",b,c,d);else if(ub.inSourceMode())x.focus();else{var e,f=B.selectedRange();F||B.hasSelection()||mb(),!n&&f&&1===f.endOffset&&f.collapsed&&(e=f.endContainer,e&&1===e.childNodes.length&&a(e.firstChild).is("br")&&(f.setStartBefore(e.firstChild),f.collapse(!0),B.selectRange(f))),t.contentWindow.focus(),u[0].focus(),z&&(B.selectRange(z),z=null)}return ub},ub.keyDown=function(a,b,c){return ub.bind("keydown",a,b,c)},ub.keyPress=function(a,b,c){return ub.bind("keypress",a,b,c)},ub.keyUp=function(a,b,c){return ub.bind("keyup",a,b,c)},ub.nodeChanged=function(a){return ub.bind("nodechanged",a,!1,!0)},ub.selectionChanged=function(a){return ub.bind("selectionchanged",a,!1,!0)},ub.valueChanged=function(a,b,c){return ub.bind("valuechanged",a,b,c)},nb=function(b){var c,d=0,e=ub.emoticonsCache,f=String.fromCharCode(b.which);return a(E).is("code")||a(E).parents("code").length?void 0:(e||(e=[],a.each(a.extend({},p.emoticons.more,p.emoticons.dropdown,p.emoticons.hidden),function(a,b){e[d++]=[a,h("emoticon",{key:a,url:b.url||b,tooltip:b.tooltip||a})]}),e.sort(function(a,b){return a[0].length-b[0].length}),ub.emoticonsCache=e,ub.longestEmoticonCode=e[e.length-1][0].length),c=B.raplaceKeyword(ub.emoticonsCache,!0,!0,ub.longestEmoticonCode,p.emoticonsCompat,f),c&&p.emoticonsCompat?(Bb=u.find("img[data-sceditor-emoticon]"),/^\s$/.test(f)):!c)},ob=function(){if(Bb.length){var b,c,d,e,f,g,h=ub.currentBlockNode(),i=!1,j=/[^\s\xA0\u2002\u2003\u2009\u00a0]+/;Bb=a.map(Bb,function(k){return k&&k.parentNode?a.contains(h,k)?(b=k.previousSibling,c=k.nextSibling,f=b.nodeValue,null===f&&(f=b.innerText||""),b&&j.test(b.nodeValue.slice(-1))||c&&j.test((c.nodeValue||"")[0])?(d=k.parentNode,e=B.cloneSelected(),g=e.startContainer,f+=a(k).data("sceditor-emoticon"),g===c?i=f.length+e.startOffset:g===h&&h.childNodes[e.startOffset]===c?i=f.length:g===b&&(i=e.startOffset),c&&3===c.nodeType||(c=d.insertBefore(d.ownerDocument.createTextNode(""),c)),c.insertData(0,f),d.removeChild(b),d.removeChild(k),i!==!1&&(e.setStart(c,i),e.collapse(!0),B.selectRange(e)),null):k):k:null})}},ub.emoticons=function(b){return b||b===!1?(p.emoticonsEnabled=b,b?(u.keypress(nb),ub.sourceMode()||(B.saveRange(),L(u[0]),Bb=u.find("img[data-sceditor-emoticon]"),qb(!1),B.restoreRange())):(u.find("img[data-sceditor-emoticon]").replaceWith(function(){return a(this).data("sceditor-emoticon")}),Bb=[],u.unbind("keypress",nb),qb()),ub):p.emoticonsEnabled},ub.css=function(b){return I||(I=a('

    ',toolbarButton:'
    {dispName}
    ',emoticon:'{key}',fontOpt:'{font}',sizeOpt:'{size}',pastetext:'
    ',table:'
    ',image:'
    ',email:'
    ',link:'
    ',youtubeMenu:'
    ',youtube:''};return function(b,c,d){var e=a[b];return $.each(c,function(a,b){e=e.replace(new RegExp("\\{"+a+"\\}","g"),b)}),d&&(e=$(e)),e}}.call(b,c,b,a),!(void 0!==d&&(a.exports=d))}]),function(a){"use strict";var b=a.sceditor,c=b.plugins,d=b.dom,e={bold:{txtExec:["",""]},italic:{txtExec:["",""]},underline:{txtExec:['',""]},strike:{txtExec:['',""]},subscript:{txtExec:["",""]},superscript:{txtExec:["",""]},left:{txtExec:['
    ',"
    "]},center:{txtExec:['
    ',"
    "]},right:{txtExec:['
    ',"
    "]},justify:{txtExec:['
    ',"
    "]},font:{txtExec:function(a){var c=this;b.command.get("font")._dropDown(c,a,function(a){c.insertText('',"")})}},size:{txtExec:function(a){var c=this;b.command.get("size")._dropDown(c,a,function(a){c.insertText('',"")})}},color:{txtExec:function(a){var c=this;b.command.get("color")._dropDown(c,a,function(a){c.insertText('',"")})}},bulletlist:{txtExec:["
    • ","
    "]},orderedlist:{txtExec:["
    1. ","
    "]},table:{txtExec:["
    ","
    "]},horizontalrule:{txtExec:["
    "]},code:{txtExec:["",""]},image:{txtExec:function(a,b){var c=prompt(this._("Enter the image URL:"),b);c&&this.insertText('')}},email:{txtExec:function(a,b){var c,d,e=b&&b.indexOf("@")>-1?null:b;c=prompt(this._("Enter the e-mail address:"),e?"":b),d=prompt(this._("Enter the displayed text:"),e||c)||c,c&&this.insertText(''+d+"")}},link:{txtExec:function(a,b){var c=b&&b.indexOf("http://")>-1?null:b,d=prompt(this._("Enter URL:"),c?"http://":b),e=prompt(this._("Enter the displayed text:"),c||d)||d;d&&this.insertText(''+e+"")}},quote:{txtExec:["
    ","
    "]},youtube:{txtExec:function(a){var c=this;b.command.get("youtube")._dropDown(c,a,function(a){c.insertText('')})}},rtl:{txtExec:['
    ',"
    "]},ltr:{txtExec:['
    ',"
    "]}};b.XHTMLSerializer=function(){var c,e,f,g,h,i,j,k,l,m,n=this,o={indentStr:" "},p=[],q=0;c=function(a){var b={"&":"&","<":"<",">":">",'"':"""};return a?a.replace(/[&<>"]/g,function(a){return b[a]||a}):""},e=function(a){return a.replace(/[\r\n]/," ").replace(/[^\S|\u00A0]+/g," ")},n.serialize=function(a,b){if(p=[],b)for(a=a.firstChild;a;)f(a),a=a.nextSibling;else f(a);return p.join("")},f=function(a,b){switch(a.nodeType){case 1:var c=a.nodeName.toLowerCase();"!"===c?j(a):h(a,b);break;case 3:k(a,b);break;case 4:i(a);break;case 8:j(a);break;case 9:case 11:g(a);break;case 2:case 5:case 6:case 7:case 10:case 12:}},g=function(a){for(var b=a.firstChild;b;)f(b),b=b.nextSibling},h=function(e,g){var h,i,j,k=e.nodeName.toLowerCase(),n="iframe"===k,o=e.attributes.length,p=e.firstChild,r=g||/pre(?:\-wrap)?$/i.test(a(e).css("whiteSpace")),s=!e.firstChild&&!d.canHaveChildren(e)&&!n;if(!a(e).hasClass("sceditor-ignore")){for(l("<"+k,!g&&m(e));o--;)i=e.attributes[o],(!b.ie||i.specified||"input"===k&&"value"===i.name)&&(j=b.ie<8&&/style/i.test(i.name)?e.style.cssText:i.value,l(" "+i.name.toLowerCase()+'="'+c(j)+'"',!1));for(l(s?" />":">",!1),n||(h=p);h;)q++,f(h,r),h=h.nextSibling,q--;s||l("",!r&&!n&&m(e)&&p&&m(p))}},i=function(a){l("")},j=function(a){l("")},k=function(a,b){var d=a.nodeValue;b||(d=e(d)),d&&l(c(d),!b&&m(a))},l=function(a,b){var c=q;if(b!==!1)for(p.length&&p.push("\n");c--;)p.push(o.indentStr);p.push(a)},m=function(a){var b=a.previousSibling;return 1!==a.nodeType&&b?!d.isInline(b):b||d.isInline(a.parentNode)?!d.isInline(a):!0}},c.xhtml=function(){var f,g,h,i,j,k,l,m=this,n={},o={};m.init=function(){a.isEmptyObject(c.xhtml.converters||{})||a.each(c.xhtml.converters,function(b,c){a.each(c.tags,function(a){n[a]||(n[a]=[]),n[a].push(c)})}),this.commands=a.extend(!0,{},e,this.commands)},m.signalToSource=function(a,c){return c=c.jquery?c[0]:c,f(c),i(c),k(c),l(c),(new b.XHTMLSerializer).serialize(c,!0)},m.signalToWysiwyg=function(a){return a},m.convertTagTo=d.convertElement,g=function(c,d,e){n[c]&&a.each(n[c],function(f,g){g.tags[c]?a.each(g.tags[c],function(c,f){e.getAttributeNode&&(c=e.getAttributeNode(c),!c||b.ie<8&&!c.specified||f&&a.inArray(c.value,f)<0||g.conv.call(m,e,d))}):g.conv&&g.conv.call(m,e,d)})},f=function(b){d.traverse(b,function(b){var c=a(b),d=b.nodeName.toLowerCase();g("*",c,b),g(d,c,b)},!0)},h=function(a,b){var c=a.childNodes,e=a.nodeName.toLowerCase(),f=a.nodeValue,g=c.length;if(b&&"br"===e)return!0;if(!d.canHaveChildren(a))return!1;if(f&&/\S|\u00A0/.test(f))return!1;for(;g--;)if(!h(c[g],!a.previousSibling&&!a.nextSibling))return!1;return!0},i=function(b){d.traverse(b,function(b){var e,f=b.nodeName.toLowerCase(),g="iframe"!==f&&h(b),i=b.parentNode,j=b.nodeType,k=!d.isInline(b),l=b.previousSibling,m=b.nextSibling,n=b.ownerDocument,o=c.xhtml.allowedTags,p=c.xhtml.disallowedTags;if(3!==j&&(4===j?f="!cdata":("!"===f||8===j)&&(f="!comment"),g?e=!0:o&&o.length?e=a.inArray(f,o)<0:p&&p.length&&(e=a.inArray(f,p)>-1),e)){if(!g){for(k&&l&&d.isInline(l)&&i.insertBefore(n.createTextNode(" "),b);b.firstChild;)i.insertBefore(b.firstChild,m);k&&m&&d.isInline(m)&&i.insertBefore(n.createTextNode(" "),m)}i.removeChild(b)}},!0)},j=function(b,c){var d={};return b&&a.extend(d,b),c?(a.each(c,function(b,c){a.isArray(c)?d[b]=a.merge(d[b]||[],c):d[b]||(d[b]=null)}),d):d},l=function(b){var c=[],e=function(){c.length&&(a("

    ",b.ownerDocument).insertBefore(c[0]).append(c),c=[])};d.removeWhiteSpace(b);for(var f=b.firstChild;f;)d.isInline(f)&&!a(f).is(".sceditor-ignore")?c.push(f):e(),f=f.nextSibling;e()},k=function(b){var e,f,g,h,i,k,l=c.xhtml.allowedAttribs,m=l&&!a.isEmptyObject(l),n=c.xhtml.disallowedAttribs,p=n&&!a.isEmptyObject(n);o={},d.traverse(b,function(b){if(b.attributes&&(e=b.nodeName.toLowerCase(),h=b.attributes.length))for(o[e]||(o[e]=m?j(l["*"],l[e]):j(n["*"],n[e]));h--;)f=b.attributes[h],g=f.name,i=o[e][g],k=!1,m?k=null!==i&&(!a.isArray(i)||a.inArray(f.value,i)<0):p&&(k=null===i||a.isArray(i)&&a.inArray(f.value,i)>-1),k&&b.removeAttribute(g)})}},c.xhtml.converters=[{tags:{"*":{width:null}},conv:function(a,b){b.css("width",b.attr("width")).removeAttr("width")}},{tags:{"*":{height:null}},conv:function(a,b){b.css("height",b.attr("height")).removeAttr("height")}},{tags:{li:{value:null}},conv:function(a,c){b.ie<8?a.removeAttribute("value"):c.removeAttr("value")}},{tags:{"*":{text:null}},conv:function(a,b){b.css("color",b.attr("text")).removeAttr("text")}},{tags:{"*":{color:null}},conv:function(a,b){b.css("color",b.attr("color")).removeAttr("color")}},{tags:{"*":{face:null}},conv:function(a,b){b.css("fontFamily",b.attr("face")).removeAttr("face")}},{tags:{"*":{align:null}},conv:function(a,b){b.css("textAlign",b.attr("align")).removeAttr("align")}},{tags:{"*":{border:null}},conv:function(a,b){b.css("borderWidth",b.attr("border")).removeAttr("border")}},{tags:{applet:{name:null},img:{name:null},layer:{name:null},map:{name:null},object:{name:null},param:{name:null}},conv:function(a,b){b.attr("id")||b.attr("id",b.attr("name")),b.removeAttr("name")}},{tags:{"*":{vspace:null}},conv:function(a,b){b.css("marginTop",b.attr("vspace")-0).css("marginBottom",b.attr("vspace")-0).removeAttr("vspace")}},{tags:{"*":{hspace:null}},conv:function(a,b){b.css("marginLeft",b.attr("hspace")-0).css("marginRight",b.attr("hspace")-0).removeAttr("hspace")}},{tags:{hr:{noshade:null}},conv:function(a,b){b.css("borderStyle","solid").removeAttr("noshade")}},{tags:{"*":{nowrap:null}},conv:function(a,b){b.css("white-space","nowrap").removeAttr("nowrap")}},{tags:{big:null},conv:function(b){a(this.convertTagTo(b,"span")).css("fontSize","larger")}},{tags:{small:null},conv:function(b){a(this.convertTagTo(b,"span")).css("fontSize","smaller")}},{tags:{b:null},conv:function(b){a(this.convertTagTo(b,"strong"))}},{tags:{u:null},conv:function(b){a(this.convertTagTo(b,"span")).css("textDecoration","underline")}},{tags:{i:null},conv:function(b){a(this.convertTagTo(b,"em"))}},{tags:{s:null,strike:null},conv:function(b){a(this.convertTagTo(b,"span")).css("textDecoration","line-through")}},{tags:{dir:null},conv:function(a){this.convertTagTo(a,"ul")}},{tags:{center:null},conv:function(b){a(this.convertTagTo(b,"div")).css("textAlign","center")}},{tags:{font:{size:null}},conv:function(a,c){var d=c.css("fontSize"),e=d;"+0"!==e&&(b.ie<9&&(e=10,d>1&&(e=13),d>2&&(e=16),d>3&&(e=18),d>4&&(e=24),d>5&&(e=32),d>6&&(e=48)),c.css("fontSize",e)),c.removeAttr("size")}},{tags:{font:null},conv:function(a){this.convertTagTo(a,"span")}},{tags:{"*":{type:["_moz"]}},conv:function(a,b){b.removeAttr("type")}},{tags:{"*":{_moz_dirty:null}},conv:function(a,b){b.removeAttr("_moz_dirty")}},{tags:{"*":{_moz_editor_bogus_node:null}},conv:function(a,b){b.remove()}}],c.xhtml.allowedAttribs={},c.xhtml.disallowedAttribs={},c.xhtml.allowedTags=[],c.xhtml.disallowedTags=[]}(jQuery); \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.buttons.css b/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.buttons.css deleted file mode 100644 index 1d12561..0000000 --- a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.buttons.css +++ /dev/null @@ -1,143 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -html, body, p, code:before, table { - margin: 0; - padding: 0; - font-family: Tahoma, Verdana, Arial, Sans-Serif; - font-size: 14px; - color: #111; -} - -html { - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - height: 100%; - - /* Needed for iOS scrolling bug fix */ - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -body { - /* Needed for iOS scrolling bug fix */ - position: relative; - overflow: auto; - - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - min-height: 100%; - word-wrap: break-word; -} - -table, td { - border: 1px dotted #000; - - /* Show empty cells so they can be edited */ - empty-cells: show; -} - -code:before { - font-weight: bold; - content: 'Code:'; - display: block; - border-bottom: 1px solid #ccc; - padding: 4px 0 3px 0; - margin-bottom: 10px; -} - -code.phpcodeblock:before { - content: 'PHP Code:' !important; -} - -code { - font-family: Monaco, Consolas, Courier, monospace; - font-size: 13px !important; - padding: 10px; - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - white-space: pre; - display: block; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -.ie6 code, .ie7 code { - margin-top: 0; -} - -code:before, code { - display: block; - text-align: left; -} - -blockquote { - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - padding: 10px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -blockquote cite { - font-weight: bold; - font-style: normal; - display: block; - font-size: 1em; - border-bottom: 1px solid #ccc; - margin-bottom: 10px; - padding-bottom: 3px; -} - -/* prevent divs from being collapsed */ -div { - min-height: 1.25em; -} - -h1, h2, h3, h4, h5, h6 { - padding: 0; - margin: 0; -} - -ul, ol { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} - -img { - max-width: 100%; -} - -font[size="1"] { - font-size: xx-small; -} - -font[size="2"] { - font-size: x-small; -} - -font[size="3"] { - font-size: small; -} - -font[size="4"] { - font-size: medium; -} - -font[size="5"] { - font-size: large; -} - -font[size="6"] { - font-size: x-large; -} - -font[size="7"] { - font-size: xx-large; -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.default.css b/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.default.css deleted file mode 100644 index 1d12561..0000000 --- a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.default.css +++ /dev/null @@ -1,143 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -html, body, p, code:before, table { - margin: 0; - padding: 0; - font-family: Tahoma, Verdana, Arial, Sans-Serif; - font-size: 14px; - color: #111; -} - -html { - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - height: 100%; - - /* Needed for iOS scrolling bug fix */ - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -body { - /* Needed for iOS scrolling bug fix */ - position: relative; - overflow: auto; - - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - min-height: 100%; - word-wrap: break-word; -} - -table, td { - border: 1px dotted #000; - - /* Show empty cells so they can be edited */ - empty-cells: show; -} - -code:before { - font-weight: bold; - content: 'Code:'; - display: block; - border-bottom: 1px solid #ccc; - padding: 4px 0 3px 0; - margin-bottom: 10px; -} - -code.phpcodeblock:before { - content: 'PHP Code:' !important; -} - -code { - font-family: Monaco, Consolas, Courier, monospace; - font-size: 13px !important; - padding: 10px; - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - white-space: pre; - display: block; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -.ie6 code, .ie7 code { - margin-top: 0; -} - -code:before, code { - display: block; - text-align: left; -} - -blockquote { - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - padding: 10px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -blockquote cite { - font-weight: bold; - font-style: normal; - display: block; - font-size: 1em; - border-bottom: 1px solid #ccc; - margin-bottom: 10px; - padding-bottom: 3px; -} - -/* prevent divs from being collapsed */ -div { - min-height: 1.25em; -} - -h1, h2, h3, h4, h5, h6 { - padding: 0; - margin: 0; -} - -ul, ol { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} - -img { - max-width: 100%; -} - -font[size="1"] { - font-size: xx-small; -} - -font[size="2"] { - font-size: x-small; -} - -font[size="3"] { - font-size: small; -} - -font[size="4"] { - font-size: medium; -} - -font[size="5"] { - font-size: large; -} - -font[size="6"] { - font-size: x-large; -} - -font[size="7"] { - font-size: xx-large; -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.modern.css b/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.modern.css deleted file mode 100644 index 1d12561..0000000 --- a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.modern.css +++ /dev/null @@ -1,143 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -html, body, p, code:before, table { - margin: 0; - padding: 0; - font-family: Tahoma, Verdana, Arial, Sans-Serif; - font-size: 14px; - color: #111; -} - -html { - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - height: 100%; - - /* Needed for iOS scrolling bug fix */ - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -body { - /* Needed for iOS scrolling bug fix */ - position: relative; - overflow: auto; - - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - min-height: 100%; - word-wrap: break-word; -} - -table, td { - border: 1px dotted #000; - - /* Show empty cells so they can be edited */ - empty-cells: show; -} - -code:before { - font-weight: bold; - content: 'Code:'; - display: block; - border-bottom: 1px solid #ccc; - padding: 4px 0 3px 0; - margin-bottom: 10px; -} - -code.phpcodeblock:before { - content: 'PHP Code:' !important; -} - -code { - font-family: Monaco, Consolas, Courier, monospace; - font-size: 13px !important; - padding: 10px; - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - white-space: pre; - display: block; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -.ie6 code, .ie7 code { - margin-top: 0; -} - -code:before, code { - display: block; - text-align: left; -} - -blockquote { - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - padding: 10px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -blockquote cite { - font-weight: bold; - font-style: normal; - display: block; - font-size: 1em; - border-bottom: 1px solid #ccc; - margin-bottom: 10px; - padding-bottom: 3px; -} - -/* prevent divs from being collapsed */ -div { - min-height: 1.25em; -} - -h1, h2, h3, h4, h5, h6 { - padding: 0; - margin: 0; -} - -ul, ol { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} - -img { - max-width: 100%; -} - -font[size="1"] { - font-size: xx-small; -} - -font[size="2"] { - font-size: x-small; -} - -font[size="3"] { - font-size: small; -} - -font[size="4"] { - font-size: medium; -} - -font[size="5"] { - font-size: large; -} - -font[size="6"] { - font-size: x-large; -} - -font[size="7"] { - font-size: xx-large; -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.monocons.css b/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.monocons.css deleted file mode 100644 index 1d12561..0000000 --- a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.monocons.css +++ /dev/null @@ -1,143 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -html, body, p, code:before, table { - margin: 0; - padding: 0; - font-family: Tahoma, Verdana, Arial, Sans-Serif; - font-size: 14px; - color: #111; -} - -html { - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - height: 100%; - - /* Needed for iOS scrolling bug fix */ - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -body { - /* Needed for iOS scrolling bug fix */ - position: relative; - overflow: auto; - - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - min-height: 100%; - word-wrap: break-word; -} - -table, td { - border: 1px dotted #000; - - /* Show empty cells so they can be edited */ - empty-cells: show; -} - -code:before { - font-weight: bold; - content: 'Code:'; - display: block; - border-bottom: 1px solid #ccc; - padding: 4px 0 3px 0; - margin-bottom: 10px; -} - -code.phpcodeblock:before { - content: 'PHP Code:' !important; -} - -code { - font-family: Monaco, Consolas, Courier, monospace; - font-size: 13px !important; - padding: 10px; - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - white-space: pre; - display: block; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -.ie6 code, .ie7 code { - margin-top: 0; -} - -code:before, code { - display: block; - text-align: left; -} - -blockquote { - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - padding: 10px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -blockquote cite { - font-weight: bold; - font-style: normal; - display: block; - font-size: 1em; - border-bottom: 1px solid #ccc; - margin-bottom: 10px; - padding-bottom: 3px; -} - -/* prevent divs from being collapsed */ -div { - min-height: 1.25em; -} - -h1, h2, h3, h4, h5, h6 { - padding: 0; - margin: 0; -} - -ul, ol { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} - -img { - max-width: 100%; -} - -font[size="1"] { - font-size: xx-small; -} - -font[size="2"] { - font-size: x-small; -} - -font[size="3"] { - font-size: small; -} - -font[size="4"] { - font-size: medium; -} - -font[size="5"] { - font-size: large; -} - -font[size="6"] { - font-size: x-large; -} - -font[size="7"] { - font-size: xx-large; -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.mybb.css b/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.mybb.css deleted file mode 100644 index 01fe3df..0000000 --- a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.mybb.css +++ /dev/null @@ -1,143 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -html, body, p, code:before, table { - margin: 0; - padding: 0; - font-family: Tahoma, Verdana, Arial, Sans-Serif; - font-size: 14px; - color: #333; -} - -html { - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - height: 100%; - - /* Needed for iOS scrolling bug fix */ - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -body { - /* Needed for iOS scrolling bug fix */ - position: relative; - overflow: auto; - - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - min-height: 100%; - word-wrap: break-word; -} - -table, td { - border: 1px dotted #000; - - /* Show empty cells so they can be edited */ - empty-cells: show; -} - -code:before { - font-weight: bold; - content: 'Code:'; - display: block; - border-bottom: 1px solid #ccc; - padding: 4px 0 3px 0; - margin-bottom: 10px; -} - -code.phpcodeblock:before { - content: 'PHP Code:' !important; -} - -code { - font-family: Monaco, Consolas, Courier, monospace; - font-size: 13px !important; - padding: 10px; - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - white-space: pre; - display: block; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -.ie6 code, .ie7 code { - margin-top: 0; -} - -code:before, code { - display: block; - text-align: left; -} - -blockquote { - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - padding: 10px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -blockquote cite { - font-weight: bold; - font-style: normal; - display: block; - font-size: 1em; - border-bottom: 1px solid #ccc; - margin-bottom: 10px; - padding-bottom: 3px; -} - -/* prevent divs from being collapsed */ -div { - min-height: 1.25em; -} - -h1, h2, h3, h4, h5, h6 { - padding: 0; - margin: 0; -} - -ul, ol { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} - -img { - max-width: 100%; -} - -font[size="1"] { - font-size: xx-small; -} - -font[size="2"] { - font-size: x-small; -} - -font[size="3"] { - font-size: small; -} - -font[size="4"] { - font-size: medium; -} - -font[size="5"] { - font-size: large; -} - -font[size="6"] { - font-size: x-large; -} - -font[size="7"] { - font-size: xx-large; -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.office-toolbar.css b/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.office-toolbar.css deleted file mode 100644 index 1d12561..0000000 --- a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.office-toolbar.css +++ /dev/null @@ -1,143 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -html, body, p, code:before, table { - margin: 0; - padding: 0; - font-family: Tahoma, Verdana, Arial, Sans-Serif; - font-size: 14px; - color: #111; -} - -html { - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - height: 100%; - - /* Needed for iOS scrolling bug fix */ - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -body { - /* Needed for iOS scrolling bug fix */ - position: relative; - overflow: auto; - - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - min-height: 100%; - word-wrap: break-word; -} - -table, td { - border: 1px dotted #000; - - /* Show empty cells so they can be edited */ - empty-cells: show; -} - -code:before { - font-weight: bold; - content: 'Code:'; - display: block; - border-bottom: 1px solid #ccc; - padding: 4px 0 3px 0; - margin-bottom: 10px; -} - -code.phpcodeblock:before { - content: 'PHP Code:' !important; -} - -code { - font-family: Monaco, Consolas, Courier, monospace; - font-size: 13px !important; - padding: 10px; - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - white-space: pre; - display: block; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -.ie6 code, .ie7 code { - margin-top: 0; -} - -code:before, code { - display: block; - text-align: left; -} - -blockquote { - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - padding: 10px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -blockquote cite { - font-weight: bold; - font-style: normal; - display: block; - font-size: 1em; - border-bottom: 1px solid #ccc; - margin-bottom: 10px; - padding-bottom: 3px; -} - -/* prevent divs from being collapsed */ -div { - min-height: 1.25em; -} - -h1, h2, h3, h4, h5, h6 { - padding: 0; - margin: 0; -} - -ul, ol { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} - -img { - max-width: 100%; -} - -font[size="1"] { - font-size: xx-small; -} - -font[size="2"] { - font-size: x-small; -} - -font[size="3"] { - font-size: small; -} - -font[size="4"] { - font-size: medium; -} - -font[size="5"] { - font-size: large; -} - -font[size="6"] { - font-size: x-large; -} - -font[size="7"] { - font-size: xx-large; -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.office.css b/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.office.css deleted file mode 100644 index 1d12561..0000000 --- a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.office.css +++ /dev/null @@ -1,143 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -html, body, p, code:before, table { - margin: 0; - padding: 0; - font-family: Tahoma, Verdana, Arial, Sans-Serif; - font-size: 14px; - color: #111; -} - -html { - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - height: 100%; - - /* Needed for iOS scrolling bug fix */ - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -body { - /* Needed for iOS scrolling bug fix */ - position: relative; - overflow: auto; - - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - min-height: 100%; - word-wrap: break-word; -} - -table, td { - border: 1px dotted #000; - - /* Show empty cells so they can be edited */ - empty-cells: show; -} - -code:before { - font-weight: bold; - content: 'Code:'; - display: block; - border-bottom: 1px solid #ccc; - padding: 4px 0 3px 0; - margin-bottom: 10px; -} - -code.phpcodeblock:before { - content: 'PHP Code:' !important; -} - -code { - font-family: Monaco, Consolas, Courier, monospace; - font-size: 13px !important; - padding: 10px; - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - white-space: pre; - display: block; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -.ie6 code, .ie7 code { - margin-top: 0; -} - -code:before, code { - display: block; - text-align: left; -} - -blockquote { - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - padding: 10px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -blockquote cite { - font-weight: bold; - font-style: normal; - display: block; - font-size: 1em; - border-bottom: 1px solid #ccc; - margin-bottom: 10px; - padding-bottom: 3px; -} - -/* prevent divs from being collapsed */ -div { - min-height: 1.25em; -} - -h1, h2, h3, h4, h5, h6 { - padding: 0; - margin: 0; -} - -ul, ol { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} - -img { - max-width: 100%; -} - -font[size="1"] { - font-size: xx-small; -} - -font[size="2"] { - font-size: x-small; -} - -font[size="3"] { - font-size: small; -} - -font[size="4"] { - font-size: medium; -} - -font[size="5"] { - font-size: large; -} - -font[size="6"] { - font-size: x-large; -} - -font[size="7"] { - font-size: xx-large; -} \ No newline at end of file diff --git a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.square.css b/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.square.css deleted file mode 100644 index 1d12561..0000000 --- a/html/forums/jscripts/sceditor/textarea_styles/jquery.sceditor.square.css +++ /dev/null @@ -1,143 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -html, body, p, code:before, table { - margin: 0; - padding: 0; - font-family: Tahoma, Verdana, Arial, Sans-Serif; - font-size: 14px; - color: #111; -} - -html { - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - height: 100%; - - /* Needed for iOS scrolling bug fix */ - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -body { - /* Needed for iOS scrolling bug fix */ - position: relative; - overflow: auto; - - /* Needed so the cursor will be placed at the end of the content - when the there isn't enought content to fill the full viewport */ - min-height: 100%; - word-wrap: break-word; -} - -table, td { - border: 1px dotted #000; - - /* Show empty cells so they can be edited */ - empty-cells: show; -} - -code:before { - font-weight: bold; - content: 'Code:'; - display: block; - border-bottom: 1px solid #ccc; - padding: 4px 0 3px 0; - margin-bottom: 10px; -} - -code.phpcodeblock:before { - content: 'PHP Code:' !important; -} - -code { - font-family: Monaco, Consolas, Courier, monospace; - font-size: 13px !important; - padding: 10px; - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - white-space: pre; - display: block; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -.ie6 code, .ie7 code { - margin-top: 0; -} - -code:before, code { - display: block; - text-align: left; -} - -blockquote { - position: relative; - background: white; - margin: .25em .05em 0 0; - border: 1px solid #ccc; - padding: 10px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} - -blockquote cite { - font-weight: bold; - font-style: normal; - display: block; - font-size: 1em; - border-bottom: 1px solid #ccc; - margin-bottom: 10px; - padding-bottom: 3px; -} - -/* prevent divs from being collapsed */ -div { - min-height: 1.25em; -} - -h1, h2, h3, h4, h5, h6 { - padding: 0; - margin: 0; -} - -ul, ol { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} - -img { - max-width: 100%; -} - -font[size="1"] { - font-size: xx-small; -} - -font[size="2"] { - font-size: x-small; -} - -font[size="3"] { - font-size: small; -} - -font[size="4"] { - font-size: medium; -} - -font[size="5"] { - font-size: large; -} - -font[size="6"] { - font-size: x-large; -} - -font[size="7"] { - font-size: xx-large; -} \ No newline at end of file diff --git a/html/forums/jscripts/select2/select2-spinner.gif b/html/forums/jscripts/select2/select2-spinner.gif deleted file mode 100644 index 5b33f7e..0000000 Binary files a/html/forums/jscripts/select2/select2-spinner.gif and /dev/null differ diff --git a/html/forums/jscripts/select2/select2.css b/html/forums/jscripts/select2/select2.css deleted file mode 100644 index f851510..0000000 --- a/html/forums/jscripts/select2/select2.css +++ /dev/null @@ -1,696 +0,0 @@ -/* -Version: 3.5.3 Timestamp: Wed Aug 19 21:55:46 EDT 2015 -*/ -.select2-container { - margin: 0; - position: relative; - display: inline-block; - vertical-align: middle; -} - -.select2-container, -.select2-drop, -.select2-search, -.select2-search input { - /* - Force border-box so that % widths fit the parent - container without overlap because of margin/padding. - More Info : http://www.quirksmode.org/css/box.html - */ - -webkit-box-sizing: border-box; /* webkit */ - -moz-box-sizing: border-box; /* firefox */ - box-sizing: border-box; /* css3 */ -} - -.select2-container .select2-choice { - display: block; - height: 26px; - padding: 0 0 0 8px; - overflow: hidden; - position: relative; - - border: 1px solid #aaa; - white-space: nowrap; - line-height: 26px; - color: #444; - text-decoration: none; - - border-radius: 4px; - - background-clip: padding-box; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - background-color: #fff; - background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.5, #fff)); - background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 50%); - background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 50%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0); - background-image: linear-gradient(to top, #eee 0%, #fff 50%); -} - -html[dir="rtl"] .select2-container .select2-choice { - padding: 0 8px 0 0; -} - -.select2-container.select2-drop-above .select2-choice { - border-bottom-color: #aaa; - - border-radius: 0 0 4px 4px; - - background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.9, #fff)); - background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 90%); - background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 90%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); - background-image: linear-gradient(to bottom, #eee 0%, #fff 90%); -} - -.select2-container.select2-allowclear .select2-choice .select2-chosen { - margin-right: 42px; -} - -.select2-container .select2-choice > .select2-chosen { - margin-right: 26px; - display: block; - overflow: hidden; - - white-space: nowrap; - - text-overflow: ellipsis; - float: none; - width: auto; - - /* MyBB modification start - Search container min-width */ - min-width: 120px; - /* MyBB modification end */ -} - -html[dir="rtl"] .select2-container .select2-choice > .select2-chosen { - margin-left: 26px; - margin-right: 0; -} - -.select2-container .select2-choice abbr { - display: none; - width: 12px; - height: 12px; - position: absolute; - right: 24px; - top: 8px; - - font-size: 1px; - text-decoration: none; - - border: 0; - background: url('select2.png') right top no-repeat; - cursor: pointer; - outline: 0; -} - -.select2-container.select2-allowclear .select2-choice abbr { - display: inline-block; -} - -.select2-container .select2-choice abbr:hover { - background-position: right -11px; - cursor: pointer; -} - -.select2-drop-mask { - border: 0; - margin: 0; - padding: 0; - position: fixed; - left: 0; - top: 0; - min-height: 100%; - min-width: 100%; - height: auto; - width: auto; - opacity: 0; - z-index: 9998; - /* styles required for IE to work */ - background-color: #fff; - filter: alpha(opacity=0); -} - -.select2-drop { - width: 100%; - margin-top: -1px; - position: absolute; - z-index: 9999; - top: 100%; - - background: #fff; - color: #000; - border: 1px solid #aaa; - border-top: 0; - - border-radius: 0 0 4px 4px; - - -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); - box-shadow: 0 4px 5px rgba(0, 0, 0, .15); -} - -.select2-drop.select2-drop-above { - margin-top: 1px; - border-top: 1px solid #aaa; - border-bottom: 0; - - border-radius: 4px 4px 0 0; - - -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); - box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); -} - -.select2-drop-active { - border: 1px solid #5897fb; - border-top: none; -} - -.select2-drop.select2-drop-above.select2-drop-active { - border-top: 1px solid #5897fb; -} - -.select2-drop-auto-width { - border-top: 1px solid #aaa; - width: auto; -} - -.select2-container .select2-choice .select2-arrow { - display: inline-block; - width: 18px; - height: 100%; - position: absolute; - right: 0; - top: 0; - - border-left: 1px solid #aaa; - border-radius: 0 4px 4px 0; - - background-clip: padding-box; - - background: #ccc; - background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee)); - background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%); - background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0); - background-image: linear-gradient(to top, #ccc 0%, #eee 60%); -} - -html[dir="rtl"] .select2-container .select2-choice .select2-arrow { - left: 0; - right: auto; - - border-left: none; - border-right: 1px solid #aaa; - border-radius: 4px 0 0 4px; -} - -.select2-container .select2-choice .select2-arrow b { - display: block; - width: 100%; - height: 100%; - background: url('select2.png') no-repeat 0 1px; -} - -html[dir="rtl"] .select2-container .select2-choice .select2-arrow b { - background-position: 2px 1px; -} - -.select2-search { - display: inline-block; - width: 100%; - min-height: 26px; - margin: 0; - padding: 4px 4px 0 4px; - - position: relative; - z-index: 10000; - - white-space: nowrap; -} - -.select2-search input { - width: 100%; - height: auto !important; - min-height: 26px; - padding: 4px 20px 4px 5px; - margin: 0; - - outline: 0; - font-family: sans-serif; - font-size: 1em; - - border: 1px solid #aaa; - border-radius: 0; - - -webkit-box-shadow: none; - box-shadow: none; - - background: #fff url('select2.png') no-repeat 100% -22px; - background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); - background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2.png') no-repeat 100% -22px, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0; -} - -html[dir="rtl"] .select2-search input { - padding: 4px 5px 4px 20px; - - background: #fff url('select2.png') no-repeat -37px -22px; - background: url('select2.png') no-repeat -37px -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); - background: url('select2.png') no-repeat -37px -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2.png') no-repeat -37px -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2.png') no-repeat -37px -22px, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0; -} - -.select2-search input.select2-active { - background: #fff url('select2-spinner.gif') no-repeat 100%; - background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); - background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0; -} - -.select2-container-active .select2-choice, -.select2-container-active .select2-choices { - border: 1px solid #5897fb; - outline: none; - - -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3); - box-shadow: 0 0 5px rgba(0, 0, 0, .3); -} - -.select2-dropdown-open .select2-choice { - border-bottom-color: transparent; - -webkit-box-shadow: 0 1px 0 #fff inset; - box-shadow: 0 1px 0 #fff inset; - - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - - background-color: #eee; - background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee)); - background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%); - background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); - background-image: linear-gradient(to top, #fff 0%, #eee 50%); -} - -.select2-dropdown-open.select2-drop-above .select2-choice, -.select2-dropdown-open.select2-drop-above .select2-choices { - border: 1px solid #5897fb; - border-top-color: transparent; - - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(0.5, #eee)); - background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%); - background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); - background-image: linear-gradient(to bottom, #fff 0%, #eee 50%); -} - -.select2-dropdown-open .select2-choice .select2-arrow { - background: transparent; - border-left: none; - filter: none; -} -html[dir="rtl"] .select2-dropdown-open .select2-choice .select2-arrow { - border-right: none; -} - -.select2-dropdown-open .select2-choice .select2-arrow b { - background-position: -18px 1px; -} - -html[dir="rtl"] .select2-dropdown-open .select2-choice .select2-arrow b { - background-position: -16px 1px; -} - -.select2-hidden-accessible { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -/* results */ -.select2-results { - max-height: 200px; - padding: 0 0 0 4px; - margin: 4px 4px 4px 0; - position: relative; - overflow-x: hidden; - overflow-y: auto; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -html[dir="rtl"] .select2-results { - padding: 0 4px 0 0; - margin: 4px 0 4px 4px; -} - -.select2-results ul.select2-result-sub { - margin: 0; - padding-left: 0; -} - -.select2-results li { - list-style: none; - display: list-item; - background-image: none; -} - -.select2-results li.select2-result-with-children > .select2-result-label { - font-weight: bold; -} - -.select2-results .select2-result-label { - padding: 3px 7px 4px; - margin: 0; - cursor: pointer; - - min-height: 1em; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.select2-results-dept-1 .select2-result-label { padding-left: 20px } -.select2-results-dept-2 .select2-result-label { padding-left: 40px } -.select2-results-dept-3 .select2-result-label { padding-left: 60px } -.select2-results-dept-4 .select2-result-label { padding-left: 80px } -.select2-results-dept-5 .select2-result-label { padding-left: 100px } -.select2-results-dept-6 .select2-result-label { padding-left: 110px } -.select2-results-dept-7 .select2-result-label { padding-left: 120px } - -.select2-results .select2-highlighted { - background: #3875d7; - color: #fff; -} - -.select2-results li em { - background: #feffde; - font-style: normal; -} - -.select2-results .select2-highlighted em { - background: transparent; -} - -.select2-results .select2-highlighted ul { - background: #fff; - color: #000; -} - -.select2-results .select2-no-results, -.select2-results .select2-searching, -.select2-results .select2-ajax-error, -.select2-results .select2-selection-limit { - background: #f4f4f4; - display: list-item; - padding-left: 5px; -} - -/* -disabled look for disabled choices in the results dropdown -*/ -.select2-results .select2-disabled.select2-highlighted { - color: #666; - background: #f4f4f4; - display: list-item; - cursor: default; -} -.select2-results .select2-disabled { - background: #f4f4f4; - display: list-item; - cursor: default; -} - -.select2-results .select2-selected { - display: none; -} - -.select2-more-results.select2-active { - background: #f4f4f4 url('select2-spinner.gif') no-repeat 100%; -} - -.select2-results .select2-ajax-error { - background: rgba(255, 50, 50, .2); -} - -.select2-more-results { - background: #f4f4f4; - display: list-item; -} - -/* disabled styles */ - -.select2-container.select2-container-disabled .select2-choice { - background-color: #f4f4f4; - background-image: none; - border: 1px solid #ddd; - cursor: default; -} - -.select2-container.select2-container-disabled .select2-choice .select2-arrow { - background-color: #f4f4f4; - background-image: none; - border-left: 0; -} - -.select2-container.select2-container-disabled .select2-choice abbr { - display: none; -} - - -/* multiselect */ - -.select2-container-multi .select2-choices { - height: auto !important; - height: 1%; - margin: 0; - padding: 0 5px 0 0; - position: relative; - - border: 1px solid #aaa; - cursor: text; - overflow: hidden; - - background-color: #fff; - background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff)); - background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%); - background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%); - background-image: linear-gradient(to bottom, #eee 1%, #fff 15%); -} - -html[dir="rtl"] .select2-container-multi .select2-choices { - padding: 0 0 0 5px; -} - -.select2-locked { - padding: 3px 5px 3px 5px !important; -} - -.select2-container-multi .select2-choices { - min-height: 26px; -} - -.select2-container-multi.select2-container-active .select2-choices { - border: 1px solid #5897fb; - outline: none; - - -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3); - box-shadow: 0 0 5px rgba(0, 0, 0, .3); -} -.select2-container-multi .select2-choices li { - float: left; - list-style: none; -} -html[dir="rtl"] .select2-container-multi .select2-choices li -{ - float: right; -} -.select2-container-multi .select2-choices .select2-search-field { - margin: 0; - padding: 0; - white-space: nowrap; -} - -.select2-container-multi .select2-choices .select2-search-field input { - padding: 5px; - margin: 1px 0; - - font-family: sans-serif; - font-size: 100%; - color: #666; - outline: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - background: transparent !important; -} - -.select2-container-multi .select2-choices .select2-search-field input.select2-active { - background: #fff url('select2-spinner.gif') no-repeat 100% !important; -} - -.select2-default { - color: #999 !important; -} - -.select2-container-multi .select2-choices .select2-search-choice { - padding: 3px 5px 3px 18px; - margin: 3px 0 3px 5px; - position: relative; - - line-height: 13px; - color: #333; - cursor: default; - border: 1px solid #aaaaaa; - - border-radius: 3px; - - -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05); - box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05); - - background-clip: padding-box; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - background-color: #e4e4e4; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0); - background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee)); - background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); - background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); - background-image: linear-gradient(to bottom, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); -} -html[dir="rtl"] .select2-container-multi .select2-choices .select2-search-choice -{ - margin: 3px 5px 3px 0; - padding: 3px 18px 3px 5px; -} -.select2-container-multi .select2-choices .select2-search-choice .select2-chosen { - cursor: default; -} -.select2-container-multi .select2-choices .select2-search-choice-focus { - background: #d4d4d4; -} - -.select2-search-choice-close { - display: block; - width: 12px; - height: 13px; - position: absolute; - right: 3px; - top: 4px; - - font-size: 1px; - outline: none; - background: url('select2.png') right top no-repeat; -} -html[dir="rtl"] .select2-search-choice-close { - right: auto; - left: 3px; -} - -.select2-container-multi .select2-search-choice-close { - left: 3px; -} - -html[dir="rtl"] .select2-container-multi .select2-search-choice-close { - left: auto; - right: 2px; -} - -.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover { - background-position: right -11px; -} -.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close { - background-position: right -11px; -} - -/* disabled styles */ -.select2-container-multi.select2-container-disabled .select2-choices { - background-color: #f4f4f4; - background-image: none; - border: 1px solid #ddd; - cursor: default; -} - -.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice { - padding: 3px 5px 3px 5px; - border: 1px solid #ddd; - background-image: none; - background-color: #f4f4f4; -} - -.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { display: none; - background: none; -} -/* end multiselect */ - - -.select2-result-selectable .select2-match, -.select2-result-unselectable .select2-match { - text-decoration: underline; -} - -.select2-offscreen, .select2-offscreen:focus { - clip: rect(0 0 0 0) !important; - width: 1px !important; - height: 1px !important; - border: 0 !important; - margin: 0 !important; - padding: 0 !important; - overflow: hidden !important; - position: absolute !important; - outline: 0 !important; - left: 0px !important; - top: 0px !important; -} - -.select2-display-none { - display: none; -} - -.select2-measure-scrollbar { - position: absolute; - top: -10000px; - left: -10000px; - width: 100px; - height: 100px; - overflow: scroll; -} - -/* Retina-ize icons */ - -@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 2dppx) { - .select2-search input, - .select2-search-choice-close, - .select2-container .select2-choice abbr, - .select2-container .select2-choice .select2-arrow b { - background-image: url('select2x2.png') !important; - background-repeat: no-repeat !important; - background-size: 60px 40px !important; - } - - .select2-search input { - background-position: 100% -21px !important; - } -} diff --git a/html/forums/jscripts/select2/select2.min.js b/html/forums/jscripts/select2/select2.min.js deleted file mode 100644 index 22fe4c6..0000000 --- a/html/forums/jscripts/select2/select2.min.js +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2014 Igor Vaynberg - -Version: 3.5.3 Timestamp: Wed Aug 19 21:55:46 EDT 2015 - -This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU -General Public License version 2 (the "GPL License"). You may choose either license to govern your -use of this software only upon the condition that you accept all of the terms of either the Apache -License or the GPL License. - -You may obtain a copy of the Apache License and the GPL License at: - -http://www.apache.org/licenses/LICENSE-2.0 -http://www.gnu.org/licenses/gpl-2.0.html - -Unless required by applicable law or agreed to in writing, software distributed under the Apache License -or the GPL License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -either express or implied. See the Apache License and the GPL License for the specific language governing -permissions and limitations under the Apache License and the GPL License. -*/ -!function(a){"undefined"==typeof a.fn.each2&&a.extend(a.fn,{each2:function(b){for(var c=a([0]),d=-1,e=this.length;++dc;c+=1)if(r(a,b[c]))return c;return-1}function q(){var b=a(l);b.appendTo(document.body);var c={width:b.width()-b[0].clientWidth,height:b.height()-b[0].clientHeight};return b.remove(),c}function r(a,c){return a===c?!0:a===b||c===b?!1:null===a||null===c?!1:a.constructor===String?a+""==c+"":c.constructor===String?c+""==a+"":!1}function s(a,b,c){var d,e,f;if(null===a||a.length<1)return[];for(d=a.split(b),e=0,f=d.length;f>e;e+=1)d[e]=c(d[e]);return d}function t(a){return a.outerWidth(!1)-a.width()}function u(c){var d="keyup-change-value";c.on("keydown",function(){a.data(c,d)===b&&a.data(c,d,c.val())}),c.on("keyup",function(){var e=a.data(c,d);e!==b&&c.val()!==e&&(a.removeData(c,d),c.trigger("keyup-change"))})}function v(c){c.on("mousemove",function(c){var d=h;(d===b||d.x!==c.pageX||d.y!==c.pageY)&&a(c.target).trigger("mousemove-filtered",c)})}function w(a,c,d){d=d||b;var e;return function(){var b=arguments;window.clearTimeout(e),e=window.setTimeout(function(){c.apply(d,b)},a)}}function x(a,b){var c=w(a,function(a){b.trigger("scroll-debounced",a)});b.on("scroll",function(a){p(a.target,b.get())>=0&&c(a)})}function y(a){a[0]!==document.activeElement&&window.setTimeout(function(){var d,b=a[0],c=a.val().length;a.focus();var e=b.offsetWidth>0||b.offsetHeight>0;e&&b===document.activeElement&&(b.setSelectionRange?b.setSelectionRange(c,c):b.createTextRange&&(d=b.createTextRange(),d.collapse(!1),d.select()))},0)}function z(b){b=a(b)[0];var c=0,d=0;if("selectionStart"in b)c=b.selectionStart,d=b.selectionEnd-c;else if("selection"in document){b.focus();var e=document.selection.createRange();d=document.selection.createRange().text.length,e.moveStart("character",-b.value.length),c=e.text.length-d}return{offset:c,length:d}}function A(a){a.preventDefault(),a.stopPropagation()}function B(a){a.preventDefault(),a.stopImmediatePropagation()}function C(b){if(!g){var c=b[0].currentStyle||window.getComputedStyle(b[0],null);g=a(document.createElement("div")).css({position:"absolute",left:"-10000px",top:"-10000px",display:"none",fontSize:c.fontSize,fontFamily:c.fontFamily,fontStyle:c.fontStyle,fontWeight:c.fontWeight,letterSpacing:c.letterSpacing,textTransform:c.textTransform,whiteSpace:"nowrap"}),g.attr("class","select2-sizer"),a(document.body).append(g)}return g.text(b.val()),g.width()}function D(b,c,d){var e,g,f=[];e=a.trim(b.attr("class")),e&&(e=""+e,a(e.split(/\s+/)).each2(function(){0===this.indexOf("select2-")&&f.push(this)})),e=a.trim(c.attr("class")),e&&(e=""+e,a(e.split(/\s+/)).each2(function(){0!==this.indexOf("select2-")&&(g=d(this),g&&f.push(g))})),b.attr("class",f.join(" "))}function E(a,b,c,d){var e=o(a.toUpperCase()).indexOf(o(b.toUpperCase())),f=b.length;return 0>e?(c.push(d(a)),void 0):(c.push(d(a.substring(0,e))),c.push(""),c.push(d(a.substring(e,e+f))),c.push(""),c.push(d(a.substring(e+f,a.length))),void 0)}function F(a){var b={"\\":"\","&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};return String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})}function G(c){var d,e=null,f=c.quietMillis||100,g=c.url,h=this;return function(i){window.clearTimeout(d),d=window.setTimeout(function(){var d=c.data,f=g,j=c.transport||a.fn.select2.ajaxDefaults.transport,k={type:c.type||"GET",cache:c.cache||!1,jsonpCallback:c.jsonpCallback||b,dataType:c.dataType||"json"},l=a.extend({},a.fn.select2.ajaxDefaults.params,k);d=d?d.call(h,i.term,i.page,i.context):null,f="function"==typeof f?f.call(h,i.term,i.page,i.context):f,e&&"function"==typeof e.abort&&e.abort(),c.params&&(a.isFunction(c.params)?a.extend(l,c.params.call(h)):a.extend(l,c.params)),a.extend(l,{url:f,dataType:c.dataType,data:d,success:function(a){var b=c.results(a,i.page,i);i.callback(b)},error:function(a,b,c){var d={hasError:!0,jqXHR:a,textStatus:b,errorThrown:c};i.callback(d)}}),e=j.call(h,l)},f)}}function H(b){var d,e,c=b,f=function(a){return""+a.text};a.isArray(c)&&(e=c,c={results:e}),a.isFunction(c)===!1&&(e=c,c=function(){return e});var g=c();return g.text&&(f=g.text,a.isFunction(f)||(d=g.text,f=function(a){return a[d]})),function(b){var g,d=b.term,e={results:[]};return""===d?(b.callback(c()),void 0):(g=function(c,e){var h,i;if(c=c[0],c.children){h={};for(i in c)c.hasOwnProperty(i)&&(h[i]=c[i]);h.children=[],a(c.children).each2(function(a,b){g(b,h.children)}),(h.children.length||b.matcher(d,f(h),c))&&e.push(h)}else b.matcher(d,f(c),c)&&e.push(c)},a(c().results).each2(function(a,b){g(b,e.results)}),b.callback(e),void 0)}}function I(c){var d=a.isFunction(c);return function(e){var f=e.term,g={results:[]},h=d?c(e):c;a.isArray(h)&&(a(h).each(function(){var a=this.text!==b,c=a?this.text:this;(""===f||e.matcher(f,c))&&g.results.push(a?this:{id:this,text:this})}),e.callback(g))}}function J(b,c){if(a.isFunction(b))return!0;if(!b)return!1;if("string"==typeof b)return!0;throw new Error(c+" must be a string, function, or falsy value")}function K(b,c){if(a.isFunction(b)){var d=Array.prototype.slice.call(arguments,2);return b.apply(c,d)}return b}function L(b){var c=0;return a.each(b,function(a,b){b.children?c+=L(b.children):c++}),c}function M(a,c,d,e){var h,i,j,k,l,f=a,g=!1;if(!e.createSearchChoice||!e.tokenSeparators||e.tokenSeparators.length<1)return b;for(;;){for(i=-1,j=0,k=e.tokenSeparators.length;k>j&&(l=e.tokenSeparators[j],i=a.indexOf(l),!(i>=0));j++);if(0>i)break;if(h=a.substring(0,i),a=a.substring(i+l.length),h.length>0&&(h=e.createSearchChoice.call(this,h,c),h!==b&&null!==h&&e.id(h)!==b&&null!==e.id(h))){for(g=!1,j=0,k=c.length;k>j;j++)if(r(e.id(h),e.id(c[j]))){g=!0;break}g||d(h)}}return f!==a?a:void 0}function N(){var b=this;a.each(arguments,function(a,c){b[c].remove(),b[c]=null})}function O(b,c){var d=function(){};return d.prototype=new b,d.prototype.constructor=d,d.prototype.parent=b.prototype,d.prototype=a.extend(d.prototype,c),d}if(window.Select2===b){var c,d,e,f,g,i,j,h={x:0,y:0},k={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(a){switch(a=a.which?a.which:a){case k.LEFT:case k.RIGHT:case k.UP:case k.DOWN:return!0}return!1},isControl:function(a){var b=a.which;switch(b){case k.SHIFT:case k.CTRL:case k.ALT:return!0}return a.metaKey?!0:!1},isFunctionKey:function(a){return a=a.which?a.which:a,a>=112&&123>=a}},l="

    ",m={"\u24b6":"A","\uff21":"A","\xc0":"A","\xc1":"A","\xc2":"A","\u1ea6":"A","\u1ea4":"A","\u1eaa":"A","\u1ea8":"A","\xc3":"A","\u0100":"A","\u0102":"A","\u1eb0":"A","\u1eae":"A","\u1eb4":"A","\u1eb2":"A","\u0226":"A","\u01e0":"A","\xc4":"A","\u01de":"A","\u1ea2":"A","\xc5":"A","\u01fa":"A","\u01cd":"A","\u0200":"A","\u0202":"A","\u1ea0":"A","\u1eac":"A","\u1eb6":"A","\u1e00":"A","\u0104":"A","\u023a":"A","\u2c6f":"A","\ua732":"AA","\xc6":"AE","\u01fc":"AE","\u01e2":"AE","\ua734":"AO","\ua736":"AU","\ua738":"AV","\ua73a":"AV","\ua73c":"AY","\u24b7":"B","\uff22":"B","\u1e02":"B","\u1e04":"B","\u1e06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24b8":"C","\uff23":"C","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\xc7":"C","\u1e08":"C","\u0187":"C","\u023b":"C","\ua73e":"C","\u24b9":"D","\uff24":"D","\u1e0a":"D","\u010e":"D","\u1e0c":"D","\u1e10":"D","\u1e12":"D","\u1e0e":"D","\u0110":"D","\u018b":"D","\u018a":"D","\u0189":"D","\ua779":"D","\u01f1":"DZ","\u01c4":"DZ","\u01f2":"Dz","\u01c5":"Dz","\u24ba":"E","\uff25":"E","\xc8":"E","\xc9":"E","\xca":"E","\u1ec0":"E","\u1ebe":"E","\u1ec4":"E","\u1ec2":"E","\u1ebc":"E","\u0112":"E","\u1e14":"E","\u1e16":"E","\u0114":"E","\u0116":"E","\xcb":"E","\u1eba":"E","\u011a":"E","\u0204":"E","\u0206":"E","\u1eb8":"E","\u1ec6":"E","\u0228":"E","\u1e1c":"E","\u0118":"E","\u1e18":"E","\u1e1a":"E","\u0190":"E","\u018e":"E","\u24bb":"F","\uff26":"F","\u1e1e":"F","\u0191":"F","\ua77b":"F","\u24bc":"G","\uff27":"G","\u01f4":"G","\u011c":"G","\u1e20":"G","\u011e":"G","\u0120":"G","\u01e6":"G","\u0122":"G","\u01e4":"G","\u0193":"G","\ua7a0":"G","\ua77d":"G","\ua77e":"G","\u24bd":"H","\uff28":"H","\u0124":"H","\u1e22":"H","\u1e26":"H","\u021e":"H","\u1e24":"H","\u1e28":"H","\u1e2a":"H","\u0126":"H","\u2c67":"H","\u2c75":"H","\ua78d":"H","\u24be":"I","\uff29":"I","\xcc":"I","\xcd":"I","\xce":"I","\u0128":"I","\u012a":"I","\u012c":"I","\u0130":"I","\xcf":"I","\u1e2e":"I","\u1ec8":"I","\u01cf":"I","\u0208":"I","\u020a":"I","\u1eca":"I","\u012e":"I","\u1e2c":"I","\u0197":"I","\u24bf":"J","\uff2a":"J","\u0134":"J","\u0248":"J","\u24c0":"K","\uff2b":"K","\u1e30":"K","\u01e8":"K","\u1e32":"K","\u0136":"K","\u1e34":"K","\u0198":"K","\u2c69":"K","\ua740":"K","\ua742":"K","\ua744":"K","\ua7a2":"K","\u24c1":"L","\uff2c":"L","\u013f":"L","\u0139":"L","\u013d":"L","\u1e36":"L","\u1e38":"L","\u013b":"L","\u1e3c":"L","\u1e3a":"L","\u0141":"L","\u023d":"L","\u2c62":"L","\u2c60":"L","\ua748":"L","\ua746":"L","\ua780":"L","\u01c7":"LJ","\u01c8":"Lj","\u24c2":"M","\uff2d":"M","\u1e3e":"M","\u1e40":"M","\u1e42":"M","\u2c6e":"M","\u019c":"M","\u24c3":"N","\uff2e":"N","\u01f8":"N","\u0143":"N","\xd1":"N","\u1e44":"N","\u0147":"N","\u1e46":"N","\u0145":"N","\u1e4a":"N","\u1e48":"N","\u0220":"N","\u019d":"N","\ua790":"N","\ua7a4":"N","\u01ca":"NJ","\u01cb":"Nj","\u24c4":"O","\uff2f":"O","\xd2":"O","\xd3":"O","\xd4":"O","\u1ed2":"O","\u1ed0":"O","\u1ed6":"O","\u1ed4":"O","\xd5":"O","\u1e4c":"O","\u022c":"O","\u1e4e":"O","\u014c":"O","\u1e50":"O","\u1e52":"O","\u014e":"O","\u022e":"O","\u0230":"O","\xd6":"O","\u022a":"O","\u1ece":"O","\u0150":"O","\u01d1":"O","\u020c":"O","\u020e":"O","\u01a0":"O","\u1edc":"O","\u1eda":"O","\u1ee0":"O","\u1ede":"O","\u1ee2":"O","\u1ecc":"O","\u1ed8":"O","\u01ea":"O","\u01ec":"O","\xd8":"O","\u01fe":"O","\u0186":"O","\u019f":"O","\ua74a":"O","\ua74c":"O","\u01a2":"OI","\ua74e":"OO","\u0222":"OU","\u24c5":"P","\uff30":"P","\u1e54":"P","\u1e56":"P","\u01a4":"P","\u2c63":"P","\ua750":"P","\ua752":"P","\ua754":"P","\u24c6":"Q","\uff31":"Q","\ua756":"Q","\ua758":"Q","\u024a":"Q","\u24c7":"R","\uff32":"R","\u0154":"R","\u1e58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1e5a":"R","\u1e5c":"R","\u0156":"R","\u1e5e":"R","\u024c":"R","\u2c64":"R","\ua75a":"R","\ua7a6":"R","\ua782":"R","\u24c8":"S","\uff33":"S","\u1e9e":"S","\u015a":"S","\u1e64":"S","\u015c":"S","\u1e60":"S","\u0160":"S","\u1e66":"S","\u1e62":"S","\u1e68":"S","\u0218":"S","\u015e":"S","\u2c7e":"S","\ua7a8":"S","\ua784":"S","\u24c9":"T","\uff34":"T","\u1e6a":"T","\u0164":"T","\u1e6c":"T","\u021a":"T","\u0162":"T","\u1e70":"T","\u1e6e":"T","\u0166":"T","\u01ac":"T","\u01ae":"T","\u023e":"T","\ua786":"T","\ua728":"TZ","\u24ca":"U","\uff35":"U","\xd9":"U","\xda":"U","\xdb":"U","\u0168":"U","\u1e78":"U","\u016a":"U","\u1e7a":"U","\u016c":"U","\xdc":"U","\u01db":"U","\u01d7":"U","\u01d5":"U","\u01d9":"U","\u1ee6":"U","\u016e":"U","\u0170":"U","\u01d3":"U","\u0214":"U","\u0216":"U","\u01af":"U","\u1eea":"U","\u1ee8":"U","\u1eee":"U","\u1eec":"U","\u1ef0":"U","\u1ee4":"U","\u1e72":"U","\u0172":"U","\u1e76":"U","\u1e74":"U","\u0244":"U","\u24cb":"V","\uff36":"V","\u1e7c":"V","\u1e7e":"V","\u01b2":"V","\ua75e":"V","\u0245":"V","\ua760":"VY","\u24cc":"W","\uff37":"W","\u1e80":"W","\u1e82":"W","\u0174":"W","\u1e86":"W","\u1e84":"W","\u1e88":"W","\u2c72":"W","\u24cd":"X","\uff38":"X","\u1e8a":"X","\u1e8c":"X","\u24ce":"Y","\uff39":"Y","\u1ef2":"Y","\xdd":"Y","\u0176":"Y","\u1ef8":"Y","\u0232":"Y","\u1e8e":"Y","\u0178":"Y","\u1ef6":"Y","\u1ef4":"Y","\u01b3":"Y","\u024e":"Y","\u1efe":"Y","\u24cf":"Z","\uff3a":"Z","\u0179":"Z","\u1e90":"Z","\u017b":"Z","\u017d":"Z","\u1e92":"Z","\u1e94":"Z","\u01b5":"Z","\u0224":"Z","\u2c7f":"Z","\u2c6b":"Z","\ua762":"Z","\u24d0":"a","\uff41":"a","\u1e9a":"a","\xe0":"a","\xe1":"a","\xe2":"a","\u1ea7":"a","\u1ea5":"a","\u1eab":"a","\u1ea9":"a","\xe3":"a","\u0101":"a","\u0103":"a","\u1eb1":"a","\u1eaf":"a","\u1eb5":"a","\u1eb3":"a","\u0227":"a","\u01e1":"a","\xe4":"a","\u01df":"a","\u1ea3":"a","\xe5":"a","\u01fb":"a","\u01ce":"a","\u0201":"a","\u0203":"a","\u1ea1":"a","\u1ead":"a","\u1eb7":"a","\u1e01":"a","\u0105":"a","\u2c65":"a","\u0250":"a","\ua733":"aa","\xe6":"ae","\u01fd":"ae","\u01e3":"ae","\ua735":"ao","\ua737":"au","\ua739":"av","\ua73b":"av","\ua73d":"ay","\u24d1":"b","\uff42":"b","\u1e03":"b","\u1e05":"b","\u1e07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24d2":"c","\uff43":"c","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\xe7":"c","\u1e09":"c","\u0188":"c","\u023c":"c","\ua73f":"c","\u2184":"c","\u24d3":"d","\uff44":"d","\u1e0b":"d","\u010f":"d","\u1e0d":"d","\u1e11":"d","\u1e13":"d","\u1e0f":"d","\u0111":"d","\u018c":"d","\u0256":"d","\u0257":"d","\ua77a":"d","\u01f3":"dz","\u01c6":"dz","\u24d4":"e","\uff45":"e","\xe8":"e","\xe9":"e","\xea":"e","\u1ec1":"e","\u1ebf":"e","\u1ec5":"e","\u1ec3":"e","\u1ebd":"e","\u0113":"e","\u1e15":"e","\u1e17":"e","\u0115":"e","\u0117":"e","\xeb":"e","\u1ebb":"e","\u011b":"e","\u0205":"e","\u0207":"e","\u1eb9":"e","\u1ec7":"e","\u0229":"e","\u1e1d":"e","\u0119":"e","\u1e19":"e","\u1e1b":"e","\u0247":"e","\u025b":"e","\u01dd":"e","\u24d5":"f","\uff46":"f","\u1e1f":"f","\u0192":"f","\ua77c":"f","\u24d6":"g","\uff47":"g","\u01f5":"g","\u011d":"g","\u1e21":"g","\u011f":"g","\u0121":"g","\u01e7":"g","\u0123":"g","\u01e5":"g","\u0260":"g","\ua7a1":"g","\u1d79":"g","\ua77f":"g","\u24d7":"h","\uff48":"h","\u0125":"h","\u1e23":"h","\u1e27":"h","\u021f":"h","\u1e25":"h","\u1e29":"h","\u1e2b":"h","\u1e96":"h","\u0127":"h","\u2c68":"h","\u2c76":"h","\u0265":"h","\u0195":"hv","\u24d8":"i","\uff49":"i","\xec":"i","\xed":"i","\xee":"i","\u0129":"i","\u012b":"i","\u012d":"i","\xef":"i","\u1e2f":"i","\u1ec9":"i","\u01d0":"i","\u0209":"i","\u020b":"i","\u1ecb":"i","\u012f":"i","\u1e2d":"i","\u0268":"i","\u0131":"i","\u24d9":"j","\uff4a":"j","\u0135":"j","\u01f0":"j","\u0249":"j","\u24da":"k","\uff4b":"k","\u1e31":"k","\u01e9":"k","\u1e33":"k","\u0137":"k","\u1e35":"k","\u0199":"k","\u2c6a":"k","\ua741":"k","\ua743":"k","\ua745":"k","\ua7a3":"k","\u24db":"l","\uff4c":"l","\u0140":"l","\u013a":"l","\u013e":"l","\u1e37":"l","\u1e39":"l","\u013c":"l","\u1e3d":"l","\u1e3b":"l","\u017f":"l","\u0142":"l","\u019a":"l","\u026b":"l","\u2c61":"l","\ua749":"l","\ua781":"l","\ua747":"l","\u01c9":"lj","\u24dc":"m","\uff4d":"m","\u1e3f":"m","\u1e41":"m","\u1e43":"m","\u0271":"m","\u026f":"m","\u24dd":"n","\uff4e":"n","\u01f9":"n","\u0144":"n","\xf1":"n","\u1e45":"n","\u0148":"n","\u1e47":"n","\u0146":"n","\u1e4b":"n","\u1e49":"n","\u019e":"n","\u0272":"n","\u0149":"n","\ua791":"n","\ua7a5":"n","\u01cc":"nj","\u24de":"o","\uff4f":"o","\xf2":"o","\xf3":"o","\xf4":"o","\u1ed3":"o","\u1ed1":"o","\u1ed7":"o","\u1ed5":"o","\xf5":"o","\u1e4d":"o","\u022d":"o","\u1e4f":"o","\u014d":"o","\u1e51":"o","\u1e53":"o","\u014f":"o","\u022f":"o","\u0231":"o","\xf6":"o","\u022b":"o","\u1ecf":"o","\u0151":"o","\u01d2":"o","\u020d":"o","\u020f":"o","\u01a1":"o","\u1edd":"o","\u1edb":"o","\u1ee1":"o","\u1edf":"o","\u1ee3":"o","\u1ecd":"o","\u1ed9":"o","\u01eb":"o","\u01ed":"o","\xf8":"o","\u01ff":"o","\u0254":"o","\ua74b":"o","\ua74d":"o","\u0275":"o","\u01a3":"oi","\u0223":"ou","\ua74f":"oo","\u24df":"p","\uff50":"p","\u1e55":"p","\u1e57":"p","\u01a5":"p","\u1d7d":"p","\ua751":"p","\ua753":"p","\ua755":"p","\u24e0":"q","\uff51":"q","\u024b":"q","\ua757":"q","\ua759":"q","\u24e1":"r","\uff52":"r","\u0155":"r","\u1e59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1e5b":"r","\u1e5d":"r","\u0157":"r","\u1e5f":"r","\u024d":"r","\u027d":"r","\ua75b":"r","\ua7a7":"r","\ua783":"r","\u24e2":"s","\uff53":"s","\xdf":"s","\u015b":"s","\u1e65":"s","\u015d":"s","\u1e61":"s","\u0161":"s","\u1e67":"s","\u1e63":"s","\u1e69":"s","\u0219":"s","\u015f":"s","\u023f":"s","\ua7a9":"s","\ua785":"s","\u1e9b":"s","\u24e3":"t","\uff54":"t","\u1e6b":"t","\u1e97":"t","\u0165":"t","\u1e6d":"t","\u021b":"t","\u0163":"t","\u1e71":"t","\u1e6f":"t","\u0167":"t","\u01ad":"t","\u0288":"t","\u2c66":"t","\ua787":"t","\ua729":"tz","\u24e4":"u","\uff55":"u","\xf9":"u","\xfa":"u","\xfb":"u","\u0169":"u","\u1e79":"u","\u016b":"u","\u1e7b":"u","\u016d":"u","\xfc":"u","\u01dc":"u","\u01d8":"u","\u01d6":"u","\u01da":"u","\u1ee7":"u","\u016f":"u","\u0171":"u","\u01d4":"u","\u0215":"u","\u0217":"u","\u01b0":"u","\u1eeb":"u","\u1ee9":"u","\u1eef":"u","\u1eed":"u","\u1ef1":"u","\u1ee5":"u","\u1e73":"u","\u0173":"u","\u1e77":"u","\u1e75":"u","\u0289":"u","\u24e5":"v","\uff56":"v","\u1e7d":"v","\u1e7f":"v","\u028b":"v","\ua75f":"v","\u028c":"v","\ua761":"vy","\u24e6":"w","\uff57":"w","\u1e81":"w","\u1e83":"w","\u0175":"w","\u1e87":"w","\u1e85":"w","\u1e98":"w","\u1e89":"w","\u2c73":"w","\u24e7":"x","\uff58":"x","\u1e8b":"x","\u1e8d":"x","\u24e8":"y","\uff59":"y","\u1ef3":"y","\xfd":"y","\u0177":"y","\u1ef9":"y","\u0233":"y","\u1e8f":"y","\xff":"y","\u1ef7":"y","\u1e99":"y","\u1ef5":"y","\u01b4":"y","\u024f":"y","\u1eff":"y","\u24e9":"z","\uff5a":"z","\u017a":"z","\u1e91":"z","\u017c":"z","\u017e":"z","\u1e93":"z","\u1e95":"z","\u01b6":"z","\u0225":"z","\u0240":"z","\u2c6c":"z","\ua763":"z","\u0386":"\u0391","\u0388":"\u0395","\u0389":"\u0397","\u038a":"\u0399","\u03aa":"\u0399","\u038c":"\u039f","\u038e":"\u03a5","\u03ab":"\u03a5","\u038f":"\u03a9","\u03ac":"\u03b1","\u03ad":"\u03b5","\u03ae":"\u03b7","\u03af":"\u03b9","\u03ca":"\u03b9","\u0390":"\u03b9","\u03cc":"\u03bf","\u03cd":"\u03c5","\u03cb":"\u03c5","\u03b0":"\u03c5","\u03c9":"\u03c9","\u03c2":"\u03c3"};i=a(document),f=function(){var a=1;return function(){return a++}}(),c=O(Object,{bind:function(a){var b=this;return function(){a.apply(b,arguments)}},init:function(c){var d,e,g=".select2-results";this.opts=c=this.prepareOpts(c),this.id=c.id,c.element.data("select2")!==b&&null!==c.element.data("select2")&&c.element.data("select2").destroy(),this.container=this.createContainer(),this.liveRegion=a(".select2-hidden-accessible"),0==this.liveRegion.length&&(this.liveRegion=a("",{role:"status","aria-live":"polite"}).addClass("select2-hidden-accessible").appendTo(document.body)),this.containerId="s2id_"+(c.element.attr("id")||"autogen"+f()),this.containerEventName=this.containerId.replace(/([.])/g,"_").replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g,"\\$1"),this.container.attr("id",this.containerId),this.container.attr("title",c.element.attr("title")),this.body=a(document.body),D(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.attr("style",c.element.attr("style")),this.container.css(K(c.containerCss,this.opts.element)),this.container.addClass(K(c.containerCssClass,this.opts.element)),this.elementTabIndex=this.opts.element.attr("tabindex"),this.opts.element.data("select2",this).attr("tabindex","-1").before(this.container).on("click.select2",A),this.container.data("select2",this),this.dropdown=this.container.find(".select2-drop"),D(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(K(c.dropdownCssClass,this.opts.element)),this.dropdown.data("select2",this),this.dropdown.on("click",A),this.results=d=this.container.find(g),this.search=e=this.container.find("input.select2-input"),this.queryCount=0,this.resultsPage=0,this.context=null,this.initContainer(),this.container.on("click",A),v(this.results),this.dropdown.on("mousemove-filtered",g,this.bind(this.highlightUnderEvent)),this.dropdown.on("touchstart touchmove touchend",g,this.bind(function(a){this._touchEvent=!0,this.highlightUnderEvent(a)})),this.dropdown.on("touchmove",g,this.bind(this.touchMoved)),this.dropdown.on("touchstart touchend",g,this.bind(this.clearTouchMoved)),this.dropdown.on("click",this.bind(function(){this._touchEvent&&(this._touchEvent=!1,this.selectHighlighted())})),x(80,this.results),this.dropdown.on("scroll-debounced",g,this.bind(this.loadMoreIfNeeded)),a(this.container).on("change",".select2-input",function(a){a.stopPropagation()}),a(this.dropdown).on("change",".select2-input",function(a){a.stopPropagation()}),a.fn.mousewheel&&d.mousewheel(function(a,b,c,e){var f=d.scrollTop();e>0&&0>=f-e?(d.scrollTop(0),A(a)):0>e&&d.get(0).scrollHeight-d.scrollTop()+e<=d.height()&&(d.scrollTop(d.get(0).scrollHeight-d.height()),A(a))}),u(e),e.on("keyup-change input paste",this.bind(this.updateResults)),e.on("focus",function(){e.addClass("select2-focused")}),e.on("blur",function(){e.removeClass("select2-focused")}),this.dropdown.on("mouseup",g,this.bind(function(b){a(b.target).closest(".select2-result-selectable").length>0&&(this.highlightUnderEvent(b),this.selectHighlighted(b))})),this.dropdown.on("click mouseup mousedown touchstart touchend focusin",function(a){a.stopPropagation()}),this.lastSearchTerm=b,a.isFunction(this.opts.initSelection)&&(this.initSelection(),this.monitorSource()),null!==c.maximumInputLength&&this.search.attr("maxlength",c.maximumInputLength);var h=c.element.prop("disabled");h===b&&(h=!1),this.enable(!h);var i=c.element.prop("readonly");i===b&&(i=!1),this.readonly(i),j=j||q(),this.autofocus=c.element.prop("autofocus"),c.element.prop("autofocus",!1),this.autofocus&&this.focus(),this.search.attr("placeholder",c.searchInputPlaceholder)},destroy:function(){var a=this.opts.element,c=a.data("select2"),d=this;this.close(),a.length&&a[0].detachEvent&&d._sync&&a.each(function(){d._sync&&this.detachEvent("onpropertychange",d._sync)}),this.propertyObserver&&(this.propertyObserver.disconnect(),this.propertyObserver=null),this._sync=null,c!==b&&(c.container.remove(),c.liveRegion.remove(),c.dropdown.remove(),a.removeData("select2").off(".select2"),a.is("input[type='hidden']")?a.css("display",""):(a.show().prop("autofocus",this.autofocus||!1),this.elementTabIndex?a.attr({tabindex:this.elementTabIndex}):a.removeAttr("tabindex"),a.show())),N.call(this,"container","liveRegion","dropdown","results","search")},optionToData:function(a){return a.is("option")?{id:a.prop("value"),text:a.text(),element:a.get(),css:a.attr("class"),disabled:a.prop("disabled"),locked:r(a.attr("locked"),"locked")||r(a.data("locked"),!0)}:a.is("optgroup")?{text:a.attr("label"),children:[],element:a.get(),css:a.attr("class")}:void 0},prepareOpts:function(c){var d,e,g,h,i=this;if(d=c.element,"select"===d.get(0).tagName.toLowerCase()&&(this.select=e=c.element),e&&a.each(["id","multiple","ajax","query","createSearchChoice","initSelection","data","tags"],function(){if(this in c)throw new Error("Option '"+this+"' is not allowed for Select2 when attached to a ","
    "," ","
      ","
    ","
    "].join(""));return b},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.focusser.prop("disabled",!this.isInterfaceEnabled())},opening:function(){var b,c,d;this.opts.minimumResultsForSearch>=0&&this.showSearch(!0),this.parent.opening.apply(this,arguments),this.showSearchInput!==!1&&this.search.val(this.focusser.val()),this.opts.shouldFocusInput(this)&&(this.search.focus(),b=this.search.get(0),b.createTextRange?(c=b.createTextRange(),c.collapse(!1),c.select()):b.setSelectionRange&&(d=this.search.val().length,b.setSelectionRange(d,d))),this.prefillNextSearchTerm(),this.focusser.prop("disabled",!0).val(""),this.updateResults(!0),this.opts.element.trigger(a.Event("select2-open"))},close:function(){this.opened()&&(this.parent.close.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},focus:function(){this.opened()?this.close():(this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},isFocused:function(){return this.container.hasClass("select2-container-active")},cancel:function(){this.parent.cancel.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus()},destroy:function(){a("label[for='"+this.focusser.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments),N.call(this,"selection","focusser")},initContainer:function(){var b,g,c=this.container,d=this.dropdown,e=f();this.opts.minimumResultsForSearch<0?this.showSearch(!1):this.showSearch(!0),this.selection=b=c.find(".select2-choice"),this.focusser=c.find(".select2-focusser"),b.find(".select2-chosen").attr("id","select2-chosen-"+e),this.focusser.attr("aria-labelledby","select2-chosen-"+e),this.results.attr("id","select2-results-"+e),this.search.attr("aria-owns","select2-results-"+e),this.focusser.attr("id","s2id_autogen"+e),g=a("label[for='"+this.opts.element.attr("id")+"']"),this.opts.element.on("focus.select2",this.bind(function(){this.focus()})),this.focusser.prev().text(g.text()).attr("for",this.focusser.attr("id"));var h=this.opts.element.attr("title");this.opts.element.attr("title",h||g.text()),this.focusser.attr("tabindex",this.elementTabIndex),this.search.attr("id",this.focusser.attr("id")+"_search"),this.search.prev().text(a("label[for='"+this.focusser.attr("id")+"']").text()).attr("for",this.search.attr("id")),this.search.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()&&229!=a.keyCode){if(a.which===k.PAGE_UP||a.which===k.PAGE_DOWN)return A(a),void 0;switch(a.which){case k.UP:case k.DOWN:return this.moveHighlight(a.which===k.UP?-1:1),A(a),void 0;case k.ENTER:return this.selectHighlighted(),A(a),void 0;case k.TAB:return this.selectHighlighted({noFocus:!0}),void 0;case k.ESC:return this.cancel(a),A(a),void 0}}})),this.search.on("blur",this.bind(function(){document.activeElement===this.body.get(0)&&window.setTimeout(this.bind(function(){this.opened()&&this.results&&this.results.length>1&&this.search.focus()}),0)})),this.focusser.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()&&a.which!==k.TAB&&!k.isControl(a)&&!k.isFunctionKey(a)&&a.which!==k.ESC){if(this.opts.openOnEnter===!1&&a.which===k.ENTER)return A(a),void 0;if(a.which==k.DOWN||a.which==k.UP||a.which==k.ENTER&&this.opts.openOnEnter){if(a.altKey||a.ctrlKey||a.shiftKey||a.metaKey)return;return this.open(),A(a),void 0}return a.which==k.DELETE||a.which==k.BACKSPACE?(this.opts.allowClear&&this.clear(),A(a),void 0):void 0}})),u(this.focusser),this.focusser.on("keyup-change input",this.bind(function(a){if(this.opts.minimumResultsForSearch>=0){if(a.stopPropagation(),this.opened())return;this.open()}})),b.on("mousedown touchstart","abbr",this.bind(function(a){this.isInterfaceEnabled()&&(this.clear(),B(a),this.close(),this.selection&&this.selection.focus())})),b.on("mousedown touchstart",this.bind(function(c){n(b),this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.opened()?this.close():this.isInterfaceEnabled()&&this.open(),A(c)})),d.on("mousedown touchstart",this.bind(function(){this.opts.shouldFocusInput(this)&&this.search.focus()})),b.on("focus",this.bind(function(a){A(a)})),this.focusser.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})).on("blur",this.bind(function(){this.opened()||(this.container.removeClass("select2-container-active"),this.opts.element.trigger(a.Event("select2-blur")))})),this.search.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})),this.initContainerWidth(),this.opts.element.hide(),this.setPlaceholder()},clear:function(b){var c=this.selection.data("select2-data");if(c){var d=a.Event("select2-clearing");if(this.opts.element.trigger(d),d.isDefaultPrevented())return;var e=this.getPlaceholderOption();this.opts.element.val(e?e.val():""),this.selection.find(".select2-chosen").empty(),this.selection.removeData("select2-data"),this.setPlaceholder(),b!==!1&&(this.opts.element.trigger({type:"select2-removed",val:this.id(c),choice:c}),this.triggerChange({removed:c}))}},initSelection:function(){if(this.isPlaceholderOptionSelected())this.updateSelection(null),this.close(),this.setPlaceholder();else{var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.setPlaceholder(),c.lastSearchTerm=c.search.val())})}},isPlaceholderOptionSelected:function(){var a;return this.getPlaceholder()===b?!1:(a=this.getPlaceholderOption())!==b&&a.prop("selected")||""===this.opts.element.val()||this.opts.element.val()===b||null===this.opts.element.val()},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=a.find("option").filter(function(){return this.selected&&!this.disabled});b(c.optionToData(d))}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=c.val(),f=null;b.query({matcher:function(a,c,d){var g=r(e,b.id(d));return g&&(f=d),g},callback:a.isFunction(d)?function(){d(f)}:a.noop})}),b},getPlaceholder:function(){return this.select&&this.getPlaceholderOption()===b?b:this.parent.getPlaceholder.apply(this,arguments)},setPlaceholder:function(){var a=this.getPlaceholder();if(this.isPlaceholderOptionSelected()&&a!==b){if(this.select&&this.getPlaceholderOption()===b)return;this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(a)),this.selection.addClass("select2-default"),this.container.removeClass("select2-allowclear")}},postprocessResults:function(a,b,c){var d=0,e=this;if(this.findHighlightableChoices().each2(function(a,b){return r(e.id(b.data("select2-data")),e.opts.element.val())?(d=a,!1):void 0}),c!==!1&&(b===!0&&d>=0?this.highlight(d):this.highlight(0)),b===!0){var g=this.opts.minimumResultsForSearch;g>=0&&this.showSearch(L(a.results)>=g)}},showSearch:function(b){this.showSearchInput!==b&&(this.showSearchInput=b,this.dropdown.find(".select2-search").toggleClass("select2-search-hidden",!b),this.dropdown.find(".select2-search").toggleClass("select2-offscreen",!b),a(this.dropdown,this.container).toggleClass("select2-with-searchbox",b))},onSelect:function(a,b){if(this.triggerSelect(a)){var c=this.opts.element.val(),d=this.data();this.opts.element.val(this.id(a)),this.updateSelection(a),this.opts.element.trigger({type:"select2-selected",val:this.id(a),choice:a}),this.lastSearchTerm=this.search.val(),this.close(),b&&b.noFocus||!this.opts.shouldFocusInput(this)||this.focusser.focus(),r(c,this.id(a))||this.triggerChange({added:a,removed:d})}},updateSelection:function(a){var d,e,c=this.selection.find(".select2-chosen");this.selection.data("select2-data",a),c.empty(),null!==a&&(d=this.opts.formatSelection(a,c,this.opts.escapeMarkup)),d!==b&&c.append(d),e=this.opts.formatSelectionCssClass(a,c),e!==b&&c.addClass(e),this.selection.removeClass("select2-default"),this.opts.allowClear&&this.getPlaceholder()!==b&&this.container.addClass("select2-allowclear")},val:function(){var a,c=!1,d=null,e=this,f=this.data();if(0===arguments.length)return this.opts.element.val();if(a=arguments[0],arguments.length>1&&(c=arguments[1],this.opts.debug&&console&&console.warn&&console.warn('Select2: The second option to `select2("val")` is not supported in Select2 4.0.0. The `change` event will always be triggered in 4.0.0.')),this.select)this.opts.debug&&console&&console.warn&&console.warn('Select2: Setting the value on a "," ","","
    ","
      ","
    ","
    "].join(""));return b},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=[];a.find("option").filter(function(){return this.selected&&!this.disabled}).each2(function(a,b){d.push(c.optionToData(b))}),b(d)}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=s(c.val(),b.separator,b.transformVal),f=[];b.query({matcher:function(c,d,g){var h=a.grep(e,function(a){return r(a,b.id(g))}).length;return h&&f.push(g),h},callback:a.isFunction(d)?function(){for(var a=[],c=0;c0||(this.selectChoice(null),this.clearPlaceholder(),this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.open(),this.focusSearch(),b.preventDefault()))})),this.container.on("focus",b,this.bind(function(){this.isInterfaceEnabled()&&(this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"),this.clearPlaceholder())})),this.initContainerWidth(),this.opts.element.hide(),this.clearSearch()},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.search.prop("disabled",!this.isInterfaceEnabled())},initSelection:function(){if(""===this.opts.element.val()&&""===this.opts.element.text()&&(this.updateSelection([]),this.close(),this.clearSearch()),this.select||""!==this.opts.element.val()){var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.clearSearch())})}},clearSearch:function(){var a=this.getPlaceholder(),c=this.getMaxSearchWidth();a!==b&&0===this.getVal().length&&this.search.hasClass("select2-focused")===!1?(this.search.val(a).addClass("select2-default"),this.search.width(c>0?c:this.container.css("width"))):this.search.val("").width(10)},clearPlaceholder:function(){this.search.hasClass("select2-default")&&this.search.val("").removeClass("select2-default")},opening:function(){this.clearPlaceholder(),this.resizeSearch(),this.parent.opening.apply(this,arguments),this.focusSearch(),this.prefillNextSearchTerm(),this.updateResults(!0),this.opts.shouldFocusInput(this)&&this.search.focus(),this.opts.element.trigger(a.Event("select2-open"))},close:function(){this.opened()&&this.parent.close.apply(this,arguments)},focus:function(){this.close(),this.search.focus()},isFocused:function(){return this.search.hasClass("select2-focused")},updateSelection:function(b){var c={},d=[],e=this;a(b).each(function(){e.id(this)in c||(c[e.id(this)]=0,d.push(this))}),this.selection.find(".select2-search-choice").remove(),this.addSelectedChoice(d),e.postprocessResults()},tokenize:function(){var a=this.search.val();a=this.opts.tokenizer.call(this,a,this.data(),this.bind(this.onSelect),this.opts),null!=a&&a!=b&&(this.search.val(a),a.length>0&&this.open())},onSelect:function(a,b){this.triggerSelect(a)&&""!==a.text&&(this.addSelectedChoice(a),this.opts.element.trigger({type:"selected",val:this.id(a),choice:a}),this.lastSearchTerm=this.search.val(),this.clearSearch(),this.updateResults(),(this.select||!this.opts.closeOnSelect)&&this.postprocessResults(a,!1,this.opts.closeOnSelect===!0),this.opts.closeOnSelect?(this.close(),this.search.width(10)):this.countSelectableResults()>0?(this.search.width(10),this.resizeSearch(),this.getMaximumSelectionSize()>0&&this.val().length>=this.getMaximumSelectionSize()?this.updateResults(!0):this.prefillNextSearchTerm()&&this.updateResults(),this.positionDropdown()):(this.close(),this.search.width(10)),this.triggerChange({added:a}),b&&b.noFocus||this.focusSearch())},cancel:function(){this.close(),this.focusSearch()},addSelectedChoice:function(b){var c=this.getVal(),d=this;a(b).each(function(){c.push(d.createChoice(this))}),this.setVal(c)},createChoice:function(c){var i,j,d=!c.locked,e=a("
  • "),f=a("
  • "),g=d?e:f,h=this.id(c);return i=this.opts.formatSelection(c,g.find("div"),this.opts.escapeMarkup),i!=b&&g.find("div").replaceWith(a("
    ").html(i)),j=this.opts.formatSelectionCssClass(c,g.find("div")),j!=b&&g.addClass(j),d&&g.find(".select2-search-choice-close").on("mousedown",A).on("click dblclick",this.bind(function(b){this.isInterfaceEnabled()&&(this.unselect(a(b.target)),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"),A(b),this.close(),this.focusSearch())})).on("focus",this.bind(function(){this.isInterfaceEnabled()&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"))})),g.data("select2-data",c),g.insertBefore(this.searchContainer),h},unselect:function(b){var d,e,c=this.getVal();if(b=b.closest(".select2-search-choice"),0===b.length)throw"Invalid argument: "+b+". Must be .select2-search-choice";if(d=b.data("select2-data")){var f=a.Event("select2-removing");if(f.val=this.id(d),f.choice=d,this.opts.element.trigger(f),f.isDefaultPrevented())return!1;for(;(e=p(this.id(d),c))>=0;)c.splice(e,1),this.setVal(c),this.select&&this.postprocessResults();return b.remove(),this.opts.element.trigger({type:"select2-removed",val:this.id(d),choice:d}),this.triggerChange({removed:d}),!0}},postprocessResults:function(a,b,c){var d=this.getVal(),e=this.results.find(".select2-result"),f=this.results.find(".select2-result-with-children"),g=this;e.each2(function(a,b){var c=g.id(b.data("select2-data"));p(c,d)>=0&&(b.addClass("select2-selected"),b.find(".select2-result-selectable").addClass("select2-selected"))}),f.each2(function(a,b){b.is(".select2-result-selectable")||0!==b.find(".select2-result-selectable:not(.select2-selected)").length||b.addClass("select2-selected")}),-1==this.highlight()&&c!==!1&&this.opts.closeOnSelect===!0&&g.highlight(0),!this.opts.createSearchChoice&&!e.filter(".select2-result:not(.select2-selected)").length>0&&(!a||a&&!a.more&&0===this.results.find(".select2-no-results").length)&&J(g.opts.formatNoMatches,"formatNoMatches")&&this.results.append("
  • "+K(g.opts.formatNoMatches,g.opts.element,g.search.val())+"
  • ")},getMaxSearchWidth:function(){return this.selection.width()-t(this.search)},resizeSearch:function(){var a,b,c,d,e,f=t(this.search);a=C(this.search)+10,b=this.search.offset().left,c=this.selection.width(),d=this.selection.offset().left,e=c-(b-d)-f,a>e&&(e=c-f),40>e&&(e=c-f),0>=e&&(e=a),this.search.width(Math.floor(e))},getVal:function(){var a;return this.select?(a=this.select.val(),null===a?[]:a):(a=this.opts.element.val(),s(a,this.opts.separator,this.opts.transformVal))},setVal:function(b){if(this.select)this.select.val(b);else{var c=[],d={};a(b).each(function(){this in d||(c.push(this),d[this]=0)}),this.opts.element.val(0===c.length?"":c.join(this.opts.separator))}},buildChangeDetails:function(a,b){for(var b=b.slice(0),a=a.slice(0),c=0;c. Attach to instead.");this.search.width(0),this.searchContainer.hide()},onSortEnd:function(){var b=[],c=this;this.searchContainer.show(),this.searchContainer.appendTo(this.searchContainer.parent()),this.resizeSearch(),this.selection.find(".select2-search-choice").each(function(){b.push(c.opts.id(a(this).data("select2-data")))}),this.setVal(b),this.triggerChange()},data:function(b,c){var e,f,d=this;return 0===arguments.length?this.selection.children(".select2-search-choice").map(function(){return a(this).data("select2-data")}).get():(f=this.data(),b||(b=[]),e=a.map(b,function(a){return d.opts.id(a)}),this.setVal(e),this.updateSelection(b),this.clearSearch(),c&&this.triggerChange(this.buildChangeDetails(f,this.data())),void 0)}}),a.fn.select2=function(){var d,e,f,g,h,c=Array.prototype.slice.call(arguments,0),i=["val","destroy","opened","open","close","focus","isFocused","container","dropdown","onSortStart","onSortEnd","enable","disable","readonly","positionDropdown","data","search"],j=["opened","isFocused","container","dropdown"],k=["val","data"],l={search:"externalSearch"};return this.each(function(){if(0===c.length||"object"==typeof c[0])d=0===c.length?{}:a.extend({},c[0]),d.element=a(this),"select"===d.element.get(0).tagName.toLowerCase()?h=d.element.prop("multiple"):(h=d.multiple||!1,"tags"in d&&(d.multiple=h=!0)),e=h?new window.Select2["class"].multi:new window.Select2["class"].single,e.init(d);else{if("string"!=typeof c[0])throw"Invalid arguments to select2 plugin: "+c;if(p(c[0],i)<0)throw"Unknown method: "+c[0];if(g=b,e=a(this).data("select2"),e===b)return;if(f=c[0],"container"===f?g=e.container:"dropdown"===f?g=e.dropdown:(l[f]&&(f=l[f]),g=e[f].apply(e,c.slice(1))),p(c[0],j)>=0||p(c[0],k)>=0&&1==c.length)return!1}}),g===b?this:g},a.fn.select2.defaults={debug:!1,width:"copy",loadMorePadding:0,closeOnSelect:!0,openOnEnter:!0,containerCss:{},dropdownCss:{},containerCssClass:"",dropdownCssClass:"",formatResult:function(a,b,c,d){var e=[];return E(this.text(a),c.term,e,d),e.join("")},transformVal:function(b){return a.trim(b)},formatSelection:function(a,c,d){return a?d(this.text(a)):b},sortResults:function(a){return a},formatResultCssClass:function(a){return a.css},formatSelectionCssClass:function(){return b},minimumResultsForSearch:0,minimumInputLength:0,maximumInputLength:null,maximumSelectionSize:0,id:function(a){return a==b?null:a.id},text:function(b){return b&&this.data&&this.data.text?a.isFunction(this.data.text)?this.data.text(b):b[this.data.text]:b.text},matcher:function(a,b){return o(""+b).toUpperCase().indexOf(o(""+a).toUpperCase())>=0},separator:",",tokenSeparators:[],tokenizer:M,escapeMarkup:F,blurOnChange:!1,selectOnBlur:!1,adaptContainerCssClass:function(a){return a},adaptDropdownCssClass:function(){return null},nextSearchTerm:function(){return b},searchInputPlaceholder:"",createSearchChoicePosition:"top",shouldFocusInput:function(a){var b="ontouchstart"in window||navigator.msMaxTouchPoints>0;return b?a.opts.minimumResultsForSearch<0?!1:!0:!0}},a.fn.select2.locales=[],a.fn.select2.locales.en={formatMatches:function(a){return 1===a?"One result is available, press enter to select it.":a+" results are available, use up and down arrow keys to navigate."},formatNoMatches:function(){return"No matches found"},formatAjaxError:function(){return"Loading failed"},formatInputTooShort:function(a,b){var c=b-a.length;return"Please enter "+c+" or more character"+(1==c?"":"s")},formatInputTooLong:function(a,b){var c=a.length-b;return"Please delete "+c+" character"+(1==c?"":"s")},formatSelectionTooBig:function(a){return"You can only select "+a+" item"+(1==a?"":"s")},formatLoadMore:function(){return"Loading more results\u2026"},formatSearching:function(){return"Searching\u2026"}},a.extend(a.fn.select2.defaults,a.fn.select2.locales.en),a.fn.select2.ajaxDefaults={transport:a.ajax,params:{type:"GET",cache:!1,dataType:"json"}},window.Select2={query:{ajax:G,local:H,tags:I},util:{debounce:w,markMatch:E,escapeMarkup:F,stripDiacritics:o},"class":{"abstract":c,single:d,multi:e}}}}(jQuery); \ No newline at end of file diff --git a/html/forums/jscripts/select2/select2.png b/html/forums/jscripts/select2/select2.png deleted file mode 100644 index 44e10d6..0000000 Binary files a/html/forums/jscripts/select2/select2.png and /dev/null differ diff --git a/html/forums/jscripts/select2/select2x2.png b/html/forums/jscripts/select2/select2x2.png deleted file mode 100644 index c657a14..0000000 Binary files a/html/forums/jscripts/select2/select2x2.png and /dev/null differ diff --git a/html/forums/jscripts/thread.js b/html/forums/jscripts/thread.js deleted file mode 100644 index d03a4a3..0000000 --- a/html/forums/jscripts/thread.js +++ /dev/null @@ -1,572 +0,0 @@ -var Thread = { - init: function() - { - $(document).ready(function(){ - Thread.quickEdit(); - Thread.initQuickReply(); - Thread.initMultiQuote(); - - // Set spinner image - $('#quickreply_spinner img').attr('src', spinner_image); - }); - }, - - initMultiQuote: function() - { - var quoted = Cookie.get('multiquote'); - if(quoted) - { - var post_ids = quoted.split("|"); - - $.each(post_ids, function(key, value) { - var mquote_a = $("#multiquote_"+value).closest('a'); - if(mquote_a.length) - { - mquote_a.removeClass('postbit_multiquote').addClass('postbit_multiquote_on'); - } - }); - - var mquote_quick = $('#quickreply_multiquote'); - if(mquote_quick.length) - { - mquote_quick.show(); - } - } - return true; - }, - - multiQuote: function(pid) - { - var new_post_ids = new Array(); - var quoted = Cookie.get("multiquote"); - var is_new = true; - if(quoted) - { - var post_ids = quoted.split("|"); - - $.each(post_ids, function(key, post_id) { - if(post_id != pid && post_id != '') - { - new_post_ids[new_post_ids.length] = post_id; - } - else if(post_id == pid) - { - is_new = false; - } - }); - } - - var mquote_a = $("#multiquote_"+pid).closest('a') - if(is_new == true) - { - new_post_ids[new_post_ids.length] = pid; - mquote_a.removeClass('postbit_multiquote').addClass('postbit_multiquote_on'); - } - else - { - mquote_a.removeClass('postbit_multiquote_on').addClass('postbit_multiquote'); - } - - var mquote_quick = $('#quickreply_multiquote'); - if(mquote_quick.length) - { - if(new_post_ids.length) - { - mquote_quick.show(); - } - else - { - mquote_quick.hide(); - } - } - Cookie.set("multiquote", new_post_ids.join("|")); - }, - - loadMultiQuoted: function() - { - if(use_xmlhttprequest == 1) - { - // Spinner! - var mquote_spinner = $('#quickreply_spinner'); - mquote_spinner.show(); - - $.ajax( - { - url: 'xmlhttp.php?action=get_multiquoted&load_all=1', - type: 'get', - complete: function (request, status) - { - Thread.multiQuotedLoaded(request, status); - - // Get rid of spinner - mquote_spinner.hide(); - } - }); - - return false; - } - else - { - return true; - } - }, - - multiQuotedLoaded: function(request) - { - var json = $.parseJSON(request.responseText); - if(typeof json == 'object') - { - if(json.hasOwnProperty("errors")) - { - $.each(json.errors, function(i, message) - { - $.jGrowl(lang.post_fetch_error + ' ' + message, {theme:'jgrowl_error'}); - }); - return false; - } - } - - if(typeof $('textarea').sceditor != 'undefined') - { - $('textarea').sceditor('instance').insert(json.message); - } - else - { - var id = $('#message'); - if(id.value) - { - id.value += "\n"; - } - id.val(id.val() + json.message); - } - - Thread.clearMultiQuoted(); - $('#quickreply_multiquote').hide(); - $('#quoted_ids').val('all'); - - $('#message').focus(); - }, - - clearMultiQuoted: function() - { - $('#quickreply_multiquote').hide(); - var quoted = Cookie.get("multiquote"); - if(quoted) - { - var post_ids = quoted.split("|"); - - $.each(post_ids, function(key, post_id) { - var mquote_a = $("#multiquote_"+post_id).closest('a'); - if(mquote_a.length) - { - mquote_a.removeClass('postbit_multiquote_on').addClass('postbit_multiquote'); - } - }); - } - Cookie.unset('multiquote'); - }, - - quickEdit: function(el) - { - if(typeof el === 'undefined' || !el.length) el = '.post_body'; - - $(el).each(function() - { - // Take pid out of the id attribute - id = $(this).attr('id'); - pid = id.replace( /[^\d.]/g, ''); - - $('#pid_' + pid).editable("xmlhttp.php?action=edit_post&do=update_post&pid=" + pid + '&my_post_key=' + my_post_key, - { - indicator: spinner, - loadurl: "xmlhttp.php?action=edit_post&do=get_post&pid=" + pid, - type: "textarea", - rows: 12, - submit: lang.save_changes, - cancel: lang.cancel_edit, - event: "edit" + pid, // Triggered by the event "edit_[pid]", - onblur: "ignore", - dataType: "json", - submitdata: function (values, settings) - { - id = $(this).attr('id'); - pid = id.replace( /[^\d.]/g, ''); - return { - editreason: $("#quickedit_" + pid + "_editreason").val() - } - }, - callback: function(values, settings) - { - id = $(this).attr('id'); - pid = id.replace( /[^\d.]/g, ''); - - var json = $.parseJSON(values); - if(typeof json == 'object') - { - if(json.hasOwnProperty("errors")) - { - $(".jGrowl").jGrowl("close"); - - $.each(json.errors, function(i, message) - { - $.jGrowl(lang.quick_edit_update_error + ' ' + message, {theme:'jgrowl_error'}); - }); - $(this).html($('#pid_' + pid + '_temp').html()); - } - else if(json.hasOwnProperty("moderation_post")) - { - $(".jGrowl").jGrowl("close"); - - $(this).html(json.message); - - // No more posts on this page? (testing for "1" as the last post would be removed here) - if($('.post').length == 1) - { - alert(json.moderation_post); - window.location = json.url; - } - else - { - $.jGrowl(json.moderation_post, {theme:'jgrowl_success'}); - $('#post_' + pid).slideToggle(); - } - } - else if(json.hasOwnProperty("moderation_thread")) - { - $(".jGrowl").jGrowl("close"); - - $(this).html(json.message); - - alert(json.moderation_thread); - - // Redirect user to forum - window.location = json.url; - } - else - { - // Change html content - $(this).html(json.message); - $('#edited_by_' + pid).html(json.editedmsg); - } - } - else - { - // Change html content - $(this).html(json.message); - $('#edited_by_' + pid).html(json.editedmsg); - } - $('#pid_' + pid + '_temp').remove(); - } - }); - }); - - $('.quick_edit_button').each(function() - { - $(this).on("click", function(e) - { - e.preventDefault(); - - // Take pid out of the id attribute - id = $(this).attr('id'); - pid = id.replace( /[^\d.]/g, ''); - - // Create a copy of the post - if($('#pid_' + pid + '_temp').length == 0) - { - $('#pid_' + pid).clone().attr('id','pid_' + pid + '_temp').appendTo("body").hide(); - } - - // Trigger the edit event - $('#pid_' + pid).trigger("edit" + pid); - - // Edit Reason - $('#pid_' + pid + ' textarea').attr('id', 'quickedit_' + pid); - if(allowEditReason == 1 && $('#quickedit_' + pid + '_editreason').length == 0) - { - $('#quickedit_' + pid).after('
    '); - } - }); - }); - - return false; - }, - - initQuickReply: function() - { - if($('#quick_reply_form').length && use_xmlhttprequest == 1) - { - // Bind closing event to our popup menu - $('#quick_reply_submit').bind('click', function(e) { - return Thread.quickReply(e); - }); - } - }, - - quickReply: function(e) - { - e.stopPropagation(); - - if(this.quick_replying) - { - return false; - } - - this.quick_replying = 1; - var post_body = $('#quick_reply_form').serialize(); - - // Spinner! - var qreply_spinner = $('#quickreply_spinner'); - qreply_spinner.show(); - - $.ajax( - { - url: 'newreply.php?ajax=1', - type: 'post', - data: post_body, - dataType: 'html', - complete: function (request, status) - { - Thread.quickReplyDone(request, status); - - // Get rid of spinner - qreply_spinner.hide(); - } - }); - - return false; - }, - - quickReplyDone: function(request, status) - { - this.quick_replying = 0; - - var json = $.parseJSON(request.responseText); - if(typeof json == 'object') - { - if(json.hasOwnProperty("errors")) - { - $(".jGrowl").jGrowl("close"); - - $.each(json.errors, function(i, message) - { - $.jGrowl(lang.quick_reply_post_error + ' ' + message, {theme:'jgrowl_error'}); - }); - $('#quickreply_spinner').hide(); - } - } - - if($('#captcha_trow').length) - { - cap = json.data.match(/^([0-9a-zA-Z]+)(\|([0-9a-zA-Z]+)|)<\/captcha>/); - if(cap) - { - json.data = json.data.replace(/^(.*)<\/captcha>/, ''); - - if(cap[1] == "reload") - { - Recaptcha.reload(); - } - else if($("#captcha_img").length) - { - if(cap[1]) - { - imghash = cap[1]; - $('#imagehash').val(imghash); - if(cap[3]) - { - $('#imagestring').attr('type', 'hidden').val(cap[3]); - // hide the captcha - $('#captcha_trow').hide(); - } - else - { - $('#captcha_img').attr('src', "captcha.php?action=regimage&imagehash="+imghash); - $('#imagestring').attr('type', 'text').val(''); - $('#captcha_trow').show(); - } - } - } - } - } - - if(json.hasOwnProperty("errors")) - return false; - - if(json.data.match(/id="post_([0-9]+)"/)) - { - var pid = json.data.match(/id="post_([0-9]+)"/)[1]; - var post = document.createElement("div"); - - $('#posts').append(json.data); - - if (typeof inlineModeration != "undefined") // Guests don't have this object defined - $("#inlinemod_" + pid).on('change', inlineModeration.checkItem); - - Thread.quickEdit("#pid_" + pid); - - // Eval javascript - $(json.data).filter("script").each(function(e) { - eval($(this).text()); - }); - - $('#quick_reply_form')[0].reset(); - - var lastpid = $('#lastpid'); - if(lastpid.length) - { - lastpid.val(pid); - } - } - else - { - // Eval javascript - $(json.data).filter("script").each(function(e) { - eval($(this).text()); - }); - } - - $(".jGrowl").jGrowl("close"); - }, - - showIgnoredPost: function(pid) - { - $('#ignored_post_'+pid).slideToggle("slow"); - $('#post_'+pid).slideToggle("slow"); - }, - - showDeletedPost: function(pid) - { - $('#deleted_post_'+pid).slideToggle("slow"); - $('#post_'+pid).slideToggle("slow"); - }, - - deletePost: function(pid) - { - $.prompt(quickdelete_confirm, { - buttons:[ - {title: yes_confirm, value: true}, - {title: no_confirm, value: false} - ], - submit: function(e,v,m,f){ - if(v == true) - { - $.ajax( - { - url: 'editpost.php?ajax=1&action=deletepost&delete=1&my_post_key='+my_post_key+'&pid='+pid, - type: 'post', - complete: function (request, status) - { - var json = $.parseJSON(request.responseText); - if(json.hasOwnProperty("errors")) - { - $.each(json.errors, function(i, message) - { - $.jGrowl(lang.quick_delete_error + ' ' + message, {theme:'jgrowl_error'}); - }); - } - else if(json.hasOwnProperty("data")) - { - // Soft deleted - if(json.data == 1) - { - // Change CSS class of div 'post_[pid]' - $("#post_"+pid).addClass("unapproved_post deleted_post"); - - $("#quick_delete_" + pid).hide(); - $("#quick_restore_" + pid).show(); - - $.jGrowl(lang.quick_delete_success, {theme:'jgrowl_success'}); - } - else if(json.data == 2) - { - // Actually deleted - $('#post_'+pid).slideToggle("slow"); - - $.jGrowl(lang.quick_delete_success, {theme:'jgrowl_success'}); - } else if(json.data == 3) - { - // deleted thread --> redirect - - if(!json.hasOwnProperty("url")) - { - $.jGrowl(lang.unknown_error, {theme:'jgrowl_error'}); - } - - // set timeout for redirect - window.setTimeout(function() - { - window.location = json.url; - }, 3000); - - // print success message - $.jGrowl(lang.quick_delete_thread_success, {theme:'jgrowl_success'}); - } - } - else - { - $.jGrowl(lang.unknown_error, {theme:'jgrowl_error'}); - } - } - }); - } - } - }); - - return false; - }, - - - restorePost: function(pid) - { - $.prompt(quickrestore_confirm, { - buttons:[ - {title: yes_confirm, value: true}, - {title: no_confirm, value: false} - ], - submit: function(e,v,m,f){ - if(v == true) - { - $.ajax( - { - url: 'editpost.php?ajax=1&action=restorepost&restore=1&my_post_key='+my_post_key+'&pid='+pid, - type: 'post', - complete: function (request, status) - { - var json = $.parseJSON(request.responseText); - if(json.hasOwnProperty("errors")) - { - $.each(json.errors, function(i, message) - { - $.jGrowl(lang.quick_restore_error + ' ' + message, {theme:'jgrowl_error'}); - }); - } - else if(json.hasOwnProperty("data")) - { - // Change CSS class of div 'post_[pid]' - $("#post_"+pid).removeClass("unapproved_post deleted_post"); - - $("#quick_delete_" + pid).show(); - $("#quick_restore_" + pid).hide(); - - $.jGrowl(lang.quick_restore_success, {theme:'jgrowl_success'}); - } - else - { - $.jGrowl(lang.unknown_error, {theme:'jgrowl_error'}); - } - } - }); - } - } - }); - - return false; - }, - - viewNotes: function(tid) - { - MyBB.popupWindow("/moderation.php?action=viewthreadnotes&tid="+tid+"&modal=1"); - } -}; - -Thread.init(); \ No newline at end of file diff --git a/html/forums/jscripts/usercp.js b/html/forums/jscripts/usercp.js deleted file mode 100644 index c9de7c1..0000000 --- a/html/forums/jscripts/usercp.js +++ /dev/null @@ -1,258 +0,0 @@ -var UserCP = { - init: function() - { - }, - - openBuddySelect: function(field) - { - if(!$("#"+field).length) - { - return false; - } - this.buddy_field = '#'+field; - if($("#buddyselect_container").length) - { - UserCP.buddySelectLoaded(); - return false; - } - if(use_xmlhttprequest == 1) - { - $.ajax( - { - url: 'xmlhttp.php?action=get_buddyselect', - async: true, - complete: function (request) - { - UserCP.buddySelectLoaded(request); - } - }); - } - }, - - buddySelectLoaded: function(request) - { - var buddyselect_container = $("#buddyselect_container"); - // Using new copy - if(request) - { - try { - var json = $.parseJSON(request.responseText); - if(json.hasOwnProperty("errors")) - { - $.each(json.errors, function(i, message) - { - $.jGrowl(lang.buddylist_error + message, {theme:'jgrowl_error'}); - }); - return false; - } - } catch (e) { - if(request.responseText) - { - if(buddyselect_container.length) - { - buddyselect_container.remove(); - } - var container = $("
    "); - container.attr("id", "buddyselect_container"); - container.hide(); - container.html(request.responseText); - $("body").append(container); - } - } - } - else - { - buddyselect_container.hide(); - $("#buddyselect_container input:checked").each(function() - { - $(this).attr("checked", false); - }); - $("#buddyselect_buddies").html(""); - container = buddyselect_container; - } - - // Clone off screen - var clone = container.clone(true); - $("body").append(clone); - clone.css("width", "300px") - .css("top", "-10000px") - .css("display", "block") - .remove(); - - // Center it on the page - $("#buddyselect_container").css("top", "50%") - .css("left", "50%") - .css("position", "fixed") - .css("display", "block") - .css("z-index", "1000") - .css("text-align", "left") - .css("margin-left", -$("#buddyselect_container").outerWidth() / 2 + 'px') - .css("margin-top", -$("#buddyselect_container").outerHeight() / 2 + 'px'); - }, - - selectBuddy: function(uid, username) - { - var checkbox = $("#checkbox_"+uid); - var buddyselect_buddies_uid = $("#buddyselect_buddies_"+uid); - var buddyselect_buddies = $("#buddyselect_buddies"); - // Buddy already in list - remove - if(buddyselect_buddies_uid.length) - { - buddyselect_buddies_uid.remove(); - var buddies = buddyselect_buddies.text(); - if(buddies.charAt(0) == ",") - { - first_buddy = buddyselect_buddies.children()[0]; - first_buddy.innerHTML = first_buddy.innerHTML.substr(1, first_buddy.innerHTML.length); - } - } - // Add buddy to list - else - { - var buddies = buddyselect_buddies.text(); - if(buddies != "") - { - username = ", "+username; - } - var buddy = $(""); - buddy.attr("id", "buddyselect_buddies_"+uid) - .html(username); - buddyselect_buddies.append(buddy); - } - }, - - closeBuddySelect: function(canceled) - { - if(canceled != true) - { - var buddies = $("#buddyselect_buddies").text(); - existing_buddies = $(this.buddy_field).select2("data"); - if(existing_buddies.length) - { - // We already have stuff in our text box we must merge it with the new array we're going to create from the selected buddies - // We don't need to care about having dupes because Select2 treats items by ID and we two items have the same ID, there are no dupes because only one exists - // ^At least according to my tests :D (Pirata Nervo - so blame me for that if something goes wrong) - var newbuddies = []; - exp_buddies = buddies.split(","); - $.each(exp_buddies, function(index, buddy) - { - buddy = buddy.replace(/^\s+|\s+$/g, ""); - - var newbuddy = { id: buddy, text: buddy }; - newbuddies.push(newbuddy); - }); - - // Merge both - var newarray = $.merge(existing_buddies, newbuddies); - - // Update data - $(this.buddy_field).select2("data", newarray); - - } - else - { - var newbuddies = []; - exp_buddies = buddies.split(","); - $.each(exp_buddies, function(index, value ){ - var newbuddy = { id: value.replace(/,\s?/g, ", "), text: value.replace(/,\s?/g, ", ") }; - newbuddies.push(newbuddy); - }); - $(this.buddy_field).select2("data", newbuddies); - } - $(this.buddy_field).select2("focus"); - } - $("#buddyselect_container").hide(); - }, - - addBuddy: function(type) - { - var type_submit = $("#"+type+"_submit"); - var type_add_username = $("#"+type+"_add_username"); - - if(type_add_username.val().length == 0) - { - return false; - } - if(use_xmlhttprequest != 1) - { - return true; - } - - var old_value = type_submit.val(); - - type_add_username.attr("disabled", true); - type_submit.attr("disabled", true); - - if(type == "ignored") - { - type_submit.attr("value", lang.adding_ignored); - var list = "ignore"; - } - else - { - type_submit.attr("value", lang.adding_buddy); - var list = "buddy"; - } - - $.ajax( - { - type: 'post', - url: 'usercp.php?action=do_editlists&my_post_key='+my_post_key+'&manage='+type, - data: { ajax: 1, add_username: type_add_username.val() }, - async: false, - complete: function (request) - { - if(request.responseText.indexOf("buddy_count") >= 0 || request.responseText.indexOf("ignored_count") >= 0) - { - $("#"+list+"_list").html(request.responseText); - } - else - { - $("#sentrequests").html(request.responseText); - } - - type_submit.removeAttr("disabled"); - type_add_username.removeAttr("disabled"); - type_submit.attr("value", old_value); - type_add_username.val(""); - type_add_username.focus(); - type_add_username.select2('data', null); - } - }); - - return false; - }, - - removeBuddy: function(type, uid) - { - if(type == "ignored") - { - var message = lang.remove_ignored; - } - else - { - var message = lang.remove_buddy; - } - - $.prompt(message, { - buttons:[ - {title: yes_confirm, value: true}, - {title: no_confirm, value: false} - ], - submit: function(e,v,m,f){ - if(v == true) - { - $.ajax( - { - type: 'post', - url: 'usercp.php?action=do_editlists&my_post_key='+my_post_key+'&manage='+type+'&delete='+uid, - data: { ajax: 1 }, - async: false - }); - } - } - }); - - return false; - } -}; diff --git a/html/forums/jscripts/validate/additional-methods.min.js b/html/forums/jscripts/validate/additional-methods.min.js deleted file mode 100644 index b63c3ca..0000000 --- a/html/forums/jscripts/validate/additional-methods.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery Validation Plugin - v1.14.0 - 6/30/2015 - * http://jqueryvalidation.org/ - * Copyright (c) 2015 Jörn Zaefferer; Licensed MIT */ -!function(a){"function"==typeof define&&define.amd?define(["jquery","./jquery.validate.min"],a):a(jQuery)}(function(a){!function(){function b(a){return a.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," ").replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g,"")}a.validator.addMethod("maxWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length<=d},a.validator.format("Please enter {0} words or less.")),a.validator.addMethod("minWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length>=d},a.validator.format("Please enter at least {0} words.")),a.validator.addMethod("rangeWords",function(a,c,d){var e=b(a),f=/\b\w+\b/g;return this.optional(c)||e.match(f).length>=d[0]&&e.match(f).length<=d[1]},a.validator.format("Please enter between {0} and {1} words."))}(),a.validator.addMethod("accept",function(b,c,d){var e,f,g="string"==typeof d?d.replace(/\s/g,"").replace(/,/g,"|"):"image/*",h=this.optional(c);if(h)return h;if("file"===a(c).attr("type")&&(g=g.replace(/\*/g,".*"),c.files&&c.files.length))for(e=0;ec;c++)d=h-c,e=f.substring(c,c+1),g+=d*e;return g%11===0},"Please specify a valid bank account number"),a.validator.addMethod("bankorgiroaccountNL",function(b,c){return this.optional(c)||a.validator.methods.bankaccountNL.call(this,b,c)||a.validator.methods.giroaccountNL.call(this,b,c)},"Please specify a valid bank or giro account number"),a.validator.addMethod("bic",function(a,b){return this.optional(b)||/^([A-Z]{6}[A-Z2-9][A-NP-Z1-2])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test(a)},"Please specify a valid BIC code"),a.validator.addMethod("cifES",function(a){"use strict";var b,c,d,e,f,g,h=[];if(a=a.toUpperCase(),!a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)"))return!1;for(d=0;9>d;d++)h[d]=parseInt(a.charAt(d),10);for(c=h[2]+h[4]+h[6],e=1;8>e;e+=2)f=(2*h[e]).toString(),g=f.charAt(1),c+=parseInt(f.charAt(0),10)+(""===g?0:parseInt(g,10));return/^[ABCDEFGHJNPQRSUVW]{1}/.test(a)?(c+="",b=10-parseInt(c.charAt(c.length-1),10),a+=b,h[8].toString()===String.fromCharCode(64+b)||h[8].toString()===a.charAt(a.length-1)):!1},"Please specify a valid CIF number."),a.validator.addMethod("cpfBR",function(a){if(a=a.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g,""),11!==a.length)return!1;var b,c,d,e,f=0;if(b=parseInt(a.substring(9,10),10),c=parseInt(a.substring(10,11),10),d=function(a,b){var c=10*a%11;return(10===c||11===c)&&(c=0),c===b},""===a||"00000000000"===a||"11111111111"===a||"22222222222"===a||"33333333333"===a||"44444444444"===a||"55555555555"===a||"66666666666"===a||"77777777777"===a||"88888888888"===a||"99999999999"===a)return!1;for(e=1;9>=e;e++)f+=parseInt(a.substring(e-1,e),10)*(11-e);if(d(f,b)){for(f=0,e=1;10>=e;e++)f+=parseInt(a.substring(e-1,e),10)*(12-e);return d(f,c)}return!1},"Please specify a valid CPF number"),a.validator.addMethod("creditcardtypes",function(a,b,c){if(/[^0-9\-]+/.test(a))return!1;a=a.replace(/\D/g,"");var d=0;return c.mastercard&&(d|=1),c.visa&&(d|=2),c.amex&&(d|=4),c.dinersclub&&(d|=8),c.enroute&&(d|=16),c.discover&&(d|=32),c.jcb&&(d|=64),c.unknown&&(d|=128),c.all&&(d=255),1&d&&/^(5[12345])/.test(a)?16===a.length:2&d&&/^(4)/.test(a)?16===a.length:4&d&&/^(3[47])/.test(a)?15===a.length:8&d&&/^(3(0[012345]|[68]))/.test(a)?14===a.length:16&d&&/^(2(014|149))/.test(a)?15===a.length:32&d&&/^(6011)/.test(a)?16===a.length:64&d&&/^(3)/.test(a)?16===a.length:64&d&&/^(2131|1800)/.test(a)?15===a.length:128&d?!0:!1},"Please enter a valid credit card number."),a.validator.addMethod("currency",function(a,b,c){var d,e="string"==typeof c,f=e?c:c[0],g=e?!0:c[1];return f=f.replace(/,/g,""),f=g?f+"]":f+"]?",d="^["+f+"([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$",d=new RegExp(d),this.optional(b)||d.test(a)},"Please specify a valid currency"),a.validator.addMethod("dateFA",function(a,b){return this.optional(b)||/^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(a)},a.validator.messages.date),a.validator.addMethod("dateITA",function(a,b){var c,d,e,f,g,h=!1,i=/^\d{1,2}\/\d{1,2}\/\d{4}$/;return i.test(a)?(c=a.split("/"),d=parseInt(c[0],10),e=parseInt(c[1],10),f=parseInt(c[2],10),g=new Date(Date.UTC(f,e-1,d,12,0,0,0)),h=g.getUTCFullYear()===f&&g.getUTCMonth()===e-1&&g.getUTCDate()===d?!0:!1):h=!1,this.optional(b)||h},a.validator.messages.date),a.validator.addMethod("dateNL",function(a,b){return this.optional(b)||/^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(a)},a.validator.messages.date),a.validator.addMethod("extension",function(a,b,c){return c="string"==typeof c?c.replace(/,/g,"|"):"png|jpe?g|gif",this.optional(b)||a.match(new RegExp("\\.("+c+")$","i"))},a.validator.format("Please enter a value with a valid extension.")),a.validator.addMethod("giroaccountNL",function(a,b){return this.optional(b)||/^[0-9]{1,7}$/.test(a)},"Please specify a valid giro account number"),a.validator.addMethod("iban",function(a,b){if(this.optional(b))return!0;var c,d,e,f,g,h,i,j,k,l=a.replace(/ /g,"").toUpperCase(),m="",n=!0,o="",p="";if(c=l.substring(0,2),h={AL:"\\d{8}[\\dA-Z]{16}",AD:"\\d{8}[\\dA-Z]{12}",AT:"\\d{16}",AZ:"[\\dA-Z]{4}\\d{20}",BE:"\\d{12}",BH:"[A-Z]{4}[\\dA-Z]{14}",BA:"\\d{16}",BR:"\\d{23}[A-Z][\\dA-Z]",BG:"[A-Z]{4}\\d{6}[\\dA-Z]{8}",CR:"\\d{17}",HR:"\\d{17}",CY:"\\d{8}[\\dA-Z]{16}",CZ:"\\d{20}",DK:"\\d{14}",DO:"[A-Z]{4}\\d{20}",EE:"\\d{16}",FO:"\\d{14}",FI:"\\d{14}",FR:"\\d{10}[\\dA-Z]{11}\\d{2}",GE:"[\\dA-Z]{2}\\d{16}",DE:"\\d{18}",GI:"[A-Z]{4}[\\dA-Z]{15}",GR:"\\d{7}[\\dA-Z]{16}",GL:"\\d{14}",GT:"[\\dA-Z]{4}[\\dA-Z]{20}",HU:"\\d{24}",IS:"\\d{22}",IE:"[\\dA-Z]{4}\\d{14}",IL:"\\d{19}",IT:"[A-Z]\\d{10}[\\dA-Z]{12}",KZ:"\\d{3}[\\dA-Z]{13}",KW:"[A-Z]{4}[\\dA-Z]{22}",LV:"[A-Z]{4}[\\dA-Z]{13}",LB:"\\d{4}[\\dA-Z]{20}",LI:"\\d{5}[\\dA-Z]{12}",LT:"\\d{16}",LU:"\\d{3}[\\dA-Z]{13}",MK:"\\d{3}[\\dA-Z]{10}\\d{2}",MT:"[A-Z]{4}\\d{5}[\\dA-Z]{18}",MR:"\\d{23}",MU:"[A-Z]{4}\\d{19}[A-Z]{3}",MC:"\\d{10}[\\dA-Z]{11}\\d{2}",MD:"[\\dA-Z]{2}\\d{18}",ME:"\\d{18}",NL:"[A-Z]{4}\\d{10}",NO:"\\d{11}",PK:"[\\dA-Z]{4}\\d{16}",PS:"[\\dA-Z]{4}\\d{21}",PL:"\\d{24}",PT:"\\d{21}",RO:"[A-Z]{4}[\\dA-Z]{16}",SM:"[A-Z]\\d{10}[\\dA-Z]{12}",SA:"\\d{2}[\\dA-Z]{18}",RS:"\\d{18}",SK:"\\d{20}",SI:"\\d{15}",ES:"\\d{20}",SE:"\\d{20}",CH:"\\d{5}[\\dA-Z]{12}",TN:"\\d{20}",TR:"\\d{5}[\\dA-Z]{17}",AE:"\\d{3}\\d{16}",GB:"[A-Z]{4}\\d{14}",VG:"[\\dA-Z]{4}\\d{16}"},g=h[c],"undefined"!=typeof g&&(i=new RegExp("^[A-Z]{2}\\d{2}"+g+"$",""),!i.test(l)))return!1;for(d=l.substring(4,l.length)+l.substring(0,4),j=0;j9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number"),a.validator.addMethod("nieES",function(a){"use strict";return a=a.toUpperCase(),a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")?/^[T]{1}/.test(a)?a[8]===/^[T]{1}[A-Z0-9]{8}$/.test(a):/^[XYZ]{1}/.test(a)?a[8]==="TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.replace("X","0").replace("Y","1").replace("Z","2").substring(0,8)%23):!1:!1},"Please specify a valid NIE number."),a.validator.addMethod("nifES",function(a){"use strict";return a=a.toUpperCase(),a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")?/^[0-9]{8}[A-Z]{1}$/.test(a)?"TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,0)%23)===a.charAt(8):/^[KLM]{1}/.test(a)?a[8]===String.fromCharCode(64):!1:!1},"Please specify a valid NIF number."),jQuery.validator.addMethod("notEqualTo",function(b,c,d){return this.optional(c)||!a.validator.methods.equalTo.call(this,b,c,d)},"Please enter a different value, values must not be the same."),a.validator.addMethod("nowhitespace",function(a,b){return this.optional(b)||/^\S+$/i.test(a)},"No white space please"),a.validator.addMethod("pattern",function(a,b,c){return this.optional(b)?!0:("string"==typeof c&&(c=new RegExp("^(?:"+c+")$")),c.test(a))},"Invalid format."),a.validator.addMethod("phoneNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid phone number."),a.validator.addMethod("phoneUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number"),a.validator.addMethod("phoneUS",function(a,b){return a=a.replace(/\s+/g,""),this.optional(b)||a.length>9&&a.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/)},"Please specify a valid phone number"),a.validator.addMethod("phonesUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number"),a.validator.addMethod("postalCodeCA",function(a,b){return this.optional(b)||/^[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeBR",function(a,b){return this.optional(b)||/^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test(a)},"Informe um CEP válido."),a.validator.addMethod("postalcodeIT",function(a,b){return this.optional(b)||/^\d{5}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeNL",function(a,b){return this.optional(b)||/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postcodeUK",function(a,b){return this.optional(b)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(a)},"Please specify a valid UK postcode"),a.validator.addMethod("require_from_group",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_req_grp")?f.data("valid_req_grp"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length>=d[0];return f.data("valid_req_grp",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),h},a.validator.format("Please fill at least {0} of these fields.")),a.validator.addMethod("skip_or_fill_minimum",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_skip")?f.data("valid_skip"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length,i=0===h||h>=d[0];return f.data("valid_skip",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),i},a.validator.format("Please either skip these fields or fill at least {0} of them.")),a.validator.addMethod("stateUS",function(a,b,c){var d,e="undefined"==typeof c,f=e||"undefined"==typeof c.caseSensitive?!1:c.caseSensitive,g=e||"undefined"==typeof c.includeTerritories?!1:c.includeTerritories,h=e||"undefined"==typeof c.includeMilitary?!1:c.includeMilitary;return d=g||h?g&&h?"^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":g?"^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":"^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$":"^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$",d=f?new RegExp(d):new RegExp(d,"i"),this.optional(b)||d.test(a)},"Please specify a valid state"),a.validator.addMethod("strippedminlength",function(b,c,d){return a(b).text().length>=d},a.validator.format("Please enter at least {0} characters")),a.validator.addMethod("time",function(a,b){return this.optional(b)||/^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(a)},"Please enter a valid time, between 00:00 and 23:59"),a.validator.addMethod("time12h",function(a,b){return this.optional(b)||/^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(a)},"Please enter a valid time in 12-hour am/pm format"),a.validator.addMethod("url2",function(a,b){return this.optional(b)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},a.validator.messages.url),a.validator.addMethod("vinUS",function(a){if(17!==a.length)return!1;var b,c,d,e,f,g,h=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"],i=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9],j=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],k=0;for(b=0;17>b;b++){if(e=j[b],d=a.slice(b,b+1),8===b&&(g=d),isNaN(d)){for(c=0;c").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),e=c.settings.submitHandler.call(c,c.currentForm,b),c.submitButton&&d.remove(),void 0!==e?e:!1):!0}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,d=d.concat(c.errorList)}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(b,c){i[c]=f[c],delete f[c],"required"===c&&a(j).removeAttr("aria-required")}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g),a(j).attr("aria-required","true")),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}),a.extend(a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){return!!a.trim(""+a(b).val())},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||-1!==a.inArray(c.keyCode,d)||(b.name in this.submitted||b===this.lastElement)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date ( ISO ).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c=a.data(this.form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!a(this).is(e.ignore)&&e[d].call(c,this,b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler),a(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required","true")},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c=this.clean(b),d=this.validationTargetFor(c),e=!0;return this.lastElement=d,void 0===d?delete this.invalid[c.name]:(this.prepareElement(d),this.currentElements=a(d),e=this.check(d)!==!1,e?delete this.invalid[d.name]:this.invalid[d.name]=!0),a(b).attr("aria-invalid",!e),this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),e},showErrors:function(b){if(b){a.extend(this.errorMap,b),this.errorList=[];for(var c in b)this.errorList.push({message:b[c],element:this.findByName(c)[0]});this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors();var b,c=this.elements().removeData("previousValue").removeAttr("aria-invalid");if(this.settings.unhighlight)for(b=0;c[b];b++)this.settings.unhighlight.call(this,c[b],this.settings.errorClass,"");else c.removeClass(this.settings.errorClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){return!this.name&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in c||!b.objectLength(a(this).rules())?!1:(c[this.name]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([]),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d=a(b),e=b.type;return"radio"===e||"checkbox"===e?this.findByName(b.name).filter(":checked").val():"number"===e&&"undefined"!=typeof b.validity?b.validity.badInput?!1:d.val():(c=d.val(),"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f=a(b).rules(),g=a.map(f,function(a,b){return b}).length,h=!1,i=this.elementValue(b);for(d in f){e={method:d,parameters:f[d]};try{if(c=a.validator.methods[d].call(this,i,b,e.parameters),"dependency-mismatch"===c&&1===g){h=!0;continue}if(h=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(j){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",j),j instanceof TypeError&&(j.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),j}}if(!h)return this.objectLength(f)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;aWarning: No message defined for "+b.name+"")},formatAndAdd:function(b,c){var d=this.defaultMessage(b,c.method),e=/\$?\{(\d+)\}/g;"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),this.errorList.push({message:d,element:b,method:c.method}),this.errorMap[b.name]=d,this.submitted[b.name]=d},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g=this.errorsFor(b),h=this.idOrName(b),i=a(b).attr("aria-describedby");g.length?(g.removeClass(this.settings.validClass).addClass(this.settings.errorClass),g.html(c)):(g=a("<"+this.settings.errorElement+">").attr("id",h+"-error").addClass(this.settings.errorClass).html(c||""),d=g,this.settings.wrapper&&(d=g.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement(d,a(b)):d.insertAfter(b),g.is("label")?g.attr("for",h):0===g.parents("label[for='"+h+"']").length&&(f=g.attr("id").replace(/(:|\.|\[|\]|\$)/g,"\\$1"),i?i.match(new RegExp("\\b"+f+"\\b"))||(i+=" "+f):i=f,a(b).attr("aria-describedby",i),e=this.groups[b.name],e&&a.each(this.groups,function(b,c){c===e&&a("[name='"+b+"']",this.currentForm).attr("aria-describedby",g.attr("id"))}))),!c&&this.settings.success&&(g.text(""),"string"==typeof this.settings.success?g.addClass(this.settings.success):this.settings.success(g,b)),this.toShow=this.toShow.add(g)},errorsFor:function(b){var c=this.idOrName(b),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+d.replace(/\s+/g,", #")),this.errors().filter(e)},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+b+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return this.dependTypes[typeof a]?this.dependTypes[typeof a](a,b):!0},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(a){this.pending[a.name]||(this.pendingRequest++,this.pending[a.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b){return a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,"remote")})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0!==e.param?e.param:!0:delete b[d]}}),a.each(b,function(d,e){b[d]=a.isFunction(e)?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},creditcard:function(a,b){if(this.optional(b))return"dependency-mismatch";if(/[^0-9 \-]+/.test(a))return!1;var c,d,e=0,f=0,g=!1;if(a=a.replace(/\D/g,""),a.length<13||a.length>19)return!1;for(c=a.length-1;c>=0;c--)d=a.charAt(c),f=parseInt(d,10),g&&(f*=2)>9&&(f-=9),e+=f,g=!g;return e%10===0},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||d>=e},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||c>=a},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.off(".validate-equalTo").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d){if(this.optional(c))return"dependency-mismatch";var e,f,g=this.previousValue(c);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),g.originalMessage=this.settings.messages[c.name].remote,this.settings.messages[c.name].remote=g.message,d="string"==typeof d&&{url:d}||d,g.old===b?g.valid:(g.old=b,e=this,this.startRequest(c),f={},f[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:f,context:e.currentForm,success:function(d){var f,h,i,j=d===!0||"true"===d;e.settings.messages[c.name].remote=g.originalMessage,j?(i=e.formSubmitted,e.prepareElement(c),e.formSubmitted=i,e.successList.push(c),delete e.invalid[c.name],e.showErrors()):(f={},h=d||e.defaultMessage(c,"remote"),f[c.name]=g.message=a.isFunction(h)?h(b):h,e.invalid[c.name]=!0,e.showErrors(f)),g.valid=j,e.stopRequest(c,j)}},d)),"pending")}}});var b,c={};a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)})}); \ No newline at end of file diff --git a/html/forums/managegroup.php b/html/forums/managegroup.php deleted file mode 100644 index 7fb85bb..0000000 --- a/html/forums/managegroup.php +++ /dev/null @@ -1,441 +0,0 @@ -load("managegroup"); - -$gid = $mybb->get_input('gid', MyBB::INPUT_INT); -if(!isset($groupscache[$gid])) -{ - error($lang->invalid_group); -} -$usergroup = $groupscache[$gid]; -$lang->nav_group_management = $lang->sprintf($lang->nav_group_management, htmlspecialchars_uni($usergroup['title'])); -add_breadcrumb($lang->nav_group_memberships, "usercp.php?action=usergroups"); -add_breadcrumb($lang->nav_group_management, "managegroup.php?gid=$gid"); - -$mybb->input['action'] = $mybb->get_input('action'); - -if($mybb->input['action'] == "joinrequests") -{ - add_breadcrumb($lang->nav_join_requests); -} - -// Check that this user is actually a leader of this group -$query = $db->simple_select("groupleaders", "*", "uid='{$mybb->user['uid']}' AND gid='{$gid}'"); -$groupleader = $db->fetch_array($query); - -if(!$groupleader['uid'] && $mybb->usergroup['cancp'] != 1) -{ - error($lang->not_leader_of_this_group); -} - -if($mybb->input['action'] == "do_add" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($groupleader['canmanagemembers'] == 0) - { - error_no_permission(); - } - - $plugins->run_hooks("managegroup_do_add_start"); - - $options = array( - 'fields' => array('additionalgroups', 'usergroup') - ); - - $user = get_user_by_username($mybb->get_input('username'), $options); - - if($user['uid']) - { - $additionalgroups = explode(',', $user['additionalgroups']); - if($user['usergroup'] != $gid && !in_array($gid, $additionalgroups)) - { - join_usergroup($user['uid'], $gid); - $db->delete_query("joinrequests", "uid='{$user['uid']}' AND gid='{$gid}'"); - $plugins->run_hooks("managegroup_do_add_end"); - redirect("managegroup.php?gid=".$gid, $lang->user_added); - } - else - { - error($lang->error_alreadyingroup); - } - } - else - { - error($lang->error_invalidusername); - } -} -elseif($mybb->input['action'] == "do_invite" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($groupleader['caninvitemembers'] == 0) - { - error_no_permission(); - } - - $plugins->run_hooks("managegroup_do_invite_start"); - - $options = array( - 'fields' => array('additionalgroups', 'usergroup', 'language') - ); - - $user = get_user_by_username($mybb->get_input('inviteusername'), $options); - - if($user['uid']) - { - $additionalgroups = explode(',', $user['additionalgroups']); - if($user['usergroup'] != $gid && !in_array($gid, $additionalgroups)) - { - $query = $db->simple_select("joinrequests", "rid", "uid = '".(int)$user['uid']."' AND gid = '".(int)$gid."'", array("limit" => 1)); - $pendinginvite = $db->fetch_array($query); - if($pendinginvite['rid']) - { - error($lang->error_alreadyinvited); - } - else - { - $usergroups_cache = $cache->read('usergroups'); - $usergroup = $usergroups_cache[$gid]; - - $joinrequest = array( - "uid" => $user['uid'], - "gid" => $usergroup['gid'], - "dateline" => TIME_NOW, - "invite" => 1 - ); - $db->insert_query("joinrequests", $joinrequest); - - $lang_var = 'invite_pm_message'; - if($mybb->settings['deleteinvites'] != 0) - { - $lang_var .= '_expires'; - } - - $pm = array( - 'subject' => array('invite_pm_subject', $usergroup['title']), - 'message' => array($lang_var, $usergroup['title'], $mybb->settings['bburl'], $mybb->settings['deleteinvites']), - 'touid' => $user['uid'], - 'language' => $user['language'], - 'language_file' => 'managegroup' - ); - - send_pm($pm, $mybb->user['uid'], true); - - $plugins->run_hooks("managegroup_do_invite_end"); - - redirect("managegroup.php?gid=".$gid, $lang->user_invited); - } - } - else - { - error($lang->error_alreadyingroup); - } - } - else - { - error($lang->error_invalidusername); - } -} -elseif($mybb->input['action'] == "do_joinrequests" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($groupleader['canmanagerequests'] == 0) - { - error_no_permission(); - } - - $plugins->run_hooks("managegroup_do_joinrequests_start"); - - $uidin = null; - if(is_array($mybb->get_input('request', MyBB::INPUT_ARRAY))) - { - $uidin = array(); - foreach($mybb->get_input('request', MyBB::INPUT_ARRAY) as $uid => $what) - { - if($what == "accept") - { - join_usergroup($uid, $gid); - $uidin[] = (int)$uid; - } - elseif($what == "decline") - { - $uidin[] = (int)$uid; - } - } - } - if(is_array($uidin) && !empty($uidin)) - { - $uids = implode(",", $uidin); - $db->delete_query("joinrequests", "uid IN ({$uids}) AND gid='{$gid}'"); - } - - $plugins->run_hooks("managegroup_do_joinrequests_end"); - - redirect("managegroup.php?gid={$gid}", $lang->join_requests_moderated); -} -elseif($mybb->input['action'] == "joinrequests") -{ - $users = ""; - $plugins->run_hooks("managegroup_joinrequests_start"); - - $query = $db->query(" - SELECT j.*, u.uid, u.username, u.postnum, u.regdate - FROM ".TABLE_PREFIX."joinrequests j - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=j.uid) - WHERE j.gid='{$gid}' AND j.uid != 0 - ORDER BY u.username ASC - "); - while($user = $db->fetch_array($query)) - { - $user['reason'] = htmlspecialchars_uni($user['reason']); - $altbg = alt_trow(); - $regdate = my_date($mybb->settings['dateformat'], $user['regdate']); - $user['username'] = htmlspecialchars_uni($user['username']); - $user['profilelink'] = build_profile_link($user['username'], $user['uid']); - eval("\$users .= \"".$templates->get("managegroup_joinrequests_request")."\";"); - } - if(!$users) - { - error($lang->no_requests); - } - $lang->join_requests = $lang->sprintf($lang->join_requests_title, htmlspecialchars_uni($usergroup['title'])); - - $plugins->run_hooks("managegroup_joinrequests_end"); - - eval("\$joinrequests = \"".$templates->get("managegroup_joinrequests")."\";"); - output_page($joinrequests); -} -elseif($mybb->input['action'] == "do_manageusers" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($groupleader['canmanagemembers'] == 0) - { - error_no_permission(); - } - - $plugins->run_hooks("managegroup_do_manageusers_start"); - - if(is_array($mybb->get_input('removeuser', MyBB::INPUT_ARRAY))) - { - foreach($mybb->get_input('removeuser', MyBB::INPUT_ARRAY) as $uid) - { - leave_usergroup($uid, $gid); - } - } - else - { - error($lang->no_users_selected); - } - - $plugins->run_hooks("managegroup_do_manageusers_end"); - - redirect("managegroup.php?gid={$gid}", $lang->users_removed); -} -else -{ - $plugins->run_hooks("managegroup_start"); - - $lang->members_of = $lang->sprintf($lang->members_of, htmlspecialchars_uni($usergroup['title'])); - $lang->add_member = $lang->sprintf($lang->add_member, htmlspecialchars_uni($usergroup['title'])); - $lang->invite_member = $lang->sprintf($lang->invite_member, htmlspecialchars_uni($usergroup['title'])); - $joinrequests = ''; - if($usergroup['type'] == 5) - { - $usergrouptype = $lang->group_public_invite; - } - elseif($usergroup['type'] == 4) - { - $query = $db->simple_select("joinrequests", "COUNT(*) AS req", "gid='{$gid}'"); - $numrequests = $db->fetch_array($query); - if($numrequests['req']) - { - $lang->num_requests_pending = $lang->sprintf($lang->num_requests_pending, $numrequests['req']); - eval("\$joinrequests = \"".$templates->get("managegroup_requestnote")."\";"); - } - $usergrouptype = $lang->group_public_moderated; - } - elseif($usergroup['type'] == 3) - { - $usergrouptype = $lang->group_public_not_moderated; - } - elseif($usergroup['type'] == 2) - { - $usergrouptype = $lang->group_private; - } - else - { - $usergrouptype = $lang->group_default; - } - - $group_leaders = ''; - - // Display group leaders (if there is any) - $query = $db->query(" - SELECT g.*, u.username, u.usergroup, u.displaygroup - FROM ".TABLE_PREFIX."groupleaders g - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=g.uid) - WHERE g.gid = '{$gid}' - "); - - $leaders_array = array(); - - if($db->num_rows($query)) - { - $loop = 1; - $leaders = ''; - $leader_count = $db->num_rows($query); - while($leader = $db->fetch_array($query)) - { - $leader['username'] = htmlspecialchars_uni($leader['username']); - $leader_name = format_name($leader['username'], $leader['usergroup'], $leader['displaygroup']); - $leader_profile_link = build_profile_link($leader_name, $leader['uid']); - - $leaders_array[] = $leader['uid']; - - // Get commas... - if($loop != $leader_count) - { - $comma = $lang->comma; - } - else - { - $comma = ''; - } - - ++$loop; - eval("\$leaders .= \"".$templates->get("managegroup_leaders_bit")."\";"); - } - - eval("\$group_leaders = \"".$templates->get("managegroup_leaders")."\";"); - } - - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("users", "*", "','||additionalgroups||',' LIKE '%,{$gid},%' OR usergroup='{$gid}'", array('order_by' => 'username')); - break; - default: - $query = $db->simple_select("users", "*", "CONCAT(',',additionalgroups,',') LIKE '%,{$gid},%' OR usergroup='{$gid}'", array('order_by' => 'username')); - } - - $numusers = $db->num_rows($query); - - $perpage = (int)$mybb->settings['membersperpage']; - if($perpage < 1) - { - $perpage = 20; - } - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - if($page && $page > 0) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - $multipage = multipage($numusers, $perpage, $page, "managegroup.php?gid=".$gid); - - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("users", "*", "','||additionalgroups||',' LIKE '%,{$gid},%' OR usergroup='{$gid}'", array('order_by' => 'username', 'limit' => $perpage, 'limit_start' => $start)); - break; - default: - $query = $db->simple_select("users", "*", "CONCAT(',',additionalgroups,',') LIKE '%,{$gid},%' OR usergroup='{$gid}'", array('order_by' => 'username', 'limit' => $perpage, 'limit_start' => $start)); - } - - $users = ""; - while($user = $db->fetch_array($query)) - { - $altbg = alt_trow(); - $regdate = my_date('relative', $user['regdate']); - $post = $user; - $sendpm = $email = ''; - if($mybb->settings['enablepms'] == 1 && $post['receivepms'] != 0 && $mybb->usergroup['cansendpms'] == 1 && my_strpos(",".$post['ignorelist'].",", ",".$mybb->user['uid'].",") === false) - { - eval("\$sendpm = \"".$templates->get("postbit_pm")."\";"); - } - - if($user['hideemail'] != 1) - { - eval("\$email = \"".$templates->get("postbit_email")."\";"); - } - else - { - $email = ''; - } - - $user['username'] = htmlspecialchars_uni($user['username']); - $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']); - $user['profilelink'] = build_profile_link($user['username'], $user['uid']); - if(in_array($user['uid'], $leaders_array)) - { - $leader = $lang->leader; - } - else - { - $leader = ''; - } - - // Checkbox for user management - only if current user is allowed - $checkbox = ''; - if($groupleader['canmanagemembers'] == 1) - { - eval("\$checkbox = \"".$templates->get("managegroup_user_checkbox")."\";"); - } - - eval("\$users .= \"".$templates->get("managegroup_user")."\";"); - } - - if(!$users) - { - eval("\$users = \"".$templates->get("managegroup_no_users")."\";"); - } - - $add_user = ''; - $remove_users = ''; - if($groupleader['canmanagemembers'] == 1) - { - eval("\$add_user = \"".$templates->get("managegroup_adduser")."\";"); - eval("\$remove_users = \"".$templates->get("managegroup_removeusers")."\";"); - } - - if($usergroup['type'] == 5 && $groupleader['caninvitemembers'] == 1) - { - eval("\$invite_user = \"".$templates->get("managegroup_inviteuser")."\";"); - } - - $plugins->run_hooks("managegroup_end"); - - eval("\$manageusers = \"".$templates->get("managegroup")."\";"); - output_page($manageusers); -} diff --git a/html/forums/member.php b/html/forums/member.php deleted file mode 100644 index cca9e0a..0000000 --- a/html/forums/member.php +++ /dev/null @@ -1,3068 +0,0 @@ -load("member"); - -$mybb->input['action'] = $mybb->get_input('action'); - -// Make navigation -switch($mybb->input['action']) -{ - case "register": - case "do_register": - add_breadcrumb($lang->nav_register); - break; - case "activate": - add_breadcrumb($lang->nav_activate); - break; - case "resendactivation": - add_breadcrumb($lang->nav_resendactivation); - break; - case "lostpw": - add_breadcrumb($lang->nav_lostpw); - break; - case "resetpassword": - add_breadcrumb($lang->nav_resetpassword); - break; - case "login": - add_breadcrumb($lang->nav_login); - break; - case "emailuser": - add_breadcrumb($lang->nav_emailuser); - break; -} - -if(($mybb->input['action'] == "register" || $mybb->input['action'] == "do_register") && $mybb->usergroup['cancp'] != 1) -{ - if($mybb->settings['disableregs'] == 1) - { - error($lang->registrations_disabled); - } - if($mybb->user['uid'] != 0) - { - error($lang->error_alreadyregistered); - } - if($mybb->settings['betweenregstime'] && $mybb->settings['maxregsbetweentime']) - { - $time = TIME_NOW; - $datecut = $time-(60*60*$mybb->settings['betweenregstime']); - $query = $db->simple_select("users", "*", "regip=".$db->escape_binary($session->packedip)." AND regdate > '$datecut'"); - $regcount = $db->num_rows($query); - if($regcount >= $mybb->settings['maxregsbetweentime']) - { - $lang->error_alreadyregisteredtime = $lang->sprintf($lang->error_alreadyregisteredtime, $regcount, $mybb->settings['betweenregstime']); - error($lang->error_alreadyregisteredtime); - } - } -} - -if($mybb->input['action'] == "do_register" && $mybb->request_method == "post") -{ - $plugins->run_hooks("member_do_register_start"); - - // Are checking how long it takes for users to register? - if($mybb->settings['regtime'] > 0) - { - // Is the field actually set? - if(isset($mybb->input['regtime'])) - { - // Check how long it took for this person to register - $timetook = TIME_NOW - $mybb->get_input('regtime', MyBB::INPUT_INT); - - // See if they registered faster than normal - if($timetook < $mybb->settings['regtime']) - { - // This user registered pretty quickly, bot detected! - $lang->error_spam_deny_time = $lang->sprintf($lang->error_spam_deny_time, $mybb->settings['regtime'], $timetook); - error($lang->error_spam_deny_time); - } - } - else - { - error($lang->error_spam_deny); - } - } - - // If we have hidden CATPCHA enabled and it's filled, deny registration - if($mybb->settings['hiddencaptchaimage']) - { - $string = $mybb->settings['hiddencaptchaimagefield']; - - if(!empty($mybb->input[$string])) - { - error($lang->error_spam_deny); - } - } - - if($mybb->settings['regtype'] == "randompass") - { - - $password_length = (int)$mybb->settings['minpasswordlength']; - if($password_length < 8) - { - $password_length = min(8, (int)$mybb->settings['maxpasswordlength']); - } - - $mybb->input['password'] = random_str($password_length, $mybb->settings['requirecomplexpasswords']); - $mybb->input['password2'] = $mybb->input['password']; - } - - if($mybb->settings['regtype'] == "verify" || $mybb->settings['regtype'] == "admin" || $mybb->settings['regtype'] == "both" || $mybb->get_input('coppa', MyBB::INPUT_INT) == 1) - { - $usergroup = 5; - } - else - { - $usergroup = 2; - } - - // Set up user handler. - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler("insert"); - - $coppauser = 0; - if(isset($mybb->cookies['coppauser'])) - { - $coppauser = (int)$mybb->cookies['coppauser']; - } - - // Set the data for the new user. - $user = array( - "username" => $mybb->get_input('username'), - "password" => $mybb->get_input('password'), - "password2" => $mybb->get_input('password2'), - "email" => $mybb->get_input('email'), - "email2" => $mybb->get_input('email2'), - "usergroup" => $usergroup, - "referrer" => $mybb->get_input('referrername'), - "timezone" => $mybb->get_input('timezoneoffset'), - "language" => $mybb->get_input('language'), - "profile_fields" => $mybb->get_input('profile_fields', MyBB::INPUT_ARRAY), - "regip" => $session->packedip, - "coppa_user" => $coppauser, - "regcheck1" => $mybb->get_input('regcheck1'), - "regcheck2" => $mybb->get_input('regcheck2'), - "registration" => true - ); - - // Do we have a saved COPPA DOB? - if(isset($mybb->cookies['coppadob'])) - { - list($dob_day, $dob_month, $dob_year) = explode("-", $mybb->cookies['coppadob']); - $user['birthday'] = array( - "day" => $dob_day, - "month" => $dob_month, - "year" => $dob_year - ); - } - - $user['options'] = array( - "allownotices" => $mybb->get_input('allownotices', MyBB::INPUT_INT), - "hideemail" => $mybb->get_input('hideemail', MyBB::INPUT_INT), - "subscriptionmethod" => $mybb->get_input('subscriptionmethod', MyBB::INPUT_INT), - "receivepms" => $mybb->get_input('receivepms', MyBB::INPUT_INT), - "pmnotice" => $mybb->get_input('pmnotice', MyBB::INPUT_INT), - "pmnotify" => $mybb->get_input('pmnotify', MyBB::INPUT_INT), - "invisible" => $mybb->get_input('invisible', MyBB::INPUT_INT), - "dstcorrection" => $mybb->get_input('dstcorrection') - ); - - $userhandler->set_data($user); - - $errors = ""; - - if(!$userhandler->validate_user()) - { - $errors = $userhandler->get_friendly_errors(); - } - - if($mybb->settings['enablestopforumspam_on_register']) - { - require_once MYBB_ROOT . '/inc/class_stopforumspamchecker.php'; - - $stop_forum_spam_checker = new StopForumSpamChecker( - $plugins, - $mybb->settings['stopforumspam_min_weighting_before_spam'], - $mybb->settings['stopforumspam_check_usernames'], - $mybb->settings['stopforumspam_check_emails'], - $mybb->settings['stopforumspam_check_ips'], - $mybb->settings['stopforumspam_log_blocks'] - ); - - try { - if($stop_forum_spam_checker->is_user_a_spammer($user['username'], $user['email'], get_ip())) - { - error($lang->sprintf($lang->error_stop_forum_spam_spammer, - $stop_forum_spam_checker->getErrorText(array( - 'stopforumspam_check_usernames', - 'stopforumspam_check_emails', - 'stopforumspam_check_ips' - )))); - } - } - catch (Exception $e) - { - if($mybb->settings['stopforumspam_block_on_error']) - { - error($lang->error_stop_forum_spam_fetching); - } - } - } - - if($mybb->settings['captchaimage']) - { - require_once MYBB_ROOT.'inc/class_captcha.php'; - $captcha = new captcha; - - if($captcha->validate_captcha() == false) - { - // CAPTCHA validation failed - foreach($captcha->get_errors() as $error) - { - $errors[] = $error; - } - } - } - - // If we have a security question, check to see if answer is correct - if($mybb->settings['securityquestion']) - { - $question_id = $db->escape_string($mybb->get_input('question_id')); - $answer = $db->escape_string($mybb->get_input('answer')); - - $query = $db->query(" - SELECT q.*, s.sid - FROM ".TABLE_PREFIX."questionsessions s - LEFT JOIN ".TABLE_PREFIX."questions q ON (q.qid=s.qid) - WHERE q.active='1' AND s.sid='{$question_id}' - "); - if($db->num_rows($query) > 0) - { - $question = $db->fetch_array($query); - $valid_answers = explode("\n", $question['answer']); - $validated = 0; - - foreach($valid_answers as $answers) - { - if(my_strtolower($answers) == my_strtolower($answer)) - { - $validated = 1; - } - } - - if($validated != 1) - { - $update_question = array( - "incorrect" => $question['incorrect'] + 1 - ); - $db->update_query("questions", $update_question, "qid='{$question['qid']}'"); - - $errors[] = $lang->error_question_wrong; - } - else - { - $update_question = array( - "correct" => $question['correct'] + 1 - ); - $db->update_query("questions", $update_question, "qid='{$question['qid']}'"); - } - - $db->delete_query("questionsessions", "sid='{$sid}'"); - } - } - - if(is_array($errors)) - { - $username = htmlspecialchars_uni($mybb->get_input('username')); - $email = htmlspecialchars_uni($mybb->get_input('email')); - $email2 = htmlspecialchars_uni($mybb->get_input('email2')); - $referrername = htmlspecialchars_uni($mybb->get_input('referrername')); - - $allownoticescheck = $hideemailcheck = $no_auto_subscribe_selected = $instant_email_subscribe_selected = $instant_pm_subscribe_selected = $no_subscribe_selected = ''; - $receivepmscheck = $pmnoticecheck = $pmnotifycheck = $invisiblecheck = $dst_auto_selected = $dst_enabled_selected = $dst_disabled_selected = ''; - - if($mybb->get_input('allownotices', MyBB::INPUT_INT) == 1) - { - $allownoticescheck = "checked=\"checked\""; - } - - if($mybb->get_input('hideemail', MyBB::INPUT_INT) == 1) - { - $hideemailcheck = "checked=\"checked\""; - } - - if($mybb->get_input('subscriptionmethod', MyBB::INPUT_INT) == 1) - { - $no_subscribe_selected = "selected=\"selected\""; - } - else if($mybb->get_input('subscriptionmethod', MyBB::INPUT_INT) == 2) - { - $instant_email_subscribe_selected = "selected=\"selected\""; - } - else if($mybb->get_input('subscriptionmethod', MyBB::INPUT_INT) == 3) - { - $instant_pm_subscribe_selected = "selected=\"selected\""; - } - else - { - $no_auto_subscribe_selected = "selected=\"selected\""; - } - - if($mybb->get_input('receivepms', MyBB::INPUT_INT) == 1) - { - $receivepmscheck = "checked=\"checked\""; - } - - if($mybb->get_input('pmnotice', MyBB::INPUT_INT) == 1) - { - $pmnoticecheck = " checked=\"checked\""; - } - - if($mybb->get_input('pmnotify', MyBB::INPUT_INT) == 1) - { - $pmnotifycheck = "checked=\"checked\""; - } - - if($mybb->get_input('invisible', MyBB::INPUT_INT) == 1) - { - $invisiblecheck = "checked=\"checked\""; - } - - if($mybb->get_input('dstcorrection', MyBB::INPUT_INT) == 2) - { - $dst_auto_selected = "selected=\"selected\""; - } - else if($mybb->get_input('dstcorrection', MyBB::INPUT_INT) == 1) - { - $dst_enabled_selected = "selected=\"selected\""; - } - else - { - $dst_disabled_selected = "selected=\"selected\""; - } - - $regerrors = inline_error($errors); - $mybb->input['action'] = "register"; - $fromreg = 1; - } - else - { - $user_info = $userhandler->insert_user(); - - // Invalidate solved captcha - if($mybb->settings['captchaimage']) - { - $captcha->invalidate_captcha(); - } - - if($mybb->settings['regtype'] != "randompass" && !isset($mybb->cookies['coppauser'])) - { - // Log them in - my_setcookie("mybbuser", $user_info['uid']."_".$user_info['loginkey'], null, true); - } - - if(isset($mybb->cookies['coppauser'])) - { - $lang->redirect_registered_coppa_activate = $lang->sprintf($lang->redirect_registered_coppa_activate, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username'])); - my_unsetcookie("coppauser"); - my_unsetcookie("coppadob"); - $plugins->run_hooks("member_do_register_end"); - error($lang->redirect_registered_coppa_activate); - } - else if($mybb->settings['regtype'] == "verify") - { - $activationcode = random_str(); - $now = TIME_NOW; - $activationarray = array( - "uid" => $user_info['uid'], - "dateline" => TIME_NOW, - "code" => $activationcode, - "type" => "r" - ); - $db->insert_query("awaitingactivation", $activationarray); - $emailsubject = $lang->sprintf($lang->emailsubject_activateaccount, $mybb->settings['bbname']); - switch($mybb->settings['username_method']) - { - case 0: - $emailmessage = $lang->sprintf($lang->email_activateaccount, $user_info['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user_info['uid'], $activationcode); - break; - case 1: - $emailmessage = $lang->sprintf($lang->email_activateaccount1, $user_info['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user_info['uid'], $activationcode); - break; - case 2: - $emailmessage = $lang->sprintf($lang->email_activateaccount2, $user_info['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user_info['uid'], $activationcode); - break; - default: - $emailmessage = $lang->sprintf($lang->email_activateaccount, $user_info['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user_info['uid'], $activationcode); - break; - } - my_mail($user_info['email'], $emailsubject, $emailmessage); - - $lang->redirect_registered_activation = $lang->sprintf($lang->redirect_registered_activation, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username'])); - - $plugins->run_hooks("member_do_register_end"); - - error($lang->redirect_registered_activation); - } - else if($mybb->settings['regtype'] == "randompass") - { - $emailsubject = $lang->sprintf($lang->emailsubject_randompassword, $mybb->settings['bbname']); - switch($mybb->settings['username_method']) - { - case 0: - $emailmessage = $lang->sprintf($lang->email_randompassword, $user['username'], $mybb->settings['bbname'], $user_info['username'], $user_info['password']); - break; - case 1: - $emailmessage = $lang->sprintf($lang->email_randompassword1, $user['username'], $mybb->settings['bbname'], $user_info['username'], $user_info['password']); - break; - case 2: - $emailmessage = $lang->sprintf($lang->email_randompassword2, $user['username'], $mybb->settings['bbname'], $user_info['username'], $user_info['password']); - break; - default: - $emailmessage = $lang->sprintf($lang->email_randompassword, $user['username'], $mybb->settings['bbname'], $user_info['username'], $user_info['password']); - break; - } - my_mail($user_info['email'], $emailsubject, $emailmessage); - - $plugins->run_hooks("member_do_register_end"); - - error($lang->redirect_registered_passwordsent); - } - else if($mybb->settings['regtype'] == "admin") - { - $groups = $cache->read("usergroups"); - $admingroups = array(); - if(!empty($groups)) // Shouldn't be... - { - foreach($groups as $group) - { - if($group['cancp'] == 1) - { - $admingroups[] = (int)$group['gid']; - } - } - } - - if(!empty($admingroups)) - { - $sqlwhere = 'usergroup IN ('.implode(',', $admingroups).')'; - foreach($admingroups as $admingroup) - { - switch($db->type) - { - case 'pgsql': - case 'sqlite': - $sqlwhere .= " OR ','||additionalgroups||',' LIKE '%,{$admingroup},%'"; - break; - default: - $sqlwhere .= " OR CONCAT(',',additionalgroups,',') LIKE '%,{$admingroup},%'"; - break; - } - } - $q = $db->simple_select('users', 'uid,username,email,language', $sqlwhere); - while($recipient = $db->fetch_array($q)) - { - // First we check if the user's a super admin: if yes, we don't care about permissions - $is_super_admin = is_super_admin($recipient['uid']); - if(!$is_super_admin) - { - // Include admin functions - if(!file_exists(MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions.php")) - { - continue; - } - - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions.php"; - - // Verify if we have permissions to access user-users - require_once MYBB_ROOT.$mybb->config['admin_dir']."/modules/user/module_meta.php"; - if(function_exists("user_admin_permissions")) - { - // Get admin permissions - $adminperms = get_admin_permissions($recipient['uid']); - - $permissions = user_admin_permissions(); - if(array_key_exists('users', $permissions['permissions']) && $adminperms['user']['users'] != 1) - { - continue; // No permissions - } - } - } - - // Load language - if($recipient['language'] != $lang->language && $lang->language_exists($recipient['language'])) - { - $reset_lang = true; - $lang->set_language($recipient['language']); - $lang->load("member"); - } - - $subject = $lang->sprintf($lang->newregistration_subject, $mybb->settings['bbname']); - $message = $lang->sprintf($lang->newregistration_message, $recipient['username'], $mybb->settings['bbname'], $user['username']); - my_mail($recipient['email'], $subject, $message); - } - - // Reset language - if(isset($reset_lang)) - { - $lang->set_language($mybb->settings['bblanguage']); - $lang->load("member"); - } - } - - $lang->redirect_registered_admin_activate = $lang->sprintf($lang->redirect_registered_admin_activate, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username'])); - - $plugins->run_hooks("member_do_register_end"); - - error($lang->redirect_registered_admin_activate); - } - else if($mybb->settings['regtype'] == "both") - { - $groups = $cache->read("usergroups"); - $admingroups = array(); - if(!empty($groups)) // Shouldn't be... - { - foreach($groups as $group) - { - if($group['cancp'] == 1) - { - $admingroups[] = (int)$group['gid']; - } - } - } - - if(!empty($admingroups)) - { - $sqlwhere = 'usergroup IN ('.implode(',', $admingroups).')'; - foreach($admingroups as $admingroup) - { - switch($db->type) - { - case 'pgsql': - case 'sqlite': - $sqlwhere .= " OR ','||additionalgroups||',' LIKE '%,{$admingroup},%'"; - break; - default: - $sqlwhere .= " OR CONCAT(',',additionalgroups,',') LIKE '%,{$admingroup},%'"; - break; - } - } - $q = $db->simple_select('users', 'uid,username,email,language', $sqlwhere); - while($recipient = $db->fetch_array($q)) - { - // First we check if the user's a super admin: if yes, we don't care about permissions - $is_super_admin = is_super_admin($recipient['uid']); - if(!$is_super_admin) - { - // Include admin functions - if(!file_exists(MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions.php")) - { - continue; - } - - require_once MYBB_ROOT.$mybb->config['admin_dir']."/inc/functions.php"; - - // Verify if we have permissions to access user-users - require_once MYBB_ROOT.$mybb->config['admin_dir']."/modules/user/module_meta.php"; - if(function_exists("user_admin_permissions")) - { - // Get admin permissions - $adminperms = get_admin_permissions($recipient['uid']); - - $permissions = user_admin_permissions(); - if(array_key_exists('users', $permissions['permissions']) && $adminperms['user']['users'] != 1) - { - continue; // No permissions - } - } - } - - // Load language - if($recipient['language'] != $lang->language && $lang->language_exists($recipient['language'])) - { - $reset_lang = true; - $lang->set_language($recipient['language']); - $lang->load("member"); - } - - $subject = $lang->sprintf($lang->newregistration_subject, $mybb->settings['bbname']); - $message = $lang->sprintf($lang->newregistration_message, $recipient['username'], $mybb->settings['bbname'], $user['username']); - my_mail($recipient['email'], $subject, $message); - } - - // Reset language - if(isset($reset_lang)) - { - $lang->set_language($mybb->settings['bblanguage']); - $lang->load("member"); - } - } - - $activationcode = random_str(); - $activationarray = array( - "uid" => $user_info['uid'], - "dateline" => TIME_NOW, - "code" => $activationcode, - "type" => "b" - ); - $db->insert_query("awaitingactivation", $activationarray); - $emailsubject = $lang->sprintf($lang->emailsubject_activateaccount, $mybb->settings['bbname']); - switch($mybb->settings['username_method']) - { - case 0: - $emailmessage = $lang->sprintf($lang->email_activateaccount, $user_info['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user_info['uid'], $activationcode); - break; - case 1: - $emailmessage = $lang->sprintf($lang->email_activateaccount1, $user_info['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user_info['uid'], $activationcode); - break; - case 2: - $emailmessage = $lang->sprintf($lang->email_activateaccount2, $user_info['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user_info['uid'], $activationcode); - break; - default: - $emailmessage = $lang->sprintf($lang->email_activateaccount, $user_info['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user_info['uid'], $activationcode); - break; - } - my_mail($user_info['email'], $emailsubject, $emailmessage); - - $lang->redirect_registered_activation = $lang->sprintf($lang->redirect_registered_activation, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username'])); - - $plugins->run_hooks("member_do_register_end"); - - error($lang->redirect_registered_activation); - } - else - { - $lang->redirect_registered = $lang->sprintf($lang->redirect_registered, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username'])); - - $plugins->run_hooks("member_do_register_end"); - - redirect("index.php", $lang->redirect_registered); - } - } -} - -if($mybb->input['action'] == "coppa_form") -{ - if(!$mybb->settings['faxno']) - { - $mybb->settings['faxno'] = " "; - } - - $plugins->run_hooks("member_coppa_form"); - - eval("\$coppa_form = \"".$templates->get("member_coppa_form")."\";"); - output_page($coppa_form); -} - -if($mybb->input['action'] == "register") -{ - $bdaysel = ''; - if($mybb->settings['coppa'] == "disabled") - { - $bdaysel = $bday2blank = ''; - } - $mybb->input['bday1'] = $mybb->get_input('bday1', MyBB::INPUT_INT); - for($day = 1; $day <= 31; ++$day) - { - $selected = ''; - if($mybb->input['bday1'] == $day) - { - $selected = " selected=\"selected\""; - } - - eval("\$bdaysel .= \"".$templates->get("member_register_day")."\";"); - } - - $mybb->input['bday2'] = $mybb->get_input('bday2', MyBB::INPUT_INT); - $bdaymonthsel = array(); - foreach(range(1, 12) as $number) - { - $bdaymonthsel[$number] = ''; - } - $bdaymonthsel[$mybb->input['bday2']] = "selected=\"selected\""; - $mybb->input['bday3'] = $mybb->get_input('bday3', MyBB::INPUT_INT); - - if($mybb->input['bday3'] == 0) - { - $mybb->input['bday3'] = ''; - } - - // Is COPPA checking enabled? - if($mybb->settings['coppa'] != "disabled" && !isset($mybb->input['step'])) - { - // Just selected DOB, we check - if($mybb->input['bday1'] && $mybb->input['bday2'] && $mybb->input['bday3']) - { - my_unsetcookie("coppauser"); - - $months = get_bdays($mybb->input['bday3']); - if($mybb->input['bday2'] < 1 || $mybb->input['bday2'] > 12 || $mybb->input['bday3'] < (date("Y")-100) || $mybb->input['bday3'] > date("Y") || $mybb->input['bday1'] > $months[$mybb->input['bday2']-1]) - { - error($lang->error_invalid_birthday); - } - - $bdaytime = @mktime(0, 0, 0, $mybb->input['bday2'], $mybb->input['bday1'], $mybb->input['bday3']); - - // Store DOB in cookie so we can save it with the registration - my_setcookie("coppadob", "{$mybb->input['bday1']}-{$mybb->input['bday2']}-{$mybb->input['bday3']}", -1); - - // User is <= 13, we mark as a coppa user - if($bdaytime >= mktime(0, 0, 0, my_date('n'), my_date('d'), my_date('Y')-13)) - { - my_setcookie("coppauser", 1, -0); - $under_thirteen = true; - } - $mybb->request_method = ""; - } - // Show DOB select form - else - { - $plugins->run_hooks("member_register_coppa"); - - my_unsetcookie("coppauser"); - - eval("\$coppa = \"".$templates->get("member_register_coppa")."\";"); - output_page($coppa); - exit; - } - } - - if((!isset($mybb->input['agree']) && !isset($mybb->input['regsubmit'])) && $fromreg == 0 || $mybb->request_method != "post") - { - $coppa_agreement = ''; - // Is this user a COPPA user? We need to show the COPPA agreement too - if($mybb->settings['coppa'] != "disabled" && ($mybb->cookies['coppauser'] == 1 || $under_thirteen)) - { - if($mybb->settings['coppa'] == "deny") - { - error($lang->error_need_to_be_thirteen); - } - $lang->coppa_agreement_1 = $lang->sprintf($lang->coppa_agreement_1, $mybb->settings['bbname']); - eval("\$coppa_agreement = \"".$templates->get("member_register_agreement_coppa")."\";"); - } - - $plugins->run_hooks("member_register_agreement"); - - eval("\$agreement = \"".$templates->get("member_register_agreement")."\";"); - output_page($agreement); - } - else - { - $plugins->run_hooks("member_register_start"); - - $validator_extra = ''; - - if(isset($mybb->input['timezoneoffset'])) - { - $timezoneoffset = $mybb->get_input('timezoneoffset'); - } - else - { - $timezoneoffset = $mybb->settings['timezoneoffset']; - } - $tzselect = build_timezone_select("timezoneoffset", $timezoneoffset, true); - - $stylelist = build_theme_select("style"); - - if($mybb->settings['usertppoptions']) - { - $tppoptions = ''; - $explodedtpp = explode(",", $mybb->settings['usertppoptions']); - if(is_array($explodedtpp)) - { - foreach($explodedtpp as $val) - { - $val = trim($val); - $tpp_option = $lang->sprintf($lang->tpp_option, $val); - eval("\$tppoptions .= \"".$templates->get("usercp_options_tppselect_option")."\";"); - } - } - eval("\$tppselect = \"".$templates->get("usercp_options_tppselect")."\";"); - } - if($mybb->settings['userpppoptions']) - { - $pppoptions = ''; - $explodedppp = explode(",", $mybb->settings['userpppoptions']); - if(is_array($explodedppp)) - { - foreach($explodedppp as $val) - { - $val = trim($val); - $ppp_option = $lang->sprintf($lang->ppp_option, $val); - eval("\$pppoptions .= \"".$templates->get("usercp_options_pppselect_option")."\";"); - } - } - eval("\$pppselect = \"".$templates->get("usercp_options_pppselect")."\";"); - } - if($mybb->settings['usereferrals'] == 1 && !$mybb->user['uid']) - { - if(isset($mybb->cookies['mybb']['referrer'])) - { - $query = $db->simple_select("users", "uid,username", "uid='".(int)$mybb->cookies['mybb']['referrer']."'"); - $ref = $db->fetch_array($query); - $ref['username'] = htmlspecialchars_uni($ref['username']); - $referrername = $ref['username']; - } - elseif(isset($referrer)) - { - $query = $db->simple_select("users", "username", "uid='".(int)$referrer['uid']."'"); - $ref = $db->fetch_array($query); - $ref['username'] = htmlspecialchars_uni($ref['username']); - $referrername = $ref['username']; - } - elseif(!empty($referrername)) - { - $ref = get_user_by_username($referrername); - if(!$ref['uid']) - { - $errors[] = $lang->error_badreferrer; - } - } - else - { - $referrername = ''; - } - if(isset($quickreg)) - { - $refbg = "trow1"; - } - else - { - $refbg = "trow2"; - } - eval("\$referrer = \"".$templates->get("member_register_referrer")."\";"); - } - else - { - $referrer = ''; - } - $mybb->input['profile_fields'] = $mybb->get_input('profile_fields', MyBB::INPUT_ARRAY); - // Custom profile fields baby! - $altbg = "trow1"; - $requiredfields = $customfields = ''; - - if($mybb->settings['regtype'] == "verify" || $mybb->settings['regtype'] == "admin" || $mybb->settings['regtype'] == "both" || $mybb->get_input('coppa', MyBB::INPUT_INT) == 1) - { - $usergroup = 5; - } - else - { - $usergroup = 2; - } - - $pfcache = $cache->read('profilefields'); - - if(is_array($pfcache)) - { - foreach($pfcache as $profilefield) - { - if($profilefield['required'] != 1 && $profilefield['registration'] != 1 || !is_member($profilefield['editableby'], array('usergroup' => $mybb->user['usergroup'], 'additionalgroups' => $usergroup))) - { - continue; - } - - $code = $select = $val = $options = $expoptions = $useropts = ''; - $seloptions = array(); - $profilefield['type'] = htmlspecialchars_uni($profilefield['type']); - $thing = explode("\n", $profilefield['type'], "2"); - $type = trim($thing[0]); - $options = $thing[1]; - $select = ''; - $field = "fid{$profilefield['fid']}"; - $profilefield['description'] = htmlspecialchars_uni($profilefield['description']); - $profilefield['name'] = htmlspecialchars_uni($profilefield['name']); - if($errors && isset($mybb->input['profile_fields'][$field])) - { - $userfield = $mybb->input['profile_fields'][$field]; - } - else - { - $userfield = ''; - } - if($type == "multiselect") - { - if($errors) - { - $useropts = $userfield; - } - else - { - $useropts = explode("\n", $userfield); - } - if(is_array($useropts)) - { - foreach($useropts as $key => $val) - { - $seloptions[$val] = $val; - } - } - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $val = trim($val); - $val = str_replace("\n", "\\n", $val); - - $sel = ""; - if(isset($seloptions[$val]) && $val == $seloptions[$val]) - { - $sel = ' selected="selected"'; - } - - eval("\$select .= \"".$templates->get("usercp_profile_profilefields_select_option")."\";"); - } - if(!$profilefield['length']) - { - $profilefield['length'] = 3; - } - - eval("\$code = \"".$templates->get("usercp_profile_profilefields_multiselect")."\";"); - } - } - elseif($type == "select") - { - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $val = trim($val); - $val = str_replace("\n", "\\n", $val); - $sel = ""; - if($val == $userfield) - { - $sel = ' selected="selected"'; - } - - eval("\$select .= \"".$templates->get("usercp_profile_profilefields_select_option")."\";"); - } - if(!$profilefield['length']) - { - $profilefield['length'] = 1; - } - - eval("\$code = \"".$templates->get("usercp_profile_profilefields_select")."\";"); - } - } - elseif($type == "radio") - { - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $checked = ""; - if($val == $userfield) - { - $checked = 'checked="checked"'; - } - - eval("\$code .= \"".$templates->get("usercp_profile_profilefields_radio")."\";"); - } - } - } - elseif($type == "checkbox") - { - if($errors) - { - $useropts = $userfield; - } - else - { - $useropts = explode("\n", $userfield); - } - if(is_array($useropts)) - { - foreach($useropts as $key => $val) - { - $seloptions[$val] = $val; - } - } - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $checked = ""; - if(isset($seloptions[$val]) && $val == $seloptions[$val]) - { - $checked = 'checked="checked"'; - } - - eval("\$code .= \"".$templates->get("usercp_profile_profilefields_checkbox")."\";"); - } - } - } - elseif($type == "textarea") - { - $value = htmlspecialchars_uni($userfield); - eval("\$code = \"".$templates->get("usercp_profile_profilefields_textarea")."\";"); - } - else - { - $value = htmlspecialchars_uni($userfield); - $maxlength = ""; - if($profilefield['maxlength'] > 0) - { - $maxlength = " maxlength=\"{$profilefield['maxlength']}\""; - } - - eval("\$code = \"".$templates->get("usercp_profile_profilefields_text")."\";"); - } - - if($profilefield['required'] == 1) - { - // JS validator extra, choose correct selectors for everything except single select which always has value - if($type != 'select') - { - if($type == "textarea") - { - $inp_selector = "$('textarea[name=\"profile_fields[{$field}]\"]')"; - } - elseif($type == "multiselect") - { - $inp_selector = "$('select[name=\"profile_fields[{$field}][]\"]')"; - } - elseif($type == "checkbox") - { - $inp_selector = "$('input[name=\"profile_fields[{$field}][]\"]')"; - } - else - { - $inp_selector = "$('input[name=\"profile_fields[{$field}]\"]')"; - } - - $validator_extra .= " - {$inp_selector}.rules('add', { - required: true, - messages: { - required: '{$lang->js_validator_not_empty}' - } - });\n"; - } - - eval("\$requiredfields .= \"".$templates->get("member_register_customfield")."\";"); - } - else - { - eval("\$customfields .= \"".$templates->get("member_register_customfield")."\";"); - } - } - - if($requiredfields) - { - eval("\$requiredfields = \"".$templates->get("member_register_requiredfields")."\";"); - } - - if($customfields) - { - eval("\$customfields = \"".$templates->get("member_register_additionalfields")."\";"); - } - } - - if(!isset($fromreg)) - { - $allownoticescheck = "checked=\"checked\""; - $hideemailcheck = ''; - $receivepmscheck = "checked=\"checked\""; - $pmnoticecheck = " checked=\"checked\""; - $pmnotifycheck = ''; - $invisiblecheck = ''; - if($mybb->settings['dstcorrection'] == 1) - { - $enabledstcheck = "checked=\"checked\""; - } - $no_auto_subscribe_selected = $instant_email_subscribe_selected = $instant_pm_subscribe_selected = $no_subscribe_selected = ''; - $dst_auto_selected = $dst_enabled_selected = $dst_disabled_selected = ''; - $username = $email = $email2 = ''; - $regerrors = ''; - } - // Spambot registration image thingy - if($mybb->settings['captchaimage']) - { - require_once MYBB_ROOT.'inc/class_captcha.php'; - $captcha = new captcha(true, "member_register_regimage"); - - if($captcha->html) - { - $regimage = $captcha->html; - - if($mybb->settings['captchaimage'] == 1) - { - // JS validator extra for our default CAPTCHA - $validator_extra .= " - $('#imagestring').rules('add', { - required: true, - remote:{ - url: 'xmlhttp.php?action=validate_captcha', - type: 'post', - dataType: 'json', - data: - { - imagehash: function () { - return $('#imagehash').val(); - }, - my_post_key: my_post_key - }, - }, - messages: { - remote: '{$lang->js_validator_no_image_text}' - } - });\n"; - } - } - } - - // Security Question - $questionbox = ''; - if($mybb->settings['securityquestion']) - { - $sid = generate_question(); - $query = $db->query(" - SELECT q.question, s.sid - FROM ".TABLE_PREFIX."questionsessions s - LEFT JOIN ".TABLE_PREFIX."questions q ON (q.qid=s.qid) - WHERE q.active='1' AND s.sid='{$sid}' - "); - if($db->num_rows($query) > 0) - { - $question = $db->fetch_array($query); - - $refresh = ''; - // Total questions - $q = $db->simple_select('questions', 'COUNT(qid) as num', 'active=1'); - $num = $db->fetch_field($q, 'num'); - if($num > 1) - { - eval("\$refresh = \"".$templates->get("member_register_question_refresh")."\";"); - } - - eval("\$questionbox = \"".$templates->get("member_register_question")."\";"); - - $validator_extra .= " - $('#answer').rules('add', { - required: true, - remote:{ - url: 'xmlhttp.php?action=validate_question', - type: 'post', - dataType: 'json', - data: - { - question: function () { - return $('#question_id').val(); - }, - my_post_key: my_post_key - }, - }, - messages: { - remote: '{$lang->js_validator_no_security_question}' - } - });\n"; - } - } - - $hiddencaptcha = ''; - // Hidden CAPTCHA for Spambots - if($mybb->settings['hiddencaptchaimage']) - { - $captcha_field = $mybb->settings['hiddencaptchaimagefield']; - - eval("\$hiddencaptcha = \"".$templates->get("member_register_hiddencaptcha")."\";"); - } - if($mybb->settings['regtype'] != "randompass") - { - // JS validator extra - $lang->js_validator_password_length = $lang->sprintf($lang->js_validator_password_length, $mybb->settings['minpasswordlength']); - - // See if the board has "require complex passwords" enabled. - if($mybb->settings['requirecomplexpasswords'] == 1) - { - $lang->password = $lang->complex_password = $lang->sprintf($lang->complex_password, $mybb->settings['minpasswordlength']); - - $validator_extra .= " - $('#password').rules('add', { - required: true, - minlength: {$mybb->settings['minpasswordlength']}, - remote:{ - url: 'xmlhttp.php?action=complex_password', - type: 'post', - dataType: 'json', - data: - { - my_post_key: my_post_key - }, - }, - messages: { - minlength: '{$lang->js_validator_password_length}', - required: '{$lang->js_validator_password_length}', - remote: '{$lang->js_validator_no_image_text}' - } - });\n"; - } - else - { - $validator_extra .= " - $('#password').rules('add', { - required: true, - minlength: {$mybb->settings['minpasswordlength']}, - messages: { - minlength: '{$lang->js_validator_password_length}', - required: '{$lang->js_validator_password_length}' - } - });\n"; - } - - $validator_extra .= " - $('#password2').rules('add', { - required: true, - minlength: {$mybb->settings['minpasswordlength']}, - equalTo: '#password', - messages: { - minlength: '{$lang->js_validator_password_length}', - required: '{$lang->js_validator_password_length}', - equalTo: '{$lang->js_validator_password_matches}' - } - });\n"; - - eval("\$passboxes = \"".$templates->get("member_register_password")."\";"); - } - - // JS validator extra - if($mybb->settings['maxnamelength'] > 0 && $mybb->settings['minnamelength'] > 0) - { - $lang->js_validator_username_length = $lang->sprintf($lang->js_validator_username_length, $mybb->settings['minnamelength'], $mybb->settings['maxnamelength']); - } - - $languages = $lang->get_languages(); - $langoptions = $boardlanguage = ''; - if(count($languages) > 1) - { - foreach($languages as $name => $language) - { - $language = htmlspecialchars_uni($language); - - $sel = ''; - if($mybb->get_input('language') == $name) - { - $sel = " selected=\"selected\""; - } - - eval('$langoptions .= "'.$templates->get('usercp_options_language_option').'";'); - } - - eval('$boardlanguage = "'.$templates->get('member_register_language').'";'); - } - - // Set the time so we can find automated signups - $time = TIME_NOW; - - $plugins->run_hooks("member_register_end"); - - eval("\$registration = \"".$templates->get("member_register")."\";"); - output_page($registration); - } -} - -if($mybb->input['action'] == "activate") -{ - $plugins->run_hooks("member_activate_start"); - - if(isset($mybb->input['username'])) - { - $mybb->input['username'] = $mybb->get_input('username'); - $options = array( - 'username_method' => $mybb->settings['username_method'], - 'fields' => '*', - ); - $user = get_user_by_username($mybb->input['username'], $options); - if(!$user) - { - switch($mybb->settings['username_method']) - { - case 0: - error($lang->error_invalidpworusername); - break; - case 1: - error($lang->error_invalidpworusername1); - break; - case 2: - error($lang->error_invalidpworusername2); - break; - default: - error($lang->error_invalidpworusername); - break; - } - } - $uid = $user['uid']; - } - else - { - $user = get_user($mybb->get_input('uid', MyBB::INPUT_INT)); - } - if(isset($mybb->input['code']) && $user) - { - $query = $db->simple_select("awaitingactivation", "*", "uid='".$user['uid']."' AND (type='r' OR type='e' OR type='b')"); - $activation = $db->fetch_array($query); - if(!$activation['uid']) - { - error($lang->error_alreadyactivated); - } - if($activation['code'] !== $mybb->get_input('code')) - { - error($lang->error_badactivationcode); - } - - if($activation['type'] == "b" && $activation['validated'] == 1) - { - error($lang->error_alreadyvalidated); - } - - $db->delete_query("awaitingactivation", "uid='".$user['uid']."' AND (type='r' OR type='e')"); - - if($user['usergroup'] == 5 && $activation['type'] != "e" && $activation['type'] != "b") - { - $db->update_query("users", array("usergroup" => 2), "uid='".$user['uid']."'"); - - $cache->update_awaitingactivation(); - } - if($activation['type'] == "e") - { - $newemail = array( - "email" => $db->escape_string($activation['misc']), - ); - $db->update_query("users", $newemail, "uid='".$user['uid']."'"); - $plugins->run_hooks("member_activate_emailupdated"); - - redirect("usercp.php", $lang->redirect_emailupdated); - } - elseif($activation['type'] == "b") - { - $update = array( - "validated" => 1, - ); - $db->update_query("awaitingactivation", $update, "uid='".$user['uid']."' AND type='b'"); - $plugins->run_hooks("member_activate_emailactivated"); - - redirect("index.php", $lang->redirect_accountactivated_admin, "", true); - } - else - { - $plugins->run_hooks("member_activate_accountactivated"); - - redirect("index.php", $lang->redirect_accountactivated); - } - } - else - { - $plugins->run_hooks("member_activate_form"); - - $code = htmlspecialchars_uni($mybb->get_input('code')); - - if(!isset($user['username'])) - { - $user['username'] = ''; - } - $user['username'] = htmlspecialchars_uni($user['username']); - - eval("\$activate = \"".$templates->get("member_activate")."\";"); - output_page($activate); - } -} - -if($mybb->input['action'] == "resendactivation") -{ - $plugins->run_hooks("member_resendactivation"); - - if($mybb->settings['regtype'] == "admin") - { - error($lang->error_activated_by_admin); - } - if($mybb->user['uid'] && $mybb->user['usergroup'] != 5) - { - error($lang->error_alreadyactivated); - } - - $query = $db->simple_select("awaitingactivation", "*", "uid='".$user['uid']."' AND type='b'"); - $activation = $db->fetch_array($query); - - if($activation['validated'] == 1) - { - error($lang->error_activated_by_admin); - } - - $plugins->run_hooks("member_resendactivation_end"); - - eval("\$activate = \"".$templates->get("member_resendactivation")."\";"); - output_page($activate); -} - -if($mybb->input['action'] == "do_resendactivation" && $mybb->request_method == "post") -{ - $plugins->run_hooks("member_do_resendactivation_start"); - - if($mybb->settings['regtype'] == "admin") - { - error($lang->error_activated_by_admin); - } - - $query = $db->query(" - SELECT u.uid, u.username, u.usergroup, u.email, a.code, a.type, a.validated - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."awaitingactivation a ON (a.uid=u.uid AND a.type='r' OR a.type='b') - WHERE u.email='".$db->escape_string($mybb->get_input('email'))."' - "); - $numusers = $db->num_rows($query); - if($numusers < 1) - { - error($lang->error_invalidemail); - } - else - { - while($user = $db->fetch_array($query)) - { - if($user['type'] == "b" && $user['validated'] == 1) - { - error($lang->error_activated_by_admin); - } - - if($user['usergroup'] == 5) - { - if(!$user['code']) - { - $user['code'] = random_str(); - $uid = $user['uid']; - $awaitingarray = array( - "uid" => $uid, - "dateline" => TIME_NOW, - "code" => $user['code'], - "type" => $user['type'] - ); - $db->insert_query("awaitingactivation", $awaitingarray); - } - $username = $user['username']; - $email = $user['email']; - $activationcode = $user['code']; - $emailsubject = $lang->sprintf($lang->emailsubject_activateaccount, $mybb->settings['bbname']); - switch($mybb->settings['username_method']) - { - case 0: - $emailmessage = $lang->sprintf($lang->email_activateaccount, $user['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user['uid'], $activationcode); - break; - case 1: - $emailmessage = $lang->sprintf($lang->email_activateaccount1, $user['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user['uid'], $activationcode); - break; - case 2: - $emailmessage = $lang->sprintf($lang->email_activateaccount2, $user['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user['uid'], $activationcode); - break; - default: - $emailmessage = $lang->sprintf($lang->email_activateaccount, $user['username'], $mybb->settings['bbname'], $mybb->settings['bburl'], $user['uid'], $activationcode); - break; - } - my_mail($email, $emailsubject, $emailmessage); - } - } - $plugins->run_hooks("member_do_resendactivation_end"); - - redirect("index.php", $lang->redirect_activationresent); - } -} - -if($mybb->input['action'] == "lostpw") -{ - $plugins->run_hooks("member_lostpw"); - - eval("\$lostpw = \"".$templates->get("member_lostpw")."\";"); - output_page($lostpw); -} - -if($mybb->input['action'] == "do_lostpw" && $mybb->request_method == "post") -{ - $plugins->run_hooks("member_do_lostpw_start"); - - $email = $db->escape_string($email); - $query = $db->simple_select("users", "*", "email='".$db->escape_string($mybb->get_input('email'))."'"); - $numusers = $db->num_rows($query); - if($numusers < 1) - { - error($lang->error_invalidemail); - } - else - { - while($user = $db->fetch_array($query)) - { - $db->delete_query("awaitingactivation", "uid='{$user['uid']}' AND type='p'"); - $user['activationcode'] = random_str(30); - $now = TIME_NOW; - $uid = $user['uid']; - $awaitingarray = array( - "uid" => $user['uid'], - "dateline" => TIME_NOW, - "code" => $user['activationcode'], - "type" => "p" - ); - $db->insert_query("awaitingactivation", $awaitingarray); - $username = $user['username']; - $email = $user['email']; - $activationcode = $user['activationcode']; - $emailsubject = $lang->sprintf($lang->emailsubject_lostpw, $mybb->settings['bbname']); - switch($mybb->settings['username_method']) - { - case 0: - $emailmessage = $lang->sprintf($lang->email_lostpw, $username, $mybb->settings['bbname'], $mybb->settings['bburl'], $uid, $activationcode); - break; - case 1: - $emailmessage = $lang->sprintf($lang->email_lostpw1, $username, $mybb->settings['bbname'], $mybb->settings['bburl'], $uid, $activationcode); - break; - case 2: - $emailmessage = $lang->sprintf($lang->email_lostpw2, $username, $mybb->settings['bbname'], $mybb->settings['bburl'], $uid, $activationcode); - break; - default: - $emailmessage = $lang->sprintf($lang->email_lostpw, $username, $mybb->settings['bbname'], $mybb->settings['bburl'], $uid, $activationcode); - break; - } - my_mail($email, $emailsubject, $emailmessage); - } - } - $plugins->run_hooks("member_do_lostpw_end"); - - redirect("index.php", $lang->redirect_lostpwsent, "", true); -} - -if($mybb->input['action'] == "resetpassword") -{ - $plugins->run_hooks("member_resetpassword_start"); - - if(isset($mybb->input['username'])) - { - $mybb->input['username'] = $mybb->get_input('username'); - $options = array( - 'username_method' => $mybb->settings['username_method'], - 'fields' => '*', - ); - $user = get_user_by_username($mybb->input['username'], $options); - if(!$user) - { - switch($mybb->settings['username_method']) - { - case 0: - error($lang->error_invalidpworusername); - break; - case 1: - error($lang->error_invalidpworusername1); - break; - case 2: - error($lang->error_invalidpworusername2); - break; - default: - error($lang->error_invalidpworusername); - break; - } - } - } - else - { - $user = get_user($mybb->get_input('uid', MyBB::INPUT_INT)); - } - - if(isset($mybb->input['code']) && $user) - { - $query = $db->simple_select("awaitingactivation", "code", "uid='".$user['uid']."' AND type='p'"); - $activationcode = $db->fetch_field($query, 'code'); - $now = TIME_NOW; - if(!$activationcode || $activationcode !== $mybb->get_input('code')) - { - error($lang->error_badlostpwcode); - } - $db->delete_query("awaitingactivation", "uid='".$user['uid']."' AND type='p'"); - $username = $user['username']; - - // Generate a new password, then update it - $password_length = (int)$mybb->settings['minpasswordlength']; - - if($password_length < 8) - { - $password_length = min(8, (int)$mybb->settings['maxpasswordlength']); - } - - // Set up user handler. - require_once MYBB_ROOT.'inc/datahandlers/user.php'; - $userhandler = new UserDataHandler('update'); - - while(!$userhandler->verify_password()) - { - $password = random_str($password_length, $mybb->settings['requirecomplexpasswords']); - - $userhandler->set_data(array( - 'uid' => $user['uid'], - 'username' => $user['username'], - 'email' => $user['email'], - 'password' => $password - )); - - $userhandler->set_validated(true); - $userhandler->errors = array(); - } - - $userhandler->update_user(); - - $logindetails = array( - 'salt' => $userhandler->data['salt'], - 'password' => $userhandler->data['saltedpw'], - 'loginkey' => $userhandler->data['loginkey'], - ); - - $email = $user['email']; - - $plugins->run_hooks("member_resetpassword_process"); - - $emailsubject = $lang->sprintf($lang->emailsubject_passwordreset, $mybb->settings['bbname']); - $emailmessage = $lang->sprintf($lang->email_passwordreset, $username, $mybb->settings['bbname'], $password); - my_mail($email, $emailsubject, $emailmessage); - - $plugins->run_hooks("member_resetpassword_reset"); - - error($lang->redirect_passwordreset); - } - else - { - $plugins->run_hooks("member_resetpassword_form"); - - switch($mybb->settings['username_method']) - { - case 0: - $lang_username = $lang->username; - break; - case 1: - $lang_username = $lang->username1; - break; - case 2: - $lang_username = $lang->username2; - break; - default: - $lang_username = $lang->username; - break; - } - - $code = $mybb->get_input('code'); - - if(!isset($user['username'])) - { - $user['username'] = ''; - } - $user['username'] = htmlspecialchars_uni($user['username']); - - eval("\$activate = \"".$templates->get("member_resetpassword")."\";"); - output_page($activate); - } -} - -$do_captcha = $correct = false; -$inline_errors = ""; -if($mybb->input['action'] == "do_login" && $mybb->request_method == "post") -{ - $plugins->run_hooks("member_do_login_start"); - - // Is a fatal call if user has had too many tries - $errors = array(); - $logins = login_attempt_check(); - - require_once MYBB_ROOT."inc/datahandlers/login.php"; - $loginhandler = new LoginDataHandler("get"); - - if($mybb->get_input('quick_password') && $mybb->get_input('quick_username')) - { - $mybb->input['password'] = $mybb->get_input('quick_password'); - $mybb->input['username'] = $mybb->get_input('quick_username'); - $mybb->input['remember'] = $mybb->get_input('quick_remember'); - } - - $user = array( - 'username' => $mybb->get_input('username'), - 'password' => $mybb->get_input('password'), - 'remember' => $mybb->get_input('remember'), - 'imagestring' => $mybb->get_input('imagestring') - ); - - $options = array( - 'fields' => 'loginattempts', - 'username_method' => (int)$mybb->settings['username_method'], - ); - - $user_loginattempts = get_user_by_username($user['username'], $options); - $user['loginattempts'] = (int)$user_loginattempts['loginattempts']; - - $loginhandler->set_data($user); - $validated = $loginhandler->validate_login(); - - if(!$validated) - { - $mybb->input['action'] = "login"; - $mybb->request_method = "get"; - - my_setcookie('loginattempts', $logins + 1); - $db->update_query("users", array('loginattempts' => 'loginattempts+1'), "uid='".(int)$loginhandler->login_data['uid']."'", 1, true); - - $errors = $loginhandler->get_friendly_errors(); - - $user['loginattempts'] = (int)$loginhandler->login_data['loginattempts']; - - // If we need a captcha set it here - if($mybb->settings['failedcaptchalogincount'] > 0 && ($user['loginattempts'] > $mybb->settings['failedcaptchalogincount'] || (int)$mybb->cookies['loginattempts'] > $mybb->settings['failedcaptchalogincount'])) - { - $do_captcha = true; - $correct = $loginhandler->captcha_verified; - } - } - else if($validated && $loginhandler->captcha_verified == true) - { - // Successful login - if($loginhandler->login_data['coppauser']) - { - error($lang->error_awaitingcoppa); - } - - $loginhandler->complete_login(); - - $plugins->run_hooks("member_do_login_end"); - - $mybb->input['url'] = $mybb->get_input('url'); - - if(!empty($mybb->input['url']) && my_strpos(basename($mybb->input['url']), 'member.php') === false && !preg_match('#^javascript:#i', $mybb->input['url'])) - { - if((my_strpos(basename($mybb->input['url']), 'newthread.php') !== false || my_strpos(basename($mybb->input['url']), 'newreply.php') !== false) && my_strpos($mybb->input['url'], '&processed=1') !== false) - { - $mybb->input['url'] = str_replace('&processed=1', '', $mybb->input['url']); - } - - $mybb->input['url'] = str_replace('&', '&', $mybb->input['url']); - - // Redirect to the URL if it is not member.php - redirect($mybb->input['url'], $lang->redirect_loggedin); - } - else - { - - redirect("index.php", $lang->redirect_loggedin); - } - } - - $plugins->run_hooks("member_do_login_end"); -} - -if($mybb->input['action'] == "login") -{ - $plugins->run_hooks("member_login"); - - $member_loggedin_notice = ""; - if($mybb->user['uid'] != 0) - { - $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); - $lang->already_logged_in = $lang->sprintf($lang->already_logged_in, build_profile_link($mybb->user['username'], $mybb->user['uid'])); - eval("\$member_loggedin_notice = \"".$templates->get("member_loggedin_notice")."\";"); - } - - // Checks to make sure the user can login; they haven't had too many tries at logging in. - // Is a fatal call if user has had too many tries - login_attempt_check(); - - // Redirect to the page where the user came from, but not if that was the login page. - if(isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], "action=login") === false) - { - $redirect_url = htmlentities($_SERVER['HTTP_REFERER']); - } - else - { - $redirect_url = ''; - } - - $captcha = ''; - // Show captcha image for guests if enabled and only if we have to do - if($mybb->settings['captchaimage'] && $do_captcha == true) - { - require_once MYBB_ROOT.'inc/class_captcha.php'; - $login_captcha = new captcha(false, "post_captcha"); - - if($login_captcha->type == 1) - { - if(!$correct) - { - $login_captcha->build_captcha(); - } - else - { - $captcha = $login_captcha->build_hidden_captcha(); - } - } - elseif($login_captcha->type == 2 || $login_captcha->type == 4) - { - $login_captcha->build_recaptcha(); - } - - if($login_captcha->html) - { - $captcha = $login_captcha->html; - } - } - - $username = ""; - $password = ""; - if(isset($mybb->input['username']) && $mybb->request_method == "post") - { - $username = htmlspecialchars_uni($mybb->get_input('username')); - } - - if(isset($mybb->input['password']) && $mybb->request_method == "post") - { - $password = htmlspecialchars_uni($mybb->get_input('password')); - } - - if(!empty($errors)) - { - $mybb->input['action'] = "login"; - $mybb->request_method = "get"; - - $inline_errors = inline_error($errors); - } - - switch($mybb->settings['username_method']) - { - case 1: - $lang->username = $lang->username1; - break; - case 2: - $lang->username = $lang->username2; - break; - default: - break; - } - - $plugins->run_hooks("member_login_end"); - - eval("\$login = \"".$templates->get("member_login")."\";"); - output_page($login); -} - -if($mybb->input['action'] == "logout") -{ - $plugins->run_hooks("member_logout_start"); - - if(!$mybb->user['uid']) - { - redirect("index.php", $lang->redirect_alreadyloggedout); - } - - // Check session ID if we have one - if(isset($mybb->input['sid']) && $mybb->get_input('sid') !== $session->sid) - { - error($lang->error_notloggedout); - } - // Otherwise, check logoutkey - else if(!isset($mybb->input['sid']) && $mybb->get_input('logoutkey') !== $mybb->user['logoutkey']) - { - error($lang->error_notloggedout); - } - - my_unsetcookie("mybbuser"); - my_unsetcookie("sid"); - - if($mybb->user['uid']) - { - $time = TIME_NOW; - // Run this after the shutdown query from session system - $db->shutdown_query("UPDATE ".TABLE_PREFIX."users SET lastvisit='{$time}', lastactive='{$time}' WHERE uid='{$mybb->user['uid']}'"); - $db->delete_query("sessions", "sid = '{$session->sid}'"); - } - - $plugins->run_hooks("member_logout_end"); - - redirect("index.php", $lang->redirect_loggedout); -} - -if($mybb->input['action'] == "viewnotes") -{ - $uid = $mybb->get_input('uid', MyBB::INPUT_INT); - $user = get_user($uid); - - // Make sure we are looking at a real user here. - if(!$user) - { - error($lang->error_nomember); - } - - if($mybb->user['uid'] == 0 || $mybb->usergroup['canmodcp'] != 1) - { - error_no_permission(); - } - - $user['username'] = htmlspecialchars_uni($user['username']); - $lang->view_notes_for = $lang->sprintf($lang->view_notes_for, $user['username']); - - $user['usernotes'] = nl2br(htmlspecialchars_uni($user['usernotes'])); - - $plugins->run_hooks('member_viewnotes'); - - eval("\$viewnotes = \"".$templates->get("member_viewnotes", 1, 0)."\";"); - echo $viewnotes; - exit; -} - -if($mybb->input['action'] == "profile") -{ - $plugins->run_hooks("member_profile_start"); - - if($mybb->usergroup['canviewprofiles'] == 0) - { - error_no_permission(); - } - - $uid = $mybb->get_input('uid', MyBB::INPUT_INT); - if($uid) - { - $memprofile = get_user($uid); - } - elseif($mybb->user['uid']) - { - $memprofile = $mybb->user; - } - else - { - $memprofile = false; - } - - if(!$memprofile) - { - error($lang->error_nomember); - } - - $uid = $memprofile['uid']; - - $me_username = $memprofile['username']; - $memprofile['username'] = htmlspecialchars_uni($memprofile['username']); - $lang->profile = $lang->sprintf($lang->profile, $memprofile['username']); - - // Get member's permissions - $memperms = user_permissions($memprofile['uid']); - - $lang->nav_profile = $lang->sprintf($lang->nav_profile, $memprofile['username']); - add_breadcrumb($lang->nav_profile); - - $lang->users_forum_info = $lang->sprintf($lang->users_forum_info, $memprofile['username']); - $lang->users_contact_details = $lang->sprintf($lang->users_contact_details, $memprofile['username']); - $lang->send_pm = $lang->sprintf($lang->send_pm, $memprofile['username']); - $lang->away_note = $lang->sprintf($lang->away_note, $memprofile['username']); - $lang->users_additional_info = $lang->sprintf($lang->users_additional_info, $memprofile['username']); - $lang->users_signature = $lang->sprintf($lang->users_signature, $memprofile['username']); - $lang->send_user_email = $lang->sprintf($lang->send_user_email, $memprofile['username']); - - $useravatar = format_avatar($memprofile['avatar'], $memprofile['avatardimensions']); - eval("\$avatar = \"".$templates->get("member_profile_avatar")."\";"); - - $website = $sendemail = $sendpm = $contact_details = ''; - - if(my_validate_url($memprofile['website']) && !is_member($mybb->settings['hidewebsite']) && $memperms['canchangewebsite'] == 1) - { - $memprofile['website'] = htmlspecialchars_uni($memprofile['website']); - $bgcolor = alt_trow(); - eval("\$website = \"".$templates->get("member_profile_website")."\";"); - } - - if($memprofile['hideemail'] != 1 && (my_strpos(",".$memprofile['ignorelist'].",", ",".$mybb->user['uid'].",") === false || $mybb->usergroup['cansendemailoverride'] != 0)) - { - $bgcolor = alt_trow(); - eval("\$sendemail = \"".$templates->get("member_profile_email")."\";"); - } - - if($mybb->settings['enablepms'] != 0 && (($memprofile['receivepms'] != 0 && $memperms['canusepms'] != 0 && my_strpos(",".$memprofile['ignorelist'].",", ",".$mybb->user['uid'].",") === false) || $mybb->usergroup['canoverridepm'] == 1)) - { - $bgcolor = alt_trow(); - eval('$sendpm = "'.$templates->get("member_profile_pm").'";'); - } - - $contact_fields = array(); - $any_contact_field = false; - foreach(array('icq', 'aim', 'yahoo', 'skype', 'google') as $field) - { - $contact_fields[$field] = ''; - $settingkey = 'allow'.$field.'field'; - - if(!empty($memprofile[$field]) && is_member($mybb->settings[$settingkey], array('usergroup' => $memprofile['usergroup'], 'additionalgroups' => $memprofile['additionalgroups']))) - { - $any_contact_field = true; - - if($field == 'icq') - { - $memprofile[$field] = (int)$memprofile[$field]; - } - else - { - $memprofile[$field] = htmlspecialchars_uni($memprofile[$field]); - } - $tmpl = 'member_profile_contact_fields_'.$field; - - $bgcolors[$field] = alt_trow(); - eval('$contact_fields[\''.$field.'\'] = "'.$templates->get($tmpl).'";'); - } - } - - if($any_contact_field || $sendemail || $sendpm || $website) - { - eval('$contact_details = "'.$templates->get("member_profile_contact_details").'";'); - } - - $signature = ''; - if($memprofile['signature'] && ($memprofile['suspendsignature'] == 0 || $memprofile['suspendsigtime'] < TIME_NOW) && !is_member($mybb->settings['hidesignatures']) && $memperms['canusesig'] && $memperms['canusesigxposts'] <= $memprofile['postnum']) - { - $sig_parser = array( - "allow_html" => $mybb->settings['sightml'], - "allow_mycode" => $mybb->settings['sigmycode'], - "allow_smilies" => $mybb->settings['sigsmilies'], - "allow_imgcode" => $mybb->settings['sigimgcode'], - "me_username" => $me_username, - "filter_badwords" => 1 - ); - - if($memperms['signofollow']) - { - $sig_parser['nofollow_on'] = 1; - } - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $sig_parser['allow_imgcode'] = 0; - } - - $memprofile['signature'] = $parser->parse_message($memprofile['signature'], $sig_parser); - eval("\$signature = \"".$templates->get("member_profile_signature")."\";"); - } - - $daysreg = (TIME_NOW - $memprofile['regdate']) / (24*3600); - - if($daysreg < 1) - { - $daysreg = 1; - } - - $stats = $cache->read("stats"); - - // Format post count, per day count and percent of total - $ppd = $memprofile['postnum'] / $daysreg; - $ppd = round($ppd, 2); - if($ppd > $memprofile['postnum']) - { - $ppd = $memprofile['postnum']; - } - - $numposts = $stats['numposts']; - if($numposts == 0) - { - $post_percent = "0"; - } - else - { - $post_percent = $memprofile['postnum']*100/$numposts; - $post_percent = round($post_percent, 2); - } - - if($post_percent > 100) - { - $post_percent = 100; - } - - // Format thread count, per day count and percent of total - $tpd = $memprofile['threadnum'] / $daysreg; - $tpd = round($tpd, 2); - if($tpd > $memprofile['threadnum']) - { - $tpd = $memprofile['threadnum']; - } - - $numthreads = $stats['numthreads']; - if($numthreads == 0) - { - $thread_percent = "0"; - } - else - { - $thread_percent = $memprofile['threadnum']*100/$numthreads; - $thread_percent = round($thread_percent, 2); - } - - if($thread_percent > 100) - { - $thread_percent = 100; - } - - $findposts = $findthreads = ''; - if($mybb->usergroup['cansearch'] == 1) - { - eval("\$findposts = \"".$templates->get("member_profile_findposts")."\";"); - eval("\$findthreads = \"".$templates->get("member_profile_findthreads")."\";"); - } - - $awaybit = ''; - if($memprofile['away'] == 1 && $mybb->settings['allowaway'] != 0) - { - $lang->away_note = $lang->sprintf($lang->away_note, $memprofile['username']); - $awaydate = my_date($mybb->settings['dateformat'], $memprofile['awaydate']); - if(!empty($memprofile['awayreason'])) - { - $reason = $parser->parse_badwords($memprofile['awayreason']); - $awayreason = htmlspecialchars_uni($reason); - } - else - { - $awayreason = $lang->away_no_reason; - } - if($memprofile['returndate'] == '') - { - $returndate = "$lang->unknown"; - } - else - { - $returnhome = explode("-", $memprofile['returndate']); - - // PHP native date functions use integers so timestamps for years after 2038 will not work - // Thus we use adodb_mktime - if($returnhome[2] >= 2038) - { - require_once MYBB_ROOT."inc/functions_time.php"; - $returnmkdate = adodb_mktime(0, 0, 0, $returnhome[1], $returnhome[0], $returnhome[2]); - $returndate = my_date($mybb->settings['dateformat'], $returnmkdate, "", 1, true); - } - else - { - $returnmkdate = mktime(0, 0, 0, $returnhome[1], $returnhome[0], $returnhome[2]); - $returndate = my_date($mybb->settings['dateformat'], $returnmkdate); - } - - // If our away time has expired already, we should be back, right? - if($returnmkdate < TIME_NOW) - { - $db->update_query('users', array('away' => '0', 'awaydate' => '0', 'returndate' => '', 'awayreason' => ''), 'uid=\''.(int)$memprofile['uid'].'\''); - - // Update our status to "not away" - $memprofile['away'] = 0; - } - } - - // Check if our away status is set to 1, it may have been updated already (see a few lines above) - if($memprofile['away'] == 1) - { - eval("\$awaybit = \"".$templates->get("member_profile_away")."\";"); - } - } - - $memprofile['timezone'] = (float)$memprofile['timezone']; - - if($memprofile['dst'] == 1) - { - $memprofile['timezone']++; - if(my_substr($memprofile['timezone'], 0, 1) != "-") - { - $memprofile['timezone'] = "+{$memprofile['timezone']}"; - } - } - - $memregdate = my_date($mybb->settings['dateformat'], $memprofile['regdate']); - $memlocaldate = gmdate($mybb->settings['dateformat'], TIME_NOW + ($memprofile['timezone'] * 3600)); - $memlocaltime = gmdate($mybb->settings['timeformat'], TIME_NOW + ($memprofile['timezone'] * 3600)); - - $localtime = $lang->sprintf($lang->local_time_format, $memlocaldate, $memlocaltime); - - if($memprofile['lastactive']) - { - $memlastvisitdate = my_date($mybb->settings['dateformat'], $memprofile['lastactive']); - $memlastvisitsep = $lang->comma; - $memlastvisittime = my_date($mybb->settings['timeformat'], $memprofile['lastactive']); - } - else - { - $memlastvisitdate = $lang->lastvisit_never; - $memlastvisitsep = ''; - $memlastvisittime = ''; - } - - if($memprofile['birthday']) - { - $membday = explode("-", $memprofile['birthday']); - - if($memprofile['birthdayprivacy'] != 'none') - { - if($membday[0] && $membday[1] && $membday[2]) - { - $lang->membdayage = $lang->sprintf($lang->membdayage, get_age($memprofile['birthday'])); - - $bdayformat = fix_mktime($mybb->settings['dateformat'], $membday[2]); - $membday = mktime(0, 0, 0, $membday[1], $membday[0], $membday[2]); - $membday = date($bdayformat, $membday); - - $membdayage = $lang->membdayage; - } - elseif($membday[2]) - { - $membday = mktime(0, 0, 0, 1, 1, $membday[2]); - $membday = date("Y", $membday); - $membdayage = ''; - } - else - { - $membday = mktime(0, 0, 0, $membday[1], $membday[0], 0); - $membday = date("F j", $membday); - $membdayage = ''; - } - } - - if($memprofile['birthdayprivacy'] == 'age') - { - $membday = $lang->birthdayhidden; - } - else if($memprofile['birthdayprivacy'] == 'none') - { - $membday = $lang->birthdayhidden; - $membdayage = ''; - } - } - else - { - $membday = $lang->not_specified; - $membdayage = ''; - } - - if(!$memprofile['displaygroup']) - { - $memprofile['displaygroup'] = $memprofile['usergroup']; - } - - // Grab the following fields from the user's displaygroup - $displaygroupfields = array( - "title", - "usertitle", - "stars", - "starimage", - "image", - "usereputationsystem" - ); - $displaygroup = usergroup_displaygroup($memprofile['displaygroup']); - - // Get the user title for this user - unset($usertitle); - unset($stars); - $starimage = ''; - if(trim($memprofile['usertitle']) != '') - { - // User has custom user title - $usertitle = $memprofile['usertitle']; - } - elseif(trim($displaygroup['usertitle']) != '') - { - // User has group title - $usertitle = $displaygroup['usertitle']; - } - else - { - // No usergroup title so get a default one - $usertitles = $cache->read('usertitles'); - - if(is_array($usertitles)) - { - foreach($usertitles as $title) - { - if($memprofile['postnum'] >= $title['posts']) - { - $usertitle = $title['title']; - $stars = $title['stars']; - $starimage = $title['starimage']; - - break; - } - } - } - } - - $usertitle = htmlspecialchars_uni($usertitle); - - if($displaygroup['stars'] || $displaygroup['usertitle']) - { - // Set the number of stars if display group has constant number of stars - $stars = $displaygroup['stars']; - } - elseif(!$stars) - { - if(!is_array($usertitles)) - { - $usertitles = $cache->read('usertitles'); - } - - // This is for cases where the user has a title, but the group has no defined number of stars (use number of stars as per default usergroups) - if(is_array($usertitles)) - { - foreach($usertitles as $title) - { - if($memprofile['postnum'] >= $title['posts']) - { - $stars = $title['stars']; - $starimage = $title['starimage']; - break; - } - } - } - } - - $groupimage = ''; - if(!empty($displaygroup['image'])) - { - if(!empty($mybb->user['language'])) - { - $language = $mybb->user['language']; - } - else - { - $language = $mybb->settings['bblanguage']; - } - $displaygroup['image'] = str_replace("{lang}", $language, $displaygroup['image']); - $displaygroup['image'] = str_replace("{theme}", $theme['imgdir'], $displaygroup['image']); - eval("\$groupimage = \"".$templates->get("member_profile_groupimage")."\";"); - } - - if(empty($starimage)) - { - $starimage = $displaygroup['starimage']; - } - - if(!empty($starimage)) - { - // Only display stars if we have an image to use... - $starimage = str_replace("{theme}", $theme['imgdir'], $starimage); - $userstars = ''; - for($i = 0; $i < $stars; ++$i) - { - eval("\$userstars .= \"".$templates->get("member_profile_userstar", 1, 0)."\";"); - } - } - - // User is currently online and this user has permissions to view the user on the WOL - $timesearch = TIME_NOW - $mybb->settings['wolcutoffmins']*60; - $query = $db->simple_select("sessions", "location,nopermission", "uid='$uid' AND time>'{$timesearch}'", array('order_by' => 'time', 'order_dir' => 'DESC', 'limit' => 1)); - $session = $db->fetch_array($query); - - $online_status = ''; - if($memprofile['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $memprofile['uid'] == $mybb->user['uid']) - { - // Lastvisit - if($memprofile['lastactive']) - { - $memlastvisitsep = $lang->comma; - $memlastvisitdate = my_date('relative', $memprofile['lastactive']); - } - - // Time Online - $timeonline = $lang->none_registered; - if($memprofile['timeonline'] > 0) - { - $timeonline = nice_time($memprofile['timeonline']); - } - - // Online? - if(!empty($session)) - { - // Fetch their current location - $lang->load("online"); - require_once MYBB_ROOT."inc/functions_online.php"; - $activity = fetch_wol_activity($session['location'], $session['nopermission']); - $location = build_friendly_wol_location($activity); - $location_time = my_date($mybb->settings['timeformat'], $memprofile['lastactive']); - - eval("\$online_status = \"".$templates->get("member_profile_online")."\";"); - } - // User is offline - else - { - eval("\$online_status = \"".$templates->get("member_profile_offline")."\";"); - } - } - - if($memprofile['invisible'] == 1 && $mybb->usergroup['canviewwolinvis'] != 1 && $memprofile['uid'] != $mybb->user['uid']) - { - $memlastvisitsep = ''; - $memlastvisittime = ''; - $memlastvisitdate = $lang->lastvisit_never; - - if($memprofile['lastactive']) - { - // We have had at least some active time, hide it instead - $memlastvisitdate = $lang->lastvisit_hidden; - } - - $timeonline = $lang->timeonline_hidden; - } - - // Reset the background colours to keep it inline - $alttrow = 'trow1'; - - // Build Referral - $referrals = ''; - if($mybb->settings['usereferrals'] == 1) - { - $bg_color = alt_trow(); - - eval("\$referrals = \"".$templates->get("member_profile_referrals")."\";"); - } - - // Fetch the reputation for this user - $reputation = ''; - if($memperms['usereputationsystem'] == 1 && $displaygroup['usereputationsystem'] == 1 && $mybb->settings['enablereputation'] == 1) - { - $bg_color = alt_trow(); - $reputation = get_reputation($memprofile['reputation']); - - // If this user has permission to give reputations show the vote link - $vote_link = ''; - if($mybb->usergroup['cangivereputations'] == 1 && $memprofile['uid'] != $mybb->user['uid'] && ($mybb->settings['posrep'] || $mybb->settings['neurep'] || $mybb->settings['negrep'])) - { - eval("\$vote_link = \"".$templates->get("member_profile_reputation_vote")."\";"); - } - - eval("\$reputation = \"".$templates->get("member_profile_reputation")."\";"); - } - - $warning_level = ''; - if($mybb->settings['enablewarningsystem'] != 0 && $memperms['canreceivewarnings'] != 0 && ($mybb->usergroup['canwarnusers'] != 0 || ($mybb->user['uid'] == $memprofile['uid'] && $mybb->settings['canviewownwarning'] != 0))) - { - $bg_color = alt_trow(); - - if($mybb->settings['maxwarningpoints'] < 1) - { - $mybb->settings['maxwarningpoints'] = 10; - } - - $warning_level = round($memprofile['warningpoints']/$mybb->settings['maxwarningpoints']*100); - - if($warning_level > 100) - { - $warning_level = 100; - } - - $warn_user = ''; - $warning_link = 'usercp.php'; - $warning_level = get_colored_warning_level($warning_level); - if($mybb->usergroup['canwarnusers'] != 0 && $memprofile['uid'] != $mybb->user['uid']) - { - eval("\$warn_user = \"".$templates->get("member_profile_warn")."\";"); - $warning_link = "warnings.php?uid={$memprofile['uid']}"; - } - - eval("\$warning_level = \"".$templates->get("member_profile_warninglevel")."\";"); - } - - $bgcolor = $alttrow = 'trow1'; - $customfields = $profilefields = ''; - - $query = $db->simple_select("userfields", "*", "ufid = '{$uid}'"); - $userfields = $db->fetch_array($query); - - // If this user is an Administrator or a Moderator then we wish to show all profile fields - $pfcache = $cache->read('profilefields'); - - if(is_array($pfcache)) - { - foreach($pfcache as $customfield) - { - if($mybb->usergroup['cancp'] != 1 && $mybb->usergroup['issupermod'] != 1 && $mybb->usergroup['canmodcp'] != 1 && !is_member($customfield['viewableby']) || !$customfield['profile']) - { - continue; - } - - $thing = explode("\n", $customfield['type'], "2"); - $type = trim($thing[0]); - - $customfieldval = $customfield_val = ''; - $field = "fid{$customfield['fid']}"; - - if(isset($userfields[$field])) - { - $useropts = explode("\n", $userfields[$field]); - $customfieldval = $comma = ''; - if(is_array($useropts) && ($type == "multiselect" || $type == "checkbox")) - { - foreach($useropts as $val) - { - if($val != '') - { - eval("\$customfield_val .= \"".$templates->get("member_profile_customfields_field_multi_item")."\";"); - } - } - if($customfield_val != '') - { - eval("\$customfieldval = \"".$templates->get("member_profile_customfields_field_multi")."\";"); - } - } - else - { - $parser_options = array( - "allow_html" => $customfield['allowhtml'], - "allow_mycode" => $customfield['allowmycode'], - "allow_smilies" => $customfield['allowsmilies'], - "allow_imgcode" => $customfield['allowimgcode'], - "allow_videocode" => $customfield['allowvideocode'], - #"nofollow_on" => 1, - "filter_badwords" => 1 - ); - - if($customfield['type'] == "textarea") - { - $parser_options['me_username'] = $memprofile['username']; - } - else - { - $parser_options['nl2br'] = 0; - } - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_imgcode'] = 0; - } - - $customfieldval = $parser->parse_message($userfields[$field], $parser_options); - } - } - - if($customfieldval) - { - $customfield['name'] = htmlspecialchars_uni($customfield['name']); - eval("\$customfields .= \"".$templates->get("member_profile_customfields_field")."\";"); - $bgcolor = alt_trow(); - } - } - } - - if($customfields) - { - eval("\$profilefields = \"".$templates->get("member_profile_customfields")."\";"); - } - - $memprofile['postnum'] = my_number_format($memprofile['postnum']); - $lang->ppd_percent_total = $lang->sprintf($lang->ppd_percent_total, my_number_format($ppd), $post_percent); - - $memprofile['threadnum'] = my_number_format($memprofile['threadnum']); - $lang->tpd_percent_total = $lang->sprintf($lang->tpd_percent_total, my_number_format($tpd), $thread_percent); - - $formattedname = format_name($memprofile['username'], $memprofile['usergroup'], $memprofile['displaygroup']); - - $bannedbit = ''; - if($memperms['isbannedgroup'] == 1 && $mybb->usergroup['canbanusers'] == 1) - { - // Fetch details on their ban - $query = $db->simple_select('banned b LEFT JOIN '.TABLE_PREFIX.'users a ON (b.admin=a.uid)', 'b.*, a.username AS adminuser', "b.uid='{$uid}'", array('limit' => 1)); - $memban = $db->fetch_array($query); - - if($memban['reason']) - { - $memban['reason'] = htmlspecialchars_uni($parser->parse_badwords($memban['reason'])); - } - else - { - $memban['reason'] = $lang->na; - } - - if($memban['lifted'] == 'perm' || $memban['lifted'] == '' || $memban['bantime'] == 'perm' || $memban['bantime'] == '---') - { - $banlength = $lang->permanent; - $timeremaining = $lang->na; - } - else - { - // Set up the array of ban times. - $bantimes = fetch_ban_times(); - - $banlength = $bantimes[$memban['bantime']]; - $remaining = $memban['lifted']-TIME_NOW; - - $timeremaining = nice_time($remaining, array('short' => 1, 'seconds' => false)).""; - - $banned_class = ''; - if($remaining < 3600) - { - $banned_class = "high_banned"; - } - else if($remaining < 86400) - { - $banned_class = "moderate_banned"; - } - else if($remaining < 604800) - { - $banned_class = "low_banned"; - } - else - { - $banned_class = "normal_banned"; - } - - eval('$timeremaining = "'.$templates->get('member_profile_banned_remaining').'";'); - } - - $memban['adminuser'] = build_profile_link(htmlspecialchars_uni($memban['adminuser']), $memban['admin']); - - // Display a nice warning to the user - eval('$bannedbit = "'.$templates->get('member_profile_banned').'";'); - } - - $adminoptions = ''; - if($mybb->usergroup['cancp'] == 1 && $mybb->config['hide_admin_links'] != 1) - { - eval("\$adminoptions = \"".$templates->get("member_profile_adminoptions")."\";"); - } - - $modoptions = $viewnotes = $editnotes = $editprofile = $banuser = $manageuser = ''; - $can_purge_spammer = purgespammer_show($memprofile['postnum'], $memprofile['usergroup'], $memprofile['uid']); - if($mybb->usergroup['canmodcp'] == 1 || $can_purge_spammer) - { - if($mybb->usergroup['canuseipsearch'] == 1) - { - $memprofile['regip'] = my_inet_ntop($db->unescape_binary($memprofile['regip'])); - $memprofile['lastip'] = my_inet_ntop($db->unescape_binary($memprofile['lastip'])); - - eval("\$ipaddress = \"".$templates->get("member_profile_modoptions_ipaddress")."\";"); - } - - $memprofile['usernotes'] = nl2br(htmlspecialchars_uni($memprofile['usernotes'])); - - if(!empty($memprofile['usernotes'])) - { - if(strlen($memprofile['usernotes']) > 100) - { - eval("\$viewnotes = \"".$templates->get("member_profile_modoptions_viewnotes")."\";"); - $memprofile['usernotes'] = my_substr($memprofile['usernotes'], 0, 100)."... {$viewnotes}"; - } - } - else - { - $memprofile['usernotes'] = $lang->no_usernotes; - } - - if($mybb->usergroup['caneditprofiles'] == 1) - { - eval("\$editprofile = \"".$templates->get("member_profile_modoptions_editprofile")."\";"); - eval("\$editnotes = \"".$templates->get("member_profile_modoptions_editnotes")."\";"); - } - - if($mybb->usergroup['canbanusers'] == 1 && (!$memban['uid'] || $memban['uid'] && ($mybb->user['uid'] == $memban['admin']) || $mybb->usergroup['issupermod'] == 1 || $mybb->usergroup['cancp'] == 1)) - { - eval("\$banuser = \"".$templates->get("member_profile_modoptions_banuser")."\";"); - } - - if($can_purge_spammer) - { - eval("\$purgespammer = \"".$templates->get('member_profile_modoptions_purgespammer')."\";"); - } - - if(!empty($editprofile) || !empty($banuser) || !empty($purgespammer)) - { - eval("\$manageuser = \"".$templates->get("member_profile_modoptions_manageuser")."\";"); - } - - eval("\$modoptions = \"".$templates->get("member_profile_modoptions")."\";"); - } - - $add_remove_options = array(); - $buddy_options = $ignore_options = $report_options = ''; - if($mybb->user['uid'] != $memprofile['uid'] && $mybb->user['uid'] != 0) - { - $buddy_list = explode(',', $mybb->user['buddylist']); - $ignore_list = explode(',', $mybb->user['ignorelist']); - - if(in_array($uid, $buddy_list)) - { - $add_remove_options = array('url' => "usercp.php?action=do_editlists&delete={$uid}&my_post_key={$mybb->post_code}", 'class' => 'remove_buddy_button', 'lang' => $lang->remove_from_buddy_list); - } - else - { - $add_remove_options = array('url' => "usercp.php?action=do_editlists&add_username=".urlencode($memprofile['username'])."&my_post_key={$mybb->post_code}", 'class' => 'add_buddy_button', 'lang' => $lang->add_to_buddy_list); - } - - if(!in_array($uid, $ignore_list)) - { - eval("\$buddy_options = \"".$templates->get("member_profile_addremove")."\";"); // Add/Remove Buddy - } - - if(in_array($uid, $ignore_list)) - { - $add_remove_options = array('url' => "usercp.php?action=do_editlists&manage=ignored&delete={$uid}&my_post_key={$mybb->post_code}", 'class' => 'remove_ignore_button', 'lang' => $lang->remove_from_ignore_list); - } - else - { - $add_remove_options = array('url' => "usercp.php?action=do_editlists&manage=ignored&add_username=".urlencode($memprofile['username'])."&my_post_key={$mybb->post_code}", 'class' => 'add_ignore_button', 'lang' => $lang->add_to_ignore_list); - } - - if(!in_array($uid, $buddy_list)) - { - eval("\$ignore_options = \"".$templates->get("member_profile_addremove")."\";"); // Add/Remove Ignore - } - - if(isset($memperms['canbereported']) && $memperms['canbereported'] == 1) - { - $add_remove_options = array('url' => "javascript:Report.reportUser({$memprofile['uid']});", 'class' => 'report_user_button', 'lang' => $lang->report_user); - eval("\$report_options = \"".$templates->get("member_profile_addremove")."\";"); // Report User - } - } - - $plugins->run_hooks("member_profile_end"); - - eval("\$profile = \"".$templates->get("member_profile")."\";"); - output_page($profile); -} - -if($mybb->input['action'] == "do_emailuser" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("member_do_emailuser_start"); - - // Guests or those without permission can't email other users - if($mybb->usergroup['cansendemail'] == 0) - { - error_no_permission(); - } - - // Check group limits - if($mybb->usergroup['maxemails'] > 0) - { - if($mybb->user['uid'] > 0) - { - $user_check = "fromuid='{$mybb->user['uid']}'"; - } - else - { - $user_check = "ipaddress=".$db->escape_binary($session->packedip); - } - - $query = $db->simple_select("maillogs", "COUNT(*) AS sent_count", "{$user_check} AND dateline >= '".(TIME_NOW - (60*60*24))."'"); - $sent_count = $db->fetch_field($query, "sent_count"); - if($sent_count >= $mybb->usergroup['maxemails']) - { - $lang->error_max_emails_day = $lang->sprintf($lang->error_max_emails_day, $mybb->usergroup['maxemails']); - error($lang->error_max_emails_day); - } - } - - // Check email flood control - if($mybb->usergroup['emailfloodtime'] > 0) - { - if($mybb->user['uid'] > 0) - { - $user_check = "fromuid='{$mybb->user['uid']}'"; - } - else - { - $user_check = "ipaddress=".$db->escape_binary($session->packedip); - } - - $timecut = TIME_NOW-$mybb->usergroup['emailfloodtime']*60; - - $query = $db->simple_select("maillogs", "mid, dateline", "{$user_check} AND dateline > '{$timecut}'", array('order_by' => "dateline", 'order_dir' => "DESC")); - $last_email = $db->fetch_array($query); - - // Users last email was within the flood time, show the error - if($last_email['mid']) - { - $remaining_time = ($mybb->usergroup['emailfloodtime']*60)-(TIME_NOW-$last_email['dateline']); - - if($remaining_time == 1) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_1_second, $mybb->usergroup['emailfloodtime']); - } - elseif($remaining_time < 60) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_seconds, $mybb->usergroup['emailfloodtime'], $remaining_time); - } - elseif($remaining_time > 60 && $remaining_time < 120) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_1_minute, $mybb->usergroup['emailfloodtime']); - } - else - { - $remaining_time_minutes = ceil($remaining_time/60); - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_minutes, $mybb->usergroup['emailfloodtime'], $remaining_time_minutes); - } - - error($lang->error_emailflooding); - } - } - - $query = $db->simple_select("users", "uid, username, email, hideemail", "uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"); - $to_user = $db->fetch_array($query); - - if(!$to_user['username']) - { - error($lang->error_invalidusername); - } - - if($to_user['hideemail'] != 0) - { - error($lang->error_hideemail); - } - - $errors = array(); - - if($mybb->user['uid']) - { - $mybb->input['fromemail'] = $mybb->user['email']; - $mybb->input['fromname'] = $mybb->user['username']; - } - - if(!validate_email_format($mybb->input['fromemail'])) - { - $errors[] = $lang->error_invalidfromemail; - } - - if(empty($mybb->input['fromname'])) - { - $errors[] = $lang->error_noname; - } - - if(empty($mybb->input['subject'])) - { - $errors[] = $lang->error_no_email_subject; - } - - if(empty($mybb->input['message'])) - { - $errors[] = $lang->error_no_email_message; - } - - if($mybb->settings['captchaimage'] && $mybb->user['uid'] == 0) - { - require_once MYBB_ROOT.'inc/class_captcha.php'; - $captcha = new captcha; - - if($captcha->validate_captcha() == false) - { - // CAPTCHA validation failed - foreach($captcha->get_errors() as $error) - { - $errors[] = $error; - } - } - } - - if(count($errors) == 0) - { - if($mybb->settings['mail_handler'] == 'smtp') - { - $from = $mybb->input['fromemail']; - } - else - { - $from = "{$mybb->input['fromname']} <{$mybb->input['fromemail']}>"; - } - - $message = $lang->sprintf($lang->email_emailuser, $to_user['username'], $mybb->input['fromname'], $mybb->settings['bbname'], $mybb->settings['bburl'], $mybb->get_input('message')); - my_mail($to_user['email'], $mybb->get_input('subject'), $message, $from, "", "", false, "text", "", $mybb->input['fromemail']); - - if($mybb->settings['mail_logging'] > 0) - { - // Log the message - $log_entry = array( - "subject" => $db->escape_string($mybb->get_input('subject')), - "message" => $db->escape_string($mybb->get_input('message')), - "dateline" => TIME_NOW, - "fromuid" => $mybb->user['uid'], - "fromemail" => $db->escape_string($mybb->input['fromemail']), - "touid" => $to_user['uid'], - "toemail" => $db->escape_string($to_user['email']), - "tid" => 0, - "ipaddress" => $db->escape_binary($session->packedip), - "type" => 1 - ); - $db->insert_query("maillogs", $log_entry); - } - - $plugins->run_hooks("member_do_emailuser_end"); - - redirect(get_profile_link($to_user['uid']), $lang->redirect_emailsent); - } - else - { - $mybb->input['action'] = "emailuser"; - } -} - -if($mybb->input['action'] == "emailuser") -{ - $plugins->run_hooks("member_emailuser_start"); - - // Guests or those without permission can't email other users - if($mybb->usergroup['cansendemail'] == 0) - { - error_no_permission(); - } - - // Check group limits - if($mybb->usergroup['maxemails'] > 0) - { - if($mybb->user['uid'] > 0) - { - $user_check = "fromuid='{$mybb->user['uid']}'"; - } - else - { - $user_check = "ipaddress=".$db->escape_binary($session->packedip); - } - - $query = $db->simple_select("maillogs", "COUNT(*) AS sent_count", "{$user_check} AND dateline >= '".(TIME_NOW - (60*60*24))."'"); - $sent_count = $db->fetch_field($query, "sent_count"); - if($sent_count >= $mybb->usergroup['maxemails']) - { - $lang->error_max_emails_day = $lang->sprintf($lang->error_max_emails_day, $mybb->usergroup['maxemails']); - error($lang->error_max_emails_day); - } - } - - // Check email flood control - if($mybb->usergroup['emailfloodtime'] > 0) - { - if($mybb->user['uid'] > 0) - { - $user_check = "fromuid='{$mybb->user['uid']}'"; - } - else - { - $user_check = "ipaddress=".$db->escape_binary($session->packedip); - } - - $timecut = TIME_NOW-$mybb->usergroup['emailfloodtime']*60; - - $query = $db->simple_select("maillogs", "mid, dateline", "{$user_check} AND dateline > '{$timecut}'", array('order_by' => "dateline", 'order_dir' => "DESC")); - $last_email = $db->fetch_array($query); - - // Users last email was within the flood time, show the error - if($last_email['mid']) - { - $remaining_time = ($mybb->usergroup['emailfloodtime']*60)-(TIME_NOW-$last_email['dateline']); - - if($remaining_time == 1) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_1_second, $mybb->usergroup['emailfloodtime']); - } - elseif($remaining_time < 60) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_seconds, $mybb->usergroup['emailfloodtime'], $remaining_time); - } - elseif($remaining_time > 60 && $remaining_time < 120) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_1_minute, $mybb->usergroup['emailfloodtime']); - } - else - { - $remaining_time_minutes = ceil($remaining_time/60); - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_minutes, $mybb->usergroup['emailfloodtime'], $remaining_time_minutes); - } - - error($lang->error_emailflooding); - } - } - - $query = $db->simple_select("users", "uid, username, email, hideemail, ignorelist", "uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"); - $to_user = $db->fetch_array($query); - - $to_user['username'] = htmlspecialchars_uni($to_user['username']); - $lang->email_user = $lang->sprintf($lang->email_user, $to_user['username']); - - if(!$to_user['uid']) - { - error($lang->error_invaliduser); - } - - if($to_user['hideemail'] != 0) - { - error($lang->error_hideemail); - } - - if($to_user['ignorelist'] && (my_strpos(",".$to_user['ignorelist'].",", ",".$mybb->user['uid'].",") !== false && $mybb->usergroup['cansendemailoverride'] != 1)) - { - error_no_permission(); - } - - if(isset($errors) && count($errors) > 0) - { - $errors = inline_error($errors); - $fromname = htmlspecialchars_uni($mybb->get_input('fromname')); - $fromemail = htmlspecialchars_uni($mybb->get_input('fromemail')); - $subject = htmlspecialchars_uni($mybb->get_input('subject')); - $message = htmlspecialchars_uni($mybb->get_input('message')); - } - else - { - $errors = ''; - $fromname = ''; - $fromemail = ''; - $subject = ''; - $message = ''; - } - - // Generate CAPTCHA? - if($mybb->settings['captchaimage'] && $mybb->user['uid'] == 0) - { - require_once MYBB_ROOT.'inc/class_captcha.php'; - $post_captcha = new captcha(true, "post_captcha"); - - if($post_captcha->html) - { - $captcha = $post_captcha->html; - } - } - else - { - $captcha = ''; - } - - $from_email = ''; - if($mybb->user['uid'] == 0) - { - eval("\$from_email = \"".$templates->get("member_emailuser_guest")."\";"); - } - - $plugins->run_hooks("member_emailuser_end"); - - eval("\$emailuser = \"".$templates->get("member_emailuser")."\";"); - output_page($emailuser); -} - -if(!$mybb->input['action']) -{ - header("Location: index.php"); -} diff --git a/html/forums/memberlist.php b/html/forums/memberlist.php deleted file mode 100644 index a690000..0000000 --- a/html/forums/memberlist.php +++ /dev/null @@ -1,459 +0,0 @@ -load("memberlist"); - -if($mybb->settings['enablememberlist'] == 0) -{ - error($lang->memberlist_disabled); -} - -$plugins->run_hooks("memberlist_start"); - -add_breadcrumb($lang->nav_memberlist, "memberlist.php"); - -if($mybb->usergroup['canviewmemberlist'] == 0) -{ - error_no_permission(); -} - -// Showing advanced search page? -if($mybb->get_input('action') == "search") -{ - $plugins->run_hooks("memberlist_search"); - add_breadcrumb($lang->nav_memberlist_search); - - $contact_fields = array(); - foreach(array('aim', 'skype', 'google', 'yahoo', 'icq') as $field) - { - $contact_fields[$field] = ''; - $settingkey = 'allow'.$field.'field'; - - if($mybb->settings[$settingkey] != '' && is_member($mybb->settings[$settingkey], array('usergroup' => $mybb->usergroup['usergroup'], 'additionalgroups' => $mybb->usergroup['additionalgroups']))) - { - $tmpl = 'memberlist_search_'.$field; - - $lang_string = 'search_'.$field; - $lang_string = $lang->{$lang_string}; - - $bgcolors[$field] = alt_trow(); - eval('$contact_fields[\''.$field.'\'] = "'.$templates->get('memberlist_search_contact_field').'";'); - } - } - - eval("\$search_page = \"".$templates->get("memberlist_search")."\";"); - output_page($search_page); -} -else -{ - $colspan = 6; - $search_url = ''; - - // Incoming sort field? - if(isset($mybb->input['sort'])) - { - $mybb->input['sort'] = strtolower($mybb->get_input('sort')); - } - else - { - $mybb->input['sort'] = $mybb->settings['default_memberlist_sortby']; - } - - $sort_selected = array( - 'regdate' => '', - 'lastvisit' => '', - 'reputation' => '', - 'postnum' => '', - 'referrals' => '', - 'username' => '' - ); - - switch($mybb->input['sort']) - { - case "regdate": - $sort_field = "u.regdate"; - break; - case "lastvisit": - $sort_field = "u.lastactive"; - break; - case "reputation": - $sort_field = "u.reputation"; - break; - case "postnum": - $sort_field = "u.postnum"; - break; - case "threadnum": - $sort_field = "u.threadnum"; - break; - case "referrals": - $sort_field = "u.referrals"; - break; - default: - $sort_field = "u.username"; - $mybb->input['sort'] = 'username'; - break; - } - $sort_selected[$mybb->input['sort']] = " selected=\"selected\""; - - // Incoming sort order? - if(isset($mybb->input['order'])) - { - $mybb->input['order'] = strtolower($mybb->input['order']); - } - else - { - $mybb->input['order'] = strtolower($mybb->settings['default_memberlist_order']); - } - - $order_check = array('ascending' => '', 'descending' => ''); - if($mybb->input['order'] == "ascending" || (!$mybb->input['order'] && $mybb->input['sort'] == 'username')) - { - $sort_order = "ASC"; - $sortordernow = "ascending"; - $oppsort = $lang->desc; - $oppsortnext = "descending"; - $mybb->input['order'] = "ascending"; - } - else - { - $sort_order = "DESC"; - $sortordernow = "descending"; - $oppsort = $lang->asc; - $oppsortnext = "ascending"; - $mybb->input['order'] = "descending"; - } - $order_check[$mybb->input['order']] = " checked=\"checked\""; - - // Incoming results per page? - $mybb->input['perpage'] = $mybb->get_input('perpage', MyBB::INPUT_INT); - if($mybb->input['perpage'] > 0 && $mybb->input['perpage'] <= 500) - { - $per_page = $mybb->input['perpage']; - } - else if($mybb->settings['membersperpage']) - { - $per_page = $mybb->input['perpage'] = (int)$mybb->settings['membersperpage']; - } - else - { - $per_page = $mybb->input['perpage'] = 20; - } - - $search_query = '1=1'; - $search_url = ""; - - // Limiting results to a certain letter - if(isset($mybb->input['letter'])) - { - $letter = chr(ord($mybb->get_input('letter'))); - if($mybb->input['letter'] == -1) - { - $search_query .= " AND u.username NOT REGEXP('[a-zA-Z]')"; - } - else if(strlen($letter) == 1) - { - $search_query .= " AND u.username LIKE '".$db->escape_string_like($letter)."%'"; - } - $search_url .= "&letter={$letter}"; - } - - // Searching for a matching username - $search_username = htmlspecialchars_uni(trim($mybb->get_input('username'))); - if($search_username != '') - { - $username_like_query = $db->escape_string_like($search_username); - - // Name begins with - if($mybb->input['username_match'] == "begins") - { - $search_query .= " AND u.username LIKE '".$username_like_query."%'"; - $search_url .= "&username_match=begins"; - } - // Just contains - else - { - $search_query .= " AND u.username LIKE '%".$username_like_query."%'"; - } - - $search_url .= "&username=".urlencode($search_username); - } - - // Website contains - $mybb->input['website'] = trim($mybb->get_input('website')); - $search_website = htmlspecialchars_uni($mybb->input['website']); - if(trim($mybb->input['website'])) - { - $search_query .= " AND u.website LIKE '%".$db->escape_string_like($mybb->input['website'])."%'"; - $search_url .= "&website=".urlencode($mybb->input['website']); - } - - // Search by contact field input - foreach(array('aim', 'icq', 'google', 'skype', 'yahoo') as $cfield) - { - $csetting = 'allow'.$cfield.'field'; - $mybb->input[$cfield] = trim($mybb->get_input($cfield)); - if($mybb->input[$cfield] && $mybb->settings[$csetting] != '') - { - if($mybb->settings[$csetting] != -1) - { - $gids = explode(',', (string)$mybb->settings[$csetting]); - - $search_query .= " AND ("; - $or = ''; - foreach($gids as $gid) - { - $gid = (int)$gid; - $search_query .= $or.'u.usergroup=\''.$gid.'\''; - switch($db->type) - { - case 'pgsql': - case 'sqlite': - $search_query .= " OR ','||u.additionalgroups||',' LIKE '%,{$gid},%'"; - break; - default: - $search_query .= " OR CONCAT(',',u.additionalgroups,',') LIKE '%,{$gid},%'"; - break; - } - $or = ' OR '; - } - $search_query .= ")"; - } - if($cfield == 'icq') - { - $search_query .= " AND u.{$cfield} LIKE '%".(int)$mybb->input[$cfield]."%'"; - } - else - { - $search_query .= " AND u.{$cfield} LIKE '%".$db->escape_string_like($mybb->input[$cfield])."%'"; - } - $search_url .= "&{$cfield}=".urlencode($mybb->input[$cfield]); - } - } - - $usergroups_cache = $cache->read('usergroups'); - - $group = array(); - foreach($usergroups_cache as $gid => $groupcache) - { - if($groupcache['showmemberlist'] == 0) - { - $group[] = (int)$gid; - } - } - - if(is_array($group) && !empty($group)) - { - $hiddengroup = implode(',', $group); - - $search_query .= " AND u.usergroup NOT IN ({$hiddengroup})"; - - foreach($group as $hidegid) - { - switch($db->type) - { - case "pgsql": - case "sqlite": - $search_query .= " AND ','||u.additionalgroups||',' NOT LIKE '%,{$hidegid},%'"; - break; - default: - $search_query .= " AND CONCAT(',',u.additionalgroups,',') NOT LIKE '%,{$hidegid},%'"; - break; - } - } - } - - $sorturl = htmlspecialchars_uni("memberlist.php?perpage={$mybb->input['perpage']}{$search_url}"); - $search_url = htmlspecialchars_uni("memberlist.php?sort={$mybb->input['sort']}&order={$mybb->input['order']}&perpage={$mybb->input['perpage']}{$search_url}"); - - $plugins->run_hooks('memberlist_intermediate'); - - $query = $db->simple_select("users u", "COUNT(*) AS users", "{$search_query}"); - $num_users = $db->fetch_field($query, "users"); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - if($page && $page > 0) - { - $start = ($page - 1) * $per_page; - } - else - { - $start = 0; - $page = 1; - } - - $sort = htmlspecialchars_uni($mybb->input['sort']); - eval("\$orderarrow['{$sort}'] = \"".$templates->get("memberlist_orderarrow")."\";"); - - // Referral? - if($mybb->settings['usereferrals'] == 1) - { - $colspan = 7; - eval("\$referral_header = \"".$templates->get("memberlist_referrals")."\";"); - } - - $multipage = multipage($num_users, $per_page, $page, $search_url); - - // Cache a few things - $usertitles = $cache->read('usertitles'); - $usertitles_cache = array(); - foreach($usertitles as $usertitle) - { - $usertitles_cache[$usertitle['posts']] = $usertitle; - } - $users = ''; - $query = $db->query(" - SELECT u.*, f.* - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - WHERE {$search_query} - ORDER BY {$sort_field} {$sort_order} - LIMIT {$start}, {$per_page} - "); - while($user = $db->fetch_array($query)) - { - $user = $plugins->run_hooks("memberlist_user", $user); - - $alt_bg = alt_trow(); - - $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); - - $user['profilelink'] = build_profile_link($user['username'], $user['uid']); - - // Get the display usergroup - if(empty($user['displaygroup'])) - { - $user['displaygroup'] = $user['usergroup']; - } - $usergroup = $usergroups_cache[$user['displaygroup']]; - - // Build referral? - if($mybb->settings['usereferrals'] == 1) - { - eval("\$referral_bit = \"".$templates->get("memberlist_referrals_bit")."\";"); - } - - $usergroup['groupimage'] = ''; - // Work out the usergroup/title stuff - if(!empty($usergroup['image'])) - { - if(!empty($mybb->user['language'])) - { - $language = $mybb->user['language']; - } - else - { - $language = $mybb->settings['bblanguage']; - } - $usergroup['image'] = str_replace("{lang}", $language, $usergroup['image']); - $usergroup['image'] = str_replace("{theme}", $theme['imgdir'], $usergroup['image']); - eval("\$usergroup['groupimage'] = \"".$templates->get("memberlist_user_groupimage")."\";"); - } - - $has_custom_title = 0; - if(trim($user['usertitle']) != "") - { - $has_custom_title = 1; - } - - if($usergroup['usertitle'] != "" && !$has_custom_title) - { - $user['usertitle'] = $usergroup['usertitle']; - } - elseif(is_array($usertitles_cache) && !$usergroup['usertitle']) - { - foreach($usertitles_cache as $posts => $titleinfo) - { - if($user['postnum'] >= $posts) - { - if(!$has_custom_title) - { - $user['usertitle'] = $titleinfo['title']; - } - $user['stars'] = $titleinfo['stars']; - $user['starimage'] = $titleinfo['starimage']; - break; - } - } - } - - $user['usertitle'] = htmlspecialchars_uni($user['usertitle']); - - if(!empty($usergroup['stars'])) - { - $user['stars'] = $usergroup['stars']; - } - - if(empty($user['starimage'])) - { - $user['starimage'] = $usergroup['starimage']; - } - - $user['userstars'] = ''; - if(!empty($user['starimage'])) - { - // Only display stars if we have an image to use... - $starimage = str_replace("{theme}", $theme['imgdir'], $user['starimage']); - - for($i = 0; $i < $user['stars']; ++$i) - { - eval("\$user['userstars'] .= \"".$templates->get("memberlist_user_userstar", 1, 0)."\";"); - } - } - - if($user['userstars'] && $usergroup['groupimage']) - { - $user['userstars'] = "
    ".$user['userstars']; - } - - // Show avatar - $useravatar = format_avatar($user['avatar'], $user['avatardimensions'], my_strtolower($mybb->settings['memberlistmaxavatarsize'])); - eval("\$user['avatar'] = \"".$templates->get("memberlist_user_avatar")."\";"); - - if($user['invisible'] == 1 && $mybb->usergroup['canviewwolinvis'] != 1 && $user['uid'] != $mybb->user['uid']) - { - $user['lastvisit'] = $lang->lastvisit_never; - - if($user['lastvisit']) - { - // We have had at least some active time, hide it instead - $user['lastvisit'] = $lang->lastvisit_hidden; - } - } - else - { - $user['lastvisit'] = my_date('relative', $user['lastactive']); - } - - $user['regdate'] = my_date('relative', $user['regdate']); - $user['postnum'] = my_number_format($user['postnum']); - $user['threadnum'] = my_number_format($user['threadnum']); - eval("\$users .= \"".$templates->get("memberlist_user")."\";"); - } - - // Do we have no results? - if(!$users) - { - eval("\$users = \"".$templates->get("memberlist_error")."\";"); - } - - $plugins->run_hooks("memberlist_end"); - - eval("\$memberlist = \"".$templates->get("memberlist")."\";"); - output_page($memberlist); -} \ No newline at end of file diff --git a/html/forums/misc.php b/html/forums/misc.php deleted file mode 100644 index 2038dfa..0000000 --- a/html/forums/misc.php +++ /dev/null @@ -1,1082 +0,0 @@ -load("misc"); - -$plugins->run_hooks("misc_start"); - -$mybb->input['action'] = $mybb->get_input('action'); -if($mybb->input['action'] == "dstswitch" && $mybb->request_method == "post" && $mybb->user['uid'] > 0) -{ - if($mybb->user['dstcorrection'] == 2) - { - if($mybb->user['dst'] == 1) - { - $update_array = array("dst" => 0); - } - else - { - $update_array = array("dst" => 1); - } - } - $db->update_query("users", $update_array, "uid='{$mybb->user['uid']}'"); - if(!isset($mybb->input['ajax'])) - { - redirect("index.php", $lang->dst_settings_updated); - } - else - { - echo "done"; - exit; - } -} -elseif($mybb->input['action'] == "markread") -{ - if($mybb->user['uid'] && verify_post_check($mybb->get_input('my_post_key'), true) !== true) - { - // Protect our user's unread forums from CSRF - error($lang->invalid_post_code); - } - - if(isset($mybb->input['fid'])) - { - $validforum = get_forum($mybb->input['fid']); - if(!$validforum) - { - if(!isset($mybb->input['ajax'])) - { - error($lang->error_invalidforum); - } - else - { - echo 0; - exit; - } - } - - require_once MYBB_ROOT."/inc/functions_indicators.php"; - mark_forum_read($mybb->input['fid']); - - $plugins->run_hooks("misc_markread_forum"); - - if(!isset($mybb->input['ajax'])) - { - redirect(get_forum_link($mybb->input['fid']), $lang->redirect_markforumread); - } - else - { - echo 1; - exit; - } - } - else - { - - $plugins->run_hooks("misc_markread_end"); - require_once MYBB_ROOT."/inc/functions_indicators.php"; - mark_all_forums_read(); - redirect("index.php", $lang->redirect_markforumsread); - } -} -elseif($mybb->input['action'] == "clearpass") -{ - $plugins->run_hooks("misc_clearpass"); - - if(isset($mybb->input['fid'])) - { - if(!verify_post_check($mybb->get_input('my_post_key'))) - { - error($lang->invalid_post_code); - } - - my_unsetcookie("forumpass[".$mybb->get_input('fid', MyBB::INPUT_INT)."]"); - redirect("index.php", $lang->redirect_forumpasscleared); - } -} -elseif($mybb->input['action'] == "rules") -{ - if(isset($mybb->input['fid'])) - { - $plugins->run_hooks("misc_rules_start"); - - $fid = $mybb->input['fid']; - - $forum = get_forum($fid); - if(!$forum || $forum['type'] != "f" || $forum['rules'] == '') - { - error($lang->error_invalidforum); - } - - $forumpermissions = forum_permissions($forum['fid']); - if($forumpermissions['canview'] != 1) - { - error_no_permission(); - } - - if(!$forum['rulestitle']) - { - $forum['rulestitle'] = $lang->sprintf($lang->forum_rules, $forum['name']); - } - - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser(); - $parser_options = array( - "allow_html" => 1, - "allow_mycode" => 1, - "allow_smilies" => 1, - "allow_imgcode" => 1, - "filter_badwords" => 1 - ); - - $forum['rules'] = $parser->parse_message($forum['rules'], $parser_options); - - // Make navigation - build_forum_breadcrumb($mybb->input['fid']); - add_breadcrumb($forum['rulestitle']); - - $plugins->run_hooks("misc_rules_end"); - - eval("\$rules = \"".$templates->get("misc_rules_forum")."\";"); - output_page($rules); - } - -} -elseif($mybb->input['action'] == "do_helpsearch" && $mybb->request_method == "post") -{ - $plugins->run_hooks("misc_do_helpsearch_start"); - - if($mybb->settings['helpsearch'] != 1) - { - error($lang->error_helpsearchdisabled); - } - - // Check if search flood checking is enabled and user is not admin - if($mybb->settings['searchfloodtime'] > 0 && $mybb->usergroup['cancp'] != 1) - { - // Fetch the time this user last searched - $timecut = TIME_NOW-$mybb->settings['searchfloodtime']; - $query = $db->simple_select("searchlog", "*", "uid='{$mybb->user['uid']}' AND dateline > '$timecut'", array('order_by' => "dateline", 'order_dir' => "DESC")); - $last_search = $db->fetch_array($query); - // Users last search was within the flood time, show the error - if($last_search['sid']) - { - $remaining_time = $mybb->settings['searchfloodtime']-(TIME_NOW-$last_search['dateline']); - if($remaining_time == 1) - { - $lang->error_searchflooding = $lang->sprintf($lang->error_searchflooding_1, $mybb->settings['searchfloodtime']); - } - else - { - $lang->error_searchflooding = $lang->sprintf($lang->error_searchflooding, $mybb->settings['searchfloodtime'], $remaining_time); - } - error($lang->error_searchflooding); - } - } - - if($mybb->get_input('name', MyBB::INPUT_INT) != 1 && $mybb->get_input('document', MyBB::INPUT_INT) != 1) - { - error($lang->error_nosearchresults); - } - - if($mybb->get_input('document', MyBB::INPUT_INT) == 1) - { - $resulttype = "helpdoc"; - } - else - { - $resulttype = "helpname"; - } - - $search_data = array( - "keywords" => $mybb->get_input('keywords'), - "name" => $mybb->get_input('name', MyBB::INPUT_INT), - "document" => $mybb->get_input('document', MyBB::INPUT_INT), - ); - - if($db->can_search == true) - { - require_once MYBB_ROOT."inc/functions_search.php"; - - $search_results = helpdocument_perform_search_mysql($search_data); - } - else - { - error($lang->error_no_search_support); - } - $sid = md5(uniqid(microtime(), true)); - $searcharray = array( - "sid" => $db->escape_string($sid), - "uid" => $mybb->user['uid'], - "dateline" => TIME_NOW, - "ipaddress" => $db->escape_binary($session->packedip), - "threads" => '', - "posts" => '', - "resulttype" => $resulttype, - "querycache" => $search_results['querycache'], - "keywords" => $db->escape_string($mybb->get_input('keywords')), - ); - $plugins->run_hooks("misc_do_helpsearch_process"); - - $db->insert_query("searchlog", $searcharray); - - $plugins->run_hooks("misc_do_helpsearch_end"); - redirect("misc.php?action=helpresults&sid={$sid}", $lang->redirect_searchresults); -} -elseif($mybb->input['action'] == "helpresults") -{ - if($mybb->settings['helpsearch'] != 1) - { - error($lang->error_helpsearchdisabled); - } - - $sid = $mybb->get_input('sid'); - $query = $db->simple_select("searchlog", "*", "sid='".$db->escape_string($sid)."' AND uid='{$mybb->user['uid']}'"); - $search = $db->fetch_array($query); - - if(!$search) - { - error($lang->error_invalidsearch); - } - - $plugins->run_hooks("misc_helpresults_start"); - - add_breadcrumb($lang->nav_helpdocs, "misc.php?action=help"); - add_breadcrumb($lang->search_results, "misc.php?action=helpresults&sid={$sid}"); - - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - // Work out pagination, which page we're at, as well as the limits. - $perpage = $mybb->settings['threadsperpage']; - $page = $mybb->get_input('page', MyBB::INPUT_INT); - if($page > 0) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - $end = $start + $perpage; - $lower = $start+1; - $upper = $end; - - // Work out if we have terms to highlight - $highlight = ""; - if($search['keywords']) - { - $highlight = "&highlight=".urlencode($search['keywords']); - } - - // Do Multi Pages - $query = $db->simple_select("helpdocs", "COUNT(*) AS total", "hid IN(".$db->escape_string($search['querycache']).")"); - $helpcount = $db->fetch_array($query); - - if($upper > $helpcount) - { - $upper = $helpcount; - } - $multipage = multipage($helpcount['total'], $perpage, $page, "misc.php?action=helpresults&sid='".htmlspecialchars_uni($mybb->get_input('sid'))."'"); - $helpdoclist = ''; - - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser(); - - $query = $db->query(" - SELECT h.*, s.enabled - FROM ".TABLE_PREFIX."helpdocs h - LEFT JOIN ".TABLE_PREFIX."helpsections s ON (s.sid=h.sid) - WHERE h.hid IN(".$db->escape_string($search['querycache']).") AND h.enabled='1' AND s.enabled='1' - LIMIT {$start}, {$perpage} - "); - while($helpdoc = $db->fetch_array($query)) - { - $bgcolor = alt_trow(); - - if(my_strlen($helpdoc['name']) > 50) - { - $helpdoc['name'] = htmlspecialchars_uni(my_substr($helpdoc['name'], 0, 50)."..."); - } - else - { - $helpdoc['name'] = htmlspecialchars_uni($helpdoc['name']); - } - - $parser_options = array( - 'allow_html' => 1, - 'allow_mycode' => 0, - 'allow_smilies' => 0, - 'allow_imgcode' => 0, - 'filter_badwords' => 1 - ); - $helpdoc['helpdoc'] = my_strip_tags($parser->parse_message($helpdoc['document'], $parser_options)); - - if(my_strlen($helpdoc['helpdoc']) > 350) - { - $prev = my_substr($helpdoc['helpdoc'], 0, 350)."..."; - } - else - { - $prev = $helpdoc['helpdoc']; - } - - $plugins->run_hooks("misc_helpresults_bit"); - - eval("\$helpdoclist .= \"".$templates->get("misc_helpresults_bit")."\";"); - } - - if($db->num_rows($query) == 0) - { - eval("\$helpdoclist = \"".$templates->get("misc_helpresults_noresults")."\";"); - } - - $plugins->run_hooks("misc_helpresults_end"); - - eval("\$helpresults = \"".$templates->get("misc_helpresults")."\";"); - output_page($helpresults); -} -elseif($mybb->input['action'] == "help") -{ - $lang->load("helpdocs"); - $lang->load("helpsections"); - $lang->load("customhelpdocs"); - $lang->load("customhelpsections"); - - $hid = $mybb->get_input('hid', MyBB::INPUT_INT); - add_breadcrumb($lang->nav_helpdocs, "misc.php?action=help"); - - if($hid) - { - $query = $db->query(" - SELECT h.*, s.enabled AS section - FROM ".TABLE_PREFIX."helpdocs h - LEFT JOIN ".TABLE_PREFIX."helpsections s ON (s.sid=h.sid) - WHERE h.hid='{$hid}' - "); - - $helpdoc = $db->fetch_array($query); - if($helpdoc['section'] != 0 && $helpdoc['enabled'] != 0) - { - $plugins->run_hooks("misc_help_helpdoc_start"); - - // If we have incoming search terms to highlight - get it done (only if not using translation). - if(!empty($mybb->input['highlight']) && $helpdoc['usetranslation'] != 1) - { - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser(); - - $highlight = $mybb->input['highlight']; - $helpdoc['name'] = $parser->highlight_message($helpdoc['name'], $highlight); - $helpdoc['document'] = $parser->highlight_message($helpdoc['document'], $highlight); - } - - if($helpdoc['usetranslation'] == 1) - { - $langnamevar = "d".$helpdoc['hid']."_name"; - $langdescvar = "d".$helpdoc['hid']."_desc"; - $langdocvar = "d".$helpdoc['hid']."_document"; - if($lang->$langnamevar) - { - $helpdoc['name'] = $lang->$langnamevar; - } - if($lang->$langdescvar) - { - $helpdoc['description'] = $lang->$langdescvar; - } - if($lang->$langdocvar) - { - $helpdoc['document'] = $lang->$langdocvar; - } - } - - if($helpdoc['hid'] == 3) - { - $helpdoc['document'] = $lang->sprintf($helpdoc['document'], $mybb->post_code); - } - - add_breadcrumb($helpdoc['name']); - - $plugins->run_hooks("misc_help_helpdoc_end"); - - eval("\$helppage = \"".$templates->get("misc_help_helpdoc")."\";"); - output_page($helppage); - } - else - { - error($lang->error_invalidhelpdoc); - } - } - else - { - $plugins->run_hooks("misc_help_section_start"); - - $query = $db->simple_select("helpdocs", "*", "", array('order_by' => 'sid, disporder')); - while($helpdoc = $db->fetch_array($query)) - { - $helpdocs[$helpdoc['sid']][$helpdoc['disporder']][$helpdoc['hid']] = $helpdoc; - } - unset($helpdoc); - $sections = ''; - $query = $db->simple_select("helpsections", "*", "enabled != 0", array('order_by' => 'disporder')); - while($section = $db->fetch_array($query)) - { - if($section['usetranslation'] == 1) - { - $langnamevar = "s".$section['sid']."_name"; - $langdescvar = "s".$section['sid']."_desc"; - if($lang->$langnamevar) - { - $section['name'] = $lang->$langnamevar; - } - if($lang->$langdescvar) - { - $section['description'] = $lang->$langdescvar; - } - } - if(is_array($helpdocs[$section['sid']])) - { - $helpbits = ''; - foreach($helpdocs[$section['sid']] as $key => $bit) - { - foreach($bit as $key => $helpdoc) - { - if($helpdoc['enabled'] != 0) - { - if($helpdoc['usetranslation'] == 1) - { - $langnamevar = "d".$helpdoc['hid'].'_name'; - $langdescvar = "d".$helpdoc['hid'].'_desc'; - if($lang->$langnamevar) - { - $helpdoc['name'] = $lang->$langnamevar; - } - if($lang->$langdescvar) - { - $helpdoc['description'] = $lang->$langdescvar; - } - } - $altbg = alt_trow(); - eval("\$helpbits .= \"".$templates->get("misc_help_section_bit")."\";"); - } - } - $expdisplay = ''; - $sname = "sid_".$section['sid']."_c"; - if(isset($collapsed[$sname]) && $collapsed[$sname] == "display: show;") - { - $expcolimage = "collapse_collapsed.png"; - $expdisplay = "display: none;"; - $expthead = " thead_collapsed"; - } - else - { - $expcolimage = "collapse.png"; - $expthead = ""; - } - } - eval("\$sections .= \"".$templates->get("misc_help_section")."\";"); - } - } - - if($mybb->settings['helpsearch'] == 1) - { - eval("\$search = \"".$templates->get("misc_help_search")."\";"); - } - - $plugins->run_hooks("misc_help_section_end"); - - eval("\$help = \"".$templates->get("misc_help")."\";"); - output_page($help); - } -} -elseif($mybb->input['action'] == "buddypopup") -{ - $plugins->run_hooks("misc_buddypopup_start"); - - if($mybb->user['uid'] == 0) - { - error_no_permission(); - } - - if(isset($mybb->input['removebuddy']) && verify_post_check($mybb->input['my_post_key'])) - { - $buddies = $mybb->user['buddylist']; - $namesarray = explode(",", $buddies); - $mybb->input['removebuddy'] = $mybb->get_input('removebuddy', MyBB::INPUT_INT); - if(is_array($namesarray)) - { - foreach($namesarray as $key => $buddyid) - { - if($buddyid == $mybb->input['removebuddy']) - { - unset($namesarray[$key]); - } - } - $buddylist = implode(',', $namesarray); - $db->update_query("users", array('buddylist' => $buddylist), "uid='".$mybb->user['uid']."'"); - $mybb->user['buddylist'] = $buddylist; - } - } - - // Load Buddies - $buddies = ''; - if($mybb->user['buddylist'] != "") - { - $buddys = array('online' => '', 'offline' => ''); - $timecut = TIME_NOW - $mybb->settings['wolcutoff']; - - $query = $db->simple_select("users", "*", "uid IN ({$mybb->user['buddylist']})", array('order_by' => 'lastactive')); - - while($buddy = $db->fetch_array($query)) - { - $buddy['username'] = htmlspecialchars_uni($buddy['username']); - $buddy_name = format_name($buddy['username'], $buddy['usergroup'], $buddy['displaygroup']); - $profile_link = build_profile_link($buddy_name, $buddy['uid'], '_blank', 'if(window.opener) { window.opener.location = this.href; return false; }'); - - $send_pm = ''; - if($mybb->user['receivepms'] != 0 && $buddy['receivepms'] != 0 && $groupscache[$buddy['usergroup']]['canusepms'] != 0) - { - eval("\$send_pm = \"".$templates->get("misc_buddypopup_user_sendpm")."\";"); - } - - if($buddy['lastactive']) - { - $last_active = $lang->sprintf($lang->last_active, my_date('relative', $buddy['lastactive'])); - } - else - { - $last_active = $lang->sprintf($lang->last_active, $lang->never); - } - - $buddy['avatar'] = format_avatar($buddy['avatar'], $buddy['avatardimensions'], '44x44'); - - if($buddy['lastactive'] > $timecut && ($buddy['invisible'] == 0 || $mybb->user['usergroup'] == 4) && $buddy['lastvisit'] != $buddy['lastactive']) - { - $bonline_alt = alt_trow(); - eval("\$buddys['online'] .= \"".$templates->get("misc_buddypopup_user_online")."\";"); - } - else - { - $boffline_alt = alt_trow(); - eval("\$buddys['offline'] .= \"".$templates->get("misc_buddypopup_user_offline")."\";"); - } - } - - $colspan = ' colspan="2"'; - if(empty($buddys['online'])) - { - $error = $lang->online_none; - eval("\$buddys['online'] = \"".$templates->get("misc_buddypopup_user_none")."\";"); - } - - if(empty($buddys['offline'])) - { - $error = $lang->offline_none; - eval("\$buddys['offline'] = \"".$templates->get("misc_buddypopup_user_none")."\";"); - } - - eval("\$buddies = \"".$templates->get("misc_buddypopup_user")."\";"); - } - else - { - // No buddies? :( - $colspan = ''; - $error = $lang->no_buddies; - eval("\$buddies = \"".$templates->get("misc_buddypopup_user_none")."\";"); - } - - $plugins->run_hooks("misc_buddypopup_end"); - - eval("\$buddylist = \"".$templates->get("misc_buddypopup", 1, 0)."\";"); - echo $buddylist; - exit; -} -elseif($mybb->input['action'] == "whoposted") -{ - $numposts = 0; - $altbg = alt_trow(); - $whoposted = ''; - $tid = $mybb->get_input('tid', MyBB::INPUT_INT); - $thread = get_thread($tid); - - // Make sure we are looking at a real thread here. - if(!$thread) - { - error($lang->error_invalidthread); - } - - // Make sure we are looking at a real thread here. - if(($thread['visible'] == -1 && !is_moderator($thread['fid'], "canviewdeleted")) || ($thread['visible'] == 0 && !is_moderator($thread['fid'], "canviewunapprove")) || $thread['visible'] > 1) - { - error($lang->error_invalidthread); - } - - if(is_moderator($thread['fid'], "canviewdeleted") || is_moderator($thread['fid'], "canviewunapprove")) - { - if(is_moderator($thread['fid'], "canviewunapprove") && !is_moderator($thread['fid'], "canviewdeleted")) - { - $show_posts = "p.visible IN (0,1)"; - } - elseif(is_moderator($thread['fid'], "canviewdeleted") && !is_moderator($thread['fid'], "canviewunapprove")) - { - $show_posts = "p.visible IN (-1,1)"; - } - else - { - $show_posts = "p.visible IN (-1,0,1)"; - } - } - else - { - $show_posts = "p.visible = 1"; - } - - // Does the thread belong to a valid forum? - $forum = get_forum($thread['fid']); - if(!$forum || $forum['type'] != "f") - { - error($lang->error_invalidforum); - } - - // Does the user have permission to view this thread? - $forumpermissions = forum_permissions($forum['fid']); - - if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0 || (isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0 && $thread['uid'] != $mybb->user['uid'])) - { - error_no_permission(); - } - - // Check if this forum is password protected and we have a valid password - check_forum_password($forum['fid']); - - if($mybb->get_input('sort') != 'username') - { - $sortsql = ' ORDER BY posts DESC'; - } - else - { - $sortsql = ' ORDER BY p.username ASC'; - } - $whoposted = ''; - $query = $db->query(" - SELECT COUNT(p.pid) AS posts, p.username AS postusername, u.uid, u.username, u.usergroup, u.displaygroup - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE tid='".$tid."' AND $show_posts - GROUP BY u.uid, p.username, u.uid, u.username, u.usergroup, u.displaygroup - ".$sortsql." - "); - while($poster = $db->fetch_array($query)) - { - if($poster['username'] == '') - { - $poster['username'] = $poster['postusername']; - } - $poster['username'] = htmlspecialchars_uni($poster['username']); - $poster['postusername'] = htmlspecialchars_uni($poster['postusername']); - $poster_name = format_name($poster['username'], $poster['usergroup'], $poster['displaygroup']); - if($poster['uid']) - { - $onclick = "opener.location.href='".get_profile_link($poster['uid'])."'; return false;"; - } - $profile_link = build_profile_link($poster_name, $poster['uid'], '_blank', $onclick); - $numposts += $poster['posts']; - eval("\$whoposted .= \"".$templates->get("misc_whoposted_poster")."\";"); - $altbg = alt_trow(); - } - $numposts = my_number_format($numposts); - $poster['posts'] = my_number_format($poster['posts']); - eval("\$whop = \"".$templates->get("misc_whoposted", 1, 0)."\";"); - echo $whop; - exit; -} -elseif($mybb->input['action'] == "smilies") -{ - $smilies = ''; - if(!empty($mybb->input['popup']) && !empty($mybb->input['editor'])) - { // make small popup list of smilies - $editor = preg_replace('#([^a-zA-Z0-9_-]+)#', '', $mybb->get_input('editor')); - $e = 1; - $smile_icons = ''; - $class = alt_trow(1); - $smilies_cache = $cache->read("smilies"); - - if(is_array($smilies_cache)) - { - $extra_class = ' smilie_pointer'; - foreach($smilies_cache as $smilie) - { - $smilie['image'] = str_replace("{theme}", $theme['imgdir'], $smilie['image']); - $smilie['image'] = htmlspecialchars_uni($mybb->get_asset_url($smilie['image'])); - $smilie['name'] = htmlspecialchars_uni($smilie['name']); - - // Only show the first text to replace in the box - $temp = explode("\n", $smilie['find']); // use temporary variable for php 5.3 compatibility - $smilie['find'] = $temp[0]; - - $smilie['find'] = htmlspecialchars_uni($smilie['find']); - $smilie_insert = str_replace(array('\\', "'"), array('\\\\', "\'"), $smilie['find']); - - $onclick = " onclick=\"MyBBEditor.insertText(' $smilie_insert ');\""; - eval('$smilie_image = "'.$templates->get('smilie', 1, 0).'";'); - eval("\$smile_icons .= \"".$templates->get("misc_smilies_popup_smilie")."\";"); - if($e == 2) - { - eval("\$smilies .= \"".$templates->get("misc_smilies_popup_row")."\";"); - $smile_icons = ''; - $e = 1; - $class = alt_trow(); - } - else - { - $e = 2; - } - } - } - - if($e == 2) - { - eval("\$smilies .= \"".$templates->get("misc_smilies_popup_empty")."\";"); - } - - if(!$smilies) - { - eval("\$smilies = \"".$templates->get("misc_smilies_popup_no_smilies")."\";"); - } - - eval("\$smiliespage = \"".$templates->get("misc_smilies_popup", 1, 0)."\";"); - output_page($smiliespage); - } - else - { - add_breadcrumb($lang->nav_smilies); - $class = "trow1"; - $smilies_cache = $cache->read("smilies"); - - if(is_array($smilies_cache)) - { - $extra_class = $onclick = ''; - foreach($smilies_cache as $smilie) - { - $smilie['image'] = str_replace("{theme}", $theme['imgdir'], $smilie['image']); - $smilie['image'] = htmlspecialchars_uni($mybb->get_asset_url($smilie['image'])); - $smilie['name'] = htmlspecialchars_uni($smilie['name']); - - $smilie['find'] = nl2br(htmlspecialchars_uni($smilie['find'])); - eval('$smilie_image = "'.$templates->get('smilie').'";'); - eval("\$smilies .= \"".$templates->get("misc_smilies_smilie")."\";"); - $class = alt_trow(); - } - } - - if(!$smilies) - { - eval("\$smilies = \"".$templates->get("misc_smilies_no_smilies")."\";"); - } - - eval("\$smiliespage = \"".$templates->get("misc_smilies")."\";"); - output_page($smiliespage); - } -} -elseif($mybb->input['action'] == "imcenter") -{ - $mybb->input['imtype'] = $mybb->get_input('imtype'); - if($mybb->input['imtype'] != "aim" && $mybb->input['imtype'] != "skype" && $mybb->input['imtype'] != "yahoo") - { - $message = $lang->error_invalidimtype; - eval("\$error = \"".$templates->get("misc_imcenter_error", 1, 0)."\";"); - echo $error; - exit; - } - - $uid = $mybb->get_input('uid', MyBB::INPUT_INT); - $user = get_user($uid); - - if(!$user) - { - $message = $lang->error_invaliduser; - eval("\$error = \"".$templates->get("misc_imcenter_error", 1, 0)."\";"); - echo $error; - exit; - } - - if(empty($user[$mybb->input['imtype']])) - { - $message = $lang->error_invalidimtype; - eval("\$error = \"".$templates->get("misc_imcenter_error", 1, 0)."\";"); - echo $error; - exit; - } - - $settingkey = 'allow'.$mybb->input['imtype'].'field'; - if(!is_member($mybb->settings[$settingkey], $user)) - { - $message = $lang->error_nopermission_user_ajax; - eval("\$error = \"".$templates->get("misc_imcenter_error", 1, 0)."\";"); - echo $error; - exit; - } - - // Build IM navigation bar - $navigationbar = $navsep = $imtype = $imtype_lang = ''; - if(!empty($user['aim']) && is_member($mybb->settings['allowaimfield'], array('usergroup' => $user['usergroup'], 'additionalgroups' => $user['additionalgroups']))) - { - $imtype = "aim"; - $imtype_lang = $lang->aol_im; - eval("\$navigationbar .= \"".$templates->get("misc_imcenter_nav")."\";"); - $navsep = ' - '; - } - if(!empty($user['skype']) && is_member($mybb->settings['allowskypefield'], array('usergroup' => $user['usergroup'], 'additionalgroups' => $user['additionalgroups']))) - { - $imtype = "skype"; - $imtype_lang = $lang->skype; - eval("\$navigationbar .= \"".$templates->get("misc_imcenter_nav")."\";"); - $navsep = ' - '; - } - if(!empty($user['yahoo']) && is_member($mybb->settings['allowyahoofield'], array('usergroup' => $user['usergroup'], 'additionalgroups' => $user['additionalgroups']))) - { - $imtype = "yahoo"; - $imtype_lang = $lang->yahoo_im; - eval("\$navigationbar .= \"".$templates->get("misc_imcenter_nav")."\";"); - } - - $user['skype'] = htmlspecialchars_uni($user['skype']); - $user['yahoo'] = htmlspecialchars_uni($user['yahoo']); - $user['aim'] = htmlspecialchars_uni($user['aim']); - - $user['username'] = htmlspecialchars_uni($user['username']); - - $lang->chat_on_skype = $lang->sprintf($lang->chat_on_skype, $user['username']); - $lang->call_on_skype = $lang->sprintf($lang->call_on_skype, $user['username']); - - $imtemplate = "misc_imcenter_".$mybb->input['imtype']; - eval("\$imcenter = \"".$templates->get($imtemplate, 1, 0)."\";"); - echo $imcenter; - exit; -} -elseif($mybb->input['action'] == "syndication") -{ - $plugins->run_hooks("misc_syndication_start"); - - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - $version = $mybb->get_input('version'); - $new_limit = $mybb->get_input('limit', MyBB::INPUT_INT); - $forums = $mybb->get_input('forums', MyBB::INPUT_ARRAY); - $limit = 15; - if(!empty($new_limit) && $new_limit != $limit) - { - $limit = $new_limit; - } - $feedurl = ''; - $add = false; - - add_breadcrumb($lang->nav_syndication); - $unviewable = get_unviewable_forums(); - $inactiveforums = get_inactive_forums(); - $unexp1 = explode(',', $unviewable); - $unexp2 = explode(',', $inactiveforums); - $unexp = array_merge($unexp1, $unexp2); - - if(is_array($forums)) - { - foreach($unexp as $fid) - { - $unview[$fid] = true; - } - - $syndicate = ''; - $comma = ''; - $all = false; - foreach($forums as $fid) - { - if($fid == "all") - { - $all = true; - break; - } - elseif(ctype_digit($fid)) - { - if(!isset($unview[$fid])) - { - $syndicate .= $comma.$fid; - $comma = ","; - $flist[$fid] = true; - } - } - } - $url = $mybb->settings['bburl']."/syndication.php"; - if(!$all) - { - $url .= "?fid=$syndicate"; - $add = true; - } - - // If the version is not RSS2.0, set the type to Atom1.0. - if($version != "rss2.0") - { - if(!$add) - { - $url .= "?"; - } - else - { - $url .= "&"; - } - $url .= "type=atom1.0"; - $add = true; - } - if((int)$limit > 0) - { - if($limit > 50) - { - $limit = 50; - } - if(!$add) - { - $url .= "?"; - } - else - { - $url .= "&"; - } - if(is_numeric($limit)) - { - $url .= "limit=$limit"; - } - } - eval("\$feedurl = \"".$templates->get("misc_syndication_feedurl")."\";"); - } - unset($GLOBALS['forumcache']); - - // If there is no version in the input, check the default (RSS2.0). - if($version == "atom1.0") - { - $atom1check = "checked=\"checked\""; - $rss2check = ''; - } - else - { - $atom1check = ''; - $rss2check = "checked=\"checked\""; - } - $forumselect = makesyndicateforums(); - - $plugins->run_hooks("misc_syndication_end"); - - eval("\$syndication = \"".$templates->get("misc_syndication")."\";"); - output_page($syndication); -} -elseif($mybb->input['action'] == "clearcookies") -{ - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("misc_clearcookies"); - - $remove_cookies = array('mybbuser', 'mybb[announcements]', 'mybb[lastvisit]', 'mybb[lastactive]', 'collapsed', 'mybb[forumread]', 'mybb[threadsread]', 'mybbadmin', - 'mybblang', 'mybbtheme', 'multiquote', 'mybb[readallforums]', 'coppauser', 'coppadob', 'mybb[referrer]'); - - foreach($remove_cookies as $name) - { - my_unsetcookie($name); - } - redirect("index.php", $lang->redirect_cookiescleared); -} - -/** - * Build a list of forums for RSS multiselect. - * - * @param int $pid Parent forum ID. - * @param string $selitem deprecated - * @param boolean $addselect Whether to add selected attribute or not. - * @param string $depth HTML for the depth of the forum. - * @return string HTML of the list of forums for CSS. - */ -function makesyndicateforums($pid=0, $selitem="", $addselect=true, $depth="") -{ - global $db, $forumcache, $permissioncache, $mybb, $forumlist, $forumlistbits, $flist, $lang, $unexp, $templates; - - $pid = (int)$pid; - $forumlist = ''; - - if(!is_array($forumcache)) - { - // Get Forums - $query = $db->simple_select("forums", "*", "linkto = '' AND active!=0", array('order_by' => 'pid, disporder')); - while($forum = $db->fetch_array($query)) - { - $forumcache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; - } - } - - if(!is_array($permissioncache)) - { - $permissioncache = forum_permissions(); - } - - if(is_array($forumcache[$pid])) - { - foreach($forumcache[$pid] as $key => $main) - { - foreach($main as $key => $forum) - { - $perms = $permissioncache[$forum['fid']]; - if($perms['canview'] == 1 || $mybb->settings['hideprivateforums'] == 0) - { - $optionselected = ''; - if(isset($flist[$forum['fid']])) - { - $optionselected = 'selected="selected"'; - $selecteddone = "1"; - } - - if($forum['password'] == '' && !in_array($forum['fid'], $unexp) || $forum['password'] && isset($mybb->cookies['forumpass'][$forum['fid']]) && $mybb->cookies['forumpass'][$forum['fid']] === md5($mybb->user['uid'].$forum['password'])) - { - eval("\$forumlistbits .= \"".$templates->get("misc_syndication_forumlist_forum")."\";"); - } - - if(!empty($forumcache[$forum['fid']])) - { - $newdepth = $depth."    "; - $forumlistbits .= makesyndicateforums($forum['fid'], '', 0, $newdepth); - } - } - } - } - } - - if($addselect) - { - $addsel = ''; - if(empty($selecteddone)) - { - $addsel = ' selected="selected"'; - } - - eval("\$forumlist = \"".$templates->get("misc_syndication_forumlist")."\";"); - } - - return $forumlist; -} diff --git a/html/forums/modcp.php b/html/forums/modcp.php deleted file mode 100644 index 841bc8b..0000000 --- a/html/forums/modcp.php +++ /dev/null @@ -1,4830 +0,0 @@ -load("modcp"); -$lang->load("announcements"); - -if($mybb->user['uid'] == 0 || $mybb->usergroup['canmodcp'] != 1) -{ - error_no_permission(); -} - -if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) -{ - $mybb->settings['threadsperpage'] = 20; -} - -$tflist = $flist = $tflist_queue_threads = $flist_queue_threads = $tflist_queue_posts = $flist_queue_posts = $tflist_queue_attach = -$flist_queue_attach = $wflist_reports = $tflist_reports = $flist_reports = $tflist_modlog = $flist_modlog = $errors = ''; -// SQL for fetching items only related to forums this user moderates -$moderated_forums = array(); -if($mybb->usergroup['issupermod'] != 1) -{ - $query = $db->simple_select("moderators", "*", "(id='{$mybb->user['uid']}' AND isgroup = '0') OR (id='{$mybb->user['usergroup']}' AND isgroup = '1')"); - - $numannouncements = $nummodqueuethreads = $nummodqueueposts = $nummodqueueattach = $numreportedposts = $nummodlogs = 0; - while($forum = $db->fetch_array($query)) - { - // For Announcements - if($forum['canmanageannouncements'] == 1) - { - ++$numannouncements; - } - - // For the Mod Queues - if($forum['canapproveunapprovethreads'] == 1) - { - $flist_queue_threads .= ",'{$forum['fid']}'"; - - $children = get_child_list($forum['fid']); - if(!empty($children)) - { - $flist_queue_threads .= ",'".implode("','", $children)."'"; - } - ++$nummodqueuethreads; - } - - if($forum['canapproveunapproveposts'] == 1) - { - $flist_queue_posts .= ",'{$forum['fid']}'"; - - $children = get_child_list($forum['fid']); - if(!empty($children)) - { - $flist_queue_posts .= ",'".implode("','", $children)."'"; - } - ++$nummodqueueposts; - } - - if($forum['canapproveunapproveattachs'] == 1) - { - $flist_queue_attach .= ",'{$forum['fid']}'"; - - $children = get_child_list($forum['fid']); - if(!empty($children)) - { - $flist_queue_attach .= ",'".implode("','", $children)."'"; - } - ++$nummodqueueattach; - } - - // For Reported posts - if($forum['canmanagereportedposts'] == 1) - { - $flist_reports .= ",'{$forum['fid']}'"; - - $children = get_child_list($forum['fid']); - if(!empty($children)) - { - $flist_reports .= ",'".implode("','", $children)."'"; - } - ++$numreportedposts; - } - - // For the Mod Log - if($forum['canviewmodlog'] == 1) - { - $flist_modlog .= ",'{$forum['fid']}'"; - - $children = get_child_list($forum['fid']); - if(!empty($children)) - { - $flist_modlog .= ",'".implode("','", $children)."'"; - } - ++$nummodlogs; - } - - $flist .= ",'{$forum['fid']}'"; - - $children = get_child_list($forum['fid']); - if(!empty($children)) - { - $flist .= ",'".implode("','", $children)."'"; - } - $moderated_forums[] = $forum['fid']; - } - if($flist_queue_threads) - { - $tflist_queue_threads = " AND t.fid IN (0{$flist_queue_threads})"; - $flist_queue_threads = " AND fid IN (0{$flist_queue_threads})"; - } - if($flist_queue_posts) - { - $tflist_queue_posts = " AND t.fid IN (0{$flist_queue_posts})"; - $flist_queue_posts = " AND fid IN (0{$flist_queue_posts})"; - } - if($flist_queue_attach) - { - $tflist_queue_attach = " AND t.fid IN (0{$flist_queue_attach})"; - $flist_queue_attach = " AND fid IN (0{$flist_queue_attach})"; - } - if($flist_reports) - { - $wflist_reports = "WHERE r.id3 IN (0{$flist_reports})"; - $tflist_reports = " AND r.id3 IN (0{$flist_reports})"; - $flist_reports = " AND id3 IN (0{$flist_reports})"; - } - if($flist_modlog) - { - $tflist_modlog = " AND t.fid IN (0{$flist_modlog})"; - $flist_modlog = " AND fid IN (0{$flist_modlog})"; - } - if($flist) - { - $tflist = " AND t.fid IN (0{$flist})"; - $flist = " AND fid IN (0{$flist})"; - } -} - -// Retrieve a list of unviewable forums -$unviewableforums = get_unviewable_forums(); -$inactiveforums = get_inactive_forums(); -$unviewablefids1 = $unviewablefids2 = array(); - -if($unviewableforums) -{ - $flist .= " AND fid NOT IN ({$unviewableforums})"; - $tflist .= " AND t.fid NOT IN ({$unviewableforums})"; - - $unviewablefids1 = explode(',', $unviewableforums); -} - -if($inactiveforums) -{ - $flist .= " AND fid NOT IN ({$inactiveforums})"; - $tflist .= " AND t.fid NOT IN ({$inactiveforums})"; - - $unviewablefids2 = explode(',', $inactiveforums); -} - -$unviewableforums = array_merge($unviewablefids1, $unviewablefids2); - -if(!isset($collapsedimg['modcpforums'])) -{ - $collapsedimg['modcpforums'] = ''; -} - -if(!isset($collapsed['modcpforums_e'])) -{ - $collapsed['modcpforums_e'] = ''; -} - -if(!isset($collapsedimg['modcpusers'])) -{ - $collapsedimg['modcpusers'] = ''; -} - -if(!isset($collapsed['modcpusers_e'])) -{ - $collapsed['modcpusers_e'] = ''; -} - -// Fetch the Mod CP menu -$nav_announcements = $nav_modqueue = $nav_reportcenter = $nav_modlogs = $nav_editprofile = $nav_banning = $nav_warninglogs = $nav_ipsearch = $nav_forums_posts = $modcp_nav_users = ''; -if(($numannouncements > 0 || $mybb->usergroup['issupermod'] == 1) && $mybb->usergroup['canmanageannounce'] == 1) -{ - eval("\$nav_announcements = \"".$templates->get("modcp_nav_announcements")."\";"); -} - -if(($nummodqueuethreads > 0 || $nummodqueueposts > 0 || $nummodqueueattach > 0 || $mybb->usergroup['issupermod'] == 1) && $mybb->usergroup['canmanagemodqueue'] == 1) -{ - eval("\$nav_modqueue = \"".$templates->get("modcp_nav_modqueue")."\";"); -} - -if(($numreportedposts > 0 || $mybb->usergroup['issupermod'] == 1) && $mybb->usergroup['canmanagereportedcontent'] == 1) -{ - eval("\$nav_reportcenter = \"".$templates->get("modcp_nav_reportcenter")."\";"); -} - -if(($nummodlogs > 0 || $mybb->usergroup['issupermod'] == 1) && $mybb->usergroup['canviewmodlogs'] == 1) -{ - eval("\$nav_modlogs = \"".$templates->get("modcp_nav_modlogs")."\";"); -} - -if($mybb->usergroup['caneditprofiles'] == 1) -{ - eval("\$nav_editprofile = \"".$templates->get("modcp_nav_editprofile")."\";"); -} - -if($mybb->usergroup['canbanusers'] == 1) -{ - eval("\$nav_banning = \"".$templates->get("modcp_nav_banning")."\";"); -} - -if($mybb->usergroup['canviewwarnlogs'] == 1) -{ - eval("\$nav_warninglogs = \"".$templates->get("modcp_nav_warninglogs")."\";"); -} - -if($mybb->usergroup['canuseipsearch'] == 1) -{ - eval("\$nav_ipsearch = \"".$templates->get("modcp_nav_ipsearch")."\";"); -} - -$plugins->run_hooks("modcp_nav"); - -if(!empty($nav_announcements) || !empty($nav_modqueue) || !empty($nav_reportcenter) || !empty($nav_modlogs)) -{ - eval("\$modcp_nav_forums_posts = \"".$templates->get("modcp_nav_forums_posts")."\";"); -} - -if(!empty($nav_editprofile) || !empty($nav_banning) || !empty($nav_warninglogs) || !empty($nav_ipsearch)) -{ - eval("\$modcp_nav_users = \"".$templates->get("modcp_nav_users")."\";"); -} - -eval("\$modcp_nav = \"".$templates->get("modcp_nav")."\";"); - -$plugins->run_hooks("modcp_start"); - -// Make navigation -add_breadcrumb($lang->nav_modcp, "modcp.php"); - -$mybb->input['action'] = $mybb->get_input('action'); -if($mybb->input['action'] == "do_reports") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $mybb->input['reports'] = $mybb->get_input('reports', MyBB::INPUT_ARRAY); - if(empty($mybb->input['reports'])) - { - error($lang->error_noselected_reports); - } - - $sql = '1=1'; - if(empty($mybb->input['allbox'])) - { - $mybb->input['reports'] = array_map("intval", $mybb->input['reports']); - $rids = implode("','", $mybb->input['reports']); - - $sql = "rid IN ('0','{$rids}')"; - } - - $plugins->run_hooks("modcp_do_reports"); - - $db->update_query("reportedcontent", array('reportstatus' => 1), "{$sql}{$flist_reports}"); - $cache->update_reportedcontent(); - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - - redirect("modcp.php?action=reports&page={$page}", $lang->redirect_reportsmarked); -} - -if($mybb->input['action'] == "reports") -{ - if($mybb->usergroup['canmanagereportedcontent'] == 0) - { - error_no_permission(); - } - - if($numreportedposts == 0 && $mybb->usergroup['issupermod'] != 1) - { - error($lang->you_cannot_view_reported_posts); - } - - $lang->load('report'); - add_breadcrumb($lang->mcp_nav_report_center, "modcp.php?action=reports"); - - $perpage = $mybb->settings['threadsperpage']; - if(!$perpage) - { - $perpage = 20; - } - - // Multipage - if($mybb->usergroup['cancp'] || $mybb->usergroup['issupermod']) - { - $query = $db->simple_select("reportedcontent", "COUNT(rid) AS count", "reportstatus ='0'"); - $report_count = $db->fetch_field($query, "count"); - } - else - { - $query = $db->simple_select('reportedcontent', 'id3', "reportstatus='0' AND (type = 'post' OR type = '')"); - - $report_count = 0; - while($fid = $db->fetch_field($query, 'id3')) - { - if(is_moderator($fid, "canmanagereportedposts")) - { - ++$report_count; - } - } - unset($fid); - } - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - - $postcount = (int)$report_count; - $pages = $postcount / $perpage; - $pages = ceil($pages); - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page && $page > 0) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $multipage = $reportspages = ''; - if($postcount > $perpage) - { - $multipage = multipage($postcount, $perpage, $page, "modcp.php?action=reports"); - eval("\$reportspages = \"".$templates->get("modcp_reports_multipage")."\";"); - } - - $plugins->run_hooks("modcp_reports_start"); - - // Reports - $reports = ''; - $query = $db->query(" - SELECT r.*, u.username, rr.title - FROM ".TABLE_PREFIX."reportedcontent r - LEFT JOIN ".TABLE_PREFIX."users u ON (r.uid = u.uid) - LEFT JOIN ".TABLE_PREFIX."reportreasons rr ON (r.reasonid = rr.rid) - WHERE r.reportstatus = '0'{$tflist_reports} - ORDER BY r.reports DESC - LIMIT {$start}, {$perpage} - "); - - if(!$db->num_rows($query)) - { - // No unread reports - eval("\$reports = \"".$templates->get("modcp_reports_noreports")."\";"); - } - else - { - $reportedcontent = $cache->read("reportedcontent"); - $reportcache = $usercache = $postcache = array(); - - while($report = $db->fetch_array($query)) - { - if($report['type'] == 'profile' || $report['type'] == 'reputation') - { - // Profile UID is in ID - if(!isset($usercache[$report['id']])) - { - $usercache[$report['id']] = $report['id']; - } - - // Reputation comment? The offender is the ID2 - if($report['type'] == 'reputation') - { - if(!isset($usercache[$report['id2']])) - { - $usercache[$report['id2']] = $report['id2']; - } - if(!isset($usercache[$report['id3']])) - { - // The user who was offended - $usercache[$report['id3']] = $report['id3']; - } - } - } - else if(!$report['type'] || $report['type'] == 'post') - { - // This (should) be a post - $postcache[$report['id']] = $report['id']; - } - - // Lastpost info - is it missing (pre-1.8)? - $lastposter = $report['uid']; - if(!$report['lastreport']) - { - // Last reporter is our first reporter - $report['lastreport'] = $report['dateline']; - } - - if($report['reporters']) - { - $reporters = my_unserialize($report['reporters']); - - if(is_array($reporters)) - { - $lastposter = end($reporters); - } - } - - if(!isset($usercache[$lastposter])) - { - $usercache[$lastposter] = $lastposter; - } - - $report['lastreporter'] = $lastposter; - $reportcache[] = $report; - } - - // Report Center gets messy - // Find information about our users (because we don't log it when they file a report) - if(!empty($usercache)) - { - $sql = implode(',', array_keys($usercache)); - $query = $db->simple_select("users", "uid, username", "uid IN ({$sql})"); - - while($user = $db->fetch_array($query)) - { - $usercache[$user['uid']] = $user; - } - } - - // Messy * 2 - // Find out post information for our reported posts - if(!empty($postcache)) - { - $sql = implode(',', array_keys($postcache)); - $query = $db->query(" - SELECT p.pid, p.uid, p.username, p.tid, t.subject - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (p.tid = t.tid) - WHERE p.pid IN ({$sql}) - "); - - while($post = $db->fetch_array($query)) - { - $postcache[$post['pid']] = $post; - } - } - - $plugins->run_hooks('modcp_reports_intermediate'); - - // Now that we have all of the information needed, display the reports - foreach($reportcache as $report) - { - $trow = alt_trow(); - - if(!$report['type']) - { - // Assume a post - $report['type'] = 'post'; - } - - // Report Information - $report_data = array(); - - switch($report['type']) - { - case 'post': - $post = get_post_link($report['id'])."#pid{$report['id']}"; - $user = build_profile_link(htmlspecialchars_uni($postcache[$report['id']]['username']), $postcache[$report['id']]['uid']); - $report_data['content'] = $lang->sprintf($lang->report_info_post, $post, $user); - - $thread_link = get_thread_link($postcache[$report['id']]['tid']); - $thread_subject = htmlspecialchars_uni($parser->parse_badwords($postcache[$report['id']]['subject'])); - $report_data['content'] .= $lang->sprintf($lang->report_info_post_thread, $thread_link, $thread_subject); - - break; - case 'profile': - $user = build_profile_link(htmlspecialchars_uni($usercache[$report['id']]['username']), $usercache[$report['id']]['uid']); - $report_data['content'] = $lang->sprintf($lang->report_info_profile, $user); - break; - case 'reputation': - $reputation_link = "reputation.php?uid={$usercache[$report['id3']]['uid']}#rid{$report['id']}"; - $bad_user = build_profile_link(htmlspecialchars_uni($usercache[$report['id2']]['username']), $usercache[$report['id2']]['uid']); - $report_data['content'] = $lang->sprintf($lang->report_info_reputation, $reputation_link, $bad_user); - - $good_user = build_profile_link(htmlspecialchars_uni($usercache[$report['id3']]['username']), $usercache[$report['id3']]['uid']); - $report_data['content'] .= $lang->sprintf($lang->report_info_rep_profile, $good_user); - break; - } - - // Report reason and comment - if($report['reasonid'] > 0) - { - $reason = htmlspecialchars_uni($lang->parse($report['title'])); - - if(empty($report['reason'])) - { - eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment")."\";"); - } - else - { - $comment = htmlspecialchars_uni($report['reason']); - eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment_extra")."\";"); - } - } - else - { - $report_data['comment'] = $lang->na; - } - - $report_reports = 1; - if($report['reports']) - { - $report_data['reports'] = my_number_format($report['reports']); - } - - if($report['lastreporter']) - { - if(is_array($usercache[$report['lastreporter']])) - { - $lastreport_user = build_profile_link(htmlspecialchars_uni($usercache[$report['lastreporter']]['username']), $report['lastreporter']); - } - elseif($usercache[$report['lastreporter']] > 0) - { - $lastreport_user = $lang->na_deleted; - } - - $lastreport_date = my_date('relative', $report['lastreport']); - $report_data['lastreporter'] = $lang->sprintf($lang->report_info_lastreporter, $lastreport_date, $lastreport_user); - } - - $plugins->run_hooks("modcp_reports_report"); - eval("\$reports .= \"".$templates->get("modcp_reports_report")."\";"); - } - } - - $plugins->run_hooks("modcp_reports_end"); - - eval("\$reportedcontent = \"".$templates->get("modcp_reports")."\";"); - output_page($reportedcontent); -} - -if($mybb->input['action'] == "allreports") -{ - if($mybb->usergroup['canmanagereportedcontent'] == 0) - { - error_no_permission(); - } - - $lang->load('report'); - - add_breadcrumb($lang->report_center, "modcp.php?action=reports"); - add_breadcrumb($lang->all_reports, "modcp.php?action=allreports"); - - if(!$mybb->settings['threadsperpage']) - { - $mybb->settings['threadsperpage'] = 20; - } - - // Figure out if we need to display multiple pages. - $perpage = $mybb->settings['threadsperpage']; - if($mybb->get_input('page') != "last") - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - } - - if($mybb->usergroup['cancp'] || $mybb->usergroup['issupermod']) - { - $query = $db->simple_select("reportedcontent", "COUNT(rid) AS count"); - $report_count = $db->fetch_field($query, "count"); - } - else - { - $query = $db->simple_select('reportedcontent', 'id3', "type = 'post' OR type = ''"); - - $report_count = 0; - while($fid = $db->fetch_field($query, 'id3')) - { - if(is_moderator($fid, "canmanagereportedposts")) - { - ++$report_count; - } - } - unset($fid); - } - - if(isset($mybb->input['rid'])) - { - $mybb->input['rid'] = $mybb->get_input('rid', MyBB::INPUT_INT); - $query = $db->simple_select("reportedcontent", "COUNT(rid) AS count", "rid <= '".$mybb->input['rid']."'"); - $result = $db->fetch_field($query, "count"); - if(($result % $perpage) == 0) - { - $page = $result / $perpage; - } - else - { - $page = (int)$result / $perpage + 1; - } - } - $postcount = (int)$report_count; - $pages = $postcount / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - $upper = $start+$perpage; - - $multipage = multipage($postcount, $perpage, $page, "modcp.php?action=allreports"); - $allreportspages = ''; - if($postcount > $perpage) - { - eval("\$allreportspages = \"".$templates->get("modcp_reports_multipage")."\";"); - } - - $plugins->run_hooks("modcp_allreports_start"); - - $query = $db->query(" - SELECT r.*, u.username, p.username AS postusername, up.uid AS postuid, t.subject AS threadsubject, prrep.username AS repusername, pr.username AS profileusername, rr.title - FROM ".TABLE_PREFIX."reportedcontent r - LEFT JOIN ".TABLE_PREFIX."posts p ON (r.id=p.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (p.tid=t.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (r.uid=u.uid) - LEFT JOIN ".TABLE_PREFIX."users up ON (p.uid=up.uid) - LEFT JOIN ".TABLE_PREFIX."users pr ON (pr.uid=r.id) - LEFT JOIN ".TABLE_PREFIX."users prrep ON (prrep.uid=r.id2) - LEFT JOIN ".TABLE_PREFIX."reportreasons rr ON (r.reasonid = rr.rid) - {$wflist_reports} - ORDER BY r.dateline DESC - LIMIT {$start}, {$perpage} - "); - - $allreports = ''; - if(!$db->num_rows($query)) - { - eval("\$allreports = \"".$templates->get("modcp_reports_allnoreports")."\";"); - } - else - { - while($report = $db->fetch_array($query)) - { - $trow = alt_trow(); - - if($report['type'] == 'post') - { - $post = get_post_link($report['id'])."#pid{$report['id']}"; - $user = build_profile_link(htmlspecialchars_uni($report['postusername']), $report['postuid']); - $report_data['content'] = $lang->sprintf($lang->report_info_post, $post, $user); - - $thread_link = get_thread_link($report['id2']); - $thread_subject = htmlspecialchars_uni($parser->parse_badwords($report['threadsubject'])); - $report_data['content'] .= $lang->sprintf($lang->report_info_post_thread, $thread_link, $thread_subject); - } - else if($report['type'] == 'profile') - { - $user = build_profile_link(htmlspecialchars_uni($report['profileusername']), $report['id']); - $report_data['content'] = $lang->sprintf($lang->report_info_profile, $user); - } - else if($report['type'] == 'reputation') - { - $user = build_profile_link(htmlspecialchars_uni($report['repusername']), $report['id2']); - $reputation_link = "reputation.php?uid={$report['id3']}#rid{$report['id']}"; - $report_data['content'] = $lang->sprintf($lang->report_info_reputation, $reputation_link, $user); - } - - // Report reason and comment - if($report['reasonid'] > 0) - { - $reason = htmlspecialchars_uni($lang->parse($report['title'])); - - if(empty($report['reason'])) - { - eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment")."\";"); - } - else - { - $comment = htmlspecialchars_uni($report['reason']); - eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment_extra")."\";"); - } - } - else - { - $report_data['comment'] = $lang->na; - } - - $report['reporterlink'] = get_profile_link($report['uid']); - if(!$report['username']) - { - $report['username'] = $lang->na_deleted; - $report['reporterlink'] = $post; - } - $report['username'] = htmlspecialchars_uni($report['username']); - - $report_data['reports'] = my_number_format($report['reports']); - $report_data['time'] = my_date('relative', $report['dateline']); - - $plugins->run_hooks("modcp_allreports_report"); - eval("\$allreports .= \"".$templates->get("modcp_reports_allreport")."\";"); - } - } - - $plugins->run_hooks("modcp_allreports_end"); - - eval("\$allreportedcontent = \"".$templates->get("modcp_reports_allreports")."\";"); - output_page($allreportedcontent); -} - -if($mybb->input['action'] == "modlogs") -{ - if($mybb->usergroup['canviewmodlogs'] == 0) - { - error_no_permission(); - } - - if($nummodlogs == 0 && $mybb->usergroup['issupermod'] != 1) - { - error($lang->you_cannot_view_mod_logs); - } - - add_breadcrumb($lang->mcp_nav_modlogs, "modcp.php?action=modlogs"); - - $perpage = $mybb->get_input('perpage', MyBB::INPUT_INT); - if(!$perpage || $perpage <= 0) - { - $perpage = $mybb->settings['threadsperpage']; - } - - $where = ''; - - // Searching for entries by a particular user - if($mybb->get_input('uid', MyBB::INPUT_INT)) - { - $where .= " AND l.uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"; - } - - // Searching for entries in a specific forum - if($mybb->get_input('fid', MyBB::INPUT_INT)) - { - $where .= " AND t.fid='".$mybb->get_input('fid', MyBB::INPUT_INT)."'"; - } - - $mybb->input['sortby'] = $mybb->get_input('sortby'); - - // Order? - switch($mybb->input['sortby']) - { - case "username": - $sortby = "u.username"; - break; - case "forum": - $sortby = "f.name"; - break; - case "thread": - $sortby = "t.subject"; - break; - default: - $sortby = "l.dateline"; - } - $order = $mybb->get_input('order'); - if($order != "asc") - { - $order = "desc"; - } - - $plugins->run_hooks("modcp_modlogs_start"); - - $query = $db->query(" - SELECT COUNT(l.dateline) AS count - FROM ".TABLE_PREFIX."moderatorlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=l.uid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=l.tid) - WHERE 1=1 {$where}{$tflist_modlog} - "); - $rescount = $db->fetch_field($query, "count"); - - // Figure out if we need to display multiple pages. - if($mybb->get_input('page') != "last") - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - } - - $postcount = (int)$rescount; - $pages = $postcount / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $page_url = 'modcp.php?action=modlogs&perpage='.$perpage; - foreach(array('uid', 'fid') as $field) - { - $mybb->input[$field] = $mybb->get_input($field, MyBB::INPUT_INT); - if(!empty($mybb->input[$field])) - { - $page_url .= "&{$field}=".$mybb->input[$field]; - } - } - foreach(array('sortby', 'order') as $field) - { - $mybb->input[$field] = htmlspecialchars_uni($mybb->get_input($field)); - if(!empty($mybb->input[$field])) - { - $page_url .= "&{$field}=".$mybb->input[$field]; - } - } - - $multipage = multipage($postcount, $perpage, $page, $page_url); - $resultspages = ''; - if($postcount > $perpage) - { - eval("\$resultspages = \"".$templates->get("modcp_modlogs_multipage")."\";"); - } - $query = $db->query(" - SELECT l.*, u.username, u.usergroup, u.displaygroup, t.subject AS tsubject, f.name AS fname, p.subject AS psubject - FROM ".TABLE_PREFIX."moderatorlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=l.uid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=l.tid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=l.fid) - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=l.pid) - WHERE 1=1 {$where}{$tflist_modlog} - ORDER BY {$sortby} {$order} - LIMIT {$start}, {$perpage} - "); - $results = ''; - while($logitem = $db->fetch_array($query)) - { - $information = ''; - $logitem['action'] = htmlspecialchars_uni($logitem['action']); - $log_date = my_date('relative', $logitem['dateline']); - $trow = alt_trow(); - $logitem['username'] = htmlspecialchars_uni($logitem['username']); - $username = format_name($logitem['username'], $logitem['usergroup'], $logitem['displaygroup']); - $logitem['profilelink'] = build_profile_link($username, $logitem['uid']); - $logitem['ipaddress'] = my_inet_ntop($db->unescape_binary($logitem['ipaddress'])); - - if($logitem['tsubject']) - { - $logitem['tsubject'] = htmlspecialchars_uni($parser->parse_badwords($logitem['tsubject'])); - $logitem['thread'] = get_thread_link($logitem['tid']); - eval("\$information .= \"".$templates->get("modcp_modlogs_result_thread")."\";"); - } - if($logitem['fname']) - { - $logitem['forum'] = get_forum_link($logitem['fid']); - eval("\$information .= \"".$templates->get("modcp_modlogs_result_forum")."\";"); - } - if($logitem['psubject']) - { - $logitem['psubject'] = htmlspecialchars_uni($parser->parse_badwords($logitem['psubject'])); - $logitem['post'] = get_post_link($logitem['pid']); - eval("\$information .= \"".$templates->get("modcp_modlogs_result_post")."\";"); - } - - // Edited a user or managed announcement? - if(!$logitem['tsubject'] || !$logitem['fname'] || !$logitem['psubject']) - { - $data = my_unserialize($logitem['data']); - if(!empty($data['uid'])) - { - $data['username'] = htmlspecialchars_uni($data['username']); - $information = $lang->sprintf($lang->edited_user_info, htmlspecialchars_uni($data['username']), get_profile_link($data['uid'])); - } - if(!empty($data['aid'])) - { - $data['subject'] = htmlspecialchars_uni($parser->parse_badwords($data['subject'])); - $data['announcement'] = get_announcement_link($data['aid']); - eval("\$information .= \"".$templates->get("modcp_modlogs_result_announcement")."\";"); - } - } - - $plugins->run_hooks("modcp_modlogs_result"); - - eval("\$results .= \"".$templates->get("modcp_modlogs_result")."\";"); - } - - if(!$results) - { - eval("\$results = \"".$templates->get("modcp_modlogs_noresults")."\";"); - } - - $plugins->run_hooks("modcp_modlogs_filter"); - - // Fetch filter options - $sortbysel = array('username' => '', 'forum' => '', 'thread' => '', 'dateline' => ''); - $sortbysel[$mybb->input['sortby']] = "selected=\"selected\""; - $ordersel = array('asc' => '', 'desc' => ''); - $ordersel[$order] = "selected=\"selected\""; - $user_options = ''; - $query = $db->query(" - SELECT DISTINCT l.uid, u.username - FROM ".TABLE_PREFIX."moderatorlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (l.uid=u.uid) - ORDER BY u.username ASC - "); - while($user = $db->fetch_array($query)) - { - // Deleted Users - if(!$user['username']) - { - $user['username'] = $lang->na_deleted; - } - - $selected = ''; - if($mybb->get_input('uid', MyBB::INPUT_INT) == $user['uid']) - { - $selected = " selected=\"selected\""; - } - - $user['username'] = htmlspecialchars_uni($user['username']); - eval("\$user_options .= \"".$templates->get("modcp_modlogs_user")."\";"); - } - - $forum_select = build_forum_jump("", $mybb->get_input('fid', MyBB::INPUT_INT), 1, '', 0, true, '', "fid"); - - eval("\$modlogs = \"".$templates->get("modcp_modlogs")."\";"); - output_page($modlogs); -} - -if($mybb->input['action'] == "do_delete_announcement") -{ - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->usergroup['canmanageannounce'] == 0) - { - error_no_permission(); - } - - $aid = $mybb->get_input('aid'); - $query = $db->simple_select("announcements", "aid, subject, fid", "aid='{$aid}'"); - $announcement = $db->fetch_array($query); - - if(!$announcement) - { - error($lang->error_invalid_announcement); - } - if(($mybb->usergroup['issupermod'] != 1 && $announcement['fid'] == -1) || ($announcement['fid'] != -1 && !is_moderator($announcement['fid'], "canmanageannouncements")) || ($unviewableforums && in_array($announcement['fid'], $unviewableforums))) - { - error_no_permission(); - } - - $plugins->run_hooks("modcp_do_delete_announcement"); - - $db->delete_query("announcements", "aid='{$aid}'"); - log_moderator_action(array("aid" => $announcement['aid'], "subject" => $announcement['subject']), $lang->announcement_deleted); - $cache->update_forumsdisplay(); - - redirect("modcp.php?action=announcements", $lang->redirect_delete_announcement); -} - -if($mybb->input['action'] == "delete_announcement") -{ - if($mybb->usergroup['canmanageannounce'] == 0) - { - error_no_permission(); - } - - $aid = $mybb->get_input('aid'); - $query = $db->simple_select("announcements", "aid, subject, fid", "aid='{$aid}'"); - - $announcement = $db->fetch_array($query); - $announcement['subject'] = htmlspecialchars_uni($parser->parse_badwords($announcement['subject'])); - - if(!$announcement) - { - error($lang->error_invalid_announcement); - } - - if(($mybb->usergroup['issupermod'] != 1 && $announcement['fid'] == -1) || ($announcement['fid'] != -1 && !is_moderator($announcement['fid'], "canmanageannouncements")) || ($unviewableforums && in_array($announcement['fid'], $unviewableforums))) - { - error_no_permission(); - } - - $plugins->run_hooks("modcp_delete_announcement"); - - eval("\$announcements = \"".$templates->get("modcp_announcements_delete")."\";"); - output_page($announcements); -} - -if($mybb->input['action'] == "do_new_announcement") -{ - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->usergroup['canmanageannounce'] == 0) - { - error_no_permission(); - } - - $announcement_fid = $mybb->get_input('fid', MyBB::INPUT_INT); - if(($mybb->usergroup['issupermod'] != 1 && $announcement_fid == -1) || ($announcement_fid != -1 && !is_moderator($announcement_fid, "canmanageannouncements")) || ($unviewableforums && in_array($announcement_fid, $unviewableforums))) - { - error_no_permission(); - } - - $errors = array(); - - $mybb->input['title'] = $mybb->get_input('title'); - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - $mybb->input['message'] = $mybb->get_input('message'); - if(!trim($mybb->input['message'])) - { - $errors[] = $lang->error_missing_message; - } - - if(!$announcement_fid) - { - $errors[] = $lang->error_missing_forum; - } - - $mybb->input['starttime_time'] = $mybb->get_input('starttime_time'); - $mybb->input['endtime_time'] = $mybb->get_input('endtime_time'); - $startdate = @explode(" ", $mybb->input['starttime_time']); - $startdate = @explode(":", $startdate[0]); - $enddate = @explode(" ", $mybb->input['endtime_time']); - $enddate = @explode(":", $enddate[0]); - - if(stristr($mybb->input['starttime_time'], "pm")) - { - $startdate[0] = 12+$startdate[0]; - if($startdate[0] >= 24) - { - $startdate[0] = "00"; - } - } - - if(stristr($mybb->input['endtime_time'], "pm")) - { - $enddate[0] = 12+$enddate[0]; - if($enddate[0] >= 24) - { - $enddate[0] = "00"; - } - } - - $mybb->input['starttime_month'] = $mybb->get_input('starttime_month'); - $months = array('01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'); - if(!in_array($mybb->input['starttime_month'], $months)) - { - $mybb->input['starttime_month'] = '01'; - } - - $localized_time_offset = (float)$mybb->user['timezone']*3600 + $mybb->user['dst']*3600; - - $startdate = gmmktime((int)$startdate[0], (int)$startdate[1], 0, $mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT)) - $localized_time_offset; - if(!checkdate($mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT)) || $startdate < 0 || $startdate == false) - { - $errors[] = $lang->error_invalid_start_date; - } - - if($mybb->get_input('endtime_type', MyBB::INPUT_INT) == 2) - { - $enddate = '0'; - $mybb->input['endtime_month'] = '01'; - } - else - { - $mybb->input['endtime_month'] = $mybb->get_input('endtime_month'); - if(!in_array($mybb->input['endtime_month'], $months)) - { - $mybb->input['endtime_month'] = '01'; - } - $enddate = gmmktime((int)$enddate[0], (int)$enddate[1], 0, $mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT)) - $localized_time_offset; - if(!checkdate($mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT)) || $enddate < 0 || $enddate == false) - { - $errors[] = $lang->error_invalid_end_date; - } - - if($enddate <= $startdate) - { - $errors[] = $lang->error_end_before_start; - } - } - - if($mybb->get_input('allowhtml', MyBB::INPUT_INT) == 1) - { - $allowhtml = 1; - } - else - { - $allowhtml = 0; - } - if($mybb->get_input('allowmycode', MyBB::INPUT_INT) == 1) - { - $allowmycode = 1; - } - else - { - $allowmycode = 0; - } - if($mybb->get_input('allowsmilies', MyBB::INPUT_INT) == 1) - { - $allowsmilies = 1; - } - else - { - $allowsmilies = 0; - } - - $plugins->run_hooks("modcp_do_new_announcement_start"); - - if(!$errors) - { - if(isset($mybb->input['preview'])) - { - $preview = array(); - $mybb->input['action'] = 'new_announcement'; - } - else - { - $insert_announcement = array( - 'fid' => $announcement_fid, - 'uid' => $mybb->user['uid'], - 'subject' => $db->escape_string($mybb->input['title']), - 'message' => $db->escape_string($mybb->input['message']), - 'startdate' => $startdate, - 'enddate' => $enddate, - 'allowhtml' => $allowhtml, - 'allowmycode' => $allowmycode, - 'allowsmilies' => $allowsmilies - ); - $aid = $db->insert_query("announcements", $insert_announcement); - - log_moderator_action(array("aid" => $aid, "subject" => $db->escape_string($mybb->input['title'])), $lang->announcement_added); - - $plugins->run_hooks("modcp_do_new_announcement_end"); - - $cache->update_forumsdisplay(); - redirect("modcp.php?action=announcements", $lang->redirect_add_announcement); - } - } - else - { - $mybb->input['action'] = 'new_announcement'; - } -} - -if($mybb->input['action'] == "new_announcement") -{ - if($mybb->usergroup['canmanageannounce'] == 0) - { - error_no_permission(); - } - - add_breadcrumb($lang->mcp_nav_announcements, "modcp.php?action=announcements"); - add_breadcrumb($lang->add_announcement, "modcp.php?action=new_announcements"); - - $announcement_fid = $mybb->get_input('fid', MyBB::INPUT_INT); - - if(($mybb->usergroup['issupermod'] != 1 && $announcement_fid == -1) || ($announcement_fid != -1 && !is_moderator($announcement_fid, "canmanageannouncements")) || ($unviewableforums && in_array($announcement_fid, $unviewableforums))) - { - error_no_permission(); - } - - // Deal with inline errors - if(!empty($errors) || isset($preview)) - { - if(!empty($errors)) - { - $errors = inline_error($errors); - } - else - { - $errors = ''; - } - - // Set $announcement to input stuff - $announcement['subject'] = $mybb->input['title']; - $announcement['message'] = $mybb->input['message']; - $announcement['allowhtml'] = $allowhtml; - $announcement['allowmycode'] = $allowmycode; - $announcement['allowsmilies'] = $allowsmilies; - - $startmonth = $mybb->input['starttime_month']; - $startdateyear = htmlspecialchars_uni($mybb->input['starttime_year']); - $startday = $mybb->get_input('starttime_day', MyBB::INPUT_INT); - $starttime_time = htmlspecialchars_uni($mybb->input['starttime_time']); - $endmonth = $mybb->input['endtime_month']; - $enddateyear = htmlspecialchars_uni($mybb->input['endtime_year']); - $endday = $mybb->get_input('endtime_day', MyBB::INPUT_INT); - $endtime_time = htmlspecialchars_uni($mybb->input['endtime_time']); - } - else - { - $localized_time = TIME_NOW + (float)$mybb->user['timezone']*3600 + $mybb->user['dst']*3600; - - $starttime_time = gmdate($mybb->settings['timeformat'], $localized_time); - $endtime_time = gmdate($mybb->settings['timeformat'], $localized_time); - $startday = $endday = gmdate("j", $localized_time); - $startmonth = $endmonth = gmdate("m", $localized_time); - $startdateyear = gmdate("Y", $localized_time); - - $announcement = array( - 'subject' => '', - 'message' => '', - 'allowhtml' => 1, - 'allowmycode' => 1, - 'allowsmilies' => 1 - ); - - $enddateyear = $startdateyear+1; - } - - // Generate form elements - $startdateday = $enddateday = ''; - for($day = 1; $day <= 31; ++$day) - { - if($startday == $day) - { - $selected = " selected=\"selected\""; - eval("\$startdateday .= \"".$templates->get("modcp_announcements_day")."\";"); - } - else - { - $selected = ''; - eval("\$startdateday .= \"".$templates->get("modcp_announcements_day")."\";"); - } - - if($endday == $day) - { - $selected = " selected=\"selected\""; - eval("\$enddateday .= \"".$templates->get("modcp_announcements_day")."\";"); - } - else - { - $selected = ''; - eval("\$enddateday .= \"".$templates->get("modcp_announcements_day")."\";"); - } - } - - $startmonthsel = $endmonthsel = array(); - foreach(array('01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12') as $month) - { - $startmonthsel[$month] = ''; - $endmonthsel[$month] = ''; - } - $startmonthsel[$startmonth] = "selected=\"selected\""; - $endmonthsel[$endmonth] = "selected=\"selected\""; - - $startdatemonth = $enddatemonth = ''; - - eval("\$startdatemonth .= \"".$templates->get("modcp_announcements_month_start")."\";"); - eval("\$enddatemonth .= \"".$templates->get("modcp_announcements_month_end")."\";"); - - $title = htmlspecialchars_uni($announcement['subject']); - $message = htmlspecialchars_uni($announcement['message']); - - $html_sel = $mycode_sel = $smilies_sel = array('yes' => '', 'no' => ''); - if($announcement['allowhtml']) - { - $html_sel['yes'] = ' checked="checked"'; - } - else - { - $html_sel['no'] = ' checked="checked"'; - } - - if($announcement['allowmycode']) - { - $mycode_sel['yes'] = ' checked="checked"'; - } - else - { - $mycode_sel['no'] = ' checked="checked"'; - } - - if($announcement['allowsmilies']) - { - $smilies_sel['yes'] = ' checked="checked"'; - } - else - { - $smilies_sel['no'] = ' checked="checked"'; - } - - $end_type_sel = array('infinite' => '', 'finite' => ''); - if(!isset($mybb->input['endtime_type']) || $mybb->input['endtime_type'] == 2) - { - $end_type_sel['infinite'] = ' checked="checked"'; - } - else - { - $end_type_sel['finite'] = ' checked="checked"'; - } - - // MyCode editor - $codebuttons = build_mycode_inserter(); - $smilieinserter = build_clickable_smilies(); - - if(isset($preview)) - { - $announcementarray = array( - 'aid' => 0, - 'fid' => $announcement_fid, - 'uid' => $mybb->user['uid'], - 'subject' => $mybb->input['title'], - 'message' => $mybb->input['message'], - 'allowhtml' => $mybb->get_input('allowhtml', MyBB::INPUT_INT), - 'allowmycode' => $mybb->get_input('allowmycode', MyBB::INPUT_INT), - 'allowsmilies' => $mybb->get_input('allowsmilies', MyBB::INPUT_INT), - 'dateline' => TIME_NOW, - 'userusername' => $mybb->user['username'], - ); - - $array = $mybb->user; - foreach($array as $key => $element) - { - $announcementarray[$key] = $element; - } - - // Gather usergroup data from the cache - // Field => Array Key - $data_key = array( - 'title' => 'grouptitle', - 'usertitle' => 'groupusertitle', - 'stars' => 'groupstars', - 'starimage' => 'groupstarimage', - 'image' => 'groupimage', - 'namestyle' => 'namestyle', - 'usereputationsystem' => 'usereputationsystem' - ); - - foreach($data_key as $field => $key) - { - $announcementarray[$key] = $groupscache[$announcementarray['usergroup']][$field]; - } - - require_once MYBB_ROOT."inc/functions_post.php"; - $postbit = build_postbit($announcementarray, 3); - eval("\$preview = \"".$templates->get("previewpost")."\";"); - } - else - { - $preview = ''; - } - - $plugins->run_hooks("modcp_new_announcement"); - - eval("\$announcements = \"".$templates->get("modcp_announcements_new")."\";"); - output_page($announcements); -} - -if($mybb->input['action'] == "do_edit_announcement") -{ - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->usergroup['canmanageannounce'] == 0) - { - error_no_permission(); - } - - // Get the announcement - $aid = $mybb->get_input('aid', MyBB::INPUT_INT); - $query = $db->simple_select("announcements", "*", "aid='{$aid}'"); - $announcement = $db->fetch_array($query); - - // Check that it exists - if(!$announcement) - { - error($lang->error_invalid_announcement); - } - - // Mod has permissions to edit this announcement - if(($mybb->usergroup['issupermod'] != 1 && $announcement['fid'] == -1) || ($announcement['fid'] != -1 && !is_moderator($announcement['fid'], "canmanageannouncements")) || ($unviewableforums && in_array($announcement['fid'], $unviewableforums))) - { - error_no_permission(); - } - - $errors = array(); - - // Basic error checking - $mybb->input['title'] = $mybb->get_input('title'); - if(!trim($mybb->input['title'])) - { - $errors[] = $lang->error_missing_title; - } - - $mybb->input['message'] = $mybb->get_input('message'); - if(!trim($mybb->input['message'])) - { - $errors[] = $lang->error_missing_message; - } - - $mybb->input['starttime_time'] = $mybb->get_input('starttime_time'); - $mybb->input['endtime_time'] = $mybb->get_input('endtime_time'); - $startdate = @explode(" ", $mybb->input['starttime_time']); - $startdate = @explode(":", $startdate[0]); - $enddate = @explode(" ", $mybb->input['endtime_time']); - $enddate = @explode(":", $enddate[0]); - - if(stristr($mybb->input['starttime_time'], "pm")) - { - $startdate[0] = 12+$startdate[0]; - if($startdate[0] >= 24) - { - $startdate[0] = "00"; - } - } - - if(stristr($mybb->input['endtime_time'], "pm")) - { - $enddate[0] = 12+$enddate[0]; - if($enddate[0] >= 24) - { - $enddate[0] = "00"; - } - } - - $mybb->input['starttime_month'] = $mybb->get_input('starttime_month'); - $months = array('01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'); - if(!in_array($mybb->input['starttime_month'], $months)) - { - $mybb->input['starttime_month'] = '01'; - } - - $localized_time_offset = (float)$mybb->user['timezone']*3600 + $mybb->user['dst']*3600; - - $startdate = gmmktime((int)$startdate[0], (int)$startdate[1], 0, $mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT)) - $localized_time_offset; - if(!checkdate($mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT)) || $startdate < 0 || $startdate == false) - { - $errors[] = $lang->error_invalid_start_date; - } - - if($mybb->get_input('endtime_type', MyBB::INPUT_INT) == "2") - { - $enddate = '0'; - $mybb->input['endtime_month'] = '01'; - } - else - { - $mybb->input['endtime_month'] = $mybb->get_input('endtime_month'); - if(!in_array($mybb->input['endtime_month'], $months)) - { - $mybb->input['endtime_month'] = '01'; - } - $enddate = gmmktime((int)$enddate[0], (int)$enddate[1], 0, $mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT)) - $localized_time_offset; - if(!checkdate($mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT)) || $enddate < 0 || $enddate == false) - { - $errors[] = $lang->error_invalid_end_date; - } - elseif($enddate <= $startdate) - { - $errors[] = $lang->error_end_before_start; - } - } - - if($mybb->get_input('allowhtml', MyBB::INPUT_INT) == 1) - { - $allowhtml = 1; - } - else - { - $allowhtml = 0; - } - if($mybb->get_input('allowmycode', MyBB::INPUT_INT) == 1) - { - $allowmycode = 1; - } - else - { - $allowmycode = 0; - } - if($mybb->get_input('allowsmilies', MyBB::INPUT_INT) == 1) - { - $allowsmilies = 1; - } - else - { - $allowsmilies = 0; - } - - $plugins->run_hooks("modcp_do_edit_announcement_start"); - - // Proceed to update if no errors - if(!$errors) - { - if(isset($mybb->input['preview'])) - { - $preview = array(); - $mybb->input['action'] = 'edit_announcement'; - } - else - { - $update_announcement = array( - 'uid' => $mybb->user['uid'], - 'subject' => $db->escape_string($mybb->input['title']), - 'message' => $db->escape_string($mybb->input['message']), - 'startdate' => $startdate, - 'enddate' => $enddate, - 'allowhtml' => $allowhtml, - 'allowmycode' => $allowmycode, - 'allowsmilies' => $allowsmilies - ); - $db->update_query("announcements", $update_announcement, "aid='{$aid}'"); - - log_moderator_action(array("aid" => $announcement['aid'], "subject" => $db->escape_string($mybb->input['title'])), $lang->announcement_edited); - - $plugins->run_hooks("modcp_do_edit_announcement_end"); - - $cache->update_forumsdisplay(); - redirect("modcp.php?action=announcements", $lang->redirect_edit_announcement); - } - } - else - { - $mybb->input['action'] = 'edit_announcement'; - } -} - -if($mybb->input['action'] == "edit_announcement") -{ - if($mybb->usergroup['canmanageannounce'] == 0) - { - error_no_permission(); - } - - $aid = $mybb->get_input('aid', MyBB::INPUT_INT); - - add_breadcrumb($lang->mcp_nav_announcements, "modcp.php?action=announcements"); - add_breadcrumb($lang->edit_announcement, "modcp.php?action=edit_announcements&aid={$aid}"); - - // Get announcement - if(!isset($announcement) || $mybb->request_method != 'post') - { - $query = $db->simple_select("announcements", "*", "aid='{$aid}'"); - $announcement = $db->fetch_array($query); - } - - if(!$announcement) - { - error($lang->error_invalid_announcement); - } - if(($mybb->usergroup['issupermod'] != 1 && $announcement['fid'] == -1) || ($announcement['fid'] != -1 && !is_moderator($announcement['fid'], "canmanageannouncements")) || ($unviewableforums && in_array($announcement['fid'], $unviewableforums))) - { - error_no_permission(); - } - - if(!$announcement['startdate']) - { - // No start date? Make it now. - $announcement['startdate'] = TIME_NOW; - } - - $makeshift_end = false; - if(!$announcement['enddate']) - { - $makeshift_end = true; - $makeshift_time = TIME_NOW; - if($announcement['startdate']) - { - $makeshift_time = $announcement['startdate']; - } - - // No end date? Make it a year from now. - $announcement['enddate'] = $makeshift_time + (60 * 60 * 24 * 366); - } - - // Deal with inline errors - if(!empty($errors) || isset($preview)) - { - if(!empty($errors)) - { - $errors = inline_error($errors); - } - else - { - $errors = ''; - } - - // Set $announcement to input stuff - $announcement['subject'] = $mybb->input['title']; - $announcement['message'] = $mybb->input['message']; - $announcement['allowhtml'] = $allowhtml; - $announcement['allowmycode'] = $allowmycode; - $announcement['allowsmilies'] = $allowsmilies; - - $startmonth = $mybb->input['starttime_month']; - $startdateyear = htmlspecialchars_uni($mybb->input['starttime_year']); - $startday = $mybb->get_input('starttime_day', MyBB::INPUT_INT); - $starttime_time = htmlspecialchars_uni($mybb->input['starttime_time']); - $endmonth = $mybb->input['endtime_month']; - $enddateyear = htmlspecialchars_uni($mybb->input['endtime_year']); - $endday = $mybb->get_input('endtime_day', MyBB::INPUT_INT); - $endtime_time = htmlspecialchars_uni($mybb->input['endtime_time']); - - $errored = true; - } - else - { - $localized_time_startdate = $announcement['startdate'] + (float)$mybb->user['timezone']*3600 + $mybb->user['dst']*3600; - $localized_time_enddate = $announcement['enddate'] + (float)$mybb->user['timezone']*3600 + $mybb->user['dst']*3600; - - $starttime_time = gmdate($mybb->settings['timeformat'], $localized_time_startdate); - $endtime_time = gmdate($mybb->settings['timeformat'], $localized_time_enddate); - - $startday = gmdate('j', $localized_time_startdate); - $endday = gmdate('j', $localized_time_enddate); - - $startmonth = gmdate('m', $localized_time_startdate); - $endmonth = gmdate('m', $localized_time_enddate); - - $startdateyear = gmdate('Y', $localized_time_startdate); - $enddateyear = gmdate('Y', $localized_time_enddate); - - $errored = false; - } - - // Generate form elements - $startdateday = $enddateday = ''; - for($day = 1; $day <= 31; ++$day) - { - if($startday == $day) - { - $selected = " selected=\"selected\""; - eval("\$startdateday .= \"".$templates->get("modcp_announcements_day")."\";"); - } - else - { - $selected = ''; - eval("\$startdateday .= \"".$templates->get("modcp_announcements_day")."\";"); - } - - if($endday == $day) - { - $selected = " selected=\"selected\""; - eval("\$enddateday .= \"".$templates->get("modcp_announcements_day")."\";"); - } - else - { - $selected = ''; - eval("\$enddateday .= \"".$templates->get("modcp_announcements_day")."\";"); - } - } - - $startmonthsel = $endmonthsel = array(); - foreach(array('01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12') as $month) - { - $startmonthsel[$month] = ''; - $endmonthsel[$month] = ''; - } - $startmonthsel[$startmonth] = "selected=\"selected\""; - $endmonthsel[$endmonth] = "selected=\"selected\""; - - $startdatemonth = $enddatemonth = ''; - - eval("\$startdatemonth .= \"".$templates->get("modcp_announcements_month_start")."\";"); - eval("\$enddatemonth .= \"".$templates->get("modcp_announcements_month_end")."\";"); - - $title = htmlspecialchars_uni($announcement['subject']); - $message = htmlspecialchars_uni($announcement['message']); - - $html_sel = $mycode_sel = $smilies_sel = array('yes' => '', 'no' => ''); - if($announcement['allowhtml']) - { - $html_sel['yes'] = ' checked="checked"'; - } - else - { - $html_sel['no'] = ' checked="checked"'; - } - - if($announcement['allowmycode']) - { - $mycode_sel['yes'] = ' checked="checked"'; - } - else - { - $mycode_sel['no'] = ' checked="checked"'; - } - - if($announcement['allowsmilies']) - { - $smilies_sel['yes'] = ' checked="checked"'; - } - else - { - $smilies_sel['no'] = ' checked="checked"'; - } - - $end_type_sel = array('infinite' => '', 'finite' => ''); - if(($errored && $mybb->get_input('endtime_type', MyBB::INPUT_INT) == 2) || (!$errored && (int)$announcement['enddate'] == 0) || $makeshift_end == true) - { - $end_type_sel['infinite'] = ' checked="checked"'; - } - else - { - $end_type_sel['finite'] = ' checked="checked"'; - } - - // MyCode editor - $codebuttons = build_mycode_inserter(); - $smilieinserter = build_clickable_smilies(); - - if(isset($preview)) - { - $announcementarray = array( - 'aid' => $announcement['aid'], - 'fid' => $announcement['fid'], - 'uid' => $mybb->user['uid'], - 'subject' => $mybb->input['title'], - 'message' => $mybb->input['message'], - 'allowhtml' => $mybb->get_input('allowhtml', MyBB::INPUT_INT), - 'allowmycode' => $mybb->get_input('allowmycode', MyBB::INPUT_INT), - 'allowsmilies' => $mybb->get_input('allowsmilies', MyBB::INPUT_INT), - 'dateline' => TIME_NOW, - 'userusername' => $mybb->user['username'], - ); - - $array = $mybb->user; - foreach($array as $key => $element) - { - $announcementarray[$key] = $element; - } - - // Gather usergroup data from the cache - // Field => Array Key - $data_key = array( - 'title' => 'grouptitle', - 'usertitle' => 'groupusertitle', - 'stars' => 'groupstars', - 'starimage' => 'groupstarimage', - 'image' => 'groupimage', - 'namestyle' => 'namestyle', - 'usereputationsystem' => 'usereputationsystem' - ); - - foreach($data_key as $field => $key) - { - $announcementarray[$key] = $groupscache[$announcementarray['usergroup']][$field]; - } - - require_once MYBB_ROOT."inc/functions_post.php"; - $postbit = build_postbit($announcementarray, 3); - eval("\$preview = \"".$templates->get("previewpost")."\";"); - } - else - { - $preview = ''; - } - - $plugins->run_hooks("modcp_edit_announcement"); - - eval("\$announcements = \"".$templates->get("modcp_announcements_edit")."\";"); - output_page($announcements); -} - -if($mybb->input['action'] == "announcements") -{ - if($mybb->usergroup['canmanageannounce'] == 0) - { - error_no_permission(); - } - - if($numannouncements == 0 && $mybb->usergroup['issupermod'] != 1) - { - error($lang->you_cannot_manage_announcements); - } - - add_breadcrumb($lang->mcp_nav_announcements, "modcp.php?action=announcements"); - - // Fetch announcements into their proper arrays - $query = $db->simple_select("announcements", "aid, fid, subject, enddate"); - $announcements = $global_announcements = array(); - while($announcement = $db->fetch_array($query)) - { - if($announcement['fid'] == -1) - { - $global_announcements[$announcement['aid']] = $announcement; - continue; - } - $announcements[$announcement['fid']][$announcement['aid']] = $announcement; - } - - $announcements_global = ''; - if($mybb->usergroup['issupermod'] == 1) - { - if($global_announcements && $mybb->usergroup['issupermod'] == 1) - { - // Get the global announcements - foreach($global_announcements as $aid => $announcement) - { - $trow = alt_trow(); - if($announcement['startdate'] > TIME_NOW || ($announcement['enddate'] < TIME_NOW && $announcement['enddate'] != 0)) - { - eval("\$icon = \"".$templates->get("modcp_announcements_announcement_expired")."\";"); - } - else - { - eval("\$icon = \"".$templates->get("modcp_announcements_announcement_active")."\";"); - } - - $subject = htmlspecialchars_uni($parser->parse_badwords($announcement['subject'])); - - eval("\$announcements_global .= \"".$templates->get("modcp_announcements_announcement_global")."\";"); - } - } - else - { - // No global announcements - eval("\$announcements_global = \"".$templates->get("modcp_no_announcements_global")."\";"); - } - eval("\$announcements_global = \"".$templates->get("modcp_announcements_global")."\";"); - } - - $announcements_forum = ''; - fetch_forum_announcements(); - - if(!$announcements_forum) - { - eval("\$announcements_forum = \"".$templates->get("modcp_no_announcements_forum")."\";"); - } - - $plugins->run_hooks("modcp_announcements"); - - eval("\$announcements = \"".$templates->get("modcp_announcements")."\";"); - output_page($announcements); -} - -if($mybb->input['action'] == "do_modqueue") -{ - require_once MYBB_ROOT."inc/class_moderation.php"; - $moderation = new Moderation; - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->usergroup['canmanagemodqueue'] == 0) - { - error_no_permission(); - } - - $plugins->run_hooks("modcp_do_modqueue_start"); - - $mybb->input['threads'] = $mybb->get_input('threads', MyBB::INPUT_ARRAY); - $mybb->input['posts'] = $mybb->get_input('posts', MyBB::INPUT_ARRAY); - $mybb->input['attachments'] = $mybb->get_input('attachments', MyBB::INPUT_ARRAY); - if(!empty($mybb->input['threads'])) - { - $threads = array_map("intval", array_keys($mybb->input['threads'])); - $threads_to_approve = $threads_to_delete = array(); - // Fetch threads - $query = $db->simple_select("threads", "tid", "tid IN (".implode(",", $threads)."){$flist_queue_threads}"); - while($thread = $db->fetch_array($query)) - { - if(!isset($mybb->input['threads'][$thread['tid']])) - { - continue; - } - $action = $mybb->input['threads'][$thread['tid']]; - if($action == "approve") - { - $threads_to_approve[] = $thread['tid']; - } - else if($action == "delete") - { - $threads_to_delete[] = $thread['tid']; - } - } - if(!empty($threads_to_approve)) - { - $moderation->approve_threads($threads_to_approve); - log_moderator_action(array('tids' => $threads_to_approve), $lang->multi_approve_threads); - } - if(!empty($threads_to_delete)) - { - if($mybb->settings['soft_delete'] == 1) - { - $moderation->soft_delete_threads($threads_to_delete); - log_moderator_action(array('tids' => $threads_to_delete), $lang->multi_soft_delete_threads); - } - else - { - foreach($threads_to_delete as $tid) - { - $moderation->delete_thread($tid); - } - log_moderator_action(array('tids' => $threads_to_delete), $lang->multi_delete_threads); - } - } - - $plugins->run_hooks("modcp_do_modqueue_end"); - - redirect("modcp.php?action=modqueue", $lang->redirect_threadsmoderated); - } - else if(!empty($mybb->input['posts'])) - { - $posts = array_map("intval", array_keys($mybb->input['posts'])); - // Fetch posts - $posts_to_approve = $posts_to_delete = array(); - $query = $db->simple_select("posts", "pid", "pid IN (".implode(",", $posts)."){$flist_queue_posts}"); - while($post = $db->fetch_array($query)) - { - if(!isset($mybb->input['posts'][$post['pid']])) - { - continue; - } - $action = $mybb->input['posts'][$post['pid']]; - if($action == "approve") - { - $posts_to_approve[] = $post['pid']; - } - else if($action == "delete" && $mybb->settings['soft_delete'] != 1) - { - $moderation->delete_post($post['pid']); - } - else if($action == "delete") - { - $posts_to_delete[] = $post['pid']; - } - } - if(!empty($posts_to_approve)) - { - $moderation->approve_posts($posts_to_approve); - log_moderator_action(array('pids' => $posts_to_approve), $lang->multi_approve_posts); - } - if(!empty($posts_to_delete)) - { - if($mybb->settings['soft_delete'] == 1) - { - $moderation->soft_delete_posts($posts_to_delete); - log_moderator_action(array('pids' => $posts_to_delete), $lang->multi_soft_delete_posts); - } - else - { - log_moderator_action(array('pids' => $posts_to_delete), $lang->multi_delete_posts); - } - } - - $plugins->run_hooks("modcp_do_modqueue_end"); - - redirect("modcp.php?action=modqueue&type=posts", $lang->redirect_postsmoderated); - } - else if(!empty($mybb->input['attachments'])) - { - $attachments = array_map("intval", array_keys($mybb->input['attachments'])); - $query = $db->query(" - SELECT a.pid, a.aid - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (a.pid=p.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE aid IN (".implode(",", $attachments)."){$tflist_queue_attach} - "); - while($attachment = $db->fetch_array($query)) - { - if(!isset($mybb->input['attachments'][$attachment['aid']])) - { - continue; - } - $action = $mybb->input['attachments'][$attachment['aid']]; - if($action == "approve") - { - $db->update_query("attachments", array("visible" => 1), "aid='{$attachment['aid']}'"); - } - else if($action == "delete") - { - remove_attachment($attachment['pid'], '', $attachment['aid']); - } - } - - $plugins->run_hooks("modcp_do_modqueue_end"); - - redirect("modcp.php?action=modqueue&type=attachments", $lang->redirect_attachmentsmoderated); - } -} - -if($mybb->input['action'] == "modqueue") -{ - $navsep = ''; - - if($mybb->usergroup['canmanagemodqueue'] == 0) - { - error_no_permission(); - } - - if($nummodqueuethreads == 0 && $nummodqueueposts == 0 && $nummodqueueattach == 0 && $mybb->usergroup['issupermod'] != 1) - { - error($lang->you_cannot_use_mod_queue); - } - - $mybb->input['type'] = $mybb->get_input('type'); - $threadqueue = $postqueue = $attachmentqueue = ''; - if($mybb->input['type'] == "threads" || !$mybb->input['type'] && ($nummodqueuethreads > 0 || $mybb->usergroup['issupermod'] == 1)) - { - if($nummodqueuethreads == 0 && $mybb->usergroup['issupermod'] != 1) - { - error($lang->you_cannot_moderate_threads); - } - - $forum_cache = $cache->read("forums"); - - $query = $db->simple_select("threads", "COUNT(tid) AS unapprovedthreads", "visible='0' {$flist_queue_threads}"); - $unapproved_threads = $db->fetch_field($query, "unapprovedthreads"); - - // Figure out if we need to display multiple pages. - if($mybb->get_input('page') != "last") - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - } - - $perpage = $mybb->settings['threadsperpage']; - $pages = $unapproved_threads / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $multipage = multipage($unapproved_threads, $perpage, $page, "modcp.php?action=modqueue&type=threads"); - - $query = $db->query(" - SELECT t.tid, t.dateline, t.fid, t.subject, t.username AS threadusername, p.message AS postmessage, u.username AS username, t.uid - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=t.firstpost) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=t.uid) - WHERE t.visible='0' {$tflist_queue_threads} - ORDER BY t.lastpost DESC - LIMIT {$start}, {$perpage} - "); - $threads = ''; - while($thread = $db->fetch_array($query)) - { - $altbg = alt_trow(); - $thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); - $thread['threadlink'] = get_thread_link($thread['tid']); - $forum_link = get_forum_link($thread['fid']); - $forum_name = $forum_cache[$thread['fid']]['name']; - $threaddate = my_date('relative', $thread['dateline']); - - if($thread['username'] == "") - { - if($thread['threadusername'] != "") - { - $thread['threadusername'] = htmlspecialchars_uni($thread['threadusername']); - $profile_link = $thread['threadusername']; - } - else - { - $profile_link = $lang->guest; - } - } - else - { - $thread['username'] = htmlspecialchars_uni($thread['username']); - $profile_link = build_profile_link($thread['username'], $thread['uid']); - } - - $thread['postmessage'] = nl2br(htmlspecialchars_uni($thread['postmessage'])); - eval("\$forum = \"".$templates->get("modcp_modqueue_link_forum")."\";"); - eval("\$threads .= \"".$templates->get("modcp_modqueue_threads_thread")."\";"); - } - - if(!$threads && $mybb->input['type'] == "threads") - { - eval("\$threads = \"".$templates->get("modcp_modqueue_threads_empty")."\";"); - } - - if($threads) - { - add_breadcrumb($lang->mcp_nav_modqueue_threads, "modcp.php?action=modqueue&type=threads"); - - $plugins->run_hooks("modcp_modqueue_threads_end"); - - if($nummodqueueposts > 0 || $mybb->usergroup['issupermod'] == 1) - { - $navsep = " | "; - eval("\$post_link = \"".$templates->get("modcp_modqueue_post_link")."\";"); - } - - if($mybb->settings['enableattachments'] == 1 && ($nummodqueueattach > 0 || $mybb->usergroup['issupermod'] == 1)) - { - $navsep = " | "; - eval("\$attachment_link = \"".$templates->get("modcp_modqueue_attachment_link")."\";"); - } - - eval("\$mass_controls = \"".$templates->get("modcp_modqueue_masscontrols")."\";"); - eval("\$threadqueue = \"".$templates->get("modcp_modqueue_threads")."\";"); - output_page($threadqueue); - } - $type = 'threads'; - } - - if($mybb->input['type'] == "posts" || (!$mybb->input['type'] && !$threadqueue && ($nummodqueueposts > 0 || $mybb->usergroup['issupermod'] == 1))) - { - if($nummodqueueposts == 0 && $mybb->usergroup['issupermod'] != 1) - { - error($lang->you_cannot_moderate_posts); - } - - $forum_cache = $cache->read("forums"); - - $query = $db->query(" - SELECT COUNT(pid) AS unapprovedposts - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.visible='0' {$tflist_queue_posts} AND t.firstpost != p.pid - "); - $unapproved_posts = $db->fetch_field($query, "unapprovedposts"); - - // Figure out if we need to display multiple pages. - if($mybb->get_input('page') != "last") - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - } - - $perpage = $mybb->settings['postsperpage']; - $pages = $unapproved_posts / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $multipage = multipage($unapproved_posts, $perpage, $page, "modcp.php?action=modqueue&type=posts"); - - $query = $db->query(" - SELECT p.pid, p.subject, p.message, p.username AS postusername, t.subject AS threadsubject, t.tid, u.username, p.uid, t.fid, p.dateline - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.visible='0' {$tflist_queue_posts} AND t.firstpost != p.pid - ORDER BY p.dateline DESC - LIMIT {$start}, {$perpage} - "); - $posts = ''; - while($post = $db->fetch_array($query)) - { - $altbg = alt_trow(); - $post['threadsubject'] = htmlspecialchars_uni($parser->parse_badwords($post['threadsubject'])); - $post['subject'] = htmlspecialchars_uni($parser->parse_badwords($post['subject'])); - $post['threadlink'] = get_thread_link($post['tid']); - $post['postlink'] = get_post_link($post['pid'], $post['tid']); - $forum_link = get_forum_link($post['fid']); - $forum_name = $forum_cache[$post['fid']]['name']; - $postdate = my_date('relative', $post['dateline']); - - if($post['username'] == "") - { - if($post['postusername'] != "") - { - $post['postusername'] = htmlspecialchars_uni($post['postusername']); - $profile_link = $post['postusername']; - } - else - { - $profile_link = $lang->guest; - } - } - else - { - $post['username'] = htmlspecialchars_uni($post['username']); - $profile_link = build_profile_link($post['username'], $post['uid']); - } - - eval("\$thread = \"".$templates->get("modcp_modqueue_link_thread")."\";"); - eval("\$forum = \"".$templates->get("modcp_modqueue_link_forum")."\";"); - $post['message'] = nl2br(htmlspecialchars_uni($post['message'])); - eval("\$posts .= \"".$templates->get("modcp_modqueue_posts_post")."\";"); - } - - if(!$posts && $mybb->input['type'] == "posts") - { - eval("\$posts = \"".$templates->get("modcp_modqueue_posts_empty")."\";"); - } - - if($posts) - { - add_breadcrumb($lang->mcp_nav_modqueue_posts, "modcp.php?action=modqueue&type=posts"); - - $plugins->run_hooks("modcp_modqueue_posts_end"); - - if($nummodqueuethreads > 0 || $mybb->usergroup['issupermod'] == 1) - { - $navsep = " | "; - eval("\$thread_link = \"".$templates->get("modcp_modqueue_thread_link")."\";"); - } - - if($mybb->settings['enableattachments'] == 1 && ($nummodqueueattach > 0 || $mybb->usergroup['issupermod'] == 1)) - { - $navsep = " | "; - eval("\$attachment_link = \"".$templates->get("modcp_modqueue_attachment_link")."\";"); - } - - eval("\$mass_controls = \"".$templates->get("modcp_modqueue_masscontrols")."\";"); - eval("\$postqueue = \"".$templates->get("modcp_modqueue_posts")."\";"); - output_page($postqueue); - } - } - - if($mybb->input['type'] == "attachments" || (!$mybb->input['type'] && !$postqueue && !$threadqueue && $mybb->settings['enableattachments'] == 1 && ($nummodqueueattach > 0 || $mybb->usergroup['issupermod'] == 1))) - { - if($mybb->settings['enableattachments'] == 0) - { - error($lang->attachments_disabled); - } - - if($nummodqueueattach == 0 && $mybb->usergroup['issupermod'] != 1) - { - error($lang->you_cannot_moderate_attachments); - } - - $query = $db->query(" - SELECT COUNT(aid) AS unapprovedattachments - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE a.visible='0'{$tflist_queue_attach} - "); - $unapproved_attachments = $db->fetch_field($query, "unapprovedattachments"); - - // Figure out if we need to display multiple pages. - if($mybb->get_input('page') != "last") - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - } - - $perpage = $mybb->settings['postsperpage']; - $pages = $unapproved_attachments / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $multipage = multipage($unapproved_attachments, $perpage, $page, "modcp.php?action=modqueue&type=attachments"); - - $query = $db->query(" - SELECT a.*, p.subject AS postsubject, p.dateline, p.uid, u.username, t.tid, t.subject AS threadsubject - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE a.visible='0'{$tflist_queue_attach} - ORDER BY a.dateuploaded DESC - LIMIT {$start}, {$perpage} - "); - $attachments = ''; - while($attachment = $db->fetch_array($query)) - { - $altbg = alt_trow(); - - if(!$attachment['dateuploaded']) - { - $attachment['dateuploaded'] = $attachment['dateline']; - } - - $attachdate = my_date('relative', $attachment['dateuploaded']); - - $attachment['postsubject'] = htmlspecialchars_uni($parser->parse_badwords($attachment['postsubject'])); - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - $attachment['threadsubject'] = htmlspecialchars_uni($parser->parse_badwords($attachment['threadsubject'])); - $attachment['filesize'] = get_friendly_size($attachment['filesize']); - - $link = get_post_link($attachment['pid'], $attachment['tid']) . "#pid{$attachment['pid']}"; - $thread_link = get_thread_link($attachment['tid']); - $attachment['username'] = htmlspecialchars_uni($attachment['username']); - $profile_link = build_profile_link($attachment['username'], $attachment['uid']); - - eval("\$attachments .= \"".$templates->get("modcp_modqueue_attachments_attachment")."\";"); - } - - if(!$attachments && $mybb->input['type'] == "attachments") - { - eval("\$attachments = \"".$templates->get("modcp_modqueue_attachments_empty")."\";"); - } - - if($attachments) - { - add_breadcrumb($lang->mcp_nav_modqueue_attachments, "modcp.php?action=modqueue&type=attachments"); - - $plugins->run_hooks("modcp_modqueue_attachments_end"); - - if($nummodqueuethreads > 0 || $mybb->usergroup['issupermod'] == 1) - { - eval("\$thread_link = \"".$templates->get("modcp_modqueue_thread_link")."\";"); - $navsep = " | "; - } - - if($nummodqueueposts > 0 || $mybb->usergroup['issupermod'] == 1) - { - eval("\$post_link = \"".$templates->get("modcp_modqueue_post_link")."\";"); - $navsep = " | "; - } - - eval("\$mass_controls = \"".$templates->get("modcp_modqueue_masscontrols")."\";"); - eval("\$attachmentqueue = \"".$templates->get("modcp_modqueue_attachments")."\";"); - output_page($attachmentqueue); - } - } - - // Still nothing? All queues are empty! :-D - if(!$threadqueue && !$postqueue && !$attachmentqueue) - { - add_breadcrumb($lang->mcp_nav_modqueue, "modcp.php?action=modqueue"); - - $plugins->run_hooks("modcp_modqueue_end"); - - eval("\$queue = \"".$templates->get("modcp_modqueue_empty")."\";"); - output_page($queue); - } -} - -if($mybb->input['action'] == "do_editprofile") -{ - // Verify incoming POST request - verify_post_check($mybb->input['my_post_key']); - - if($mybb->usergroup['caneditprofiles'] == 0) - { - error_no_permission(); - } - - $user = get_user($mybb->input['uid']); - if(!$user) - { - error($lang->error_nomember); - } - - // Check if the current user has permission to edit this user - if(!modcp_can_manage_user($user['uid'])) - { - error_no_permission(); - } - - $plugins->run_hooks("modcp_do_editprofile_start"); - - if($mybb->get_input('away', MyBB::INPUT_INT) == 1 && $mybb->settings['allowaway'] != 0) - { - $awaydate = TIME_NOW; - if(!empty($mybb->input['awayday'])) - { - // If the user has indicated that they will return on a specific day, but not month or year, assume it is current month and year - if(!$mybb->get_input('awaymonth', MyBB::INPUT_INT)) - { - $mybb->input['awaymonth'] = my_date('n', $awaydate); - } - if(!$mybb->get_input('awayyear', MyBB::INPUT_INT)) - { - $mybb->input['awayyear'] = my_date('Y', $awaydate); - } - - $return_month = (int)substr($mybb->get_input('awaymonth'), 0, 2); - $return_day = (int)substr($mybb->get_input('awayday'), 0, 2); - $return_year = min((int)$mybb->get_input('awayyear'), 9999); - - // Check if return date is after the away date. - $returntimestamp = gmmktime(0, 0, 0, $return_month, $return_day, $return_year); - $awaytimestamp = gmmktime(0, 0, 0, my_date('n', $awaydate), my_date('j', $awaydate), my_date('Y', $awaydate)); - if($return_year < my_date('Y', $awaydate) || ($returntimestamp < $awaytimestamp && $return_year == my_date('Y', $awaydate))) - { - error($lang->error_modcp_return_date_past); - } - - $returndate = "{$return_day}-{$return_month}-{$return_year}"; - } - else - { - $returndate = ""; - } - $away = array( - "away" => 1, - "date" => $awaydate, - "returndate" => $returndate, - "awayreason" => $mybb->get_input('awayreason') - ); - } - else - { - $away = array( - "away" => 0, - "date" => '', - "returndate" => '', - "awayreason" => '' - ); - } - - // Set up user handler. - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler('update'); - - // Set the data for the new user. - $updated_user = array( - "uid" => $user['uid'], - "profile_fields" => $mybb->get_input('profile_fields', MyBB::INPUT_ARRAY), - "profile_fields_editable" => true, - "website" => $mybb->get_input('website'), - "icq" => $mybb->get_input('icq'), - "aim" => $mybb->get_input('aim'), - "yahoo" => $mybb->get_input('yahoo'), - "skype" => $mybb->get_input('skype'), - "google" => $mybb->get_input('google'), - "signature" => $mybb->get_input('signature'), - "usernotes" => $mybb->get_input('usernotes'), - "away" => $away - ); - - $updated_user['birthday'] = array( - "day" => $mybb->get_input('birthday_day', MyBB::INPUT_INT), - "month" => $mybb->get_input('birthday_month', MyBB::INPUT_INT), - "year" => $mybb->get_input('birthday_year', MyBB::INPUT_INT) - ); - - if(!empty($mybb->input['usertitle'])) - { - $updated_user['usertitle'] = $mybb->get_input('usertitle'); - } - else if(!empty($mybb->input['reverttitle'])) - { - $updated_user['usertitle'] = ''; - } - - if(!empty($mybb->input['remove_avatar'])) - { - $updated_user['avatarurl'] = ''; - } - - // Set the data of the user in the datahandler. - $userhandler->set_data($updated_user); - $errors = ''; - - // Validate the user and get any errors that might have occurred. - if(!$userhandler->validate_user()) - { - $errors = $userhandler->get_friendly_errors(); - $mybb->input['action'] = "editprofile"; - } - else - { - // Are we removing an avatar from this user? - if(!empty($mybb->input['remove_avatar'])) - { - $extra_user_updates = array( - "avatar" => "", - "avatardimensions" => "", - "avatartype" => "" - ); - remove_avatars($user['uid']); - } - - // Moderator "Options" (suspend signature, suspend/moderate posting) - $moderator_options = array( - 1 => array( - "action" => "suspendsignature", // The moderator action we're performing - "period" => "action_period", // The time period we've selected from the dropdown box - "time" => "action_time", // The time we've entered - "update_field" => "suspendsignature", // The field in the database to update if true - "update_length" => "suspendsigtime" // The length of suspension field in the database - ), - 2 => array( - "action" => "moderateposting", - "period" => "modpost_period", - "time" => "modpost_time", - "update_field" => "moderateposts", - "update_length" => "moderationtime" - ), - 3 => array( - "action" => "suspendposting", - "period" => "suspost_period", - "time" => "suspost_time", - "update_field" => "suspendposting", - "update_length" => "suspensiontime" - ) - ); - - require_once MYBB_ROOT."inc/functions_warnings.php"; - foreach($moderator_options as $option) - { - $mybb->input[$option['time']] = $mybb->get_input($option['time'], MyBB::INPUT_INT); - $mybb->input[$option['period']] = $mybb->get_input($option['period']); - if(empty($mybb->input[$option['action']])) - { - if($user[$option['update_field']] == 1) - { - // We're revoking the suspension - $extra_user_updates[$option['update_field']] = 0; - $extra_user_updates[$option['update_length']] = 0; - } - - // Skip this option if we haven't selected it - continue; - } - - else - { - if($mybb->input[$option['time']] == 0 && $mybb->input[$option['period']] != "never" && $user[$option['update_field']] != 1) - { - // User has selected a type of ban, but not entered a valid time frame - $string = $option['action']."_error"; - $errors[] = $lang->$string; - } - - if(!is_array($errors)) - { - $suspend_length = fetch_time_length((int)$mybb->input[$option['time']], $mybb->input[$option['period']]); - - if($user[$option['update_field']] == 1 && ($mybb->input[$option['time']] || $mybb->input[$option['period']] == "never")) - { - // We already have a suspension, but entered a new time - if($suspend_length == "-1") - { - // Permanent ban on action - $extra_user_updates[$option['update_length']] = 0; - } - elseif($suspend_length && $suspend_length != "-1") - { - // Temporary ban on action - $extra_user_updates[$option['update_length']] = TIME_NOW + $suspend_length; - } - } - elseif(!$user[$option['update_field']]) - { - // New suspension for this user... bad user! - $extra_user_updates[$option['update_field']] = 1; - if($suspend_length == "-1") - { - $extra_user_updates[$option['update_length']] = 0; - } - else - { - $extra_user_updates[$option['update_length']] = TIME_NOW + $suspend_length; - } - } - } - } - } - - // Those with javascript turned off will be able to select both - cheeky! - // Check to make sure we're not moderating AND suspending posting - if(isset($extra_user_updates) && $extra_user_updates['moderateposts'] && $extra_user_updates['suspendposting']) - { - $errors[] = $lang->suspendmoderate_error; - } - - if(is_array($errors)) - { - $mybb->input['action'] = "editprofile"; - } - else - { - $plugins->run_hooks("modcp_do_editprofile_update"); - - // Continue with the update if there is no errors - $user_info = $userhandler->update_user(); - if(!empty($extra_user_updates)) - { - $db->update_query("users", $extra_user_updates, "uid='{$user['uid']}'"); - } - log_moderator_action(array("uid" => $user['uid'], "username" => $user['username']), $lang->edited_user); - - $plugins->run_hooks("modcp_do_editprofile_end"); - - redirect("modcp.php?action=finduser", $lang->redirect_user_updated); - } - } -} - -if($mybb->input['action'] == "editprofile") -{ - if($mybb->usergroup['caneditprofiles'] == 0) - { - error_no_permission(); - } - - add_breadcrumb($lang->mcp_nav_editprofile, "modcp.php?action=editprofile"); - - $user = get_user($mybb->get_input('uid', MyBB::INPUT_INT)); - if(!$user) - { - error($lang->error_nomember); - } - - // Check if the current user has permission to edit this user - if(!modcp_can_manage_user($user['uid'])) - { - error_no_permission(); - } - - if(!my_validate_url($user['website'])) - { - $user['website'] = ''; - } - - if($user['icq'] != "0") - { - $user['icq'] = (int)$user['icq']; - } - - if(!$errors) - { - $mybb->input = array_merge($user, $mybb->input); - $birthday = explode('-', $user['birthday']); - if(!isset($birthday[1])) - { - $birthday[1] = ''; - } - if(!isset($birthday[2])) - { - $birthday[2] = ''; - } - list($mybb->input['birthday_day'], $mybb->input['birthday_month'], $mybb->input['birthday_year']) = $birthday; - } - else - { - $errors = inline_error($errors); - } - - // Sanitize all input - foreach(array('usertitle', 'website', 'icq', 'aim', 'yahoo', 'skype', 'google', 'signature', 'birthday_day', 'birthday_month', 'birthday_year') as $field) - { - $mybb->input[$field] = htmlspecialchars_uni($mybb->get_input($field)); - } - - // Custom user title, check to see if we have a default group title - if(!$user['displaygroup']) - { - $user['displaygroup'] = $user['usergroup']; - } - - $displaygroupfields = array('usertitle'); - $display_group = usergroup_displaygroup($user['displaygroup']); - - if(!empty($display_group['usertitle'])) - { - $defaulttitle = htmlspecialchars_uni($display_group['usertitle']); - } - else - { - // Go for post count title if a group default isn't set - $usertitles = $cache->read('usertitles'); - - foreach($usertitles as $title) - { - if($title['posts'] <= $user['postnum']) - { - $defaulttitle = $title['title']; - break; - } - } - } - - $user['usertitle'] = htmlspecialchars_uni($user['usertitle']); - - if(empty($user['usertitle'])) - { - $lang->current_custom_usertitle = ''; - } - - $bdaydaysel = $selected = ''; - for($day = 1; $day <= 31; ++$day) - { - if($mybb->input['birthday_day'] == $day) - { - $selected = "selected=\"selected\""; - } - else - { - $selected = ''; - } - - eval("\$bdaydaysel .= \"".$templates->get("usercp_profile_day")."\";"); - } - - $bdaymonthsel = array(); - foreach(range(1, 12) as $month) - { - $bdaymonthsel[$month] = ''; - } - $bdaymonthsel[$mybb->input['birthday_month']] = 'selected="selected"'; - - if($mybb->settings['allowaway'] != 0) - { - $awaycheck = array('', ''); - if($errors) - { - if($user['away'] == 1) - { - $awaycheck[1] = "checked=\"checked\""; - } - else - { - $awaycheck[0] = "checked=\"checked\""; - } - $returndate = array(); - $returndate[0] = $mybb->get_input('awayday'); - $returndate[1] = $mybb->get_input('awaymonth'); - $returndate[2] = $mybb->get_input('awayyear', MyBB::INPUT_INT); - $user['awayreason'] = htmlspecialchars_uni($mybb->get_input('awayreason')); - } - else - { - $user['awayreason'] = htmlspecialchars_uni($user['awayreason']); - if($user['away'] == 1) - { - $awaydate = my_date($mybb->settings['dateformat'], $user['awaydate']); - $awaycheck[1] = "checked=\"checked\""; - $awaynotice = $lang->sprintf($lang->away_notice_away, $awaydate); - } - else - { - $awaynotice = $lang->away_notice; - $awaycheck[0] = "checked=\"checked\""; - } - $returndate = explode("-", $user['returndate']); - } - $returndatesel = $selected = ''; - for($day = 1; $day <= 31; ++$day) - { - if($returndate[0] == $day) - { - $selected = "selected=\"selected\""; - } - else - { - $selected = ''; - } - - eval("\$returndatesel .= \"".$templates->get("usercp_profile_day")."\";"); - } - - $returndatemonthsel = array(); - foreach(range(1, 12) as $month) - { - $returndatemonthsel[$month] = ''; - } - if(isset($returndate[1])) - { - $returndatemonthsel[$returndate[1]] = " selected=\"selected\""; - } - - if(!isset($returndate[2])) - { - $returndate[2] = ''; - } - - eval("\$awaysection = \"".$templates->get("usercp_profile_away")."\";"); - } - - $plugins->run_hooks("modcp_editprofile_start"); - - // Fetch profile fields - $query = $db->simple_select("userfields", "*", "ufid='{$user['uid']}'"); - $user_fields = $db->fetch_array($query); - - $requiredfields = ''; - $customfields = ''; - $mybb->input['profile_fields'] = $mybb->get_input('profile_fields', MyBB::INPUT_ARRAY); - - $pfcache = $cache->read('profilefields'); - - if(is_array($pfcache)) - { - foreach($pfcache as $profilefield) - { - $userfield = $code = $select = $val = $options = $expoptions = $useropts = ''; - $seloptions = array(); - $profilefield['type'] = htmlspecialchars_uni($profilefield['type']); - $profilefield['name'] = htmlspecialchars_uni($profilefield['name']); - $profilefield['description'] = htmlspecialchars_uni($profilefield['description']); - $thing = explode("\n", $profilefield['type'], "2"); - $type = $thing[0]; - if(isset($thing[1])) - { - $options = $thing[1]; - } - $field = "fid{$profilefield['fid']}"; - if($errors) - { - if(isset($mybb->input['profile_fields'][$field])) - { - $userfield = $mybb->input['profile_fields'][$field]; - } - } - else - { - $userfield = $user_fields[$field]; - } - if($type == "multiselect") - { - if($errors) - { - $useropts = $userfield; - } - else - { - $useropts = explode("\n", $userfield); - } - if(is_array($useropts)) - { - foreach($useropts as $key => $val) - { - $seloptions[$val] = $val; - } - } - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $val = trim($val); - $val = str_replace("\n", "\\n", $val); - - $sel = ""; - if(isset($seloptions[$val]) && $val == $seloptions[$val]) - { - $sel = " selected=\"selected\""; - } - - eval("\$select .= \"".$templates->get("usercp_profile_profilefields_select_option")."\";"); - } - if(!$profilefield['length']) - { - $profilefield['length'] = 3; - } - - eval("\$code = \"".$templates->get("usercp_profile_profilefields_multiselect")."\";"); - } - } - elseif($type == "select") - { - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $val = trim($val); - $val = str_replace("\n", "\\n", $val); - $sel = ""; - if($val == $userfield) - { - $sel = " selected=\"selected\""; - } - - eval("\$select .= \"".$templates->get("usercp_profile_profilefields_select_option")."\";"); - } - if(!$profilefield['length']) - { - $profilefield['length'] = 1; - } - - eval("\$code = \"".$templates->get("usercp_profile_profilefields_select")."\";"); - } - } - elseif($type == "radio") - { - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $checked = ""; - if($val == $userfield) - { - $checked = " checked=\"checked\""; - } - - eval("\$code .= \"".$templates->get("usercp_profile_profilefields_radio")."\";"); - } - } - } - elseif($type == "checkbox") - { - if($errors) - { - $useropts = $userfield; - } - else - { - $useropts = explode("\n", $userfield); - } - if(is_array($useropts)) - { - foreach($useropts as $key => $val) - { - $seloptions[$val] = $val; - } - } - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $checked = ""; - if(isset($seloptions[$val]) && $val == $seloptions[$val]) - { - $checked = " checked=\"checked\""; - } - - eval("\$code .= \"".$templates->get("usercp_profile_profilefields_checkbox")."\";"); - } - } - } - elseif($type == "textarea") - { - $value = htmlspecialchars_uni($userfield); - eval("\$code = \"".$templates->get("usercp_profile_profilefields_textarea")."\";"); - } - else - { - $value = htmlspecialchars_uni($userfield); - $maxlength = ""; - if($profilefield['maxlength'] > 0) - { - $maxlength = " maxlength=\"{$profilefield['maxlength']}\""; - } - - eval("\$code = \"".$templates->get("usercp_profile_profilefields_text")."\";"); - } - - if($profilefield['required'] == 1) - { - eval("\$requiredfields .= \"".$templates->get("usercp_profile_customfield")."\";"); - } - else - { - eval("\$customfields .= \"".$templates->get("usercp_profile_customfield")."\";"); - } - $altbg = alt_trow(); - } - } - if($customfields) - { - eval("\$customfields = \"".$templates->get("usercp_profile_profilefields")."\";"); - } - - $user['username'] = htmlspecialchars_uni($user['username']); - $lang->edit_profile = $lang->sprintf($lang->edit_profile, $user['username']); - $profile_link = build_profile_link(format_name($user['username'], $user['usergroup'], $user['displaygroup']), $user['uid']); - - $user['signature'] = htmlspecialchars_uni($user['signature']); - $codebuttons = build_mycode_inserter("signature"); - - // Do we mark the suspend signature box? - if($user['suspendsignature'] || ($mybb->get_input('suspendsignature', MyBB::INPUT_INT) && !empty($errors))) - { - $checked = 1; - $checked_item = "checked=\"checked\""; - } - else - { - $checked = 0; - $checked_item = ''; - } - - // Do we mark the moderate posts box? - if($user['moderateposts'] || ($mybb->get_input('moderateposting', MyBB::INPUT_INT) && !empty($errors))) - { - $modpost_check = 1; - $modpost_checked = "checked=\"checked\""; - } - else - { - $modpost_check = 0; - $modpost_checked = ''; - } - - // Do we mark the suspend posts box? - if($user['suspendposting'] || ($mybb->get_input('suspendposting', MyBB::INPUT_INT) && !empty($errors))) - { - $suspost_check = 1; - $suspost_checked = "checked=\"checked\""; - } - else - { - $suspost_check = 0; - $suspost_checked = ''; - } - - $moderator_options = array( - 1 => array( - "action" => "suspendsignature", // The input action for this option - "option" => "suspendsignature", // The field in the database that this option relates to - "time" => "action_time", // The time we've entered - "length" => "suspendsigtime", // The length of suspension field in the database - "select_option" => "action" // The name of the select box of this option - ), - 2 => array( - "action" => "moderateposting", - "option" => "moderateposts", - "time" => "modpost_time", - "length" => "moderationtime", - "select_option" => "modpost" - ), - 3 => array( - "action" => "suspendposting", - "option" => "suspendposting", - "time" => "suspost_time", - "length" => "suspensiontime", - "select_option" => "suspost" - ) - ); - - $periods = array( - "hours" => $lang->expire_hours, - "days" => $lang->expire_days, - "weeks" => $lang->expire_weeks, - "months" => $lang->expire_months, - "never" => $lang->expire_permanent - ); - - $suspendsignature_info = $moderateposts_info = $suspendposting_info = ''; - $action_options = $modpost_options = $suspost_options = ''; - foreach($moderator_options as $option) - { - $mybb->input[$option['time']] = $mybb->get_input($option['time'], MyBB::INPUT_INT); - // Display the suspension info, if this user has this option suspended - if($user[$option['option']]) - { - if($user[$option['length']] == 0) - { - // User has a permanent ban - $string = $option['option']."_perm"; - $suspension_info = $lang->$string; - } - else - { - // User has a temporary (or limited) ban - $string = $option['option']."_for"; - $for_date = my_date('relative', $user[$option['length']], '', 2); - $suspension_info = $lang->sprintf($lang->$string, $for_date); - } - - switch($option['option']) - { - case "suspendsignature": - eval("\$suspendsignature_info = \"".$templates->get("modcp_editprofile_suspensions_info")."\";"); - break; - case "moderateposts": - eval("\$moderateposts_info = \"".$templates->get("modcp_editprofile_suspensions_info")."\";"); - break; - case "suspendposting": - eval("\$suspendposting_info = \"".$templates->get("modcp_editprofile_suspensions_info")."\";"); - break; - } - } - - // Generate the boxes for this option - $selection_options = ''; - foreach($periods as $key => $value) - { - $string = $option['select_option']."_period"; - if($mybb->get_input($string) == $key) - { - $selected = "selected=\"selected\""; - } - else - { - $selected = ''; - } - - eval("\$selection_options .= \"".$templates->get("modcp_editprofile_select_option")."\";"); - } - - $select_name = $option['select_option']."_period"; - switch($option['option']) - { - case "suspendsignature": - eval("\$action_options = \"".$templates->get("modcp_editprofile_select")."\";"); - break; - case "moderateposts": - eval("\$modpost_options = \"".$templates->get("modcp_editprofile_select")."\";"); - break; - case "suspendposting": - eval("\$suspost_options = \"".$templates->get("modcp_editprofile_select")."\";"); - break; - } - } - - eval("\$suspend_signature = \"".$templates->get("modcp_editprofile_signature")."\";"); - - if(!isset($newtitle)) - { - $newtitle = ''; - } - - $plugins->run_hooks("modcp_editprofile_end"); - - eval("\$edituser = \"".$templates->get("modcp_editprofile")."\";"); - output_page($edituser); -} - -if($mybb->input['action'] == "finduser") -{ - if($mybb->usergroup['caneditprofiles'] == 0) - { - error_no_permission(); - } - - add_breadcrumb($lang->mcp_nav_users, "modcp.php?action=finduser"); - - $perpage = $mybb->get_input('perpage', MyBB::INPUT_INT); - if(!$perpage || $perpage <= 0) - { - $perpage = $mybb->settings['threadsperpage']; - } - $where = ''; - - if(isset($mybb->input['username'])) - { - switch($db->type) - { - case 'mysql': - case 'mysqli': - $field = 'username'; - break; - default: - $field = 'LOWER(username)'; - break; - } - $where = " AND {$field} LIKE '%".my_strtolower($db->escape_string_like($mybb->get_input('username')))."%'"; - } - - // Sort order & direction - switch($mybb->get_input('sortby')) - { - case "lastvisit": - $sortby = "lastvisit"; - break; - case "postnum": - $sortby = "postnum"; - break; - case "username": - $sortby = "username"; - break; - default: - $sortby = "regdate"; - } - $sortbysel = array('lastvisit' => '', 'postnum' => '', 'username' => '', 'regdate' => ''); - $sortbysel[$mybb->get_input('sortby')] = " selected=\"selected\""; - $order = $mybb->get_input('order'); - if($order != "asc") - { - $order = "desc"; - } - $ordersel = array('asc' => '', 'desc' => ''); - $ordersel[$order] = " selected=\"selected\""; - - $query = $db->simple_select("users", "COUNT(uid) AS count", "1=1 {$where}"); - $user_count = $db->fetch_field($query, "count"); - - // Figure out if we need to display multiple pages. - if($mybb->get_input('page') != "last") - { - $page = $mybb->get_input('page'); - } - - $pages = $user_count / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $page_url = 'modcp.php?action=finduser'; - foreach(array('username', 'sortby', 'order') as $field) - { - if(!empty($mybb->input[$field])) - { - $page_url .= "&{$field}=".$mybb->input[$field]; - } - } - - $multipage = multipage($user_count, $perpage, $page, $page_url); - - $usergroups_cache = $cache->read("usergroups"); - - $plugins->run_hooks("modcp_finduser_start"); - - // Fetch out results - $query = $db->simple_select("users", "*", "1=1 {$where}", array("order_by" => $sortby, "order_dir" => $order, "limit" => $perpage, "limit_start" => $start)); - $users = ''; - while($user = $db->fetch_array($query)) - { - $alt_row = alt_trow(); - $user['username'] = htmlspecialchars_uni($user['username']); - $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']); - $user['postnum'] = my_number_format($user['postnum']); - $regdate = my_date('relative', $user['regdate']); - - if($user['invisible'] == 1 && $mybb->usergroup['canviewwolinvis'] != 1 && $user['uid'] != $mybb->user['uid']) - { - $lastdate = $lang->lastvisit_never; - - if($user['lastvisit']) - { - // We have had at least some active time, hide it instead - $lastdate = $lang->lastvisit_hidden; - } - } - else - { - $lastdate = my_date('relative', $user['lastvisit']); - } - - $usergroup = htmlspecialchars_uni($usergroups_cache[$user['usergroup']]['title']); - eval("\$users .= \"".$templates->get("modcp_finduser_user")."\";"); - } - - // No results? - if(!$users) - { - eval("\$users = \"".$templates->get("modcp_finduser_noresults")."\";"); - } - - $plugins->run_hooks("modcp_finduser_end"); - - eval("\$finduser = \"".$templates->get("modcp_finduser")."\";"); - output_page($finduser); -} - -if($mybb->input['action'] == "warninglogs") -{ - if($mybb->usergroup['canviewwarnlogs'] == 0) - { - error_no_permission(); - } - - add_breadcrumb($lang->mcp_nav_warninglogs, "modcp.php?action=warninglogs"); - - // Filter options - $where_sql = ''; - $mybb->input['filter'] = $mybb->get_input('filter', MyBB::INPUT_ARRAY); - $mybb->input['search'] = $mybb->get_input('search', MyBB::INPUT_ARRAY); - if(!empty($mybb->input['filter']['username'])) - { - $search_user = get_user_by_username($mybb->input['filter']['username']); - - $mybb->input['filter']['uid'] = (int)$search_user['uid']; - $mybb->input['filter']['username'] = htmlspecialchars_uni($mybb->input['filter']['username']); - } - else - { - $mybb->input['filter']['username'] = ''; - } - if(!empty($mybb->input['filter']['uid'])) - { - $search['uid'] = (int)$mybb->input['filter']['uid']; - $where_sql .= " AND w.uid='{$search['uid']}'"; - if(!isset($mybb->input['search']['username'])) - { - $user = get_user($mybb->input['search']['uid']); - $mybb->input['search']['username'] = htmlspecialchars_uni($user['username']); - } - } - else - { - $mybb->input['filter']['uid'] = ''; - } - if(!empty($mybb->input['filter']['mod_username'])) - { - $mod_user = get_user_by_username($mybb->input['filter']['mod_username']); - - $mybb->input['filter']['mod_uid'] = (int)$mod_user['uid']; - $mybb->input['filter']['mod_username'] = htmlspecialchars_uni($mybb->input['filter']['mod_username']); - } - else - { - $mybb->input['filter']['mod_username'] = ''; - } - if(!empty($mybb->input['filter']['mod_uid'])) - { - $search['mod_uid'] = (int)$mybb->input['filter']['mod_uid']; - $where_sql .= " AND w.issuedby='{$search['mod_uid']}'"; - if(!isset($mybb->input['search']['mod_username'])) - { - $mod_user = get_user($mybb->input['search']['uid']); - $mybb->input['search']['mod_username'] = htmlspecialchars_uni($mod_user['username']); - } - } - else - { - $mybb->input['filter']['mod_uid'] = ''; - } - if(!empty($mybb->input['filter']['reason'])) - { - $search['reason'] = $db->escape_string_like($mybb->input['filter']['reason']); - $where_sql .= " AND (w.notes LIKE '%{$search['reason']}%' OR t.title LIKE '%{$search['reason']}%' OR w.title LIKE '%{$search['reason']}%')"; - $mybb->input['filter']['reason'] = htmlspecialchars_uni($mybb->input['filter']['reason']); - } - else - { - $mybb->input['filter']['reason'] = ''; - } - $sortbysel = array('username' => '', 'expires' => '', 'issuedby' => '', 'dateline' => ''); - if(!isset($mybb->input['filter']['sortby'])) - { - $mybb->input['filter']['sortby'] = ''; - } - switch($mybb->input['filter']['sortby']) - { - case "username": - $sortby = "u.username"; - $sortbysel['username'] = ' selected="selected"'; - break; - case "expires": - $sortby = "w.expires"; - $sortbysel['expires'] = ' selected="selected"'; - break; - case "issuedby": - $sortby = "i.username"; - $sortbysel['issuedby'] = ' selected="selected"'; - break; - default: // "dateline" - $sortby = "w.dateline"; - $sortbysel['dateline'] = ' selected="selected"'; - } - if(!isset($mybb->input['filter']['order'])) - { - $mybb->input['filter']['order'] = ''; - } - $order = $mybb->input['filter']['order']; - $ordersel = array('asc' => '', 'desc' => ''); - if($order != "asc") - { - $order = "desc"; - $ordersel['desc'] = ' selected="selected"'; - } - else - { - $ordersel['asc'] = ' selected="selected"'; - } - - $plugins->run_hooks("modcp_warninglogs_start"); - - // Pagination stuff - $sql = " - SELECT COUNT(wid) as count - FROM - ".TABLE_PREFIX."warnings w - LEFT JOIN ".TABLE_PREFIX."warningtypes t ON (w.tid=t.tid) - WHERE 1=1 - {$where_sql} - "; - $query = $db->query($sql); - $total_warnings = $db->fetch_field($query, 'count'); - $page = $mybb->get_input('page', MyBB::INPUT_INT); - if($page <= 0) - { - $page = 1; - } - $per_page = 20; - if(isset($mybb->input['filter']['per_page']) && (int)$mybb->input['filter']['per_page'] > 0) - { - $per_page = (int)$mybb->input['filter']['per_page']; - } - $start = ($page-1) * $per_page; - // Build the base URL for pagination links - $url = 'modcp.php?action=warninglogs'; - if(is_array($mybb->input['filter']) && count($mybb->input['filter'])) - { - foreach($mybb->input['filter'] as $field => $value) - { - $value = urlencode($value); - $url .= "&filter[{$field}]={$value}"; - } - } - $multipage = multipage($total_warnings, $per_page, $page, $url); - - // The actual query - $sql = " - SELECT - w.wid, w.title as custom_title, w.points, w.dateline, w.issuedby, w.expires, w.expired, w.daterevoked, w.revokedby, - t.title, - u.uid, u.username, u.usergroup, u.displaygroup, - i.uid as mod_uid, i.username as mod_username, i.usergroup as mod_usergroup, i.displaygroup as mod_displaygroup - FROM ".TABLE_PREFIX."warnings w - LEFT JOIN ".TABLE_PREFIX."users u ON (w.uid=u.uid) - LEFT JOIN ".TABLE_PREFIX."warningtypes t ON (w.tid=t.tid) - LEFT JOIN ".TABLE_PREFIX."users i ON (i.uid=w.issuedby) - WHERE 1=1 - {$where_sql} - ORDER BY {$sortby} {$order} - LIMIT {$start}, {$per_page} - "; - $query = $db->query($sql); - - - $warning_list = ''; - while($row = $db->fetch_array($query)) - { - $trow = alt_trow(); - $row['username'] = htmlspecialchars_uni($row['username']); - $username = format_name($row['username'], $row['usergroup'], $row['displaygroup']); - $username_link = build_profile_link($username, $row['uid']); - $row['mod_username'] = htmlspecialchars_uni($row['mod_username']); - $mod_username = format_name($row['mod_username'], $row['mod_usergroup'], $row['mod_displaygroup']); - $mod_username_link = build_profile_link($mod_username, $row['mod_uid']); - $issued_date = my_date($mybb->settings['dateformat'], $row['dateline']).' '.my_date($mybb->settings['timeformat'], $row['dateline']); - $revoked_text = ''; - if($row['daterevoked'] > 0) - { - $revoked_date = my_date('relative', $row['daterevoked']); - eval("\$revoked_text = \"".$templates->get("modcp_warninglogs_warning_revoked")."\";"); - } - if($row['expires'] > 0) - { - $expire_date = my_date('relative', $row['expires'], '', 2); - } - else - { - $expire_date = $lang->never; - } - $title = $row['title']; - if(empty($row['title'])) - { - $title = $row['custom_title']; - } - $title = htmlspecialchars_uni($title); - if($row['points'] >= 0) - { - $points = '+'.$row['points']; - } - - eval("\$warning_list .= \"".$templates->get("modcp_warninglogs_warning")."\";"); - } - - if(!$warning_list) - { - eval("\$warning_list = \"".$templates->get("modcp_warninglogs_nologs")."\";"); - } - - $plugins->run_hooks("modcp_warninglogs_end"); - - eval("\$warninglogs = \"".$templates->get("modcp_warninglogs")."\";"); - output_page($warninglogs); -} - -if($mybb->input['action'] == "ipsearch") -{ - if($mybb->usergroup['canuseipsearch'] == 0) - { - error_no_permission(); - } - - add_breadcrumb($lang->mcp_nav_ipsearch, "modcp.php?action=ipsearch"); - - $mybb->input['ipaddress'] = $mybb->get_input('ipaddress'); - if($mybb->input['ipaddress']) - { - if(!is_array($groupscache)) - { - $groupscache = $cache->read("usergroups"); - } - - $ipaddressvalue = htmlspecialchars_uni($mybb->input['ipaddress']); - - $ip_range = fetch_ip_range($mybb->input['ipaddress']); - - $post_results = $user_results = 0; - - // Searching post IP addresses - if(isset($mybb->input['search_posts'])) - { - if($ip_range) - { - if(!is_array($ip_range)) - { - $post_ip_sql = "p.ipaddress=".$db->escape_binary($ip_range); - } - else - { - $post_ip_sql = "p.ipaddress BETWEEN ".$db->escape_binary($ip_range[0])." AND ".$db->escape_binary($ip_range[1]); - } - } - - $plugins->run_hooks("modcp_ipsearch_posts_start"); - - if($post_ip_sql) - { - $where_sql = ''; - - $unviewable_forums = get_unviewable_forums(true); - - if($unviewable_forums) - { - $where_sql .= " AND p.fid NOT IN ({$unviewable_forums})"; - } - - if($inactiveforums) - { - $where_sql .= " AND p.fid NOT IN ({$inactiveforums})"; - } - - // Check group permissions if we can't view threads not started by us - $onlyusfids = array(); - $group_permissions = forum_permissions(); - foreach($group_permissions as $fid => $forumpermissions) - { - if(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $fid; - } - } - - if(!empty($onlyusfids)) - { - $where_sql .= " AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; - } - - // Moderators can view unapproved/deleted posts - if($mybb->usergroup['issupermod'] != 1) - { - $unapprove_forums = array(); - $deleted_forums = array(); - $visible_sql = " AND (p.visible = 1 AND t.visible = 1)"; - $query = $db->simple_select("moderators", "fid, canviewunapprove, canviewdeleted", "(id='{$mybb->user['uid']}' AND isgroup='0') OR (id='{$mybb->user['usergroup']}' AND isgroup='1')"); - while($moderator = $db->fetch_array($query)) - { - if($moderator['canviewunapprove'] == 1) - { - $unapprove_forums[] = $moderator['fid']; - } - - if($moderator['canviewdeleted'] == 1) - { - $deleted_forums[] = $moderator['fid']; - } - } - - if(!empty($unapprove_forums)) - { - $visible_sql .= " OR (p.visible = 0 AND p.fid IN(".implode(',', $unapprove_forums).")) OR (t.visible = 0 AND t.fid IN(".implode(',', $unapprove_forums)."))"; - } - if(!empty($deleted_forums)) - { - $visible_sql .= " OR (p.visible = -1 AND p.fid IN(".implode(',', $deleted_forums).")) OR (t.visible = -1 AND t.fid IN(".implode(',', $deleted_forums)."))"; - } - } - else - { - // Super moderators (and admins) - $visible_sql = " AND p.visible >= -1"; - } - - $query = $db->query(" - SELECT COUNT(p.pid) AS count - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid = p.tid) - WHERE {$post_ip_sql}{$where_sql}{$visible_sql} - "); - $post_results = $db->fetch_field($query, "count"); - } - } - - // Searching user IP addresses - if(isset($mybb->input['search_users'])) - { - if($ip_range) - { - if(!is_array($ip_range)) - { - $user_ip_sql = "regip=".$db->escape_binary($ip_range)." OR lastip=".$db->escape_binary($ip_range); - } - else - { - $user_ip_sql = "regip BETWEEN ".$db->escape_binary($ip_range[0])." AND ".$db->escape_binary($ip_range[1])." OR lastip BETWEEN ".$db->escape_binary($ip_range[0])." AND ".$db->escape_binary($ip_range[1]); - } - } - - $plugins->run_hooks("modcp_ipsearch_users_start"); - - if($user_ip_sql) - { - $query = $db->simple_select('users', 'COUNT(uid) AS count', $user_ip_sql); - - $user_results = $db->fetch_field($query, "count"); - } - } - - $total_results = $post_results+$user_results; - - if(!$total_results) - { - $total_results = 1; - } - - // Now we have the result counts, paginate - $perpage = $mybb->get_input('perpage', MyBB::INPUT_INT); - if(!$perpage || $perpage <= 0) - { - $perpage = $mybb->settings['threadsperpage']; - } - - // Figure out if we need to display multiple pages. - if($mybb->get_input('page') != "last") - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - } - - $pages = $total_results / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $page_url = "modcp.php?action=ipsearch&perpage={$perpage}"; - foreach(array('ipaddress', 'search_users', 'search_posts') as $input) - { - if(!empty($mybb->input[$input])) - { - $page_url .= "&{$input}=".urlencode($mybb->input[$input]); - } - } - $multipage = multipage($total_results, $perpage, $page, $page_url); - - $post_limit = $perpage; - $results = ''; - if(isset($mybb->input['search_users']) && $user_results && $start <= $user_results) - { - $query = $db->simple_select('users', 'username, uid, regip, lastip', $user_ip_sql, - array('order_by' => 'regdate', 'order_dir' => 'DESC', 'limit_start' => $start, 'limit' => $perpage)); - - while($ipaddress = $db->fetch_array($query)) - { - $result = false; - $ipaddress['username'] = htmlspecialchars_uni($ipaddress['username']); - $profile_link = build_profile_link($ipaddress['username'], $ipaddress['uid']); - $trow = alt_trow(); - $ip = false; - if(is_array($ip_range)) - { - if(strcmp($ip_range[0], $ipaddress['regip']) <= 0 && strcmp($ip_range[1], $ipaddress['regip']) >= 0) - { - eval("\$subject = \"".$templates->get("modcp_ipsearch_result_regip")."\";"); - $ip = my_inet_ntop($db->unescape_binary($ipaddress['regip'])); - } - elseif(strcmp($ip_range[0], $ipaddress['lastip']) <= 0 && strcmp($ip_range[1], $ipaddress['lastip']) >= 0) - { - eval("\$subject = \"".$templates->get("modcp_ipsearch_result_lastip")."\";"); - $ip = my_inet_ntop($db->unescape_binary($ipaddress['lastip'])); - } - } - elseif($ipaddress['regip'] == $ip_range) - { - eval("\$subject = \"".$templates->get("modcp_ipsearch_result_regip")."\";"); - $ip = my_inet_ntop($db->unescape_binary($ipaddress['regip'])); - } - elseif($ipaddress['lastip'] == $ip_range) - { - eval("\$subject = \"".$templates->get("modcp_ipsearch_result_lastip")."\";"); - $ip = my_inet_ntop($db->unescape_binary($ipaddress['lastip'])); - } - if($ip) - { - eval("\$results .= \"".$templates->get("modcp_ipsearch_result")."\";"); - $result = true; - } - if($result) - { - --$post_limit; - } - } - } - $post_start = 0; - if($total_results > $user_results && $post_limit) - { - $post_start = $start-$user_results; - if($post_start < 0) - { - $post_start = 0; - } - } - if(isset($mybb->input['search_posts']) && $post_results && (!isset($mybb->input['search_users']) || (isset($mybb->input['search_users']) && $post_limit > 0))) - { - $ipaddresses = $tids = $uids = array(); - - $query = $db->query(" - SELECT p.username AS postusername, p.uid, p.subject, p.pid, p.tid, p.ipaddress - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid = p.tid) - WHERE {$post_ip_sql}{$where_sql}{$visible_sql} - ORDER BY p.dateline desc - LIMIT {$post_start}, {$post_limit} - "); - while($ipaddress = $db->fetch_array($query)) - { - $tids[$ipaddress['tid']] = $ipaddress['pid']; - $uids[$ipaddress['uid']] = $ipaddress['pid']; - $ipaddresses[$ipaddress['pid']] = $ipaddress; - } - - if(!empty($ipaddresses)) - { - $query = $db->simple_select("threads", "subject, tid", "tid IN(".implode(',', array_keys($tids)).")"); - while($thread = $db->fetch_array($query)) - { - $ipaddresses[$tids[$thread['tid']]]['threadsubject'] = $thread['subject']; - } - unset($tids); - - $query = $db->simple_select("users", "username, uid", "uid IN(".implode(',', array_keys($uids)).")"); - while($user = $db->fetch_array($query)) - { - $ipaddresses[$uids[$user['uid']]]['username'] = $user['username']; - } - unset($uids); - - foreach($ipaddresses as $ipaddress) - { - $ip = my_inet_ntop($db->unescape_binary($ipaddress['ipaddress'])); - if(!$ipaddress['username']) - { - $ipaddress['username'] = $ipaddress['postusername']; // Guest username support - } - $ipaddress['username'] = htmlspecialchars_uni($ipaddress['username']); - $trow = alt_trow(); - if(!$ipaddress['subject']) - { - $ipaddress['subject'] = "RE: {$ipaddress['threadsubject']}"; - } - - $ipaddress['postlink'] = get_post_link($ipaddress['pid'], $ipaddress['tid']); - $ipaddress['subject'] = htmlspecialchars_uni($parser->parse_badwords($ipaddress['subject'])); - $ipaddress['profilelink'] = build_profile_link($ipaddress['username'], $ipaddress['uid']); - - eval("\$subject = \"".$templates->get("modcp_ipsearch_result_post")."\";"); - eval("\$results .= \"".$templates->get("modcp_ipsearch_result")."\";"); - } - } - } - - if(!$results) - { - eval("\$results = \"".$templates->get("modcp_ipsearch_noresults")."\";"); - } - - if($ipaddressvalue) - { - $lang->ipsearch_results = $lang->sprintf($lang->ipsearch_results, $ipaddressvalue); - } - else - { - $lang->ipsearch_results = $lang->ipsearch; - } - - $ipaddress = $ipaddress_url = $misc_info_link = ''; - if(!strstr($mybb->input['ipaddress'], "*") && !strstr($mybb->input['ipaddress'], "/")) - { - $ipaddress = htmlspecialchars_uni($mybb->input['ipaddress']); - $ipaddress_url = urlencode($mybb->input['ipaddress']); - eval("\$misc_info_link = \"".$templates->get("modcp_ipsearch_results_information")."\";"); - } - - eval("\$ipsearch_results = \"".$templates->get("modcp_ipsearch_results")."\";"); - } - - // Fetch filter options - if(!$mybb->input['ipaddress']) - { - $mybb->input['search_posts'] = 1; - $mybb->input['search_users'] = 1; - } - $usersearchselect = $postsearchselect = ''; - if(isset($mybb->input['search_posts'])) - { - $postsearchselect = "checked=\"checked\""; - } - if(isset($mybb->input['search_users'])) - { - $usersearchselect = "checked=\"checked\""; - } - - $plugins->run_hooks("modcp_ipsearch_end"); - - eval("\$ipsearch = \"".$templates->get("modcp_ipsearch")."\";"); - output_page($ipsearch); -} - -if($mybb->input['action'] == "iplookup") -{ - if($mybb->usergroup['canuseipsearch'] == 0) - { - error_no_permission(); - } - - $mybb->input['ipaddress'] = $mybb->get_input('ipaddress'); - $lang->ipaddress_misc_info = $lang->sprintf($lang->ipaddress_misc_info, htmlspecialchars_uni($mybb->input['ipaddress'])); - $ipaddress_location = $lang->na; - $ipaddress_host_name = $lang->na; - $modcp_ipsearch_misc_info = ''; - if(!strstr($mybb->input['ipaddress'], "*")) - { - // Return GeoIP information if it is available to us - if(function_exists('geoip_record_by_name')) - { - $ip_record = @geoip_record_by_name($mybb->input['ipaddress']); - if($ip_record) - { - $ipaddress_location = htmlspecialchars_uni(utf8_encode($ip_record['country_name'])); - if($ip_record['city']) - { - $ipaddress_location .= $lang->comma.htmlspecialchars_uni(utf8_encode($ip_record['city'])); - } - } - } - - $ipaddress_host_name = htmlspecialchars_uni(@gethostbyaddr($mybb->input['ipaddress'])); - - // gethostbyaddr returns the same ip on failure - if($ipaddress_host_name == $mybb->input['ipaddress']) - { - $ipaddress_host_name = $lang->na; - } - } - - $plugins->run_hooks("modcp_iplookup_end"); - - eval("\$iplookup = \"".$templates->get('modcp_ipsearch_misc_info', 1, 0)."\";"); - echo($iplookup); - exit; -} - -if($mybb->input['action'] == "banning") -{ - if($mybb->usergroup['canbanusers'] == 0) - { - error_no_permission(); - } - - add_breadcrumb($lang->mcp_nav_banning, "modcp.php?action=banning"); - - if(!$mybb->settings['threadsperpage']) - { - $mybb->settings['threadsperpage'] = 20; - } - - // Figure out if we need to display multiple pages. - $perpage = $mybb->settings['threadsperpage']; - if($mybb->get_input('page') != "last") - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - } - - $query = $db->simple_select("banned", "COUNT(uid) AS count"); - $banned_count = $db->fetch_field($query, "count"); - - $postcount = (int)$banned_count; - $pages = $postcount / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - $upper = $start+$perpage; - - $multipage = multipage($postcount, $perpage, $page, "modcp.php?action=banning"); - - $plugins->run_hooks("modcp_banning_start"); - - $query = $db->query(" - SELECT b.*, a.username AS adminuser, u.username - FROM ".TABLE_PREFIX."banned b - LEFT JOIN ".TABLE_PREFIX."users u ON (b.uid=u.uid) - LEFT JOIN ".TABLE_PREFIX."users a ON (b.admin=a.uid) - ORDER BY dateline DESC - LIMIT {$start}, {$perpage} - "); - - // Get the banned users - $bannedusers = ''; - while($banned = $db->fetch_array($query)) - { - $banned['username'] = htmlspecialchars_uni($banned['username']); - $profile_link = build_profile_link($banned['username'], $banned['uid']); - - // Only show the edit & lift links if current user created ban, or is super mod/admin - $edit_link = ''; - if($mybb->user['uid'] == $banned['admin'] || !$banned['adminuser'] || $mybb->usergroup['issupermod'] == 1 || $mybb->usergroup['cancp'] == 1) - { - eval("\$edit_link = \"".$templates->get("modcp_banning_edit")."\";"); - } - - $admin_profile = build_profile_link(htmlspecialchars_uni($banned['adminuser']), $banned['admin']); - - $trow = alt_trow(); - - if($banned['reason']) - { - $banned['reason'] = htmlspecialchars_uni($parser->parse_badwords($banned['reason'])); - } - else - { - $banned['reason'] = $lang->na; - } - - if($banned['lifted'] == 'perm' || $banned['lifted'] == '' || $banned['bantime'] == 'perm' || $banned['bantime'] == '---') - { - $banlength = $lang->permanent; - $timeremaining = $lang->na; - } - else - { - $banlength = $bantimes[$banned['bantime']]; - $remaining = $banned['lifted']-TIME_NOW; - - $timeremaining = nice_time($remaining, array('short' => 1, 'seconds' => false)).""; - - $banned_class = ''; - $ban_remaining = "{$timeremaining} {$lang->ban_remaining}"; - - if($remaining <= 0) - { - $banned_class = "imminent_banned"; - $ban_remaining = $lang->ban_ending_imminently; - } - if($remaining < 3600) - { - $banned_class = "high_banned"; - } - else if($remaining < 86400) - { - $banned_class = "moderate_banned"; - } - else if($remaining < 604800) - { - $banned_class = "low_banned"; - } - else - { - $banned_class = "normal_banned"; - } - - eval('$timeremaining = "'.$templates->get('modcp_banning_remaining').'";'); - } - - eval("\$bannedusers .= \"".$templates->get("modcp_banning_ban")."\";"); - } - - if(!$bannedusers) - { - eval("\$bannedusers = \"".$templates->get("modcp_banning_nobanned")."\";"); - } - - $plugins->run_hooks("modcp_banning"); - - eval("\$bannedpage = \"".$templates->get("modcp_banning")."\";"); - output_page($bannedpage); -} - -if($mybb->input['action'] == "liftban") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->usergroup['canbanusers'] == 0) - { - error_no_permission(); - } - - $query = $db->simple_select("banned", "*", "uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"); - $ban = $db->fetch_array($query); - - if(!$ban) - { - error($lang->error_invalidban); - } - - // Permission to edit this ban? - if($mybb->user['uid'] != $ban['admin'] && $mybb->usergroup['issupermod'] != 1 && $mybb->usergroup['cancp'] != 1) - { - error_no_permission(); - } - - $plugins->run_hooks("modcp_liftban_start"); - - $query = $db->simple_select("users", "username", "uid = '{$ban['uid']}'"); - $username = $db->fetch_field($query, "username"); - - $updated_group = array( - 'usergroup' => $ban['oldgroup'], - 'additionalgroups' => $ban['oldadditionalgroups'], - 'displaygroup' => $ban['olddisplaygroup'] - ); - $db->update_query("users", $updated_group, "uid='{$ban['uid']}'"); - $db->delete_query("banned", "uid='{$ban['uid']}'"); - - $cache->update_banned(); - $cache->update_moderators(); - log_moderator_action(array("uid" => $ban['uid'], "username" => $username), $lang->lifted_ban); - - $plugins->run_hooks("modcp_liftban_end"); - - redirect("modcp.php?action=banning", $lang->redirect_banlifted); -} - -if($mybb->input['action'] == "do_banuser" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->usergroup['canbanusers'] == 0) - { - error_no_permission(); - } - - // Editing an existing ban - if($mybb->get_input('uid', MyBB::INPUT_INT)) - { - // Get the users info from their uid - $query = $db->query(" - SELECT b.*, u.uid, u.username, u.usergroup, u.additionalgroups, u.displaygroup - FROM ".TABLE_PREFIX."banned b - LEFT JOIN ".TABLE_PREFIX."users u ON (b.uid=u.uid) - WHERE b.uid='{$mybb->input['uid']}' - "); - $user = $db->fetch_array($query); - - $existing_ban = false; - if($user['uid']) - { - $existing_ban = true; - } - - // Permission to edit this ban? - if($existing_ban && $mybb->user['uid'] != $user['admin'] && $mybb->usergroup['issupermod'] != 1 && $mybb->usergroup['cancp'] != 1) - { - error_no_permission(); - } - } - - // Creating a new ban - if(!$existing_ban) - { - // Get the users info from their Username - $options = array( - 'fields' => array('username', 'usergroup', 'additionalgroups', 'displaygroup') - ); - - $user = get_user_by_username($mybb->input['username'], $options); - - if(!$user['uid']) - { - $errors[] = $lang->invalid_username; - } - } - - if($user['uid'] == $mybb->user['uid']) - { - $errors[] = $lang->error_cannotbanself; - } - - // Have permissions to ban this user? - if(!modcp_can_manage_user($user['uid'])) - { - $errors[] = $lang->error_cannotbanuser; - } - - // Check for an incoming reason - if(empty($mybb->input['banreason'])) - { - $errors[] = $lang->error_nobanreason; - } - - // Check banned group - $usergroups_cache = $cache->read('usergroups'); - $usergroup = $usergroups_cache[$mybb->get_input('usergroup', MyBB::INPUT_INT)]; - $query = $db->simple_select("usergroups", "gid", "isbannedgroup=1 AND gid='".$mybb->get_input('usergroup', MyBB::INPUT_INT)."'"); - - if(empty($usergroup['gid']) || empty($usergroup['isbannedgroup'])) - { - $errors[] = $lang->error_nobangroup; - } - - // If this is a new ban, we check the user isn't already part of a banned group - if(!$existing_ban && $user['uid']) - { - $query = $db->simple_select("banned", "uid", "uid='{$user['uid']}'"); - if($db->fetch_field($query, "uid")) - { - $errors[] = $lang->error_useralreadybanned; - } - } - - $plugins->run_hooks("modcp_do_banuser_start"); - - // Still no errors? Ban the user - if(!$errors) - { - // Ban the user - if($mybb->get_input('liftafter') == '---') - { - $lifted = 0; - } - else - { - if(!isset($user['dateline'])) - { - $user['dateline'] = 0; - } - $lifted = ban_date2timestamp($mybb->get_input('liftafter'), $user['dateline']); - } - - $banreason = my_substr($mybb->get_input('banreason'), 0, 255); - - if($existing_ban) - { - $update_array = array( - 'gid' => $mybb->get_input('usergroup', MyBB::INPUT_INT), - 'dateline' => TIME_NOW, - 'bantime' => $db->escape_string($mybb->get_input('liftafter')), - 'lifted' => $db->escape_string($lifted), - 'reason' => $db->escape_string($banreason) - ); - - $db->update_query('banned', $update_array, "uid='{$user['uid']}'"); - } - else - { - $insert_array = array( - 'uid' => $user['uid'], - 'gid' => $mybb->get_input('usergroup', MyBB::INPUT_INT), - 'oldgroup' => (int)$user['usergroup'], - 'oldadditionalgroups' => (string)$user['additionalgroups'], - 'olddisplaygroup' => (int)$user['displaygroup'], - 'admin' => (int)$mybb->user['uid'], - 'dateline' => TIME_NOW, - 'bantime' => $db->escape_string($mybb->get_input('liftafter')), - 'lifted' => $db->escape_string($lifted), - 'reason' => $db->escape_string($banreason) - ); - - $db->insert_query('banned', $insert_array); - } - - // Move the user to the banned group - $update_array = array( - 'usergroup' => $mybb->get_input('usergroup', MyBB::INPUT_INT), - 'displaygroup' => 0, - 'additionalgroups' => '', - ); - $db->update_query('users', $update_array, "uid = {$user['uid']}"); - - $cache->update_banned(); - - // Log edit or add ban - if($existing_ban) - { - log_moderator_action(array("uid" => $user['uid'], "username" => $user['username']), $lang->edited_user_ban); - } - else - { - log_moderator_action(array("uid" => $user['uid'], "username" => $user['username']), $lang->banned_user); - } - - $plugins->run_hooks("modcp_do_banuser_end"); - - if($existing_ban) - { - redirect("modcp.php?action=banning", $lang->redirect_banuser_updated); - } - else - { - redirect("modcp.php?action=banning", $lang->redirect_banuser); - } - } - // Otherwise has errors, throw back to ban page - else - { - $mybb->input['action'] = "banuser"; - } -} - -if($mybb->input['action'] == "banuser") -{ - add_breadcrumb($lang->mcp_nav_banning, "modcp.php?action=banning"); - - if($mybb->usergroup['canbanusers'] == 0) - { - error_no_permission(); - } - - $mybb->input['uid'] = $mybb->get_input('uid', MyBB::INPUT_INT); - if($mybb->input['uid']) - { - add_breadcrumb($lang->mcp_nav_editing_ban); - } - else - { - add_breadcrumb($lang->mcp_nav_ban_user); - } - - $plugins->run_hooks("modcp_banuser_start"); - - $banuser_username = ''; - $banreason = ''; - - // If incoming user ID, we are editing a ban - if($mybb->input['uid']) - { - $query = $db->query(" - SELECT b.*, u.username, u.uid - FROM ".TABLE_PREFIX."banned b - LEFT JOIN ".TABLE_PREFIX."users u ON (b.uid=u.uid) - WHERE b.uid='{$mybb->input['uid']}' - "); - $banned = $db->fetch_array($query); - if($banned['username']) - { - $username = $banned['username'] = htmlspecialchars_uni($banned['username']); - $banreason = htmlspecialchars_uni($banned['reason']); - $uid = $mybb->input['uid']; - $user = get_user($banned['uid']); - $lang->ban_user = $lang->edit_ban; // Swap over lang variables - eval("\$banuser_username = \"".$templates->get("modcp_banuser_editusername")."\";"); - } - } - - // Permission to edit this ban? - if($banned['uid'] && $mybb->user['uid'] != $banned['admin'] && $mybb->usergroup['issupermod'] != 1 && $mybb->usergroup['cancp'] != 1) - { - error_no_permission(); - } - - // New ban! - if(!$banuser_username) - { - if($mybb->input['uid']) - { - $user = get_user($mybb->input['uid']); - $user['username'] = htmlspecialchars_uni($user['username']); - $username = $user['username']; - } - else - { - $username = htmlspecialchars_uni($mybb->get_input('username')); - } - eval("\$banuser_username = \"".$templates->get("modcp_banuser_addusername")."\";"); - } - - // Coming back to this page from an error? - if($errors) - { - $errors = inline_error($errors); - $banned = array( - "bantime" => $mybb->get_input('liftafter'), - "reason" => $mybb->get_input('reason'), - "gid" => $mybb->get_input('gid', MyBB::INPUT_INT) - ); - $banreason = htmlspecialchars_uni($mybb->get_input('banreason')); - } - - // Generate the banned times dropdown - $liftlist = ''; - foreach($bantimes as $time => $title) - { - $selected = ''; - if(isset($banned['bantime']) && $banned['bantime'] == $time) - { - $selected = " selected=\"selected\""; - } - - $thattime = ''; - if($time != '---') - { - $dateline = TIME_NOW; - if(isset($banned['dateline'])) - { - $dateline = $banned['dateline']; - } - - $thatime = my_date("D, jS M Y @ {$mybb->settings['timeformat']}", ban_date2timestamp($time, $dateline)); - $thattime = " ({$thatime})"; - } - - eval("\$liftlist .= \"".$templates->get("modcp_banuser_liftlist")."\";"); - } - - $bangroup_option = $bangroups = ''; - $numgroups = $banned_group = 0; - $groupscache = $cache->read("usergroups"); - - foreach($groupscache as $key => $group) - { - if($group['isbannedgroup']) - { - $selected = ""; - if(isset($banned['gid']) && $banned['gid'] == $group['gid']) - { - $selected = " selected=\"selected\""; - } - - $group['title'] = htmlspecialchars_uni($group['title']); - eval("\$bangroup_option .= \"".$templates->get("modcp_banuser_bangroups_group")."\";"); - $banned_group = $group['gid']; - ++$numgroups; - } - } - - if($numgroups == 0) - { - error($lang->no_banned_group); - } - elseif($numgroups > 1) - { - eval("\$bangroups = \"".$templates->get("modcp_banuser_bangroups")."\";"); - } - else - { - eval("\$bangroups = \"".$templates->get("modcp_banuser_bangroups_hidden")."\";"); - } - - if(!empty($banned['uid'])) - { - eval("\$lift_link = \"".$templates->get("modcp_banuser_lift")."\";"); - $uid = $banned['uid']; - } - else - { - $lift_link = ''; - $uid = 0; - } - - $plugins->run_hooks("modcp_banuser_end"); - - eval("\$banuser = \"".$templates->get("modcp_banuser")."\";"); - output_page($banuser); -} - -if($mybb->input['action'] == "do_modnotes") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("modcp_do_modnotes_start"); - - // Update Moderator Notes cache - $update_cache = array( - "modmessage" => $mybb->get_input('modnotes') - ); - $cache->update("modnotes", $update_cache); - - $plugins->run_hooks("modcp_do_modnotes_end"); - - redirect("modcp.php", $lang->redirect_modnotes); -} - -if(!$mybb->input['action']) -{ - $awaitingattachments = $awaitingposts = $awaitingthreads = $awaitingmoderation = ''; - - if($mybb->usergroup['canmanagemodqueue'] == 1) - { - if($mybb->settings['enableattachments'] == 1 && ($nummodqueueattach > 0 || $mybb->usergroup['issupermod'] == 1)) - { - if($nummodqueueposts > 0 || $mybb->usergroup['issupermod'] == 1) - { - $bgcolor = "trow1"; - } - else - { - $bgcolor = "trow2"; - } - - $query = $db->query(" - SELECT COUNT(aid) AS unapprovedattachments - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE a.visible='0' {$tflist} - "); - $unapproved_attachments = $db->fetch_field($query, "unapprovedattachments"); - - if($unapproved_attachments > 0) - { - $query = $db->query(" - SELECT t.tid, p.pid, p.uid, t.username, a.filename, a.dateuploaded - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=a.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE a.visible='0' {$tflist} - ORDER BY a.dateuploaded DESC - LIMIT 1 - "); - $attachment = $db->fetch_array($query); - $attachment['date'] = my_date('relative', $attachment['dateuploaded']); - $attachment['username'] = htmlspecialchars_uni($attachment['username']); - $attachment['profilelink'] = build_profile_link($attachment['username'], $attachment['uid']); - $attachment['link'] = get_post_link($attachment['pid'], $attachment['tid']); - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - $unapproved_attachments = my_number_format($unapproved_attachments); - - eval("\$latest_attachment = \"".$templates->get("modcp_lastattachment")."\";"); - } - else - { - eval("\$latest_attachment = \"".$templates->get("modcp_awaitingmoderation_none")."\";"); - } - - eval("\$awaitingattachments = \"".$templates->get("modcp_awaitingattachments")."\";"); - } - - if($nummodqueueposts > 0 || $mybb->usergroup['issupermod'] == 1) - { - $query = $db->query(" - SELECT COUNT(pid) AS unapprovedposts - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.visible='0' {$tflist} AND t.firstpost != p.pid - "); - $unapproved_posts = $db->fetch_field($query, "unapprovedposts"); - - if($unapproved_posts > 0) - { - $query = $db->query(" - SELECT p.pid, p.tid, p.subject, p.uid, p.username, p.dateline - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.visible='0' {$tflist} AND t.firstpost != p.pid - ORDER BY p.dateline DESC - LIMIT 1 - "); - $post = $db->fetch_array($query); - $post['date'] = my_date('relative', $post['dateline']); - $post['username'] = htmlspecialchars_uni($post['username']); - $post['profilelink'] = build_profile_link($post['username'], $post['uid']); - $post['link'] = get_post_link($post['pid'], $post['tid']); - $post['subject'] = $post['fullsubject'] = $parser->parse_badwords($post['subject']); - if(my_strlen($post['subject']) > 25) - { - $post['subject'] = my_substr($post['subject'], 0, 25)."..."; - } - $post['subject'] = htmlspecialchars_uni($post['subject']); - $post['fullsubject'] = htmlspecialchars_uni($post['fullsubject']); - $unapproved_posts = my_number_format($unapproved_posts); - - eval("\$latest_post = \"".$templates->get("modcp_lastpost")."\";"); - } - else - { - eval("\$latest_post = \"".$templates->get("modcp_awaitingmoderation_none")."\";"); - } - - eval("\$awaitingposts = \"".$templates->get("modcp_awaitingposts")."\";"); - } - - if($nummodqueuethreads > 0 || $mybb->usergroup['issupermod'] == 1) - { - $query = $db->simple_select("threads", "COUNT(tid) AS unapprovedthreads", "visible='0' {$flist_queue_threads}"); - $unapproved_threads = $db->fetch_field($query, "unapprovedthreads"); - - if($unapproved_threads > 0) - { - $query = $db->simple_select("threads", "tid, subject, uid, username, dateline", "visible='0' {$flist_queue_threads}", array('order_by' => 'dateline', 'order_dir' => 'DESC', 'limit' => 1)); - $thread = $db->fetch_array($query); - $thread['date'] = my_date('relative', $thread['dateline']); - $thread['username'] = htmlspecialchars_uni($thread['username']); - $thread['profilelink'] = build_profile_link($thread['username'], $thread['uid']); - $thread['link'] = get_thread_link($thread['tid']); - $thread['subject'] = $thread['fullsubject'] = $parser->parse_badwords($thread['subject']); - if(my_strlen($thread['subject']) > 25) - { - $post['subject'] = my_substr($thread['subject'], 0, 25)."..."; - } - $thread['subject'] = htmlspecialchars_uni($thread['subject']); - $thread['fullsubject'] = htmlspecialchars_uni($thread['fullsubject']); - $unapproved_threads = my_number_format($unapproved_threads); - - eval("\$latest_thread = \"".$templates->get("modcp_lastthread")."\";"); - } - else - { - eval("\$latest_thread = \"".$templates->get("modcp_awaitingmoderation_none")."\";"); - } - - eval("\$awaitingthreads = \"".$templates->get("modcp_awaitingthreads")."\";"); - } - - if(!empty($awaitingattachments) || !empty($awaitingposts) || !empty($awaitingthreads)) - { - eval("\$awaitingmoderation = \"".$templates->get("modcp_awaitingmoderation")."\";"); - } - } - - $latestfivemodactions = ''; - if(($nummodlogs > 0 || $mybb->usergroup['issupermod'] == 1) && $mybb->usergroup['canviewmodlogs'] == 1) - { - $where = ''; - if($tflist_modlog) - { - $where = "WHERE (t.fid <> 0 {$tflist_modlog}) OR (!l.fid)"; - } - - $query = $db->query(" - SELECT l.*, u.username, u.usergroup, u.displaygroup, t.subject AS tsubject, f.name AS fname, p.subject AS psubject - FROM ".TABLE_PREFIX."moderatorlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=l.uid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=l.tid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=l.fid) - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=l.pid) - {$where} - ORDER BY l.dateline DESC - LIMIT 5 - "); - - $modlogresults = ''; - while($logitem = $db->fetch_array($query)) - { - $information = ''; - $logitem['action'] = htmlspecialchars_uni($logitem['action']); - $log_date = my_date('relative', $logitem['dateline']); - $trow = alt_trow(); - $logitem['username'] = htmlspecialchars_uni($logitem['username']); - $username = format_name($logitem['username'], $logitem['usergroup'], $logitem['displaygroup']); - $logitem['profilelink'] = build_profile_link($username, $logitem['uid']); - $logitem['ipaddress'] = my_inet_ntop($db->unescape_binary($logitem['ipaddress'])); - - if($logitem['tsubject']) - { - $logitem['tsubject'] = htmlspecialchars_uni($parser->parse_badwords($logitem['tsubject'])); - $logitem['thread'] = get_thread_link($logitem['tid']); - eval("\$information .= \"".$templates->get("modcp_modlogs_result_thread")."\";"); - } - if($logitem['fname']) - { - $logitem['forum'] = get_forum_link($logitem['fid']); - eval("\$information .= \"".$templates->get("modcp_modlogs_result_forum")."\";"); - } - if($logitem['psubject']) - { - $logitem['psubject'] = htmlspecialchars_uni($parser->parse_badwords($logitem['psubject'])); - $logitem['post'] = get_post_link($logitem['pid']); - eval("\$information .= \"".$templates->get("modcp_modlogs_result_post")."\";"); - } - - // Edited a user or managed announcement? - if(!$logitem['tsubject'] || !$logitem['fname'] || !$logitem['psubject']) - { - $data = my_unserialize($logitem['data']); - if($data['uid']) - { - $information = $lang->sprintf($lang->edited_user_info, htmlspecialchars_uni($data['username']), get_profile_link($data['uid'])); - } - if($data['aid']) - { - $data['subject'] = htmlspecialchars_uni($parser->parse_badwords($data['subject'])); - $data['announcement'] = get_announcement_link($data['aid']); - eval("\$information .= \"".$templates->get("modcp_modlogs_result_announcement")."\";"); - } - } - - $plugins->run_hooks("modcp_modlogs_result"); - - eval("\$modlogresults .= \"".$templates->get("modcp_modlogs_result")."\";"); - } - - if(!$modlogresults) - { - eval("\$modlogresults = \"".$templates->get("modcp_modlogs_nologs")."\";"); - } - - eval("\$latestfivemodactions = \"".$templates->get("modcp_latestfivemodactions")."\";"); - } - - $query = $db->query(" - SELECT b.*, a.username AS adminuser, u.username - FROM ".TABLE_PREFIX."banned b - LEFT JOIN ".TABLE_PREFIX."users u ON (b.uid=u.uid) - LEFT JOIN ".TABLE_PREFIX."users a ON (b.admin=a.uid) - WHERE b.bantime != '---' AND b.bantime != 'perm' - ORDER BY lifted ASC - LIMIT 5 - "); - - $banned_cache = array(); - while($banned = $db->fetch_array($query)) - { - $banned['remaining'] = $banned['lifted']-TIME_NOW; - $banned_cache[$banned['remaining'].$banned['uid']] = $banned; - - unset($banned); - } - - // Get the banned users - $bannedusers = ''; - foreach($banned_cache as $banned) - { - $banned['username'] = htmlspecialchars_uni($banned['username']); - $profile_link = build_profile_link($banned['username'], $banned['uid']); - - // Only show the edit & lift links if current user created ban, or is super mod/admin - $edit_link = ''; - if($mybb->user['uid'] == $banned['admin'] || !$banned['adminuser'] || $mybb->usergroup['issupermod'] == 1 || $mybb->usergroup['cancp'] == 1) - { - eval("\$edit_link = \"".$templates->get("modcp_banning_edit")."\";"); - } - - $admin_profile = build_profile_link(htmlspecialchars_uni($banned['adminuser']), $banned['admin']); - - $trow = alt_trow(); - - if($banned['reason']) - { - $banned['reason'] = htmlspecialchars_uni($parser->parse_badwords($banned['reason'])); - } - else - { - $banned['reason'] = $lang->na; - } - - if($banned['lifted'] == 'perm' || $banned['lifted'] == '' || $banned['bantime'] == 'perm' || $banned['bantime'] == '---') - { - $banlength = $lang->permanent; - $timeremaining = $lang->na; - } - else - { - $banlength = $bantimes[$banned['bantime']]; - $remaining = $banned['remaining']; - - $timeremaining = nice_time($remaining, array('short' => 1, 'seconds' => false)).""; - - $banned_class = ''; - $ban_remaining = "{$timeremaining} {$lang->ban_remaining}"; - - if($remaining <= 0) - { - $banned_class = "imminent_banned"; - $ban_remaining = $lang->ban_ending_imminently; - } - else if($remaining < 3600) - { - $banned_class = "high_banned"; - } - else if($remaining < 86400) - { - $banned_class = "moderate_banned"; - } - else if($remaining < 604800) - { - $banned_class = "low_banned"; - } - else - { - $banned_class = "normal_banned"; - } - - eval('$timeremaining = "'.$templates->get('modcp_banning_remaining').'";'); - } - - eval("\$bannedusers .= \"".$templates->get("modcp_banning_ban")."\";"); - } - - if(!$bannedusers) - { - eval("\$bannedusers = \"".$templates->get("modcp_nobanned")."\";"); - } - - $modnotes = $cache->read("modnotes"); - $modnotes = htmlspecialchars_uni($modnotes['modmessage']); - - $plugins->run_hooks("modcp_end"); - - eval("\$modcp = \"".$templates->get("modcp")."\";"); - output_page($modcp); -} diff --git a/html/forums/moderation.php b/html/forums/moderation.php deleted file mode 100644 index d7cf7b0..0000000 --- a/html/forums/moderation.php +++ /dev/null @@ -1,3329 +0,0 @@ -load("moderation"); - -$plugins->run_hooks("moderation_start"); - -$tid = $mybb->get_input('tid', MyBB::INPUT_INT); -$pid = $mybb->get_input('pid', MyBB::INPUT_INT); -$fid = $mybb->get_input('fid', MyBB::INPUT_INT); -$pmid = $mybb->get_input('pmid', MyBB::INPUT_INT); - -if($pid) -{ - $post = get_post($pid); - if(!$post) - { - error($lang->error_invalidpost); - } - $tid = $post['tid']; -} - -if($tid) -{ - $thread = get_thread($tid); - if(!$thread) - { - error($lang->error_invalidthread); - } - $fid = $thread['fid']; -} - -if($fid) -{ - $modlogdata['fid'] = $fid; - $forum = get_forum($fid); - - // Make navigation - build_forum_breadcrumb($fid); - - // Get our permissions all nice and setup - $permissions = forum_permissions($fid); -} - -if($pmid > 0) -{ - $query = $db->simple_select('privatemessages', 'uid, subject, ipaddress, fromid', "pmid = $pmid"); - - $pm = $db->fetch_array($query); - - if(!$pm) - { - error($lang->error_invalidpm); - } -} - -// Get some navigation if we need it -$mybb->input['action'] = $mybb->get_input('action'); -switch($mybb->input['action']) -{ - case "reports": - add_breadcrumb($lang->reported_posts); - break; - case "allreports": - add_breadcrumb($lang->all_reported_posts); - break; - -} - -if(isset($thread)) -{ - $thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); - add_breadcrumb($thread['subject'], get_thread_link($thread['tid'])); - $modlogdata['tid'] = $thread['tid']; -} - -if(isset($forum)) -{ - // Check if this forum is password protected and we have a valid password - check_forum_password($forum['fid']); -} - -$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); -eval("\$loginbox = \"".$templates->get("changeuserbox")."\";"); - -$allowable_moderation_actions = array("getip", "getpmip", "cancel_delayedmoderation", "delayedmoderation", "threadnotes", "purgespammer", "viewthreadnotes"); - -if($mybb->request_method != "post" && !in_array($mybb->input['action'], $allowable_moderation_actions)) -{ - error_no_permission(); -} - -// Begin! -switch($mybb->input['action']) -{ - // Delayed Moderation - case "cancel_delayedmoderation": - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - add_breadcrumb($lang->delayed_moderation); - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - - $plugins->run_hooks('moderation_cancel_delayedmoderation'); - - $db->delete_query("delayedmoderation", "did='".$mybb->get_input('did', MyBB::INPUT_INT)."'"); - - if($tid == 0) - { - moderation_redirect(get_forum_link($fid), $lang->redirect_delayed_moderation_cancelled); - } - else - { - moderation_redirect("moderation.php?action=delayedmoderation&tid={$tid}&my_post_key={$mybb->post_code}", $lang->redirect_delayed_moderation_cancelled); - } - break; - case "do_delayedmoderation": - case "delayedmoderation": - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $localized_time_offset = $mybb->user['timezone']*3600 + $mybb->user['dst']*3600; - - if(!$mybb->get_input('date_day', MyBB::INPUT_INT)) - { - $mybb->input['date_day'] = gmdate('d', TIME_NOW + $localized_time_offset); - } - if(!$mybb->get_input('date_month', MyBB::INPUT_INT)) - { - $mybb->input['date_month'] = gmdate('m', TIME_NOW + $localized_time_offset); - } - - // Assume in-line moderation if TID is not set - if(!empty($mybb->input['tid'])) - { - $mybb->input['tids'] = $tid; - } - else - { - if($mybb->get_input('inlinetype') == 'search') - { - $tids = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - $tids = getids($fid, "forum"); - } - if(count($tids) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $mybb->input['tids'] = $tids; - } - - add_breadcrumb($lang->delayed_moderation); - - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - - $errors = array(); - $customthreadtools = ""; - - $allowed_types = array('openclosethread', 'softdeleterestorethread', 'deletethread', 'move', 'stick', 'merge', 'removeredirects', 'removesubscriptions', 'approveunapprovethread'); - - $mybb->input['type'] = $mybb->get_input('type'); - - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("modtools", 'tid, name', "(','||forums||',' LIKE '%,$fid,%' OR ','||forums||',' LIKE '%,-1,%' OR forums='') AND type = 't'"); - break; - default: - $query = $db->simple_select("modtools", 'tid, name', "(CONCAT(',',forums,',') LIKE '%,$fid,%' OR CONCAT(',',forums,',') LIKE '%,-1,%' OR forums='') AND type = 't'"); - } - while($tool = $db->fetch_array($query)) - { - $allowed_types[] = "modtool_".$tool['tid']; - - $tool['name'] = htmlspecialchars_uni($tool['name']); - - $checked = ""; - if($mybb->input['type'] == "modtool_".$tool['tid']) - { - $checked = "checked=\"checked\""; - } - - eval("\$customthreadtools .= \"".$templates->get("moderation_delayedmoderation_custommodtool")."\";"); - } - - $mybb->input['delayedmoderation'] = $mybb->get_input('delayedmoderation', MyBB::INPUT_ARRAY); - - if($mybb->input['action'] == "do_delayedmoderation" && $mybb->request_method == "post") - { - if(!in_array($mybb->input['type'], $allowed_types)) - { - $mybb->input['type'] = ''; - $errors[] = $lang->error_delayedmoderation_unsupported_type; - } - - if($mybb->input['type'] == 'move' && (!isset($mybb->input['delayedmoderation']['method']) || !in_array($mybb->input['delayedmoderation']['method'], array('move', 'redirect', 'copy')))) - { - $mybb->input['delayedmoderation']['method'] = ''; - $errors[] = $lang->error_delayedmoderation_unsupported_method; - } - - if($mybb->input['type'] == 'move') - { - $newforum = get_forum($fid); - if(!$newforum || $newforum['type'] != "f" || $newforum['type'] == "f" && $newforum['linkto'] != '') - { - $errors[] = $lang->error_invalidforum; - } - } - - if($mybb->input['date_day'] > 31 || $mybb->input['date_day'] < 1) - { - $errors[] = $lang->error_delayedmoderation_invalid_date_day; - } - - if($mybb->input['date_month'] > 12 || $mybb->input['date_month'] < 1) - { - $errors[] = $lang->error_delayedmoderation_invalid_date_month; - } - - if($mybb->input['date_year'] < gmdate('Y', TIME_NOW + $localized_time_offset)) - { - $errors[] = $lang->error_delayedmoderation_invalid_date_year; - } - - $date_time = explode(' ', $mybb->get_input('date_time')); - $date_time = explode(':', (string)$date_time[0]); - - if(stristr($mybb->input['date_time'], 'pm')) - { - $date_time[0] = 12+$date_time[0]; - if($date_time[0] >= 24) - { - $date_time[0] = '00'; - } - } - - $rundate = gmmktime((int)$date_time[0], (int)$date_time[1], date('s', TIME_NOW), $mybb->get_input('date_month', MyBB::INPUT_INT), $mybb->get_input('date_day', MyBB::INPUT_INT), $mybb->get_input('date_year', MyBB::INPUT_INT)) - $localized_time_offset; - - if(!$errors) - { - if(is_array($mybb->input['tids'])) - { - $mybb->input['tids'] = implode(',' , $mybb->input['tids']); - } - - $did = $db->insert_query("delayedmoderation", array( - 'type' => $db->escape_string($mybb->input['type']), - 'delaydateline' => (int)$rundate, - 'uid' => $mybb->user['uid'], - 'tids' => $db->escape_string($mybb->input['tids']), - 'fid' => $fid, - 'dateline' => TIME_NOW, - 'inputs' => $db->escape_string(my_serialize($mybb->input['delayedmoderation'])) - )); - - $plugins->run_hooks('moderation_do_delayedmoderation'); - - $rundate_format = my_date('relative', $rundate, '', 2); - $lang->redirect_delayed_moderation_thread = $lang->sprintf($lang->redirect_delayed_moderation_thread, $rundate_format); - - if(!empty($mybb->input['tid'])) - { - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_delayed_moderation_thread); - } - else - { - if($mybb->get_input('inlinetype') == 'search') - { - moderation_redirect(get_forum_link($fid), $lang->sprintf($lang->redirect_delayed_moderation_search, $rundate_format)); - } - else - { - moderation_redirect(get_forum_link($fid), $lang->sprintf($lang->redirect_delayed_moderation_forum, $rundate_format)); - } - } - } - else - { - $type_selected = array(); - foreach($allowed_types as $type) - { - $type_selected[$type] = ''; - } - $type_selected[$mybb->get_input('type')] = "checked=\"checked\""; - $method_selected = array('move' => '', 'redirect' => '', 'copy' => ''); - if(isset($mybb->input['delayedmoderation']['method'])) - { - $method_selected[$mybb->input['delayedmoderation']['method']] = "checked=\"checked\""; - } - - foreach(array('redirect_expire', 'new_forum', 'subject', 'threadurl') as $value) - { - if(!isset($mybb->input['delayedmoderation'][$value])) - { - $mybb->input['delayedmoderation'][$value] = ''; - } - } - $mybb->input['delayedmoderation']['redirect_expire'] = (int)$mybb->input['delayedmoderation']['redirect_expire']; - $mybb->input['delayedmoderation']['new_forum'] = (int)$mybb->input['delayedmoderation']['new_forum']; - $mybb->input['delayedmoderation']['subject'] = htmlspecialchars_uni($mybb->input['delayedmoderation']['subject']); - $mybb->input['delayedmoderation']['threadurl'] = htmlspecialchars_uni($mybb->input['delayedmoderation']['threadurl']); - - $forumselect = build_forum_jump("", $mybb->input['delayedmoderation']['new_forum'], 1, '', 0, true, '', "delayedmoderation[new_forum]"); - } - } - else - { - $type_selected = array(); - foreach($allowed_types as $type) - { - $type_selected[$type] = ''; - } - $type_selected['openclosethread'] = "checked=\"checked\""; - $method_selected = array('move' => 'checked="checked"', 'redirect' => '', 'copy' => ''); - - $mybb->input['delayedmoderation']['redirect_expire'] = ''; - $mybb->input['delayedmoderation']['subject'] = $thread['subject']; - $mybb->input['delayedmoderation']['threadurl'] = ''; - - $forumselect = build_forum_jump("", $fid, 1, '', 0, true, '', "delayedmoderation[new_forum]"); - } - - if(isset($errors) && count($errors) > 0) - { - $display_errors = inline_error($errors); - } - else - { - $display_errors = ''; - } - - $forum_cache = $cache->read("forums"); - - $actions = array( - 'openclosethread' => $lang->open_close_thread, - 'softdeleterestorethread' => $lang->softdelete_restore_thread, - 'deletethread' => $lang->delete_thread, - 'move' => $lang->move_copy_thread, - 'stick' => $lang->stick_unstick_thread, - 'merge' => $lang->merge_threads, - 'removeredirects' => $lang->remove_redirects, - 'removesubscriptions' => $lang->remove_subscriptions, - 'approveunapprovethread' => $lang->approve_unapprove_thread - ); - - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("modtools", 'tid, name', "(','||forums||',' LIKE '%,$fid,%' OR ','||forums||',' LIKE '%,-1,%' OR forums='') AND type = 't'"); - break; - default: - $query = $db->simple_select("modtools", 'tid, name', "(CONCAT(',',forums,',') LIKE '%,$fid,%' OR CONCAT(',',forums,',') LIKE '%,-1,%' OR forums='') AND type = 't'"); - } - while($tool = $db->fetch_array($query)) - { - $actions['modtool_'.$tool['tid']] = htmlspecialchars_uni($tool['name']); - } - - $delayedmods = ''; - $trow = alt_trow(1); - if($tid == 0) - { - // Inline thread moderation is used - if($mybb->get_input('inlinetype') == 'search') - { - $tids = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $tids = getids($fid, "forum"); - } - $where_array = array(); - switch($db->type) - { - case "pgsql": - case "sqlite": - foreach($tids as $like) - { - $where_array[] = "','||d.tids||',' LIKE '%,".$db->escape_string($like).",%'"; - } - $where_statement = implode(" OR ", $where_array); - break; - default: - foreach($tids as $like) - { - $where_array[] = "CONCAT(',',d.tids,',') LIKE '%,".$db->escape_string($like).",%'"; - } - $where_statement = implode(" OR ", $where_array); - } - $query = $db->query(" - SELECT d.*, u.username, f.name AS fname - FROM ".TABLE_PREFIX."delayedmoderation d - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=d.uid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=d.fid) - WHERE ".$where_statement." - ORDER BY d.dateline DESC - LIMIT 0, 20 - "); - } - else - { - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->query(" - SELECT d.*, u.username, f.name AS fname - FROM ".TABLE_PREFIX."delayedmoderation d - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=d.uid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=d.fid) - WHERE ','||d.tids||',' LIKE '%,{$tid},%' - ORDER BY d.dateline DESC - LIMIT 0, 20 - "); - break; - default: - $query = $db->query(" - SELECT d.*, u.username, f.name AS fname - FROM ".TABLE_PREFIX."delayedmoderation d - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=d.uid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=d.fid) - WHERE CONCAT(',',d.tids,',') LIKE '%,{$tid},%' - ORDER BY d.dateline DESC - LIMIT 0, 20 - "); - } - } - - while($delayedmod = $db->fetch_array($query)) - { - $delayedmod['dateline'] = my_date("jS M Y, {$mybb->settings['timeformat']}", $delayedmod['delaydateline']); - $delayedmod['username'] = htmlspecialchars_uni($delayedmod['username']); - $delayedmod['profilelink'] = build_profile_link($delayedmod['username'], $delayedmod['uid']); - $delayedmod['action'] = $actions[$delayedmod['type']]; - $info = ''; - if(strpos($delayedmod['tids'], ',') === false) - { - $delayed_thread = get_thread($delayedmod['tids']); - $delayed_thread['link'] = get_thread_link($delayed_thread['tid']); - $delayed_thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($delayed_thread['subject'])); - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_thread_single")."\";"); - } - else - { - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_thread_multiple")."\";"); - } - - if($delayedmod['fname']) - { - $delayedmod['link'] = get_forum_link($delayedmod['fid']); - $delayedmod['fname'] = htmlspecialchars_uni($delayedmod['fname']); - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_forum")."\";"); - } - $delayedmod['inputs'] = my_unserialize($delayedmod['inputs']); - - if($delayedmod['type'] == 'move') - { - $delayedmod['link'] = get_forum_link($delayedmod['inputs']['new_forum']); - $delayedmod['name'] = htmlspecialchars_uni($forum_cache[$delayedmod['inputs']['new_forum']]['name']); - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_new_forum")."\";"); - - if($delayedmod['inputs']['method'] == "redirect") - { - if((int)$delayedmod['inputs']['redirect_expire'] == 0) - { - $redirect_expire_bit = $lang->redirect_forever; - } - else - { - $redirect_expire_bit = (int)$delayedmod['inputs']['redirect_expire']." {$lang->days}"; - } - - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_redirect")."\";"); - } - } - else if($delayedmod['type'] == 'merge') - { - $delayedmod['subject'] = htmlspecialchars_uni($delayedmod['inputs']['subject']); - $delayedmod['threadurl'] = htmlspecialchars_uni($delayedmod['inputs']['threadurl']); - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_merge")."\";"); - } - - eval("\$delayedmods .= \"".$templates->get("moderation_delayedmodaction_notes")."\";"); - $trow = alt_trow(); - } - if(!$delayedmods) - { - $cols = 5; - eval("\$delayedmods = \"".$templates->get("moderation_delayedmodaction_error")."\";"); - } - - $url = ''; - if($mybb->get_input('tid', MyBB::INPUT_INT)) - { - $lang->threads = $lang->thread; - $thread['link'] = get_thread_link($tid); - eval("\$threads = \"".$templates->get("moderation_delayedmoderation_thread")."\";"); - eval("\$moderation_delayedmoderation_merge = \"".$templates->get("moderation_delayedmoderation_merge")."\";"); - } - else - { - if($mybb->get_input('inlinetype') == 'search') - { - $tids = getids($mybb->get_input('searchid'), 'search'); - $url = htmlspecialchars_uni($mybb->get_input('url')); - } - else - { - $tids = getids($fid, "forum"); - } - if(count($tids) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $threads = $lang->sprintf($lang->threads_selected, count($tids)); - $moderation_delayedmoderation_merge = ''; - } - $mybb->input['redirect_expire'] = $mybb->get_input('redirect_expire'); - eval("\$moderation_delayedmoderation_move = \"".$templates->get("moderation_delayedmoderation_move")."\";"); - - // Generate form elements for date form - $dateday = ''; - for($day = 1; $day <= 31; ++$day) - { - $selected = ''; - if($mybb->get_input('date_day', MyBB::INPUT_INT) == $day) - { - $selected = ' selected="selected"'; - } - eval('$dateday .= "'.$templates->get('moderation_delayedmoderation_date_day').'";'); - } - - $datemonth = array(); - foreach(array('01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12') as $month) - { - $datemonth[$month] = ''; - if($mybb->get_input('date_month', MyBB::INPUT_INT) == (int)$month) - { - $datemonth[$month] = ' selected="selected"'; - } - } - - - eval('$datemonth = "'.$templates->get('moderation_delayedmoderation_date_month').'";'); - - $dateyear = gmdate('Y', TIME_NOW + $localized_time_offset); - $datetime = gmdate($mybb->settings['timeformat'], TIME_NOW + $localized_time_offset); - - $plugins->run_hooks("moderation_delayedmoderation"); - - eval("\$delayedmoderation = \"".$templates->get("moderation_delayedmoderation")."\";"); - output_page($delayedmoderation); - break; - // Open or close a thread - case "openclosethread": - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "canopenclosethreads")) - { - error_no_permission(); - } - - if($thread['closed'] == 1) - { - $openclose = $lang->opened; - $redirect = $lang->redirect_openthread; - $moderation->open_threads($tid); - } - else - { - $openclose = $lang->closed; - $redirect = $lang->redirect_closethread; - $moderation->close_threads($tid); - } - - $lang->mod_process = $lang->sprintf($lang->mod_process, $openclose); - - log_moderator_action($modlogdata, $lang->mod_process); - - moderation_redirect(get_thread_link($thread['tid']), $redirect); - break; - - // Stick or unstick that post to the top bab! - case "stick": - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "canstickunstickthreads")) - { - error_no_permission(); - } - - $plugins->run_hooks("moderation_stick"); - - if($thread['sticky'] == 1) - { - $stuckunstuck = $lang->unstuck; - $redirect = $lang->redirect_unstickthread; - $moderation->unstick_threads($tid); - } - else - { - $stuckunstuck = $lang->stuck; - $redirect = $lang->redirect_stickthread; - $moderation->stick_threads($tid); - } - - $lang->mod_process = $lang->sprintf($lang->mod_process, $stuckunstuck); - - log_moderator_action($modlogdata, $lang->mod_process); - - moderation_redirect(get_thread_link($thread['tid']), $redirect); - break; - - // Remove redirects to a specific thread - case "removeredirects": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - - $plugins->run_hooks("moderation_removeredirects"); - - $moderation->remove_redirects($tid); - - log_moderator_action($modlogdata, $lang->redirects_removed); - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_redirectsremoved); - break; - - // Delete thread confirmation page - case "deletethread": - - add_breadcrumb($lang->nav_deletethread); - - if(!is_moderator($fid, "candeletethreads")) - { - if($permissions['candeletethreads'] != 1 || $mybb->user['uid'] != $thread['uid']) - { - error_no_permission(); - } - } - - $plugins->run_hooks("moderation_deletethread"); - - eval("\$deletethread = \"".$templates->get("moderation_deletethread")."\";"); - output_page($deletethread); - break; - - // Delete the actual thread here - case "do_deletethread": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "candeletethreads")) - { - if($permissions['candeletethreads'] != 1 || $mybb->user['uid'] != $thread['uid']) - { - error_no_permission(); - } - } - - $plugins->run_hooks("moderation_do_deletethread"); - - // Log the subject of the deleted thread - $modlogdata['thread_subject'] = $thread['subject']; - - $thread['subject'] = $db->escape_string($thread['subject']); - $lang->thread_deleted = $lang->sprintf($lang->thread_deleted, $thread['subject']); - log_moderator_action($modlogdata, $lang->thread_deleted); - - $moderation->delete_thread($tid); - - mark_reports($tid, "thread"); - moderation_redirect(get_forum_link($fid), $lang->redirect_threaddeleted); - break; - - // Delete the poll from a thread confirmation page - case "deletepoll": - add_breadcrumb($lang->nav_deletepoll); - - if(!is_moderator($fid, "canmanagepolls")) - { - if($permissions['candeletethreads'] != 1 || $mybb->user['uid'] != $thread['uid']) - { - error_no_permission(); - } - } - - $plugins->run_hooks("moderation_deletepoll"); - - $query = $db->simple_select("polls", "pid", "tid='$tid'"); - $poll = $db->fetch_array($query); - if(!$poll) - { - error($lang->error_invalidpoll); - } - - eval("\$deletepoll = \"".$templates->get("moderation_deletepoll")."\";"); - output_page($deletepoll); - break; - - // Delete the actual poll here! - case "do_deletepoll": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!isset($mybb->input['delete'])) - { - error($lang->redirect_pollnotdeleted); - } - if(!is_moderator($fid, "canmanagepolls")) - { - if($permissions['candeletethreads'] != 1 || $mybb->user['uid'] != $thread['uid']) - { - error_no_permission(); - } - } - $query = $db->simple_select("polls", "pid", "tid = $tid"); - $poll = $db->fetch_array($query); - if(!$poll) - { - error($lang->error_invalidpoll); - } - - $plugins->run_hooks("moderation_do_deletepoll"); - - $lang->poll_deleted = $lang->sprintf($lang->poll_deleted, $thread['subject']); - log_moderator_action($modlogdata, $lang->poll_deleted); - - $moderation->delete_poll($poll['pid']); - - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_polldeleted); - break; - - // Approve a thread - case "approvethread": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "canapproveunapprovethreads")) - { - error_no_permission(); - } - $thread = get_thread($tid); - - $plugins->run_hooks("moderation_approvethread"); - - $lang->thread_approved = $lang->sprintf($lang->thread_approved, $thread['subject']); - log_moderator_action($modlogdata, $lang->thread_approved); - - $moderation->approve_threads($tid, $fid); - - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_threadapproved); - break; - - // Unapprove a thread - case "unapprovethread": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "canapproveunapprovethreads")) - { - error_no_permission(); - } - $thread = get_thread($tid); - - $plugins->run_hooks("moderation_unapprovethread"); - - $lang->thread_unapproved = $lang->sprintf($lang->thread_unapproved, $thread['subject']); - log_moderator_action($modlogdata, $lang->thread_unapproved); - - $moderation->unapprove_threads($tid); - - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_threadunapproved); - break; - - // Restore a thread - case "restorethread": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "canrestorethreads")) - { - error_no_permission(); - } - $thread = get_thread($tid); - - $plugins->run_hooks("moderation_restorethread"); - - $lang->thread_restored = $lang->sprintf($lang->thread_restored, $thread['subject']); - log_moderator_action($modlogdata, $lang->thread_restored); - - $moderation->restore_threads($tid); - - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_threadrestored); - break; - - // Soft delete a thread - case "softdeletethread": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "cansoftdeletethreads")) - { - error_no_permission(); - } - $thread = get_thread($tid); - - $plugins->run_hooks("moderation_softdeletethread"); - - $lang->thread_soft_deleted = $lang->sprintf($lang->thread_soft_deleted, $thread['subject']); - log_moderator_action($modlogdata, $lang->thread_soft_deleted); - - $moderation->soft_delete_threads($tid); - - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_threadsoftdeleted); - break; - - // Move a thread - case "move": - add_breadcrumb($lang->nav_move); - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - - $plugins->run_hooks("moderation_move"); - - $forumselect = build_forum_jump("", '', 1, '', 0, true, '', "moveto"); - eval("\$movethread = \"".$templates->get("moderation_move")."\";"); - output_page($movethread); - break; - - // Let's get this thing moving! - case "do_move": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $moveto = $mybb->get_input('moveto', MyBB::INPUT_INT); - $method = $mybb->get_input('method'); - - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - // Check if user has moderator permission to move to destination - if(!is_moderator($moveto, "canmanagethreads") && !is_moderator($fid, "canmovetononmodforum")) - { - error_no_permission(); - } - $newperms = forum_permissions($moveto); - if($newperms['canview'] == 0 && !is_moderator($fid, "canmovetononmodforum")) - { - error_no_permission(); - } - - $newforum = get_forum($moveto); - if(!$newforum || $newforum['type'] != "f" || $newforum['type'] == "f" && $newforum['linkto'] != '') - { - error($lang->error_invalidforum); - } - if($method != "copy" && $thread['fid'] == $moveto) - { - error($lang->error_movetosameforum); - } - - $plugins->run_hooks('moderation_do_move'); - - $expire = 0; - if($mybb->get_input('redirect_expire', MyBB::INPUT_INT) > 0) - { - $expire = TIME_NOW + ($mybb->get_input('redirect_expire', MyBB::INPUT_INT) * 86400); - } - - $the_thread = $tid; - - $newtid = $moderation->move_thread($tid, $moveto, $method, $expire); - - switch($method) - { - case "copy": - log_moderator_action($modlogdata, $lang->thread_copied); - break; - default: - case "move": - case "redirect": - log_moderator_action($modlogdata, $lang->thread_moved); - break; - } - - moderation_redirect(get_thread_link($newtid), $lang->redirect_threadmoved); - break; - - // Viewing thread notes - case "viewthreadnotes": - if(!is_moderator($fid)) - { - error_no_permission(); - } - - // Make sure we are looking at a real thread here. - if(!$thread) - { - error($lang->error_nomember); - } - - $plugins->run_hooks('moderation_viewthreadnotes'); - - $lang->view_notes_for = $lang->sprintf($lang->view_notes_for, $thread['subject']); - - $thread['notes'] = nl2br(htmlspecialchars_uni($thread['notes'])); - - eval("\$viewthreadnotes = \"".$templates->get("moderation_viewthreadnotes", 1, 0)."\";"); - echo $viewthreadnotes; - break; - - // Thread notes editor - case "threadnotes": - add_breadcrumb($lang->nav_threadnotes); - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - $thread['notes'] = htmlspecialchars_uni($parser->parse_badwords($thread['notes'])); - $trow = alt_trow(1); - - if(is_moderator($fid, "canviewmodlog")) - { - $query = $db->query(" - SELECT l.*, u.username, t.subject AS tsubject, f.name AS fname, p.subject AS psubject - FROM ".TABLE_PREFIX."moderatorlog l - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=l.uid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=l.tid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=l.fid) - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=l.pid) - WHERE t.tid='$tid' - ORDER BY l.dateline DESC - LIMIT 0, 20 - "); - $modactions = ''; - while($modaction = $db->fetch_array($query)) - { - $modaction['dateline'] = my_date("jS M Y, G:i", $modaction['dateline']); - $modaction['username'] = htmlspecialchars_uni($modaction['username']); - $modaction['profilelink'] = build_profile_link($modaction['username'], $modaction['uid']); - $modaction['action'] = htmlspecialchars_uni($modaction['action']); - $info = ''; - if($modaction['tsubject']) - { - $modaction['tsubject'] = htmlspecialchars_uni($parser->parse_badwords($modaction['tsubject'])); - $modaction['threadlink'] = get_thread_link($modaction['tid']); - eval("\$info .= \"".$templates->get("moderation_threadnotes_modaction_thread")."\";"); - } - if($modaction['fname']) - { - $modaction['fname'] = htmlspecialchars_uni($modaction['fname']); - $modaction['forumlink'] = get_forum_link($modaction['fid']); - eval("\$info .= \"".$templates->get("moderation_threadnotes_modaction_forum")."\";"); - } - if($modaction['psubject']) - { - - $modaction['psubject'] = htmlspecialchars_uni($parser->parse_badwords($modaction['psubject'])); - $modaction['postlink'] = get_post_link($modaction['pid']); - eval("\$info .= \"".$templates->get("moderation_threadnotes_modaction_post")."\";"); - } - - eval("\$modactions .= \"".$templates->get("moderation_threadnotes_modaction")."\";"); - $trow = alt_trow(); - } - if(!$modactions) - { - eval("\$modactions = \"".$templates->get("moderation_threadnotes_modaction_error")."\";"); - } - } - - $actions = array( - 'openclosethread' => $lang->open_close_thread, - 'deletethread' => $lang->delete_thread, - 'move' => $lang->move_copy_thread, - 'stick' => $lang->stick_unstick_thread, - 'merge' => $lang->merge_threads, - 'removeredirects' => $lang->remove_redirects, - 'removesubscriptions' => $lang->remove_subscriptions, - 'approveunapprovethread' => $lang->approve_unapprove_thread - ); - - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("modtools", 'tid, name', "(','||forums||',' LIKE '%,$fid,%' OR ','||forums||',' LIKE '%,-1,%' OR forums='') AND type = 't'"); - break; - default: - $query = $db->simple_select("modtools", 'tid, name', "(CONCAT(',',forums,',') LIKE '%,$fid,%' OR CONCAT(',',forums,',') LIKE '%,-1,%' OR forums='') AND type = 't'"); - } - while($tool = $db->fetch_array($query)) - { - $actions['modtool_'.$tool['tid']] = htmlspecialchars_uni($tool['name']); - } - - $forum_cache = $cache->read("forums"); - - $trow = alt_trow(1); - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->query(" - SELECT d.*, u.username, f.name AS fname - FROM ".TABLE_PREFIX."delayedmoderation d - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=d.uid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=d.fid) - WHERE ','||d.tids||',' LIKE '%,{$tid},%' - ORDER BY d.dateline DESC - LIMIT 0, 20 - "); - break; - default: - $query = $db->query(" - SELECT d.*, u.username, f.name AS fname - FROM ".TABLE_PREFIX."delayedmoderation d - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=d.uid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=d.fid) - WHERE CONCAT(',',d.tids,',') LIKE '%,{$tid},%' - ORDER BY d.dateline DESC - LIMIT 0, 20 - "); - } - $delayedmods = ''; - while($delayedmod = $db->fetch_array($query)) - { - $delayedmod['dateline'] = my_date("jS M Y, G:i", $delayedmod['delaydateline']); - $delayedmod['username'] = htmlspecialchars_uni($delayedmod['username']); - $delayedmod['profilelink'] = build_profile_link($delayedmod['username'], $delayedmod['uid']); - $delayedmod['action'] = $actions[$delayedmod['type']]; - $info = ''; - if(strpos($delayedmod['tids'], ',') === false) - { - $delayed_thread['link'] = get_thread_link($delayedmod['tids']); - $delayed_thread['subject'] = htmlspecialchars_uni($thread['subject']); - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_thread_single")."\";"); - } - else - { - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_thread_multiple")."\";"); - } - - if($delayedmod['fname']) - { - $delayedmod['link'] = get_forum_link($delayedmod['fid']); - $delayedmod['fname'] = htmlspecialchars_uni($delayedmod['fname']); - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_forum")."\";"); - } - $delayedmod['inputs'] = my_unserialize($delayedmod['inputs']); - - if($delayedmod['type'] == 'move') - { - $delayedmod['link'] = get_forum_link($delayedmod['inputs']['new_forum']); - $delayedmod['name'] = htmlspecialchars_uni($forum_cache[$delayedmod['inputs']['new_forum']]['name']); - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_new_forum")."\";"); - - if($delayedmod['inputs']['method'] == "redirect") - { - if((int)$delayedmod['inputs']['redirect_expire'] == 0) - { - $redirect_expire_bit = $lang->redirect_forever; - } - else - { - $redirect_expire_bit = (int)$delayedmod['inputs']['redirect_expire']." {$lang->days}"; - } - - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_redirect")."\";"); - } - } - else if($delayedmod['type'] == 'merge') - { - $delayedmod['subject'] = htmlspecialchars_uni($delayedmod['inputs']['subject']); - $delayedmod['threadurl'] = htmlspecialchars_uni($delayedmod['inputs']['threadurl']); - eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_merge")."\";"); - } - - eval("\$delayedmods .= \"".$templates->get("moderation_threadnotes_delayedmodaction")."\";"); - $trow = alt_trow(); - } - if(!$delayedmods) - { - $cols = 4; - eval("\$delayedmods = \"".$templates->get("moderation_delayedmodaction_error")."\";"); - } - - $plugins->run_hooks("moderation_threadnotes"); - - eval("\$threadnotes = \"".$templates->get("moderation_threadnotes")."\";"); - output_page($threadnotes); - break; - - // Update the thread notes! - case "do_threadnotes": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - - $plugins->run_hooks("moderation_do_threadnotes"); - - log_moderator_action($modlogdata, $lang->thread_notes_edited); - $sqlarray = array( - "notes" => $db->escape_string($mybb->get_input('threadnotes')), - ); - $db->update_query("threads", $sqlarray, "tid='$tid'"); - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_threadnotesupdated); - break; - - // Let's look up the ip address of a post - case "getip": - add_breadcrumb($lang->nav_getip); - if(!is_moderator($fid, "canviewips")) - { - error_no_permission(); - } - - $post['ipaddress'] = my_inet_ntop($db->unescape_binary($post['ipaddress'])); - $hostname = @gethostbyaddr($post['ipaddress']); - if(!$hostname || $hostname == $post['ipaddress']) - { - $hostname = $lang->resolve_fail; - } - - $post['username'] = htmlspecialchars_uni($post['username']); - $username = build_profile_link($post['username'], $post['uid']); - - // Moderator options - $modoptions = ""; - if($mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canuseipsearch'] == 1) - { - $ipaddress = $post['ipaddress']; - eval("\$modoptions = \"".$templates->get("moderation_getip_modoptions")."\";"); - } - - $plugins->run_hooks('moderation_getip'); - - eval("\$getip = \"".$templates->get("moderation_getip")."\";"); - output_page($getip); - break; - - // Let's look up the ip address of a PM - case "getpmip": - if($pmid <= 0) - { - error($lang->error_invalidpm); - } - add_breadcrumb($lang->nav_pms, "private.php"); - $pm['subject'] = htmlspecialchars_uni($parser->parse_badwords($pm['subject'])); - add_breadcrumb($pm['subject'], "private.php?action=read&pmid={$pmid}"); - add_breadcrumb($lang->nav_getpmip); - if(!$mybb->usergroup['issupermod']) - { - error_no_permission(); - } - - $pm['ipaddress'] = my_inet_ntop($db->unescape_binary($pm['ipaddress'])); - $hostname = @gethostbyaddr($pm['ipaddress']); - if(!$hostname || $hostname == $pm['ipaddress']) - { - $hostname = $lang->resolve_fail; - } - - $name = $db->fetch_field($db->simple_select('users', 'username', "uid = {$pm['fromid']}"), 'username'); - $username = build_profile_link($name, $pm['fromid']); - - // Moderator options - $modoptions = ""; - if($mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canuseipsearch'] == 1) - { - $ipaddress = $pm['ipaddress']; - eval("\$modoptions = \"".$templates->get("moderation_getip_modoptions")."\";"); - } - - $plugins->run_hooks('moderation_getpmip'); - - eval("\$getpmip = \"".$templates->get("moderation_getpmip")."\";"); - output_page($getpmip); - break; - - // Merge threads - case "merge": - add_breadcrumb($lang->nav_merge); - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - - $plugins->run_hooks("moderation_merge"); - - eval("\$merge = \"".$templates->get("moderation_merge")."\";"); - output_page($merge); - break; - - // Let's get those threads together baby! (Merge threads) - case "do_merge": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - - $plugins->run_hooks("moderation_do_merge"); - - // explode at # sign in a url (indicates a name reference) and reassign to the url - $realurl = explode("#", $mybb->get_input('threadurl')); - $mybb->input['threadurl'] = $realurl[0]; - - // Are we using an SEO URL? - if(substr($mybb->input['threadurl'], -4) == "html") - { - // Get thread to merge's tid the SEO way - preg_match("#thread-([0-9]+)?#i", $mybb->input['threadurl'], $threadmatch); - preg_match("#post-([0-9]+)?#i", $mybb->input['threadurl'], $postmatch); - - if($threadmatch[1]) - { - $parameters['tid'] = $threadmatch[1]; - } - - if($postmatch[1]) - { - $parameters['pid'] = $postmatch[1]; - } - } - else - { - // Get thread to merge's tid the normal way - $splitloc = explode(".php", $mybb->input['threadurl']); - $temp = explode("&", my_substr($splitloc[1], 1)); - - if(!empty($temp)) - { - for($i = 0; $i < count($temp); $i++) - { - $temp2 = explode("=", $temp[$i], 2); - $parameters[$temp2[0]] = $temp2[1]; - } - } - else - { - $temp2 = explode("=", $splitloc[1], 2); - $parameters[$temp2[0]] = $temp2[1]; - } - } - - if(!empty($parameters['pid']) && empty($parameters['tid'])) - { - $post = get_post($parameters['pid']); - $mergetid = (int)$post['tid']; - } - elseif(!empty($parameters['tid'])) - { - $mergetid = (int)$parameters['tid']; - } - else - { - $mergetid = 0; - } - $mergethread = get_thread($mergetid); - if(!$mergethread) - { - error($lang->error_badmergeurl); - } - if($mergetid == $tid) - { // sanity check - error($lang->error_mergewithself); - } - if(!is_moderator($mergethread['fid'], "canmanagethreads")) - { - error_no_permission(); - } - if(isset($mybb->input['subject'])) - { - $subject = $mybb->get_input('subject'); - } - else - { - $subject = $thread['subject']; - } - - $moderation->merge_threads($mergetid, $tid, $subject); - - log_moderator_action($modlogdata, $lang->thread_merged); - - moderation_redirect(get_thread_link($tid), $lang->redirect_threadsmerged); - break; - - // Divorce the posts in this thread (Split!) - case "split": - add_breadcrumb($lang->nav_split); - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - $query = $db->query(" - SELECT p.*, u.* - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (p.uid=u.uid) - WHERE tid='$tid' - ORDER BY dateline ASC - "); - $numposts = $db->num_rows($query); - if($numposts <= 1) - { - error($lang->error_cantsplitonepost); - } - - $altbg = "trow1"; - $posts = ''; - while($post = $db->fetch_array($query)) - { - $postdate = my_date('relative', $post['dateline']); - $post['username'] = htmlspecialchars_uni($post['username']); - - $parser_options = array( - "allow_html" => $forum['allowhtml'], - "allow_mycode" => $forum['allowmycode'], - "allow_smilies" => $forum['allowsmilies'], - "allow_imgcode" => $forum['allowimgcode'], - "allow_videocode" => $forum['allowvideocode'], - "filter_badwords" => 1 - ); - if($post['smilieoff'] == 1) - { - $parser_options['allow_smilies'] = 0; - } - - $message = $parser->parse_message($post['message'], $parser_options); - eval("\$posts .= \"".$templates->get("moderation_split_post")."\";"); - $altbg = alt_trow(); - } - $forumselect = build_forum_jump("", $fid, 1, '', 0, true, '', "moveto"); - - $plugins->run_hooks("moderation_split"); - - eval("\$split = \"".$templates->get("moderation_split")."\";"); - output_page($split); - break; - - // Let's break them up buddy! (Do the split) - case "do_split": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - - $plugins->run_hooks("moderation_do_split"); - - $mybb->input['splitpost'] = $mybb->get_input('splitpost', MyBB::INPUT_ARRAY); - if(empty($mybb->input['splitpost'])) - { - error($lang->error_nosplitposts); - } - $query = $db->simple_select("posts", "COUNT(*) AS totalposts", "tid='{$tid}'"); - $count = $db->fetch_array($query); - - if($count['totalposts'] == 1) - { - error($lang->error_cantsplitonepost); - } - - if($count['totalposts'] == count($mybb->input['splitpost'])) - { - error($lang->error_cantsplitall); - } - - if(!empty($mybb->input['moveto'])) - { - $moveto = $mybb->get_input('moveto', MyBB::INPUT_INT); - } - else - { - $moveto = $fid; - } - - $newforum = get_forum($moveto); - if(!$newforum || $newforum['type'] != "f" || $newforum['type'] == "f" && $newforum['linkto'] != '') - { - error($lang->error_invalidforum); - } - - $pids = array(); - - // move the selected posts over - $query = $db->simple_select("posts", "pid", "tid='$tid'"); - while($post = $db->fetch_array($query)) - { - if(isset($mybb->input['splitpost'][$post['pid']]) && $mybb->input['splitpost'][$post['pid']] == 1) - { - $pids[] = $post['pid']; - } - mark_reports($post['pid'], "post"); - } - - $newtid = $moderation->split_posts($pids, $tid, $moveto, $mybb->get_input('newsubject')); - - log_moderator_action($modlogdata, $lang->thread_split); - - moderation_redirect(get_thread_link($newtid), $lang->redirect_threadsplit); - break; - - // Delete Thread Subscriptions - case "removesubscriptions": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!is_moderator($fid, "canmanagethreads")) - { - error_no_permission(); - } - - $plugins->run_hooks("moderation_removesubscriptions"); - - $moderation->remove_thread_subscriptions($tid, true); - - log_moderator_action($modlogdata, $lang->removed_subscriptions); - - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_removed_subscriptions); - break; - - // Delete Threads - Inline moderation - case "multideletethreads": - add_breadcrumb($lang->nav_multi_deletethreads); - - if(!empty($mybb->input['searchid'])) - { - // From search page - $threads = getids($mybb->get_input('searchid'), 'search'); - if(!is_moderator_by_tids($threads, 'candeletethreads')) - { - error_no_permission(); - } - } - else - { - $threads = getids($fid, 'forum'); - if(!is_moderator($fid, 'candeletethreads')) - { - error_no_permission(); - } - } - if(count($threads) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $inlineids = implode("|", $threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - $return_url = htmlspecialchars_uni($mybb->get_input('url')); - eval("\$multidelete = \"".$templates->get("moderation_inline_deletethreads")."\";"); - output_page($multidelete); - break; - - // Actually delete the threads - Inline moderation - case "do_multideletethreads": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $threadlist = explode("|", $mybb->get_input('threads')); - if(!is_moderator_by_tids($threadlist, "candeletethreads")) - { - error_no_permission(); - } - foreach($threadlist as $tid) - { - $tid = (int)$tid; - $moderation->delete_thread($tid); - $tlist[] = $tid; - } - log_moderator_action($modlogdata, $lang->multi_deleted_threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - mark_reports($tlist, "threads"); - moderation_redirect(get_forum_link($fid), $lang->redirect_inline_threadsdeleted); - break; - - // Open threads - Inline moderation - case "multiopenthreads": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!empty($mybb->input['searchid'])) - { - // From search page - $threads = getids($mybb->get_input('searchid'), 'search'); - if(!is_moderator_by_tids($threads, 'canopenclosethreads')) - { - error_no_permission(); - } - } - else - { - $threads = getids($fid, 'forum'); - if(!is_moderator($fid, 'canopenclosethreads')) - { - error_no_permission(); - } - } - - if(count($threads) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $moderation->open_threads($threads); - - log_moderator_action($modlogdata, $lang->multi_opened_threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - moderation_redirect(get_forum_link($fid), $lang->redirect_inline_threadsopened); - break; - - // Close threads - Inline moderation - case "multiclosethreads": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!empty($mybb->input['searchid'])) - { - // From search page - $threads = getids($mybb->get_input('searchid'), 'search'); - if(!is_moderator_by_tids($threads, 'canopenclosethreads')) - { - error_no_permission(); - } - } - else - { - $threads = getids($fid, 'forum'); - if(!is_moderator($fid, 'canopenclosethreads')) - { - error_no_permission(); - } - } - if(count($threads) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $moderation->close_threads($threads); - - log_moderator_action($modlogdata, $lang->multi_closed_threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - moderation_redirect(get_forum_link($fid), $lang->redirect_inline_threadsclosed); - break; - - // Approve threads - Inline moderation - case "multiapprovethreads": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!empty($mybb->input['searchid'])) - { - // From search page - $threads = getids($mybb->get_input('searchid'), 'search'); - if(!is_moderator_by_tids($threads, 'canapproveunapprovethreads')) - { - error_no_permission(); - } - } - else - { - $threads = getids($fid, 'forum'); - if(!is_moderator($fid, 'canapproveunapprovethreads')) - { - error_no_permission(); - } - } - if(count($threads) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $moderation->approve_threads($threads, $fid); - - log_moderator_action($modlogdata, $lang->multi_approved_threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - $cache->update_stats(); - moderation_redirect(get_forum_link($fid), $lang->redirect_inline_threadsapproved); - break; - - // Unapprove threads - Inline moderation - case "multiunapprovethreads": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!empty($mybb->input['searchid'])) - { - // From search page - $threads = getids($mybb->get_input('searchid'), 'search'); - if(!is_moderator_by_tids($threads, 'canapproveunapprovethreads')) - { - error_no_permission(); - } - } - else - { - $threads = getids($fid, 'forum'); - if(!is_moderator($fid, 'canapproveunapprovethreads')) - { - error_no_permission(); - } - } - if(count($threads) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $moderation->unapprove_threads($threads, $fid); - - log_moderator_action($modlogdata, $lang->multi_unapproved_threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - $cache->update_stats(); - moderation_redirect(get_forum_link($fid), $lang->redirect_inline_threadsunapproved); - break; - - // Restore threads - Inline moderation - case "multirestorethreads": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!empty($mybb->input['searchid'])) - { - // From search page - $threads = getids($mybb->get_input('searchid'), 'search'); - if(!is_moderator_by_tids($threads, 'canrestorethreads')) - { - error_no_permission(); - } - } - else - { - $threads = getids($fid, 'forum'); - if(!is_moderator($fid, 'canrestorethreads')) - { - error_no_permission(); - } - } - if(count($threads) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $moderation->restore_threads($threads); - - log_moderator_action($modlogdata, $lang->multi_restored_threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - $cache->update_stats(); - moderation_redirect(get_forum_link($fid), $lang->redirect_inline_threadsrestored); - break; - - // Soft delete threads - Inline moderation - case "multisoftdeletethreads": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!empty($mybb->input['searchid'])) - { - // From search page - $threads = getids($mybb->get_input('searchid'), 'search'); - if(!is_moderator_by_tids($threads, 'cansoftdeletethreads')) - { - error_no_permission(); - } - } - else - { - $threads = getids($fid, 'forum'); - if(!is_moderator($fid, 'cansoftdeletethreads')) - { - error_no_permission(); - } - } - if(count($threads) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $moderation->soft_delete_threads($threads); - - log_moderator_action($modlogdata, $lang->multi_soft_deleted_threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - $cache->update_stats(); - moderation_redirect(get_forum_link($fid), $lang->redirect_inline_threadssoftdeleted); - break; - - // Stick threads - Inline moderation - case "multistickthreads": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!empty($mybb->input['searchid'])) - { - // From search page - $threads = getids($mybb->get_input('searchid'), 'search'); - if(!is_moderator_by_tids($threads, 'canstickunstickthreads')) - { - error_no_permission(); - } - } - else - { - $threads = getids($fid, 'forum'); - if(!is_moderator($fid, 'canstickunstickthreads')) - { - error_no_permission(); - } - } - if(count($threads) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $moderation->stick_threads($threads); - - log_moderator_action($modlogdata, $lang->multi_stuck_threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - moderation_redirect(get_forum_link($fid), $lang->redirect_inline_threadsstuck); - break; - - // Unstick threads - Inline moderaton - case "multiunstickthreads": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(!empty($mybb->input['searchid'])) - { - // From search page - $threads = getids($mybb->get_input('searchid'), 'search'); - if(!is_moderator_by_tids($threads, 'canstickunstickthreads')) - { - error_no_permission(); - } - } - else - { - $threads = getids($fid, 'forum'); - if(!is_moderator($fid, 'canstickunstickthreads')) - { - error_no_permission(); - } - } - if(count($threads) < 1) - { - error($lang->error_inline_nothreadsselected); - } - - $moderation->unstick_threads($threads); - - log_moderator_action($modlogdata, $lang->multi_unstuck_threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - moderation_redirect(get_forum_link($fid), $lang->redirect_inline_threadsunstuck); - break; - - // Move threads - Inline moderation - case "multimovethreads": - add_breadcrumb($lang->nav_multi_movethreads); - - if(!empty($mybb->input['searchid'])) - { - // From search page - $threads = getids($mybb->get_input('searchid'), 'search'); - if(!is_moderator_by_tids($threads, 'canmanagethreads')) - { - error_no_permission(); - } - } - else - { - $threads = getids($fid, 'forum'); - if(!is_moderator($fid, 'canmanagethreads')) - { - error_no_permission(); - } - } - - if(count($threads) < 1) - { - error($lang->error_inline_nothreadsselected); - } - $inlineids = implode("|", $threads); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($fid, 'forum'); - } - $forumselect = build_forum_jump("", '', 1, '', 0, true, '', "moveto"); - $return_url = htmlspecialchars_uni($mybb->get_input('url')); - eval("\$movethread = \"".$templates->get("moderation_inline_movethreads")."\";"); - output_page($movethread); - break; - - // Actually move the threads in Inline moderation - case "do_multimovethreads": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $moveto = $mybb->get_input('moveto', MyBB::INPUT_INT); - $threadlist = explode("|", $mybb->get_input('threads')); - if(!is_moderator_by_tids($threadlist, 'canmanagethreads')) - { - error_no_permission(); - } - foreach($threadlist as $tid) - { - $tids[] = (int)$tid; - } - // Make sure moderator has permission to move to the new forum - $newperms = forum_permissions($moveto); - if(($newperms['canview'] == 0 || !is_moderator($moveto, 'canmanagethreads')) && !is_moderator_by_tids($tids, 'canmovetononmodforum')) - { - error_no_permission(); - } - - $newforum = get_forum($moveto); - if(!$newforum || $newforum['type'] != "f" || $newforum['type'] == "f" && $newforum['linkto'] != '') - { - error($lang->error_invalidforum); - } - - $moderation->move_threads($tids, $moveto); - - log_moderator_action($modlogdata, $lang->multi_moved_threads); - - moderation_redirect(get_forum_link($moveto), $lang->redirect_inline_threadsmoved); - break; - - // Delete posts - Inline moderation - case "multideleteposts": - add_breadcrumb($lang->nav_multi_deleteposts); - - if($mybb->get_input('inlinetype') == 'search') - { - $posts = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $posts = getids($tid, 'thread'); - } - - if(count($posts) < 1) - { - error($lang->error_inline_nopostsselected); - } - if(!is_moderator_by_pids($posts, "candeleteposts")) - { - error_no_permission(); - } - $inlineids = implode("|", $posts); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($tid, 'thread'); - } - - $return_url = htmlspecialchars_uni($mybb->get_input('url')); - - eval("\$multidelete = \"".$templates->get("moderation_inline_deleteposts")."\";"); - output_page($multidelete); - break; - - // Actually delete the posts in inline moderation - case "do_multideleteposts": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $postlist = explode("|", $mybb->get_input('posts')); - if(!is_moderator_by_pids($postlist, "candeleteposts")) - { - error_no_permission(); - } - $postlist = array_map('intval', $postlist); - $pids = implode(',', $postlist); - - $tids = array(); - if($pids) - { - $query = $db->simple_select("threads", "tid", "firstpost IN({$pids})"); - while($threadid = $db->fetch_field($query, "tid")) - { - $tids[] = $threadid; - } - } - - $deletecount = 0; - foreach($postlist as $pid) - { - $pid = (int)$pid; - $moderation->delete_post($pid); - $plist[] = $pid; - $deletecount++; - } - - // If we have multiple threads, we must be coming from the search - if(!empty($tids)) - { - foreach($tids as $tid) - { - $moderation->delete_thread($tid); - mark_reports($tid, "thread"); - $url = get_forum_link($fid); - } - } - // Otherwise we're just deleting from showthread.php - else - { - $query = $db->simple_select("posts", "pid", "tid = $tid"); - $numposts = $db->num_rows($query); - if(!$numposts) - { - $moderation->delete_thread($tid); - mark_reports($tid, "thread"); - $url = get_forum_link($fid); - } - else - { - mark_reports($plist, "posts"); - $url = get_thread_link($thread['tid']); - } - } - - $lang->deleted_selective_posts = $lang->sprintf($lang->deleted_selective_posts, $deletecount); - log_moderator_action($modlogdata, $lang->deleted_selective_posts); - moderation_redirect($url, $lang->redirect_postsdeleted); - break; - - // Merge posts - Inline moderation - case "multimergeposts": - add_breadcrumb($lang->nav_multi_mergeposts); - - if($mybb->get_input('inlinetype') == 'search') - { - $posts = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $posts = getids($tid, 'thread'); - } - - // Add the selected posts from other threads - foreach($mybb->cookies as $key => $value) - { - if(strpos($key, "inlinemod_thread") !== false && $key != "inlinemod_thread$tid") - { - $inlinepostlist = explode("|", $mybb->cookies[$key]); - foreach($inlinepostlist as $p) - { - $p = (int)$p; - - if(!empty($p)) - { - $posts[] = (int)$p; - } - } - // Remove the cookie once its data is retrieved - my_unsetcookie($key); - } - } - - if(empty($posts)) - { - error($lang->error_inline_nopostsselected); - } - - if(!is_moderator_by_pids($posts, "canmanagethreads")) - { - error_no_permission(); - } - - $postlist = ""; - $query = $db->query(" - SELECT p.*, u.* - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (p.uid=u.uid) - WHERE pid IN (".implode($posts, ",").") - ORDER BY dateline ASC - "); - $altbg = "trow1"; - while($post = $db->fetch_array($query)) - { - $postdate = my_date('relative', $post['dateline']); - - $parser_options = array( - "allow_html" => $forum['allowhtml'], - "allow_mycode" => $forum['allowmycode'], - "allow_smilies" => $forum['allowsmilies'], - "allow_imgcode" => $forum['allowimgcode'], - "allow_videocode" => $forum['allowvideocode'], - "filter_badwords" => 1 - ); - if($post['smilieoff'] == 1) - { - $parser_options['allow_smilies'] = 0; - } - - $message = $parser->parse_message($post['message'], $parser_options); - eval("\$postlist .= \"".$templates->get("moderation_mergeposts_post")."\";"); - $altbg = alt_trow(); - } - - $inlineids = implode("|", $posts); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($tid, 'thread'); - } - - $return_url = htmlspecialchars_uni($mybb->get_input('url')); - - eval("\$multimerge = \"".$templates->get("moderation_inline_mergeposts")."\";"); - output_page($multimerge); - break; - - // Actually merge the posts - Inline moderation - case "do_multimergeposts": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $mergepost = $mybb->get_input('mergepost', MyBB::INPUT_ARRAY); - if(count($mergepost) <= 1) - { - error($lang->error_nomergeposts); - } - - foreach($mergepost as $pid => $yes) - { - $postlist[] = (int)$pid; - } - - if(!is_moderator_by_pids($postlist, "canmanagethreads")) - { - error_no_permission(); - } - - $masterpid = $moderation->merge_posts($postlist, $tid, $mybb->input['sep']); - - mark_reports($postlist, "posts"); - log_moderator_action($modlogdata, $lang->merged_selective_posts); - moderation_redirect(get_post_link($masterpid)."#pid$masterpid", $lang->redirect_inline_postsmerged); - break; - - // Split posts - Inline moderation - case "multisplitposts": - add_breadcrumb($lang->nav_multi_splitposts); - - if($mybb->get_input('inlinetype') == 'search') - { - $posts = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $posts = getids($tid, 'thread'); - } - - if(count($posts) < 1) - { - error($lang->error_inline_nopostsselected); - } - - if(!is_moderator_by_pids($posts, "canmanagethreads")) - { - error_no_permission(); - } - $posts = array_map('intval', $posts); - $pidin = implode(',', $posts); - - // Make sure that we are not splitting a thread with one post - // Select number of posts in each thread that the splitted post is in - $query = $db->query(" - SELECT DISTINCT p.tid, COUNT(q.pid) as count - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."posts q ON (p.tid=q.tid) - WHERE p.pid IN ($pidin) - GROUP BY p.tid, p.pid - "); - $threads = $pcheck = array(); - while($tcheck = $db->fetch_array($query)) - { - if((int)$tcheck['count'] <= 1) - { - error($lang->error_cantsplitonepost); - } - $threads[] = $pcheck[] = $tcheck['tid']; // Save tids for below - } - - // Make sure that we are not splitting all posts in the thread - // The query does not return a row when the count is 0, so find if some threads are missing (i.e. 0 posts after removal) - $query = $db->query(" - SELECT DISTINCT p.tid, COUNT(q.pid) as count - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."posts q ON (p.tid=q.tid) - WHERE p.pid IN ($pidin) AND q.pid NOT IN ($pidin) - GROUP BY p.tid, p.pid - "); - $pcheck2 = array(); - while($tcheck = $db->fetch_array($query)) - { - if($tcheck['count'] > 0) - { - $pcheck2[] = $tcheck['tid']; - } - } - if(count($pcheck2) != count($pcheck)) - { - // One or more threads do not have posts after splitting - error($lang->error_cantsplitall); - } - - $inlineids = implode("|", $posts); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($tid, 'thread'); - } - $forumselect = build_forum_jump("", $fid, 1, '', 0, true, '', "moveto"); - - $return_url = htmlspecialchars_uni($mybb->get_input('url')); - - eval("\$splitposts = \"".$templates->get("moderation_inline_splitposts")."\";"); - output_page($splitposts); - break; - - // Actually split the posts - Inline moderation - case "do_multisplitposts": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plist = array(); - $postlist = explode("|", $mybb->get_input('posts')); - foreach($postlist as $pid) - { - $pid = (int)$pid; - $plist[] = $pid; - } - - if(!is_moderator_by_pids($plist, "canmanagethreads")) - { - error_no_permission(); - } - - // Ensure all posts exist - $posts = array(); - if(!empty($plist)) - { - $query = $db->simple_select('posts', 'pid', 'pid IN ('.implode(',', $plist).')'); - while($pid = $db->fetch_field($query, 'pid')) - { - $posts[] = $pid; - } - } - - if(empty($posts)) - { - error($lang->error_inline_nopostsselected); - } - - $pidin = implode(',', $posts); - - // Make sure that we are not splitting a thread with one post - // Select number of posts in each thread that the splitted post is in - $query = $db->query(" - SELECT DISTINCT p.tid, COUNT(q.pid) as count - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."posts q ON (p.tid=q.tid) - WHERE p.pid IN ($pidin) - GROUP BY p.tid, p.pid - "); - $pcheck = array(); - while($tcheck = $db->fetch_array($query)) - { - if((int)$tcheck['count'] <= 1) - { - error($lang->error_cantsplitonepost); - } - $pcheck[] = $tcheck['tid']; // Save tids for below - } - - // Make sure that we are not splitting all posts in the thread - // The query does not return a row when the count is 0, so find if some threads are missing (i.e. 0 posts after removal) - $query = $db->query(" - SELECT DISTINCT p.tid, COUNT(q.pid) as count - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."posts q ON (p.tid=q.tid) - WHERE p.pid IN ($pidin) AND q.pid NOT IN ($pidin) - GROUP BY p.tid, p.pid - "); - $pcheck2 = array(); - while($tcheck = $db->fetch_array($query)) - { - if($tcheck['count'] > 0) - { - $pcheck2[] = $tcheck['tid']; - } - } - if(count($pcheck2) != count($pcheck)) - { - // One or more threads do not have posts after splitting - error($lang->error_cantsplitall); - } - - if(isset($mybb->input['moveto'])) - { - $moveto = $mybb->get_input('moveto', MyBB::INPUT_INT); - } - else - { - $moveto = $fid; - } - - $newforum = get_forum($moveto); - if(!$newforum || $newforum['type'] != "f" || $newforum['type'] == "f" && $newforum['linkto'] != '') - { - error($lang->error_invalidforum); - } - - $newsubject = $mybb->get_input('newsubject'); - $newtid = $moderation->split_posts($posts, $tid, $moveto, $newsubject); - - $pid_list = implode(', ', $posts); - $lang->split_selective_posts = $lang->sprintf($lang->split_selective_posts, $pid_list, $newtid); - log_moderator_action($modlogdata, $lang->split_selective_posts); - - moderation_redirect(get_thread_link($newtid), $lang->redirect_threadsplit); - break; - - // Move posts - Inline moderation - case "multimoveposts": - add_breadcrumb($lang->nav_multi_moveposts); - - if($mybb->get_input('inlinetype') == 'search') - { - $posts = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $posts = getids($tid, 'thread'); - } - - if(count($posts) < 1) - { - error($lang->error_inline_nopostsselected); - } - - if(!is_moderator_by_pids($posts, "canmanagethreads")) - { - error_no_permission(); - } - $posts = array_map('intval', $posts); - $pidin = implode(',', $posts); - - // Make sure that we are not moving posts in a thread with one post - // Select number of posts in each thread that the moved post is in - $query = $db->query(" - SELECT DISTINCT p.tid, COUNT(q.pid) as count - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."posts q ON (p.tid=q.tid) - WHERE p.pid IN ($pidin) - GROUP BY p.tid, p.pid - "); - $threads = $pcheck = array(); - while($tcheck = $db->fetch_array($query)) - { - if((int)$tcheck['count'] <= 1) - { - error($lang->error_cantsplitonepost); - } - $threads[] = $pcheck[] = $tcheck['tid']; // Save tids for below - } - - // Make sure that we are not moving all posts in the thread - // The query does not return a row when the count is 0, so find if some threads are missing (i.e. 0 posts after removal) - $query = $db->query(" - SELECT DISTINCT p.tid, COUNT(q.pid) as count - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."posts q ON (p.tid=q.tid) - WHERE p.pid IN ($pidin) AND q.pid NOT IN ($pidin) - GROUP BY p.tid, p.pid - "); - $pcheck2 = array(); - while($tcheck = $db->fetch_array($query)) - { - if($tcheck['count'] > 0) - { - $pcheck2[] = $tcheck['tid']; - } - } - if(count($pcheck2) != count($pcheck)) - { - // One or more threads do not have posts after splitting - error($lang->error_cantmoveall); - } - - $inlineids = implode("|", $posts); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($tid, 'thread'); - } - $forumselect = build_forum_jump("", $fid, 1, '', 0, true, '', "moveto"); - eval("\$moveposts = \"".$templates->get("moderation_inline_moveposts")."\";"); - output_page($moveposts); - break; - - // Actually split the posts - Inline moderation - case "do_multimoveposts": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("moderation_do_multimoveposts"); - - // explode at # sign in a url (indicates a name reference) and reassign to the url - $realurl = explode("#", $mybb->get_input('threadurl')); - $mybb->input['threadurl'] = $realurl[0]; - - // Are we using an SEO URL? - if(substr($mybb->input['threadurl'], -4) == "html") - { - // Get thread to merge's tid the SEO way - preg_match("#thread-([0-9]+)?#i", $mybb->input['threadurl'], $threadmatch); - preg_match("#post-([0-9]+)?#i", $mybb->input['threadurl'], $postmatch); - - if($threadmatch[1]) - { - $parameters['tid'] = $threadmatch[1]; - } - - if($postmatch[1]) - { - $parameters['pid'] = $postmatch[1]; - } - } - else - { - // Get thread to merge's tid the normal way - $splitloc = explode(".php", $mybb->input['threadurl']); - $temp = explode("&", my_substr($splitloc[1], 1)); - - if(!empty($temp)) - { - for($i = 0; $i < count($temp); $i++) - { - $temp2 = explode("=", $temp[$i], 2); - $parameters[$temp2[0]] = $temp2[1]; - } - } - else - { - $temp2 = explode("=", $splitloc[1], 2); - $parameters[$temp2[0]] = $temp2[1]; - } - } - - if(!empty($parameters['pid']) && empty($parameters['tid'])) - { - $query = $db->simple_select("posts", "tid", "pid='".(int)$parameters['pid']."'"); - $post = $db->fetch_array($query); - $newtid = $post['tid']; - } - elseif(!empty($parameters['tid'])) - { - $newtid = $parameters['tid']; - } - else - { - $newtid = 0; - } - $newtid = (int)$newtid; - $newthread = get_thread($newtid); - if(!$newthread) - { - error($lang->error_badmovepostsurl); - } - if($newtid == $tid) - { // sanity check - error($lang->error_movetoself); - } - - $postlist = explode("|", $mybb->get_input('posts')); - $plist = array(); - foreach($postlist as $pid) - { - $pid = (int)$pid; - $plist[] = $pid; - } - - if(!is_moderator_by_pids($plist, "canmanagethreads")) - { - error_no_permission(); - } - - // Ensure all posts exist - $posts = array(); - if(!empty($plist)) - { - $query = $db->simple_select('posts', 'pid', 'pid IN ('.implode(',', $plist).')'); - while($pid = $db->fetch_field($query, 'pid')) - { - $posts[] = $pid; - } - } - - if(empty($posts)) - { - error($lang->error_inline_nopostsselected); - } - - $pidin = implode(',', $posts); - - // Make sure that we are not moving posts in a thread with one post - // Select number of posts in each thread that the moved post is in - $query = $db->query(" - SELECT DISTINCT p.tid, COUNT(q.pid) as count - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."posts q ON (p.tid=q.tid) - WHERE p.pid IN ($pidin) - GROUP BY p.tid, p.pid - "); - $threads = $pcheck = array(); - while($tcheck = $db->fetch_array($query)) - { - if((int)$tcheck['count'] <= 1) - { - error($lang->error_cantsplitonepost); - } - $threads[] = $pcheck[] = $tcheck['tid']; // Save tids for below - } - - // Make sure that we are not moving all posts in the thread - // The query does not return a row when the count is 0, so find if some threads are missing (i.e. 0 posts after removal) - $query = $db->query(" - SELECT DISTINCT p.tid, COUNT(q.pid) as count - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."posts q ON (p.tid=q.tid) - WHERE p.pid IN ($pidin) AND q.pid NOT IN ($pidin) - GROUP BY p.tid, p.pid - "); - $pcheck2 = array(); - while($tcheck = $db->fetch_array($query)) - { - if($tcheck['count'] > 0) - { - $pcheck2[] = $tcheck['tid']; - } - } - if(count($pcheck2) != count($pcheck)) - { - // One or more threads do not have posts after splitting - error($lang->error_cantmoveall); - } - - $newtid = $moderation->split_posts($posts, $tid, $newthread['fid'], $db->escape_string($newthread['subject']), $newtid); - - $pid_list = implode(', ', $posts); - $lang->move_selective_posts = $lang->sprintf($lang->move_selective_posts, $pid_list, $newtid); - log_moderator_action($modlogdata, $lang->move_selective_posts); - - moderation_redirect(get_thread_link($newtid), $lang->redirect_moveposts); - break; - - // Approve posts - Inline moderation - case "multiapproveposts": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->get_input('inlinetype') == 'search') - { - $posts = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $posts = getids($tid, 'thread'); - } - if(count($posts) < 1) - { - error($lang->error_inline_nopostsselected); - } - - if(!is_moderator_by_pids($posts, "canapproveunapproveposts")) - { - error_no_permission(); - } - - $pids = array(); - foreach($posts as $pid) - { - $pids[] = (int)$pid; - } - - $moderation->approve_posts($pids); - - log_moderator_action($modlogdata, $lang->multi_approve_posts); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($tid, 'thread'); - } - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_inline_postsapproved); - break; - - // Unapprove posts - Inline moderation - case "multiunapproveposts": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->get_input('inlinetype') == 'search') - { - $posts = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $posts = getids($tid, 'thread'); - } - - if(count($posts) < 1) - { - error($lang->error_inline_nopostsselected); - } - $pids = array(); - - if(!is_moderator_by_pids($posts, "canapproveunapproveposts")) - { - error_no_permission(); - } - foreach($posts as $pid) - { - $pids[] = (int)$pid; - } - - $moderation->unapprove_posts($pids); - - log_moderator_action($modlogdata, $lang->multi_unapprove_posts); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($tid, 'thread'); - } - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_inline_postsunapproved); - break; - - // Restore posts - Inline moderation - case "multirestoreposts": - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->get_input('inlinetype') == 'search') - { - $posts = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $posts = getids($tid, 'thread'); - } - if(count($posts) < 1) - { - error($lang->error_inline_nopostsselected); - } - - if(!is_moderator_by_pids($posts, "canrestoreposts")) - { - error_no_permission(); - } - - $pids = array(); - foreach($posts as $pid) - { - $pids[] = (int)$pid; - } - - $moderation->restore_posts($pids); - - log_moderator_action($modlogdata, $lang->multi_restore_posts); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($tid, 'thread'); - } - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_inline_postsrestored); - break; - - // Soft delete posts - Inline moderation - case "multisoftdeleteposts": - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->get_input('inlinetype') == 'search') - { - $posts = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $posts = getids($tid, 'thread'); - } - - if(count($posts) < 1) - { - error($lang->error_inline_nopostsselected); - } - $pids = array(); - - if(!is_moderator_by_pids($posts, "cansoftdeleteposts")) - { - error_no_permission(); - } - foreach($posts as $pid) - { - $pids[] = (int)$pid; - } - - $moderation->soft_delete_posts($pids); - log_moderator_action($modlogdata, $lang->multi_soft_delete_posts); - - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - } - else - { - clearinline($tid, 'thread'); - } - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_inline_postssoftdeleted); - break; - case "do_purgespammer": - case "purgespammer": - require_once MYBB_ROOT."inc/functions_user.php"; - - $groups = explode(",", $mybb->settings['purgespammergroups']); - if(!in_array($mybb->user['usergroup'], $groups)) - { - error_no_permission(); - } - - $uid = $mybb->input['uid']; - $user = get_user($uid); - if(!$user['uid'] || !purgespammer_show($user['postnum'], $user['usergroup'], $user['uid'])) - { - error($lang->purgespammer_invalid_user); - } - - if($mybb->input['action'] == "do_purgespammer") - { - verify_post_check($mybb->get_input('my_post_key')); - - $user_deleted = false; - - // Run the hooks first to avoid any issues when we delete the user - $plugins->run_hooks("moderation_purgespammer_purge"); - - require_once MYBB_ROOT.'inc/datahandlers/user.php'; - $userhandler = new UserDataHandler('delete'); - - if($mybb->settings['purgespammerbandelete'] == "ban") - { - // First delete everything - $userhandler->delete_content($uid); - $userhandler->delete_posts($uid); - - // Next ban him (or update the banned reason, shouldn't happen) - $query = $db->simple_select("banned", "uid", "uid = '{$uid}'"); - if($db->num_rows($query) > 0) - { - $banupdate = array( - "reason" => $db->escape_string($mybb->settings['purgespammerbanreason']) - ); - $db->update_query('banned', $banupdate, "uid = '{$uid}'"); - } - else - { - $insert = array( - "uid" => $uid, - "gid" => (int)$mybb->settings['purgespammerbangroup'], - "oldgroup" => 2, - "oldadditionalgroups" => "", - "olddisplaygroup" => 0, - "admin" => (int)$mybb->user['uid'], - "dateline" => TIME_NOW, - "bantime" => "---", - "lifted" => 0, - "reason" => $db->escape_string($mybb->settings['purgespammerbanreason']) - ); - $db->insert_query('banned', $insert); - } - - // Add the IP's to the banfilters - foreach(array($user['regip'], $user['lastip']) as $ip) - { - $ip = my_inet_ntop($db->unescape_binary($ip)); - $query = $db->simple_select("banfilters", "type", "type = 1 AND filter = '".$db->escape_string($ip)."'"); - if($db->num_rows($query) == 0) - { - $insert = array( - "filter" => $db->escape_string($ip), - "type" => 1, - "dateline" => TIME_NOW - ); - $db->insert_query("banfilters", $insert); - } - } - - // Clear the profile - $userhandler->clear_profile($uid, $mybb->settings['purgespammerbangroup']); - - $cache->update_banned(); - $cache->update_bannedips(); - $cache->update_awaitingactivation(); - - // Update reports cache - $cache->update_reportedcontent(); - } - elseif($mybb->settings['purgespammerbandelete'] == "delete") - { - $user_deleted = $userhandler->delete_user($uid, 1); - } - - // Submit the user to stop forum spam - if(!empty($mybb->settings['purgespammerapikey'])) - { - $sfs = @fetch_remote_file("http://stopforumspam.com/add.php?username=" . urlencode($user['username']) . "&ip_addr=" . urlencode(my_inet_ntop($db->unescape_binary($user['lastip']))) . "&email=" . urlencode($user['email']) . "&api_key=" . urlencode($mybb->settings['purgespammerapikey'])); - } - - log_moderator_action(array('uid' => $uid, 'username' => $user['username']), $lang->purgespammer_modlog); - - if($user_deleted) - { - redirect($mybb->settings['bburl'], $lang->purgespammer_success); - } - else - { - redirect(get_profile_link($uid), $lang->purgespammer_success); - } - } - else if($mybb->input['action'] == "purgespammer") - { - $plugins->run_hooks("moderation_purgespammer_show"); - - add_breadcrumb($lang->purgespammer); - $lang->purgespammer_purge = $lang->sprintf($lang->purgespammer_purge, htmlspecialchars_uni($user['username'])); - if($mybb->settings['purgespammerbandelete'] == "ban") - { - $lang->purgespammer_purge_desc = $lang->sprintf($lang->purgespammer_purge_desc, $lang->purgespammer_ban); - } - else - { - $lang->purgespammer_purge_desc = $lang->sprintf($lang->purgespammer_purge_desc, $lang->purgespammer_delete); - } - eval("\$purgespammer = \"".$templates->get('moderation_purgespammer')."\";"); - output_page($purgespammer); - } - break; - default: - require_once MYBB_ROOT."inc/class_custommoderation.php"; - $custommod = new CustomModeration; - $tool = $custommod->tool_info($mybb->get_input('action', MyBB::INPUT_INT)); - if($tool !== false) - { - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $options = my_unserialize($tool['threadoptions']); - - if(!is_member($tool['groups'])) - { - error_no_permission(); - } - - if(!empty($options['confirmation']) && empty($mybb->input['confirm'])) - { - add_breadcrumb($lang->confirm_execute_tool); - - $lang->confirm_execute_tool_desc = $lang->sprintf($lang->confirm_execute_tool_desc, htmlspecialchars_uni($tool['name'])); - - $modtype = $mybb->get_input('modtype'); - $inlinetype = $mybb->get_input('inlinetype'); - $searchid = $mybb->get_input('searchid'); - $url = htmlspecialchars_uni($mybb->get_input('url')); - $plugins->run_hooks('moderation_confirmation'); - - eval('$page = "'.$templates->get('moderation_confirmation').'";'); - - output_page($page); - exit; - } - - if($tool['type'] == 't' && $mybb->get_input('modtype') == 'inlinethread') - { - if($mybb->get_input('inlinetype') == 'search') - { - $tids = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $tids = getids($fid, "forum"); - } - if(count($tids) < 1) - { - error($lang->error_inline_nopostsselected); - } - if(!is_moderator_by_tids($tids, "canusecustomtools")) - { - error_no_permission(); - } - - $thread_options = my_unserialize($tool['threadoptions']); - if($thread_options['movethread'] && $forum_cache[$thread_options['movethread']]['type'] != "f") - { - error($lang->error_movetocategory); - } - - $custommod->execute($mybb->get_input('action', MyBB::INPUT_INT), $tids); - $lang->custom_tool = $lang->sprintf($lang->custom_tool, $tool['name']); - log_moderator_action($modlogdata, $lang->custom_tool); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - $lang->redirect_customtool_search = $lang->sprintf($lang->redirect_customtool_search, $tool['name']); - $return_url = htmlspecialchars_uni($mybb->get_input('url')); - redirect($return_url, $lang->redirect_customtool_search); - } - else - { - clearinline($fid, "forum"); - $lang->redirect_customtool_forum = $lang->sprintf($lang->redirect_customtool_forum, $tool['name']); - redirect(get_forum_link($fid), $lang->redirect_customtool_forum); - } - break; - } - elseif($tool['type'] == 't' && $mybb->get_input('modtype') == 'thread') - { - if(!is_moderator_by_tids($tid, "canusecustomtools")) - { - error_no_permission(); - } - - $thread_options = my_unserialize($tool['threadoptions']); - if($thread_options['movethread'] && $forum_cache[$thread_options['movethread']]['type'] != "f") - { - error($lang->error_movetocategory); - } - - $ret = $custommod->execute($mybb->get_input('action', MyBB::INPUT_INT), $tid); - $lang->custom_tool = $lang->sprintf($lang->custom_tool, $tool['name']); - log_moderator_action($modlogdata, $lang->custom_tool); - if($ret == 'forum') - { - $lang->redirect_customtool_forum = $lang->sprintf($lang->redirect_customtool_forum, $tool['name']); - moderation_redirect(get_forum_link($fid), $lang->redirect_customtool_forum); - } - else - { - $lang->redirect_customtool_thread = $lang->sprintf($lang->redirect_customtool_thread, $tool['name']); - moderation_redirect(get_thread_link($thread['tid']), $lang->redirect_customtool_thread); - } - break; - } - elseif($tool['type'] == 'p' && $mybb->get_input('modtype') == 'inlinepost') - { - if($mybb->get_input('inlinetype') == 'search') - { - $pids = getids($mybb->get_input('searchid'), 'search'); - } - else - { - $pids = getids($tid, 'thread'); - } - - if(count($pids) < 1) - { - error($lang->error_inline_nopostsselected); - } - if(!is_moderator_by_pids($pids, "canusecustomtools")) - { - error_no_permission(); - } - - // Get threads which are associated with the posts - $tids = array(); - $options = array( - 'order_by' => 'dateline', - 'order_dir' => 'asc' - ); - $query = $db->simple_select("posts", "DISTINCT tid, dateline", "pid IN (".implode(',',$pids).")", $options); - while($row = $db->fetch_array($query)) - { - $tids[] = $row['tid']; - } - - $ret = $custommod->execute($mybb->get_input('action', MyBB::INPUT_INT), $tids, $pids); - $lang->custom_tool = $lang->sprintf($lang->custom_tool, $tool['name']); - log_moderator_action($modlogdata, $lang->custom_tool); - if($mybb->get_input('inlinetype') == 'search') - { - clearinline($mybb->get_input('searchid', MyBB::INPUT_INT), 'search'); - $lang->redirect_customtool_search = $lang->sprintf($lang->redirect_customtool_search, $tool['name']); - $return_url = htmlspecialchars_uni($mybb->get_input('url')); - redirect($return_url, $lang->redirect_customtool_search); - } - else - { - clearinline($tid, 'thread'); - if($ret == 'forum') - { - $lang->redirect_customtool_forum = $lang->sprintf($lang->redirect_customtool_forum, $tool['name']); - moderation_redirect(get_forum_link($fid), $lang->redirect_customtool_forum); - } - else - { - $lang->redirect_customtool_thread = $lang->sprintf($lang->redirect_customtool_thread, $tool['name']); - moderation_redirect(get_thread_link($tid), $lang->redirect_customtool_thread); - } - } - - break; - } - } - error_no_permission(); - break; -} - -/** - * Some little handy functions for our inline moderation - * - * @param int $id - * @param string $type - * - * @return array - */ -function getids($id, $type) -{ - global $mybb; - - $newids = array(); - $cookie = "inlinemod_".$type.$id; - if(isset($mybb->cookies[$cookie])) - { - $cookie_ids = explode("|", $mybb->cookies[$cookie]); - - foreach($cookie_ids as $cookie_id) - { - if(empty($cookie_id)) - { - continue; - } - - if($cookie_id == 'ALL') - { - $newids += getallids($id, $type); - } - else - { - $newids[] = (int)$cookie_id; - } - } - } - - return $newids; -} - -/** - * @param int $id - * @param string $type - * - * @return array - */ -function getallids($id, $type) -{ - global $db, $mybb; - - $ids = array(); - - // Get any removed threads (after our user hit 'all') - $removed_ids = array(); - $cookie = "inlinemod_".$type.$id."_removed"; - if(isset($mybb->cookies[$cookie])) - { - $removed_ids = explode("|", $mybb->cookies[$cookie]); - - if(!is_array($removed_ids)) - { - $removed_ids = array(); - } - } - - // "Select all Threads in this forum" only supported by forumdisplay and search - if($type == 'forum') - { - $query = $db->simple_select("threads", "tid", "fid='".(int)$id."'"); - while($tid = $db->fetch_field($query, "tid")) - { - if(in_array($tid, $removed_ids)) - { - continue; - } - - $ids[] = $tid; - } - } - else if($type == 'search') - { - $query = $db->simple_select("searchlog", "resulttype, posts, threads", "sid='".$db->escape_string($id)."' AND uid='{$mybb->user['uid']}'", 1); - $searchlog = $db->fetch_array($query); - if($searchlog['resulttype'] == 'posts') - { - $ids = explode(',', $searchlog['posts']); - } - else - { - $ids = explode(',', $searchlog['threads']); - } - - if(is_array($ids)) - { - foreach($ids as $key => $tid) - { - if(in_array($tid, $removed_ids)) - { - unset($ids[$key]); - } - } - } - } - - return $ids; -} - -/** - * @param int $id - * @param string $type - */ -function clearinline($id, $type) -{ - my_unsetcookie("inlinemod_".$type.$id); - my_unsetcookie("inlinemod_{$type}{$id}_removed"); -} - -/** - * @param int $id - * @param string $type - */ -function extendinline($id, $type) -{ - my_setcookie("inlinemod_{$type}{$id}", '', TIME_NOW+3600); - my_setcookie("inlinemod_{$type}{$id}_removed", '', TIME_NOW+3600); -} - -/** - * Checks if the current user is a moderator of all the posts specified - * - * Note: If no posts are specified, this function will return true. It is the - * responsibility of the calling script to error-check this case if necessary. - * - * @param array $posts Array of post IDs - * @param string $permission Permission to check - * @return bool True if moderator of all; false otherwise - */ -function is_moderator_by_pids($posts, $permission='') -{ - global $db, $mybb; - - // Speedy determination for supermods/admins and guests - if($mybb->usergroup['issupermod']) - { - return true; - } - elseif(!$mybb->user['uid']) - { - return false; - } - // Make an array of threads if not an array - if(!is_array($posts)) - { - $posts = array($posts); - } - // Validate input - $posts = array_map('intval', $posts); - $posts[] = 0; - // Get forums - $posts_string = implode(',', $posts); - $query = $db->simple_select("posts", "DISTINCT fid", "pid IN ($posts_string)"); - while($forum = $db->fetch_array($query)) - { - if(!is_moderator($forum['fid'], $permission)) - { - return false; - } - } - return true; -} - -/** - * Checks if the current user is a moderator of all the threads specified - * - * Note: If no threads are specified, this function will return true. It is the - * responsibility of the calling script to error-check this case if necessary. - * - * @param array $threads Array of thread IDs - * @param string $permission Permission to check - * @return bool True if moderator of all; false otherwise - */ -function is_moderator_by_tids($threads, $permission='') -{ - global $db, $mybb; - - // Speedy determination for supermods/admins and guests - if($mybb->usergroup['issupermod']) - { - return true; - } - elseif(!$mybb->user['uid']) - { - return false; - } - // Make an array of threads if not an array - if(!is_array($threads)) - { - $threads = array($threads); - } - // Validate input - $threads = array_map('intval', $threads); - $threads[] = 0; - // Get forums - $threads_string = implode(',', $threads); - $query = $db->simple_select("threads", "DISTINCT fid", "tid IN ($threads_string)"); - while($forum = $db->fetch_array($query)) - { - if(!is_moderator($forum['fid'], $permission)) - { - return false; - } - } - return true; -} - -/** - * Special redirect that takes a return URL into account - * @param string $url URL - * @param string $message Message - * @param string $title Title - */ -function moderation_redirect($url, $message="", $title="") -{ - global $mybb; - if(!empty($mybb->input['url'])) - { - redirect(htmlentities($mybb->input['url']), $message, $title); - } - redirect($url, $message, $title); -} diff --git a/html/forums/newreply.php b/html/forums/newreply.php deleted file mode 100644 index 0e2f736..0000000 --- a/html/forums/newreply.php +++ /dev/null @@ -1,1548 +0,0 @@ -load("newreply"); - -// Get the pid and tid and replyto from the input. -$tid = $mybb->get_input('tid', MyBB::INPUT_INT); -$replyto = $mybb->get_input('replyto', MyBB::INPUT_INT); - -// AJAX quick reply? -if(!empty($mybb->input['ajax'])) -{ - unset($mybb->input['previewpost']); -} - -// Edit a draft post. -$pid = 0; -$editdraftpid = ''; -$mybb->input['action'] = $mybb->get_input('action'); -if(($mybb->input['action'] == "editdraft" || $mybb->input['action'] == "do_newreply") && $mybb->get_input('pid', MyBB::INPUT_INT)) -{ - $pid = $mybb->get_input('pid', MyBB::INPUT_INT); - $post = get_post($pid); - if(!$post) - { - error($lang->error_invalidpost); - } - else if($mybb->user['uid'] != $post['uid']) - { - error($lang->error_post_noperms); - } - $pid = $post['pid']; - $tid = $post['tid']; - eval("\$editdraftpid = \"".$templates->get("newreply_draftinput")."\";"); -} - -// Set up $thread and $forum for later use. -$thread = get_thread($tid); -if(!$thread) -{ - error($lang->error_invalidthread); -} -$fid = $thread['fid']; - -// Get forum info -$forum = get_forum($fid); -if(!$forum) -{ - error($lang->error_invalidforum); -} - -// Make navigation -build_forum_breadcrumb($fid); -$thread_subject = $thread['subject']; -$thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); -add_breadcrumb($thread['subject'], get_thread_link($thread['tid'])); -add_breadcrumb($lang->nav_newreply); - -$forumpermissions = forum_permissions($fid); - -// See if everything is valid up to here. -if(isset($post) && (($post['visible'] == 0 && !is_moderator($fid, "canviewunapprove")) || ($post['visible'] < 0 && $post['uid'] != $mybb->user['uid']))) -{ - error($lang->error_invalidpost); -} -if(($thread['visible'] == 0 && !is_moderator($fid, "canviewunapprove")) || $thread['visible'] < 0) -{ - error($lang->error_invalidthread); -} -if($forum['open'] == 0 || $forum['type'] != "f") -{ - error($lang->error_closedinvalidforum); -} -if($forumpermissions['canview'] == 0 || $forumpermissions['canpostreplys'] == 0) -{ - error_no_permission(); -} - -if($mybb->user['suspendposting'] == 1) -{ - $suspendedpostingtype = $lang->error_suspendedposting_permanent; - if($mybb->user['suspensiontime']) - { - $suspendedpostingtype = $lang->sprintf($lang->error_suspendedposting_temporal, my_date($mybb->settings['dateformat'], $mybb->user['suspensiontime'])); - } - - $lang->error_suspendedposting = $lang->sprintf($lang->error_suspendedposting, $suspendedpostingtype, my_date($mybb->settings['timeformat'], $mybb->user['suspensiontime'])); - - error($lang->error_suspendedposting); -} - -if(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] == 1 && $thread['uid'] != $mybb->user['uid']) -{ - error_no_permission(); -} - -if(isset($forumpermissions['canonlyreplyownthreads']) && $forumpermissions['canonlyreplyownthreads'] == 1 && $thread['uid'] != $mybb->user['uid']) -{ - error_no_permission(); -} - -// Coming from quick reply? Set some defaults -if($mybb->get_input('method') == "quickreply") -{ - if($mybb->user['subscriptionmethod'] == 1) - { - $mybb->input['postoptions']['subscriptionmethod'] = "none"; - } - else if($mybb->user['subscriptionmethod'] == 2) - { - $mybb->input['postoptions']['subscriptionmethod'] = "email"; - } - else if($mybb->user['subscriptionmethod'] == 3) - { - $mybb->input['postoptions']['subscriptionmethod'] = "pm"; - } -} - -// Check if this forum is password protected and we have a valid password -check_forum_password($forum['fid']); - -if($mybb->settings['bbcodeinserter'] != 0 && $forum['allowmycode'] != 0 && (!$mybb->user['uid'] || $mybb->user['showcodebuttons'] != 0)) -{ - $codebuttons = build_mycode_inserter("message", $forum['allowsmilies']); - if($forum['allowsmilies'] != 0) - { - $smilieinserter = build_clickable_smilies(); - } -} - -// Display a login box or change user box? -if($mybb->user['uid'] != 0) -{ - $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); - eval("\$loginbox = \"".$templates->get("changeuserbox")."\";"); -} -else -{ - if(empty($mybb->input['previewpost']) && $mybb->input['action'] != "do_newreply") - { - $username = ''; - } - else - { - $username = htmlspecialchars_uni($mybb->get_input('username')); - } - eval("\$loginbox = \"".$templates->get("loginbox")."\";"); -} - -// Check to see if the thread is closed, and if the user is a mod. -if(!is_moderator($fid, "canpostclosedthreads")) -{ - if($thread['closed'] == 1) - { - error($lang->redirect_threadclosed); - } -} - -// No weird actions allowed, show new reply form if no regular action. -if($mybb->input['action'] != "do_newreply" && $mybb->input['action'] != "editdraft") -{ - $mybb->input['action'] = "newreply"; -} - -// Even if we are previewing, still show the new reply form. -if(!empty($mybb->input['previewpost'])) -{ - $mybb->input['action'] = "newreply"; -} - -// Setup a unique posthash for attachment management -if(!$mybb->get_input('posthash') && !$pid) -{ - $mybb->input['posthash'] = md5($thread['tid'].$mybb->user['uid'].random_str()); -} - -if((empty($_POST) && empty($_FILES)) && $mybb->get_input('processed', MyBB::INPUT_INT) == 1) -{ - error($lang->error_cannot_upload_php_post); -} - -$errors = array(); -$maximageserror = $attacherror = ''; -if($mybb->settings['enableattachments'] == 1 && !$mybb->get_input('attachmentaid', MyBB::INPUT_INT) && ($mybb->get_input('newattachment') || $mybb->get_input('updateattachment') || ($mybb->input['action'] == "do_newreply" && $mybb->get_input('submit') && $_FILES['attachment']))) -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($pid) - { - $attachwhere = "pid='{$pid}'"; - } - else - { - $attachwhere = "posthash='".$db->escape_string($mybb->get_input('posthash'))."'"; - } - - // If there's an attachment, check it and upload it - if($forumpermissions['canpostattachments'] != 0) - { - // If attachment exists.. - if(!empty($_FILES['attachment']['name']) && !empty($_FILES['attachment']['type'])) - { - if($_FILES['attachment']['size'] > 0) - { - $query = $db->simple_select("attachments", "aid", "filename='".$db->escape_string($_FILES['attachment']['name'])."' AND {$attachwhere}"); - $updateattach = $db->fetch_field($query, "aid"); - - require_once MYBB_ROOT."inc/functions_upload.php"; - - $update_attachment = false; - if($updateattach > 0 && $mybb->get_input('updateattachment')) - { - $update_attachment = true; - } - $attachedfile = upload_attachment($_FILES['attachment'], $update_attachment); - } - else - { - $errors[] = $lang->error_uploadempty; - $mybb->input['action'] = "newreply"; - } - } - } - - if(!empty($attachedfile['error'])) - { - $errors[] = $attachedfile['error']; - $mybb->input['action'] = "newreply"; - } - - if(!$mybb->get_input('submit')) - { - eval("\$editdraftpid = \"".$templates->get("newreply_draftinput")."\";"); - $mybb->input['action'] = "newreply"; - } -} - -// Remove an attachment. -if($mybb->settings['enableattachments'] == 1 && $mybb->get_input('attachmentaid', MyBB::INPUT_INT) && $mybb->get_input('attachmentact') == "remove") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - require_once MYBB_ROOT."inc/functions_upload.php"; - remove_attachment($pid, $mybb->get_input('posthash'), $mybb->get_input('attachmentaid', MyBB::INPUT_INT)); - if(!$mybb->get_input('submit')) - { - eval("\$editdraftpid = \"".$templates->get("newreply_draftinput")."\";"); - $mybb->input['action'] = "newreply"; - } -} - -$reply_errors = ''; -$quoted_ids = array(); -$hide_captcha = false; - -// Check the maximum posts per day for this user -if($mybb->usergroup['maxposts'] > 0 && $mybb->usergroup['cancp'] != 1) -{ - $daycut = TIME_NOW-60*60*24; - $query = $db->simple_select("posts", "COUNT(*) AS posts_today", "uid='{$mybb->user['uid']}' AND visible='1' AND dateline>{$daycut}"); - $post_count = $db->fetch_field($query, "posts_today"); - if($post_count >= $mybb->usergroup['maxposts']) - { - $lang->error_maxposts = $lang->sprintf($lang->error_maxposts, $mybb->usergroup['maxposts']); - error($lang->error_maxposts); - } -} - -if($mybb->input['action'] == "do_newreply" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("newreply_do_newreply_start"); - - // If this isn't a logged in user, then we need to do some special validation. - if($mybb->user['uid'] == 0) - { - // If they didn't specify a username then give them "Guest" - if(!$mybb->get_input('username')) - { - $username = $lang->guest; - } - // Otherwise use the name they specified. - else - { - $username = $mybb->get_input('username'); - } - $uid = 0; - - - if($mybb->settings['stopforumspam_on_newreply']) - { - require_once MYBB_ROOT . '/inc/class_stopforumspamchecker.php'; - - $stop_forum_spam_checker = new StopForumSpamChecker( - $plugins, - $mybb->settings['stopforumspam_min_weighting_before_spam'], - $mybb->settings['stopforumspam_check_usernames'], - $mybb->settings['stopforumspam_check_emails'], - $mybb->settings['stopforumspam_check_ips'], - $mybb->settings['stopforumspam_log_blocks'] - ); - - try { - if($stop_forum_spam_checker->is_user_a_spammer($mybb->get_input('username'), '', get_ip())) - { - error($lang->sprintf($lang->error_stop_forum_spam_spammer, - $stop_forum_spam_checker->getErrorText(array( - 'stopforumspam_check_usernames', - 'stopforumspam_check_ips' - )))); - } - } - catch (Exception $e) - { - if($mybb->settings['stopforumspam_block_on_error']) - { - error($lang->error_stop_forum_spam_fetching); - } - } - } - } - // This user is logged in. - else - { - $username = $mybb->user['username']; - $uid = $mybb->user['uid']; - } - - // Attempt to see if this post is a duplicate or not - if($uid > 0) - { - $user_check = "p.uid='{$uid}'"; - } - else - { - $user_check = "p.ipaddress=".$db->escape_binary($session->packedip); - } - if(!$mybb->get_input('savedraft')) - { - $query = $db->simple_select("posts p", "p.pid, p.visible", "{$user_check} AND p.tid='{$thread['tid']}' AND p.subject='".$db->escape_string($mybb->get_input('subject'))."' AND p.message='".$db->escape_string($mybb->get_input('message'))."' AND p.visible != '-2' AND p.dateline>".(TIME_NOW-600)); - $duplicate_check = $db->fetch_field($query, "pid"); - if($duplicate_check) - { - error($lang->error_post_already_submitted); - } - } - - // Set up posthandler. - require_once MYBB_ROOT."inc/datahandlers/post.php"; - $posthandler = new PostDataHandler("insert"); - - // Set the post data that came from the input to the $post array. - $post = array( - "tid" => $mybb->get_input('tid', MyBB::INPUT_INT), - "replyto" => $mybb->get_input('replyto', MyBB::INPUT_INT), - "fid" => $thread['fid'], - "subject" => $mybb->get_input('subject'), - "icon" => $mybb->get_input('icon', MyBB::INPUT_INT), - "uid" => $uid, - "username" => $username, - "message" => $mybb->get_input('message'), - "ipaddress" => $session->packedip, - "posthash" => $mybb->get_input('posthash') - ); - - if(isset($mybb->input['pid'])) - { - $post['pid'] = $mybb->get_input('pid', MyBB::INPUT_INT); - } - - // Are we saving a draft post? - if($mybb->get_input('savedraft') && $mybb->user['uid']) - { - $post['savedraft'] = 1; - } - else - { - $post['savedraft'] = 0; - } - - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - if(!isset($postoptions['signature'])) - { - $postoptions['signature'] = 0; - } - if(!isset($postoptions['subscriptionmethod'])) - { - $postoptions['subscriptionmethod'] = 0; - } - if(!isset($postoptions['disablesmilies'])) - { - $postoptions['disablesmilies'] = 0; - } - - // Set up the post options from the input. - $post['options'] = array( - "signature" => $postoptions['signature'], - "subscriptionmethod" => $postoptions['subscriptionmethod'], - "disablesmilies" => $postoptions['disablesmilies'] - ); - - // Apply moderation options if we have them - $post['modoptions'] = $mybb->get_input('modoptions', MyBB::INPUT_ARRAY); - - $posthandler->set_data($post); - - // Now let the post handler do all the hard work. - $valid_post = $posthandler->validate_post(); - - $post_errors = array(); - // Fetch friendly error messages if this is an invalid post - if(!$valid_post) - { - $post_errors = $posthandler->get_friendly_errors(); - } - - // Mark thread as read - require_once MYBB_ROOT."inc/functions_indicators.php"; - mark_thread_read($tid, $fid); - - // Check captcha image - if($mybb->settings['captchaimage'] && !$mybb->user['uid']) - { - require_once MYBB_ROOT.'inc/class_captcha.php'; - $post_captcha = new captcha(false, "post_captcha"); - - if($post_captcha->validate_captcha() == false) - { - // CAPTCHA validation failed - foreach($post_captcha->get_errors() as $error) - { - $post_errors[] = $error; - } - } - else - { - $hide_captcha = true; - } - - if($mybb->get_input('ajax', MyBB::INPUT_INT)) - { - if($post_captcha->type == 1) - { - $randomstr = random_str(5); - $imagehash = md5(random_str(12)); - - $imagearray = array( - "imagehash" => $imagehash, - "imagestring" => $randomstr, - "dateline" => TIME_NOW - ); - - $db->insert_query("captcha", $imagearray); - - //header("Content-type: text/html; charset={$lang->settings['charset']}"); - $data = ''; - $data .= "$imagehash"; - - if($hide_captcha) - { - $data .= "|$randomstr"; - } - - $data .= ""; - - //header("Content-type: application/json; charset={$lang->settings['charset']}"); - $json_data = array("data" => $data); - } - else if($post_captcha->type == 2) - { - //header("Content-type: text/html; charset={$lang->settings['charset']}"); - $data = "reload"; - - //header("Content-type: application/json; charset={$lang->settings['charset']}"); - $json_data = array("data" => $data); - } - } - } - - // One or more errors returned, fetch error list and throw to newreply page - if(count($post_errors) > 0) - { - $reply_errors = inline_error($post_errors, '', $json_data); - $mybb->input['action'] = "newreply"; - } - else - { - $postinfo = $posthandler->insert_post(); - $pid = $postinfo['pid']; - $visible = $postinfo['visible']; - $closed = $postinfo['closed']; - - // Invalidate solved captcha - if($mybb->settings['captchaimage'] && !$mybb->user['uid']) - { - $post_captcha->invalidate_captcha(); - } - - $force_redirect = false; - - // Deciding the fate - if($visible == -2) - { - // Draft post - $lang->redirect_newreply = $lang->draft_saved; - $url = "usercp.php?action=drafts"; - } - elseif($visible == 1) - { - // Visible post - $lang->redirect_newreply .= $lang->redirect_newreply_post; - $url = get_post_link($pid, $tid)."#pid{$pid}"; - } - else - { - // Moderated post - $lang->redirect_newreply .= '
    '.$lang->redirect_newreply_moderation; - $url = get_thread_link($tid); - - // User must see moderation notice, regardless of redirect settings - $force_redirect = true; - } - - // Mark any quoted posts so they're no longer selected - attempts to maintain those which weren't selected - if(isset($mybb->input['quoted_ids']) && isset($mybb->cookies['multiquote']) && $mybb->settings['multiquote'] != 0) - { - // We quoted all posts - remove the entire cookie - if($mybb->get_input('quoted_ids') == "all") - { - my_unsetcookie("multiquote"); - } - // Only quoted a few - attempt to remove them from the cookie - else - { - $quoted_ids = explode("|", $mybb->get_input('quoted_ids')); - $multiquote = explode("|", $mybb->cookies['multiquote']); - if(is_array($multiquote) && is_array($quoted_ids)) - { - foreach($multiquote as $key => $quoteid) - { - // If this ID was quoted, remove it from the multiquote list - if(in_array($quoteid, $quoted_ids)) - { - unset($multiquote[$key]); - } - } - // Still have an array - set the new cookie - if(is_array($multiquote)) - { - $new_multiquote = implode(",", $multiquote); - my_setcookie("multiquote", $new_multiquote); - } - // Otherwise, unset it - else - { - my_unsetcookie("multiquote"); - } - } - } - } - - $plugins->run_hooks("newreply_do_newreply_end"); - - // This was a post made via the ajax quick reply - we need to do some special things here - if($mybb->get_input('ajax', MyBB::INPUT_INT)) - { - // Visible post - if($visible == 1) - { - // Set post counter - $postcounter = $thread['replies'] + 1; - - if(is_moderator($fid, "canviewunapprove")) - { - $postcounter += $thread['unapprovedposts']; - } - if(is_moderator($fid, "canviewdeleted")) - { - $postcounter += $thread['deletedposts']; - } - - // Was there a new post since we hit the quick reply button? - if($mybb->get_input('lastpid', MyBB::INPUT_INT)) - { - $query = $db->simple_select("posts", "pid", "tid = '{$tid}' AND pid != '{$pid}'", array("order_by" => "pid", "order_dir" => "desc")); - $new_post = $db->fetch_array($query); - if($new_post['pid'] != $mybb->get_input('lastpid', MyBB::INPUT_INT)) - { - redirect(get_thread_link($tid, 0, "lastpost")); - } - } - - if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) - { - $mybb->settings['postsperpage'] = 20; - } - - // Lets see if this post is on the same page as the one we're viewing or not - // if it isn't, redirect us - if($perpage > 0 && (($postcounter) % $perpage) == 0) - { - $post_page = ($postcounter) / $mybb->settings['postsperpage']; - } - else - { - $post_page = (int)($postcounter / $mybb->settings['postsperpage']) + 1; - } - - if($post_page > $mybb->get_input('from_page', MyBB::INPUT_INT)) - { - redirect(get_thread_link($tid, 0, "lastpost")); - exit; - } - - // Return the post HTML and display it inline - $query = $db->query(" - SELECT u.*, u.username AS userusername, p.*, f.*, eu.username AS editusername - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - LEFT JOIN ".TABLE_PREFIX."users eu ON (eu.uid=p.edituid) - WHERE p.pid='{$pid}' - "); - $post = $db->fetch_array($query); - - // Now lets fetch all of the attachments for this post - $query = $db->simple_select("attachments", "*", "pid='{$pid}'"); - while($attachment = $db->fetch_array($query)) - { - $attachcache[$attachment['pid']][$attachment['aid']] = $attachment; - } - - // Establish altbg - may seem like this is backwards, but build_postbit reverses it - if(($postcounter - $mybb->settings['postsperpage']) % 2 != 0) - { - $altbg = "trow1"; - } - else - { - $altbg = "trow2"; - } - - $charset = "UTF-8"; - if($lang->settings['charset']) - { - $charset = $lang->settings['charset']; - } - - require_once MYBB_ROOT."inc/functions_post.php"; - $pid = $post['pid']; - $post = build_postbit($post); - - $data = ''; - $data .= $post; - - // Build a new posthash incase the user wishes to quick reply again - $new_posthash = md5($mybb->user['uid'].random_str()); - $data .= "\n"; - - header("Content-type: application/json; charset={$lang->settings['charset']}"); - echo json_encode(array("data" => $data)); - - exit; - } - // Post is in the moderation queue - else - { - redirect(get_thread_link($tid, 0, "lastpost"), $lang->redirect_newreply_moderation, "", true); - exit; - } - } - else - { - $lang->redirect_newreply .= $lang->sprintf($lang->redirect_return_forum, get_forum_link($fid)); - redirect($url, $lang->redirect_newreply, "", $force_redirect); - exit; - } - } -} - -// Show the newreply form. -if($mybb->input['action'] == "newreply" || $mybb->input['action'] == "editdraft") -{ - $plugins->run_hooks("newreply_start"); - - $quote_ids = $multiquote_external = ''; - // If this isn't a preview and we're not editing a draft, then handle quoted posts - if(empty($mybb->input['previewpost']) && !$reply_errors && $mybb->input['action'] != "editdraft" && !$mybb->get_input('attachmentaid', MyBB::INPUT_INT) && !$mybb->get_input('newattachment') && !$mybb->get_input('updateattachment') && !$mybb->get_input('rem')) - { - $message = ''; - $quoted_posts = array(); - // Handle multiquote - if(isset($mybb->cookies['multiquote']) && $mybb->settings['multiquote'] != 0) - { - $multiquoted = explode("|", $mybb->cookies['multiquote']); - foreach($multiquoted as $post) - { - $quoted_posts[$post] = (int)$post; - } - } - // Handle incoming 'quote' button - if($replyto) - { - $quoted_posts[$replyto] = $replyto; - } - - // Quoting more than one post - fetch them - if(count($quoted_posts) > 0) - { - $external_quotes = 0; - $quoted_posts = implode(",", $quoted_posts); - $unviewable_forums = get_unviewable_forums(); - $inactiveforums = get_inactive_forums(); - if($unviewable_forums) - { - $unviewable_forums = "AND t.fid NOT IN ({$unviewable_forums})"; - } - if($inactiveforums) - { - $inactiveforums = "AND t.fid NOT IN ({$inactiveforums})"; - } - - // Check group permissions if we can't view threads not started by us - $group_permissions = forum_permissions(); - $onlyusfids = array(); - $onlyusforums = ''; - foreach($group_permissions as $gpfid => $forum_permissions) - { - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $gpfid; - } - } - if(!empty($onlyusfids)) - { - $onlyusforums = "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; - } - - if(is_moderator($fid, 'canviewunapprove') && is_moderator($fid, 'canviewdeleted')) - { - $visible_where = "AND p.visible IN (-1,0,1)"; - } - elseif(is_moderator($fid, 'canviewunapprove') && !is_moderator($fid, 'canviewdeleted')) - { - $visible_where = "AND p.visible IN (0,1)"; - } - elseif(!is_moderator($fid, 'canviewunapprove') && is_moderator($fid, 'canviewdeleted')) - { - $visible_where = "AND p.visible IN (-1,1)"; - } - else - { - $visible_where = "AND p.visible=1"; - } - - require_once MYBB_ROOT."inc/functions_posting.php"; - $query = $db->query(" - SELECT p.subject, p.message, p.pid, p.tid, p.username, p.dateline, u.username AS userusername - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.pid IN ({$quoted_posts}) {$unviewable_forums} {$inactiveforums} {$onlyusforums} {$visible_where} - "); - $load_all = $mybb->get_input('load_all_quotes', MyBB::INPUT_INT); - while($quoted_post = $db->fetch_array($query)) - { - // Only show messages for the current thread - if($quoted_post['tid'] == $tid || $load_all == 1) - { - // If this post was the post for which a quote button was clicked, set the subject - if($replyto == $quoted_post['pid']) - { - $subject = preg_replace('#^RE:\s?#i', '', $quoted_post['subject']); - // Subject too long? Shorten it to avoid error message - if(my_strlen($subject) > 85) - { - $subject = my_substr($subject, 0, 82).'...'; - } - $subject = "RE: ".$subject; - } - $message .= parse_quoted_message($quoted_post); - $quoted_ids[] = $quoted_post['pid']; - } - // Count the rest - else - { - ++$external_quotes; - } - } - if($mybb->settings['maxquotedepth'] != '0') - { - $message = remove_message_quotes($message); - } - if($external_quotes > 0) - { - if($external_quotes == 1) - { - $multiquote_text = $lang->multiquote_external_one; - $multiquote_deselect = $lang->multiquote_external_one_deselect; - $multiquote_quote = $lang->multiquote_external_one_quote; - } - else - { - $multiquote_text = $lang->sprintf($lang->multiquote_external, $external_quotes); - $multiquote_deselect = $lang->multiquote_external_deselect; - $multiquote_quote = $lang->multiquote_external_quote; - } - eval("\$multiquote_external = \"".$templates->get("newreply_multiquote_external")."\";"); - } - if(is_array($quoted_ids) && count($quoted_ids) > 0) - { - $quoted_ids = implode("|", $quoted_ids); - } - } - } - - if(isset($mybb->input['quoted_ids'])) - { - $quoted_ids = htmlspecialchars_uni($mybb->get_input('quoted_ids', MyBB::INPUT_INT)); - } - - if(isset($mybb->input['previewpost'])) - { - $previewmessage = $mybb->get_input('message'); - } - if(empty($message)) - { - $message = $mybb->get_input('message'); - } - $message = htmlspecialchars_uni($message); - - $postoptionschecked = array('signature' => '', 'disablesmilies' => ''); - $postoptions_subscriptionmethod_dont = $postoptions_subscriptionmethod_none = $postoptions_subscriptionmethod_email = $postoptions_subscriptionmethod_pm = ''; - - // Set up the post options. - if(!empty($mybb->input['previewpost']) || $reply_errors != '') - { - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - - if(isset($postoptions['signature']) && $postoptions['signature'] == 1) - { - $postoptionschecked['signature'] = " checked=\"checked\""; - } - if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "none") - { - $postoptions_subscriptionmethod_none = "checked=\"checked\""; - } - else if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "email") - { - $postoptions_subscriptionmethod_email = "checked=\"checked\""; - } - else if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "pm") - { - $postoptions_subscriptionmethod_pm = "checked=\"checked\""; - } - else - { - $postoptions_subscriptionmethod_dont = "checked=\"checked\""; - } - if(isset($postoptions['disablesmilies']) && $postoptions['disablesmilies'] == 1) - { - $postoptionschecked['disablesmilies'] = " checked=\"checked\""; - } - $subject = $mybb->input['subject']; - } - elseif($mybb->input['action'] == "editdraft" && $mybb->user['uid']) - { - $message = htmlspecialchars_uni($post['message']); - $subject = $post['subject']; - if($post['includesig'] != 0) - { - $postoptionschecked['signature'] = " checked=\"checked\""; - } - if($post['smilieoff'] == 1) - { - $postoptionschecked['disablesmilies'] = " checked=\"checked\""; - } - if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "none") - { - $postoptions_subscriptionmethod_none = "checked=\"checked\""; - } - else if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "email") - { - $postoptions_subscriptionmethod_email = "checked=\"checked\""; - } - else if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "pm") - { - $postoptions_subscriptionmethod_pm = "checked=\"checked\""; - } - else - { - $postoptions_subscriptionmethod_dont = "checked=\"checked\""; - } - $mybb->input['icon'] = $post['icon']; - } - else - { - if($mybb->user['signature'] != '') - { - $postoptionschecked['signature'] = " checked=\"checked\""; - } - if($mybb->user['subscriptionmethod'] == 1) - { - $postoptions_subscriptionmethod_none = "checked=\"checked\""; - } - else if($mybb->user['subscriptionmethod'] == 2) - { - $postoptions_subscriptionmethod_email = "checked=\"checked\""; - } - else if($mybb->user['subscriptionmethod'] == 3) - { - $postoptions_subscriptionmethod_pm = "checked=\"checked\""; - } - else - { - $postoptions_subscriptionmethod_dont = "checked=\"checked\""; - } - } - - if($forum['allowpicons'] != 0) - { - $posticons = get_post_icons(); - } - - // No subject? - if(!isset($subject)) - { - if(!empty($mybb->input['subject'])) - { - $subject = $mybb->get_input('subject'); - } - else - { - $subject = $thread_subject; - // Subject too long? Shorten it to avoid error message - if(my_strlen($subject) > 85) - { - $subject = my_substr($subject, 0, 82).'...'; - } - $subject = "RE: ".$subject; - } - } - - // Preview a post that was written. - $preview = ''; - if(!empty($mybb->input['previewpost'])) - { - // If this isn't a logged in user, then we need to do some special validation. - if($mybb->user['uid'] == 0) - { - // If they didn't specify a username then give them "Guest" - if(!$mybb->get_input('username')) - { - $username = $lang->guest; - } - // Otherwise use the name they specified. - else - { - $username = $mybb->get_input('username'); - } - $uid = 0; - } - // This user is logged in. - else - { - $username = $mybb->user['username']; - $uid = $mybb->user['uid']; - } - - // Set up posthandler. - require_once MYBB_ROOT."inc/datahandlers/post.php"; - $posthandler = new PostDataHandler("insert"); - $posthandler->action = "post"; - - // Set the post data that came from the input to the $post array. - $post = array( - "tid" => $mybb->get_input('tid', MyBB::INPUT_INT), - "replyto" => $mybb->get_input('replyto', MyBB::INPUT_INT), - "fid" => $thread['fid'], - "subject" => $mybb->get_input('subject'), - "icon" => $mybb->get_input('icon', MyBB::INPUT_INT), - "uid" => $uid, - "username" => $username, - "message" => $mybb->get_input('message'), - "ipaddress" => $session->packedip, - "posthash" => $mybb->get_input('posthash') - ); - - if(isset($mybb->input['pid'])) - { - $post['pid'] = $mybb->get_input('pid', MyBB::INPUT_INT); - } - - $posthandler->set_data($post); - - // Now let the post handler do all the hard work. - $valid_post = $posthandler->verify_message(); - $valid_subject = $posthandler->verify_subject(); - - // guest post --> verify author - if($post['uid'] == 0) - { - $valid_username = $posthandler->verify_author(); - } - else - { - $valid_username = true; - } - - $post_errors = array(); - // Fetch friendly error messages if this is an invalid post - if(!$valid_post || !$valid_subject || !$valid_username) - { - $post_errors = $posthandler->get_friendly_errors(); - } - - // One or more errors returned, fetch error list and throw to newreply page - if(count($post_errors) > 0) - { - $reply_errors = inline_error($post_errors); - } - else - { - $quote_ids = htmlspecialchars_uni($mybb->get_input('quote_ids')); - if(!isset($mybb->input['username'])) - { - $mybb->input['username'] = $lang->guest; - } - $mybb->input['icon'] = $mybb->get_input('icon', MyBB::INPUT_INT); - $query = $db->query(" - SELECT u.*, f.* - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - WHERE u.uid='".$mybb->user['uid']."' - "); - $post = $db->fetch_array($query); - if(!$mybb->user['uid'] || !$post['username']) - { - $post['username'] = $mybb->get_input('username'); - } - else - { - $post['userusername'] = $mybb->user['username']; - $post['username'] = $mybb->user['username']; - } - $post['message'] = $previewmessage; - $post['subject'] = $subject; - $post['icon'] = $mybb->get_input('icon', MyBB::INPUT_INT); - $mybb->input['postoptions'] = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - if(isset($mybb->input['postoptions']['disablesmilies'])) - { - $post['smilieoff'] = $mybb->input['postoptions']['disablesmilies']; - } - $post['dateline'] = TIME_NOW; - if(isset($mybb->input['postoptions']['signature'])) - { - $post['includesig'] = $mybb->input['postoptions']['signature']; - } - if(!isset($post['includesig']) || $post['includesig'] != 1) - { - $post['includesig'] = 0; - } - - // Fetch attachments assigned to this post. - if($mybb->get_input('pid', MyBB::INPUT_INT)) - { - $attachwhere = "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"; - } - else - { - $attachwhere = "posthash='".$db->escape_string($mybb->get_input('posthash'))."'"; - } - - $query = $db->simple_select("attachments", "*", $attachwhere); - while($attachment = $db->fetch_array($query)) - { - $attachcache[0][$attachment['aid']] = $attachment; - } - - $postbit = build_postbit($post, 1); - eval("\$preview = \"".$templates->get("previewpost")."\";"); - } - } - - $subject = htmlspecialchars_uni($parser->parse_badwords($subject)); - - $posthash = htmlspecialchars_uni($mybb->get_input('posthash')); - - // Do we have attachment errors? - if(count($errors) > 0) - { - $reply_errors = inline_error($errors); - } - - // Get a listing of the current attachments. - if($mybb->settings['enableattachments'] != 0 && $forumpermissions['canpostattachments'] != 0) - { - $attachcount = 0; - if($pid) - { - $attachwhere = "pid='$pid'"; - } - else - { - $attachwhere = "posthash='".$db->escape_string($posthash)."'"; - } - $attachments = ''; - $query = $db->simple_select("attachments", "*", $attachwhere); - while($attachment = $db->fetch_array($query)) - { - $attachment['size'] = get_friendly_size($attachment['filesize']); - $attachment['icon'] = get_attachment_icon(get_extension($attachment['filename'])); - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - - if($mybb->settings['bbcodeinserter'] != 0 && $forum['allowmycode'] != 0 && (!$mybb->user['uid'] || $mybb->user['showcodebuttons'] != 0)) - { - eval("\$postinsert = \"".$templates->get("post_attachments_attachment_postinsert")."\";"); - } - - $attach_mod_options = ''; - eval("\$attach_rem_options = \"".$templates->get("post_attachments_attachment_remove")."\";"); - - if($attachment['visible'] != 1) - { - eval("\$attachments .= \"".$templates->get("post_attachments_attachment_unapproved")."\";"); - } - else - { - eval("\$attachments .= \"".$templates->get("post_attachments_attachment")."\";"); - } - $attachcount++; - } - - $noshowattach = ''; - $query = $db->simple_select("attachments", "SUM(filesize) AS ausage", "uid='".$mybb->user['uid']."'"); - $usage = $db->fetch_array($query); - - if($usage['ausage'] > ($mybb->usergroup['attachquota']*1024) && $mybb->usergroup['attachquota'] != 0) - { - $noshowattach = 1; - } - - if($mybb->usergroup['attachquota'] == 0) - { - $friendlyquota = $lang->unlimited; - } - else - { - $friendlyquota = get_friendly_size($mybb->usergroup['attachquota']*1024); - } - - $friendlyusage = get_friendly_size($usage['ausage']); - $lang->attach_quota = $lang->sprintf($lang->attach_quota, $friendlyusage, $friendlyquota); - - if($mybb->settings['maxattachments'] == 0 || ($mybb->settings['maxattachments'] != 0 && $attachcount < $mybb->settings['maxattachments']) && !$noshowattach) - { - eval("\$attach_add_options = \"".$templates->get("post_attachments_add")."\";"); - } - - if(($mybb->usergroup['caneditattachments'] || $forumpermissions['caneditattachments']) && $attachcount > 0) - { - eval("\$attach_update_options = \"".$templates->get("post_attachments_update")."\";"); - } - - if($attach_add_options || $attach_update_options) - { - eval("\$newattach = \"".$templates->get("post_attachments_new")."\";"); - } - - eval("\$attachbox = \"".$templates->get("post_attachments")."\";"); - } - - // If the user is logged in, provide a save draft button. - if($mybb->user['uid']) - { - eval("\$savedraftbutton = \"".$templates->get("post_savedraftbutton", 1, 0)."\";"); - } - - // Show captcha image for guests if enabled - $captcha = ''; - if($mybb->settings['captchaimage'] && !$mybb->user['uid']) - { - $correct = false; - require_once MYBB_ROOT.'inc/class_captcha.php'; - $post_captcha = new captcha(false, "post_captcha"); - - if((!empty($mybb->input['previewpost']) || $hide_captcha == true) && $post_captcha->type == 1) - { - // If previewing a post - check their current captcha input - if correct, hide the captcha input area - // ... but only if it's a default one, reCAPTCHA and Are You a Human must be filled in every time due to draconian limits - if($post_captcha->validate_captcha() == true) - { - $correct = true; - - // Generate a hidden list of items for our captcha - $captcha = $post_captcha->build_hidden_captcha(); - } - } - - if(!$correct) - { - if($post_captcha->type == 1) - { - $post_captcha->build_captcha(); - } - elseif($post_captcha->type == 2 || $post_captcha->type == 4) - { - $post_captcha->build_recaptcha(); - } - - if($post_captcha->html) - { - $captcha = $post_captcha->html; - } - } - else if($correct && ($post_captcha->type == 2 || $post_captcha->type == 4)) - { - $post_captcha->build_recaptcha(); - - if($post_captcha->html) - { - $captcha = $post_captcha->html; - } - } - } - - $reviewmore = ''; - if($mybb->settings['threadreview'] != 0) - { - if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) - { - $mybb->settings['postsperpage'] = 20; - } - - if(is_moderator($fid, "canviewunapprove")) - { - $visibility = "(visible='1' OR visible='0')"; - } - else - { - $visibility = "visible='1'"; - } - $query = $db->simple_select("posts", "COUNT(pid) AS post_count", "tid='{$tid}' AND {$visibility}"); - $numposts = $db->fetch_field($query, "post_count"); - - if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) - { - $mybb->settings['postsperpage'] = 20; - } - - if($numposts > $mybb->settings['postsperpage']) - { - $numposts = $mybb->settings['postsperpage']; - $lang->thread_review_more = $lang->sprintf($lang->thread_review_more, $mybb->settings['postsperpage'], get_thread_link($tid)); - eval("\$reviewmore = \"".$templates->get("newreply_threadreview_more")."\";"); - } - - $query = $db->simple_select("posts", "pid", "tid='{$tid}' AND {$visibility}", array("order_by" => "dateline", "order_dir" => "desc", "limit" => $mybb->settings['postsperpage'])); - while($post = $db->fetch_array($query)) - { - $pidin[] = $post['pid']; - } - - $pidin = implode(",", $pidin); - - // Fetch attachments - $query = $db->simple_select("attachments", "*", "pid IN ($pidin)"); - while($attachment = $db->fetch_array($query)) - { - $attachcache[$attachment['pid']][$attachment['aid']] = $attachment; - } - $query = $db->query(" - SELECT p.*, u.username AS userusername - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (p.uid=u.uid) - WHERE pid IN ($pidin) - ORDER BY dateline DESC - "); - $postsdone = 0; - $altbg = "trow1"; - $reviewbits = ''; - while($post = $db->fetch_array($query)) - { - if($post['userusername']) - { - $post['username'] = $post['userusername']; - } - $reviewpostdate = my_date('relative', $post['dateline']); - $parser_options = array( - "allow_html" => $forum['allowhtml'], - "allow_mycode" => $forum['allowmycode'], - "allow_smilies" => $forum['allowsmilies'], - "allow_imgcode" => $forum['allowimgcode'], - "allow_videocode" => $forum['allowvideocode'], - "me_username" => $post['username'], - "filter_badwords" => 1 - ); - if($post['smilieoff'] == 1) - { - $parser_options['allow_smilies'] = 0; - } - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_imgcode'] = 0; - } - - if($mybb->user['showvideos'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestvideos'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_videocode'] = 0; - } - - $post['username'] = htmlspecialchars_uni($post['username']); - - if($post['visible'] != 1) - { - $altbg = "trow_shaded"; - } - - $post['message'] = $parser->parse_message($post['message'], $parser_options); - get_post_attachments($post['pid'], $post); - $reviewmessage = $post['message']; - eval("\$reviewbits .= \"".$templates->get("newreply_threadreview_post")."\";"); - if($altbg == "trow1") - { - $altbg = "trow2"; - } - else - { - $altbg = "trow1"; - } - } - eval("\$threadreview = \"".$templates->get("newreply_threadreview")."\";"); - } - - // Hide signature option if no permission - $signature = ''; - if($mybb->usergroup['canusesig'] == 1 && !$mybb->user['suspendsignature']) - { - eval("\$signature = \"".$templates->get('newreply_signature')."\";"); - } - - // Can we disable smilies or are they disabled already? - $disablesmilies = ''; - if($forum['allowsmilies'] != 0) - { - eval("\$disablesmilies = \"".$templates->get("newreply_disablesmilies")."\";"); - } - - $postoptions = ''; - if(!empty($signature) || !empty($disablesmilies)) - { - eval("\$postoptions = \"".$templates->get("newreply_postoptions")."\";"); - $bgcolor = "trow2"; - } - else - { - $bgcolor = "trow1"; - } - - $modoptions = ''; - // Show the moderator options. - if(is_moderator($fid)) - { - if($mybb->get_input('processed', MyBB::INPUT_INT)) - { - $mybb->input['modoptions'] = $mybb->get_input('modoptions', MyBB::INPUT_ARRAY); - if(!isset($mybb->input['modoptions']['closethread'])) - { - $mybb->input['modoptions']['closethread'] = 0; - } - $closed = (int)$mybb->input['modoptions']['closethread']; - if(!isset($mybb->input['modoptions']['stickthread'])) - { - $mybb->input['modoptions']['stickthread'] = 0; - } - $stuck = (int)$mybb->input['modoptions']['stickthread']; - } - else - { - $closed = $thread['closed']; - $stuck = $thread['sticky']; - } - - if($closed) - { - $closecheck = ' checked="checked"'; - } - else - { - $closecheck = ''; - } - - if($stuck) - { - $stickycheck = ' checked="checked"'; - } - else - { - $stickycheck = ''; - } - - $closeoption = ''; - if(is_moderator($thread['fid'], "canopenclosethreads")) - { - eval("\$closeoption = \"".$templates->get("newreply_modoptions_close")."\";"); - } - - $stickoption = ''; - if(is_moderator($thread['fid'], "canstickunstickthreads")) - { - eval("\$stickoption = \"".$templates->get("newreply_modoptions_stick")."\";"); - } - - if(!empty($closeoption) || !empty($stickoption)) - { - eval("\$modoptions = \"".$templates->get("newreply_modoptions")."\";"); - $bgcolor = "trow1"; - } - else - { - $bgcolor = "trow2"; - } - } - else - { - $bgcolor = "trow2"; - } - - // Fetch subscription select box - eval("\$subscriptionmethod = \"".$templates->get("post_subscription_method")."\";"); - - $lang->post_reply_to = $lang->sprintf($lang->post_reply_to, $thread['subject']); - $lang->reply_to = $lang->sprintf($lang->reply_to, $thread['subject']); - - // Do we have any forum rules to show for this forum? - $forumrules = ''; - if($forum['rulestype'] >= 2 && $forum['rules']) - { - if(!$forum['rulestitle']) - { - $forum['rulestitle'] = $lang->sprintf($lang->forum_rules, $forum['name']); - } - - if(!$parser) - { - require_once MYBB_ROOT.'inc/class_parser.php'; - $parser = new postParser; - } - - $rules_parser = array( - "allow_html" => 1, - "allow_mycode" => 1, - "allow_smilies" => 1, - "allow_imgcode" => 1 - ); - - $forum['rules'] = $parser->parse_message($forum['rules'], $rules_parser); - $foruminfo = $forum; - - if($forum['rulestype'] == 3) - { - eval("\$forumrules = \"".$templates->get("forumdisplay_rules")."\";"); - } - else if($forum['rulestype'] == 2) - { - eval("\$forumrules = \"".$templates->get("forumdisplay_rules_link")."\";"); - } - } - - $moderation_notice = ''; - if(!is_moderator($forum['fid'], "canapproveunapproveattachs")) - { - if($forumpermissions['modattachments'] == 1 && $forumpermissions['canpostattachments'] != 0) - { - $moderation_text = $lang->moderation_forum_attachments; - eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); - } - } - if(!is_moderator($forum['fid'], "canapproveunapproveposts")) - { - if($forumpermissions['modposts'] == 1) - { - $moderation_text = $lang->moderation_forum_posts; - eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); - } - - if($mybb->user['moderateposts'] == 1) - { - $moderation_text = $lang->moderation_user_posts; - eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); - } - } - - $plugins->run_hooks("newreply_end"); - - $forum['name'] = strip_tags($forum['name']); - - eval("\$newreply = \"".$templates->get("newreply")."\";"); - output_page($newreply); -} diff --git a/html/forums/newthread.php b/html/forums/newthread.php deleted file mode 100644 index 7897218..0000000 --- a/html/forums/newthread.php +++ /dev/null @@ -1,1189 +0,0 @@ -load("newthread"); - -$tid = $pid = 0; -$mybb->input['action'] = $mybb->get_input('action'); -$mybb->input['tid'] = $mybb->get_input('tid', MyBB::INPUT_INT); -$mybb->input['pid'] = $mybb->get_input('pid', MyBB::INPUT_INT); -if($mybb->input['action'] == "editdraft" || ($mybb->get_input('savedraft') && $mybb->input['tid']) || ($mybb->input['tid'] && $mybb->input['pid'])) -{ - $thread = get_thread($mybb->input['tid']); - - $query = $db->simple_select("posts", "*", "tid='".$mybb->get_input('tid', MyBB::INPUT_INT)."' AND visible='-2'", array('order_by' => 'dateline', 'limit' => 1)); - $post = $db->fetch_array($query); - - if(!$thread['tid'] || !$post['pid'] || $thread['visible'] != -2 || $thread['uid'] != $mybb->user['uid']) - { - error($lang->invalidthread); - } - - $pid = $post['pid']; - $fid = $thread['fid']; - $tid = $thread['tid']; - eval("\$editdraftpid = \"".$templates->get("newthread_draftinput")."\";"); -} -else -{ - $fid = $mybb->get_input('fid', MyBB::INPUT_INT); - $editdraftpid = ''; -} - -// Fetch forum information. -$forum = get_forum($fid); -if(!$forum) -{ - error($lang->error_invalidforum); -} - -// Draw the navigation -build_forum_breadcrumb($fid); -add_breadcrumb($lang->nav_newthread); - -$forumpermissions = forum_permissions($fid); - -if($forum['open'] == 0 || $forum['type'] != "f" || $forum['linkto'] != "") -{ - error($lang->error_closedinvalidforum); -} - -if($forumpermissions['canview'] == 0 || $forumpermissions['canpostthreads'] == 0) -{ - error_no_permission(); -} - -if($mybb->user['suspendposting'] == 1) -{ - $suspendedpostingtype = $lang->error_suspendedposting_permanent; - if($mybb->user['suspensiontime']) - { - $suspendedpostingtype = $lang->sprintf($lang->error_suspendedposting_temporal, my_date($mybb->settings['dateformat'], $mybb->user['suspensiontime'])); - } - - $lang->error_suspendedposting = $lang->sprintf($lang->error_suspendedposting, $suspendedpostingtype, my_date($mybb->settings['timeformat'], $mybb->user['suspensiontime'])); - - error($lang->error_suspendedposting); -} - -// Check if this forum is password protected and we have a valid password -check_forum_password($forum['fid']); - -// If MyCode is on for this forum and the MyCode editor is enabled in the Admin CP, draw the code buttons and smilie inserter. -if($mybb->settings['bbcodeinserter'] != 0 && $forum['allowmycode'] != 0 && (!$mybb->user['uid'] || $mybb->user['showcodebuttons'] != 0)) -{ - $codebuttons = build_mycode_inserter("message", $forum['allowsmilies']); - if($forum['allowsmilies'] != 0) - { - $smilieinserter = build_clickable_smilies(); - } -} - -// Does this forum allow post icons? If so, fetch the post icons. -if($forum['allowpicons'] != 0) -{ - $posticons = get_post_icons(); -} - -// If we have a currently logged in user then fetch the change user box. -if($mybb->user['uid'] != 0) -{ - $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); - eval("\$loginbox = \"".$templates->get("changeuserbox")."\";"); -} - -// Otherwise we have a guest, determine the "username" and get the login box. -else -{ - if(!isset($mybb->input['previewpost']) && $mybb->input['action'] != "do_newthread") - { - $username = ''; - } - else - { - $username = htmlspecialchars_uni($mybb->get_input('username')); - } - eval("\$loginbox = \"".$templates->get("loginbox")."\";"); -} - -// If we're not performing a new thread insert and not editing a draft then we're posting a new thread. -if($mybb->input['action'] != "do_newthread" && $mybb->input['action'] != "editdraft") -{ - $mybb->input['action'] = "newthread"; -} - -// Previewing a post, overwrite the action to the new thread action. -if(!empty($mybb->input['previewpost'])) -{ - $mybb->input['action'] = "newthread"; -} - -// Setup a unique posthash for attachment management -if(!$mybb->get_input('posthash') && !$pid) -{ - $mybb->input['posthash'] = md5($mybb->user['uid'].random_str()); -} - -if((empty($_POST) && empty($_FILES)) && $mybb->get_input('processed', MyBB::INPUT_INT) == 1) -{ - error($lang->error_cannot_upload_php_post); -} - -$errors = array(); -$maximageserror = $attacherror = ''; - -// Handle attachments if we've got any. -if($mybb->settings['enableattachments'] == 1 && !$mybb->get_input('attachmentaid', MyBB::INPUT_INT) && ($mybb->get_input('newattachment') || $mybb->get_input('updateattachment') || ($mybb->input['action'] == "do_newthread" && $mybb->get_input('submit') && $_FILES['attachment']))) -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->input['action'] == "editdraft" || ($mybb->input['tid'] && $mybb->input['pid'])) - { - $attachwhere = "pid='{$pid}'"; - } - else - { - $attachwhere = "posthash='".$db->escape_string($mybb->get_input('posthash'))."'"; - } - - // If there's an attachment, check it and upload it - if($forumpermissions['canpostattachments'] != 0) - { - if(!empty($_FILES['attachment']['name']) && !empty($_FILES['attachment']['type'])) - { - if($_FILES['attachment']['size'] > 0) - { - $query = $db->simple_select("attachments", "aid", "filename='".$db->escape_string($_FILES['attachment']['name'])."' AND {$attachwhere}"); - $updateattach = $db->fetch_field($query, "aid"); - - require_once MYBB_ROOT."inc/functions_upload.php"; - - $update_attachment = false; - if($updateattach > 0 && $mybb->get_input('updateattachment')) - { - $update_attachment = true; - } - $attachedfile = upload_attachment($_FILES['attachment'], $update_attachment); - } - else - { - $errors[] = $lang->error_uploadempty; - $mybb->input['action'] = "newthread"; - } - } - } - - // Error with attachments - should use new inline errors? - if(!empty($attachedfile['error'])) - { - $errors[] = $attachedfile['error']; - $mybb->input['action'] = "newthread"; - } - - // If we were dealing with an attachment but didn't click 'Post Thread', force the new thread page again. - if(!$mybb->get_input('submit')) - { - //$editdraftpid = ""; - $mybb->input['action'] = "newthread"; - } -} - -// Are we removing an attachment from the thread? -if($mybb->settings['enableattachments'] == 1 && $mybb->get_input('attachmentaid', MyBB::INPUT_INT) && $mybb->get_input('attachmentact') == "remove") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - require_once MYBB_ROOT."inc/functions_upload.php"; - remove_attachment($pid, $mybb->get_input('posthash'), $mybb->get_input('attachmentaid', MyBB::INPUT_INT)); - if(!$mybb->get_input('submit')) - { - $mybb->input['action'] = "newthread"; - } -} - -$thread_errors = ""; -$hide_captcha = false; - -// Check the maximum posts per day for this user -if($mybb->usergroup['maxposts'] > 0 && $mybb->usergroup['cancp'] != 1) -{ - $daycut = TIME_NOW-60*60*24; - $query = $db->simple_select("posts", "COUNT(*) AS posts_today", "uid='{$mybb->user['uid']}' AND visible='1' AND dateline>{$daycut}"); - $post_count = $db->fetch_field($query, "posts_today"); - if($post_count >= $mybb->usergroup['maxposts']) - { - $lang->error_maxposts = $lang->sprintf($lang->error_maxposts, $mybb->usergroup['maxposts']); - error($lang->error_maxposts); - } -} - -// Performing the posting of a new thread. -if($mybb->input['action'] == "do_newthread" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("newthread_do_newthread_start"); - - // If this isn't a logged in user, then we need to do some special validation. - if($mybb->user['uid'] == 0) - { - // If they didn't specify a username then give them "Guest" - if(!$mybb->get_input('username')) - { - $username = $lang->guest; - } - // Otherwise use the name they specified. - else - { - $username = $mybb->get_input('username'); - } - $uid = 0; - - if(!$mybb->user['uid'] && $mybb->settings['stopforumspam_on_newthread']) - { - require_once MYBB_ROOT . '/inc/class_stopforumspamchecker.php'; - - $stop_forum_spam_checker = new StopForumSpamChecker( - $plugins, - $mybb->settings['stopforumspam_min_weighting_before_spam'], - $mybb->settings['stopforumspam_check_usernames'], - $mybb->settings['stopforumspam_check_emails'], - $mybb->settings['stopforumspam_check_ips'], - $mybb->settings['stopforumspam_log_blocks'] - ); - - try { - if($stop_forum_spam_checker->is_user_a_spammer($mybb->get_input('username'), '', get_ip())) - { - $errors[] = $lang->sprintf($lang->error_stop_forum_spam_spammer, - $stop_forum_spam_checker->getErrorText(array( - 'stopforumspam_check_usernames', - 'stopforumspam_check_ips' - ))); - } - } - catch (Exception $e) - { - if($mybb->settings['stopforumspam_block_on_error']) - { - $errors[] = $lang->error_stop_forum_spam_fetching; - } - } - } - } - // This user is logged in. - else - { - $username = $mybb->user['username']; - $uid = $mybb->user['uid']; - } - - // Attempt to see if this post is a duplicate or not - if($uid > 0) - { - $user_check = "p.uid='{$uid}'"; - } - else - { - $user_check = "p.ipaddress=".$db->escape_binary($session->packedip); - } - if(!$mybb->get_input('savedraft') && !$pid) - { - $query = $db->simple_select("posts p", "p.pid", "$user_check AND p.fid='{$forum['fid']}' AND p.subject='".$db->escape_string($mybb->get_input('subject'))."' AND p.message='".$db->escape_string($mybb->get_input('message'))."' AND p.dateline>".(TIME_NOW-600)); - $duplicate_check = $db->fetch_field($query, "pid"); - if($duplicate_check) - { - error($lang->error_post_already_submitted); - } - } - - // Set up posthandler. - require_once MYBB_ROOT."inc/datahandlers/post.php"; - $posthandler = new PostDataHandler("insert"); - $posthandler->action = "thread"; - - // Set the thread data that came from the input to the $thread array. - $new_thread = array( - "fid" => $forum['fid'], - "subject" => $mybb->get_input('subject'), - "prefix" => $mybb->get_input('threadprefix', MyBB::INPUT_INT), - "icon" => $mybb->get_input('icon', MyBB::INPUT_INT), - "uid" => $uid, - "username" => $username, - "message" => $mybb->get_input('message'), - "ipaddress" => $session->packedip, - "posthash" => $mybb->get_input('posthash') - ); - - if($pid != '') - { - $new_thread['pid'] = $pid; - } - - // Are we saving a draft thread? - if($mybb->get_input('savedraft') && $mybb->user['uid']) - { - $new_thread['savedraft'] = 1; - } - else - { - $new_thread['savedraft'] = 0; - } - - // Is this thread already a draft and we're updating it? - if(isset($thread['tid']) && $thread['visible'] == -2) - { - $new_thread['tid'] = $thread['tid']; - } - - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - if(!isset($postoptions['signature'])) - { - $postoptions['signature'] = 0; - } - if(!isset($postoptions['subscriptionmethod'])) - { - $postoptions['subscriptionmethod'] = 0; - } - if(!isset($postoptions['disablesmilies'])) - { - $postoptions['disablesmilies'] = 0; - } - - // Set up the thread options from the input. - $new_thread['options'] = array( - "signature" => $postoptions['signature'], - "subscriptionmethod" => $postoptions['subscriptionmethod'], - "disablesmilies" => $postoptions['disablesmilies'] - ); - - // Apply moderation options if we have them - $new_thread['modoptions'] = $mybb->get_input('modoptions', MyBB::INPUT_ARRAY); - - $posthandler->set_data($new_thread); - - // Now let the post handler do all the hard work. - $valid_thread = $posthandler->validate_thread(); - - $post_errors = array(); - // Fetch friendly error messages if this is an invalid thread - if(!$valid_thread) - { - $post_errors = $posthandler->get_friendly_errors(); - } - - // Check captcha image - if($mybb->settings['captchaimage'] && !$mybb->user['uid']) - { - require_once MYBB_ROOT.'inc/class_captcha.php'; - $post_captcha = new captcha; - - if($post_captcha->validate_captcha() == false) - { - // CAPTCHA validation failed - foreach($post_captcha->get_errors() as $error) - { - $post_errors[] = $error; - } - } - else - { - $hide_captcha = true; - } - } - - // One or more errors returned, fetch error list and throw to newthread page - if(count($post_errors) > 0) - { - $thread_errors = inline_error($post_errors); - $mybb->input['action'] = "newthread"; - } - // No errors were found, it is safe to insert the thread. - else - { - $thread_info = $posthandler->insert_thread(); - $tid = $thread_info['tid']; - $visible = $thread_info['visible']; - - // Invalidate solved captcha - if($mybb->settings['captchaimage'] && !$mybb->user['uid']) - { - $post_captcha->invalidate_captcha(); - } - - $force_redirect = false; - - // Mark thread as read - require_once MYBB_ROOT."inc/functions_indicators.php"; - mark_thread_read($tid, $fid); - - // We were updating a draft thread, send them back to the draft listing. - if($new_thread['savedraft'] == 1) - { - $lang->redirect_newthread = $lang->draft_saved; - $url = "usercp.php?action=drafts"; - } - - // A poll was being posted with this thread, throw them to poll posting page. - else if($mybb->get_input('postpoll', MyBB::INPUT_INT) && $forumpermissions['canpostpolls']) - { - $url = "polls.php?action=newpoll&tid=$tid&polloptions=".$mybb->get_input('numpolloptions', MyBB::INPUT_INT); - $lang->redirect_newthread .= $lang->redirect_newthread_poll; - } - - // This thread is stuck in the moderation queue, send them back to the forum. - else if(!$visible) - { - // Moderated thread - $lang->redirect_newthread .= $lang->redirect_newthread_moderation; - $url = get_forum_link($fid); - - // User must see moderation notice, regardless of redirect settings - $force_redirect = true; - } - - // The thread is being made in a forum the user cannot see threads in, send them back to the forum. - else if($visible == 1 && $forumpermissions['canviewthreads'] != 1) - { - $lang->redirect_newthread .= $lang->redirect_newthread_unviewable; - $url = get_forum_link($fid); - - // User must see permission notice, regardless of redirect settings - $force_redirect = true; - } - - // This is just a normal thread - send them to it. - else - { - // Visible thread - $lang->redirect_newthread .= $lang->redirect_newthread_thread; - $url = get_thread_link($tid); - } - - // Mark any quoted posts so they're no longer selected - attempts to maintain those which weren't selected - if(isset($mybb->input['quoted_ids']) && isset($mybb->cookies['multiquote']) && $mybb->settings['multiquote'] != 0) - { - // We quoted all posts - remove the entire cookie - if($mybb->get_input('quoted_ids') == "all") - { - my_unsetcookie("multiquote"); - } - } - - $plugins->run_hooks("newthread_do_newthread_end"); - - // Hop to it! Send them to the next page. - if(!$mybb->get_input('postpoll', MyBB::INPUT_INT)) - { - $lang->redirect_newthread .= $lang->sprintf($lang->redirect_return_forum, get_forum_link($fid)); - } - redirect($url, $lang->redirect_newthread, "", $force_redirect); - } -} - -if($mybb->input['action'] == "newthread" || $mybb->input['action'] == "editdraft") -{ - $plugins->run_hooks("newthread_start"); - - // Do we have attachment errors? - if(count($errors) > 0) - { - $thread_errors = inline_error($errors); - } - - $multiquote_external = $quoted_ids = ''; - - $subject = $message = ''; - // If this isn't a preview and we're not editing a draft, then handle quoted posts - if(empty($mybb->input['previewpost']) && !$thread_errors && $mybb->input['action'] != "editdraft") - { - $quoted_posts = array(); - // Handle multiquote - if(isset($mybb->cookies['multiquote']) && $mybb->settings['multiquote'] != 0) - { - $multiquoted = explode("|", $mybb->cookies['multiquote']); - foreach($multiquoted as $post) - { - $quoted_posts[$post] = (int)$post; - } - } - - // Quoting more than one post - fetch them - if(count($quoted_posts) > 0) - { - $external_quotes = 0; - $quoted_posts = implode(",", $quoted_posts); - $unviewable_forums = get_unviewable_forums(); - $inactiveforums = get_inactive_forums(); - if($unviewable_forums) - { - $unviewable_forums = "AND t.fid NOT IN ({$unviewable_forums})"; - } - if($inactiveforums) - { - $inactiveforums = "AND t.fid NOT IN ({$inactiveforums})"; - } - - if(is_moderator($fid)) - { - $visible_where = "AND p.visible != 2"; - } - else - { - $visible_where = "AND p.visible > 0"; - } - - // Check group permissions if we can't view threads not started by us - $group_permissions = forum_permissions(); - $onlyusfids = array(); - $onlyusforums = ''; - foreach($group_permissions as $gpfid => $forum_permissions) - { - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $gpfid; - } - } - if(!empty($onlyusfids)) - { - $onlyusforums = "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; - } - - if($mybb->get_input('load_all_quotes', MyBB::INPUT_INT) == 1) - { - $query = $db->query(" - SELECT p.subject, p.message, p.pid, p.tid, p.username, p.dateline, u.username AS userusername - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.pid IN ({$quoted_posts}) {$unviewable_forums} {$inactiveforums} {$onlyusforums} {$visible_where} - ORDER BY p.dateline - "); - while($quoted_post = $db->fetch_array($query)) - { - if($quoted_post['userusername']) - { - $quoted_post['username'] = $quoted_post['userusername']; - } - $quoted_post['message'] = preg_replace('#(^|\r|\n)/me ([^\r\n<]*)#i', "\\1* {$quoted_post['username']} \\2", $quoted_post['message']); - $quoted_post['message'] = preg_replace('#(^|\r|\n)/slap ([^\r\n<]*)#i', "\\1* {$quoted_post['username']} {$lang->slaps} \\2 {$lang->with_trout}", $quoted_post['message']); - $quoted_post['message'] = preg_replace("#\[attachment=([0-9]+?)\]#i", '', $quoted_post['message']); - $message .= "[quote='{$quoted_post['username']}' pid='{$quoted_post['pid']}' dateline='{$quoted_post['dateline']}']\n{$quoted_post['message']}\n[/quote]\n\n"; - } - - $quoted_ids = "all"; - } - else - { - $query = $db->query(" - SELECT COUNT(*) AS quotes - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE p.pid IN ({$quoted_posts}) {$unviewable_forums} {$inactiveforums} {$onlyusforums} {$visible_where} - "); - $external_quotes = $db->fetch_field($query, 'quotes'); - - if($external_quotes > 0) - { - if($external_quotes == 1) - { - $multiquote_text = $lang->multiquote_external_one; - $multiquote_deselect = $lang->multiquote_external_one_deselect; - $multiquote_quote = $lang->multiquote_external_one_quote; - } - else - { - $multiquote_text = $lang->sprintf($lang->multiquote_external, $external_quotes); - $multiquote_deselect = $lang->multiquote_external_deselect; - $multiquote_quote = $lang->multiquote_external_quote; - } - eval("\$multiquote_external = \"".$templates->get("newthread_multiquote_external")."\";"); - } - } - } - } - - if(isset($mybb->input['quoted_ids'])) - { - $quoted_ids = htmlspecialchars_uni($mybb->get_input('quoted_ids')); - } - - $postoptionschecked = array('signature' => '', 'disablesmilies' => ''); - $postoptions_subscriptionmethod_dont = $postoptions_subscriptionmethod_none = $postoptions_subscriptionmethod_email = $postoptions_subscriptionmethod_pm = ''; - $postpollchecked = ''; - - // Check the various post options if we're - // a -> previewing a post - // b -> removing an attachment - // c -> adding a new attachment - // d -> have errors from posting - - if(!empty($mybb->input['previewpost']) || $mybb->get_input('attachmentaid', MyBB::INPUT_INT) || $mybb->get_input('newattachment') || $mybb->get_input('updateattachment') || $thread_errors) - { - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - if(isset($postoptions['signature']) && $postoptions['signature'] == 1) - { - $postoptionschecked['signature'] = " checked=\"checked\""; - } - if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "none") - { - $postoptions_subscriptionmethod_none = "checked=\"checked\""; - } - else if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "email") - { - $postoptions_subscriptionmethod_email = "checked=\"checked\""; - } - else if(isset($postoptions['subscriptionmethod']) && $postoptions['subscriptionmethod'] == "pm") - { - $postoptions_subscriptionmethod_pm = "checked=\"checked\""; - } - else - { - $postoptions_subscriptionmethod_dont = "checked=\"checked\""; - } - if(isset($postoptions['disablesmilies']) && $postoptions['disablesmilies'] == 1) - { - $postoptionschecked['disablesmilies'] = " checked=\"checked\""; - } - if($mybb->get_input('postpoll', MyBB::INPUT_INT) == 1) - { - $postpollchecked = "checked=\"checked\""; - } - $numpolloptions = $mybb->get_input('numpolloptions', MyBB::INPUT_INT); - } - - // Editing a draft thread - else if($mybb->input['action'] == "editdraft" && $mybb->user['uid']) - { - $mybb->input['threadprefix'] = $thread['prefix']; - $message = htmlspecialchars_uni($post['message']); - $subject = htmlspecialchars_uni($post['subject']); - if($post['includesig'] != 0) - { - $postoptionschecked['signature'] = " checked=\"checked\""; - } - if($post['smilieoff'] == 1) - { - $postoptionschecked['disablesmilies'] = " checked=\"checked\""; - } - $icon = $post['icon']; - if($forum['allowpicons'] != 0) - { - $posticons = get_post_icons(); - } - if($postoptions['subscriptionmethod'] == "none") - { - $postoptions_subscriptionmethod_none = "checked=\"checked\""; - } - else if($postoptions['subscriptionmethod'] == "email") - { - $postoptions_subscriptionmethod_email = "checked=\"checked\""; - } - else if($postoptions['subscriptionmethod'] == "pm") - { - $postoptions_subscriptionmethod_pm = "checked=\"checked\""; - } - else - { - $postoptions_subscriptionmethod_dont = "checked=\"checked\""; - } - } - - // Otherwise, this is our initial visit to this page. - else - { - if($mybb->user['signature'] != '') - { - $postoptionschecked['signature'] = " checked=\"checked\""; - } - if($mybb->user['subscriptionmethod'] == 1) - { - $postoptions_subscriptionmethod_none = "checked=\"checked\""; - } - else if($mybb->user['subscriptionmethod'] == 2) - { - $postoptions_subscriptionmethod_email = "checked=\"checked\""; - } - else if($mybb->user['subscriptionmethod'] == 3) - { - $postoptions_subscriptionmethod_pm = "checked=\"checked\""; - } - else - { - $postoptions_subscriptionmethod_dont = "checked=\"checked\""; - } - $numpolloptions = "2"; - } - - $preview = ''; - - // If we're preving a post then generate the preview. - if(!empty($mybb->input['previewpost'])) - { - // If this isn't a logged in user, then we need to do some special validation. - if($mybb->user['uid'] == 0) - { - // If they didn't specify a username then give them "Guest" - if(!$mybb->get_input('username')) - { - $username = $lang->guest; - } - // Otherwise use the name they specified. - else - { - $username = $mybb->get_input('username'); - } - $uid = 0; - } - // This user is logged in. - else - { - $username = $mybb->user['username']; - $uid = $mybb->user['uid']; - } - - // Set up posthandler. - require_once MYBB_ROOT."inc/datahandlers/post.php"; - $posthandler = new PostDataHandler("insert"); - $posthandler->action = "thread"; - - // Set the thread data that came from the input to the $thread array. - $new_thread = array( - "fid" => $forum['fid'], - "prefix" => $mybb->get_input('threadprefix', MyBB::INPUT_INT), - "subject" => $mybb->get_input('subject'), - "icon" => $mybb->get_input('icon'), - "uid" => $uid, - "username" => $username, - "message" => $mybb->get_input('message'), - "ipaddress" => $session->packedip, - "posthash" => $mybb->get_input('posthash') - ); - - if($pid != '') - { - $new_thread['pid'] = $pid; - } - - $posthandler->set_data($new_thread); - - // Now let the post handler do all the hard work. - $valid_thread = $posthandler->verify_message(); - $valid_subject = $posthandler->verify_subject(); - - // guest post --> verify author - if($new_thread['uid'] == 0) - { - $valid_username = $posthandler->verify_author(); - } - else - { - $valid_username = true; - } - - $post_errors = array(); - // Fetch friendly error messages if this is an invalid post - if(!$valid_thread || !$valid_subject || !$valid_username) - { - $post_errors = $posthandler->get_friendly_errors(); - } - - // One or more errors returned, fetch error list and throw to newreply page - if(count($post_errors) > 0) - { - $thread_errors = inline_error($post_errors); - } - else - { - if(empty($mybb->input['username'])) - { - $mybb->input['username'] = $lang->guest; - } - $query = $db->query(" - SELECT u.*, f.* - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - WHERE u.uid='".$mybb->user['uid']."' - "); - $post = $db->fetch_array($query); - if(!$mybb->user['uid'] || !$post['username']) - { - $post['username'] = htmlspecialchars_uni($mybb->get_input('username')); - } - else - { - $post['userusername'] = $mybb->user['username']; - $post['username'] = $mybb->user['username']; - } - $previewmessage = $mybb->get_input('message'); - $post['message'] = $previewmessage; - $post['subject'] = $mybb->get_input('subject'); - $post['icon'] = $mybb->get_input('icon', MyBB::INPUT_INT); - $mybb->input['postoptions'] = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - if(isset($mybb->input['postoptions']['disablesmilies'])) - { - $post['smilieoff'] = $mybb->input['postoptions']['disablesmilies']; - } - $post['dateline'] = TIME_NOW; - if(isset($mybb->input['postoptions']['signature'])) - { - $post['includesig'] = $mybb->input['postoptions']['signature']; - } - if(!isset($post['includesig']) || $post['includesig'] != 1) - { - $post['includesig'] = 0; - } - - // Fetch attachments assigned to this post - if($mybb->get_input('pid', MyBB::INPUT_INT)) - { - $attachwhere = "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"; - } - else - { - $attachwhere = "posthash='".$db->escape_string($mybb->get_input('posthash'))."'"; - } - - $query = $db->simple_select("attachments", "*", $attachwhere); - while($attachment = $db->fetch_array($query)) - { - $attachcache[0][$attachment['aid']] = $attachment; - } - - $postbit = build_postbit($post, 1); - eval("\$preview = \"".$templates->get("previewpost")."\";"); - } - $message = htmlspecialchars_uni($mybb->get_input('message')); - $subject = htmlspecialchars_uni($mybb->get_input('subject')); - } - - // Removing an attachment or adding a new one, or showing thread errors. - else if($mybb->get_input('attachmentaid', MyBB::INPUT_INT) || $mybb->get_input('newattachment') || $mybb->get_input('updateattachment') || $thread_errors) - { - $message = htmlspecialchars_uni($mybb->get_input('message')); - $subject = htmlspecialchars_uni($mybb->get_input('subject')); - } - - // Generate thread prefix selector - if(!$mybb->get_input('threadprefix', MyBB::INPUT_INT)) - { - $mybb->input['threadprefix'] = 0; - } - - $prefixselect = build_prefix_select($forum['fid'], $mybb->get_input('threadprefix', MyBB::INPUT_INT)); - - $posthash = htmlspecialchars_uni($mybb->get_input('posthash')); - - // Hide signature option if no permission - $signature = ''; - if($mybb->usergroup['canusesig'] == 1 && !$mybb->user['suspendsignature']) - { - eval("\$signature = \"".$templates->get('newthread_signature')."\";"); - } - - // Can we disable smilies or are they disabled already? - $disablesmilies = ''; - if($forum['allowsmilies'] != 0) - { - eval("\$disablesmilies = \"".$templates->get("newthread_disablesmilies")."\";"); - } - - $postoptions = ''; - if(!empty($signature) || !empty($disablesmilies)) - { - eval("\$postoptions = \"".$templates->get("newthread_postoptions")."\";"); - $bgcolor = "trow2"; - $bgcolor2 = "trow1"; - } - else - { - $bgcolor = "trow1"; - $bgcolor2 = "trow2"; - } - - $modoptions = ''; - // Show the moderator options - if(is_moderator($fid)) - { - $modoptions = $mybb->get_input('modoptions', MyBB::INPUT_ARRAY); - if(isset($modoptions['closethread']) && $modoptions['closethread'] == 1) - { - $closecheck = "checked=\"checked\""; - } - else - { - $closecheck = ''; - } - if(isset($modoptions['stickthread']) && $modoptions['stickthread'] == 1) - { - $stickycheck = "checked=\"checked\""; - } - else - { - $stickycheck = ''; - } - - $closeoption = ''; - if(is_moderator($thread['fid'], "canopenclosethreads")) - { - eval("\$closeoption = \"".$templates->get("newreply_modoptions_close")."\";"); - } - - $stickoption = ''; - if(is_moderator($thread['fid'], "canstickunstickthreads")) - { - eval("\$stickoption = \"".$templates->get("newreply_modoptions_stick")."\";"); - } - - if(!empty($closeoption) || !empty($stickoption)) - { - eval("\$modoptions = \"".$templates->get("newreply_modoptions")."\";"); - $bgcolor = "trow1"; - $bgcolor2 = "trow2"; - } - else - { - $bgcolor = "trow2"; - $bgcolor2 = "trow1"; - } - } - else - { - $bgcolor = "trow2"; - $bgcolor2 = "trow1"; - } - - // Fetch subscription select box - eval("\$subscriptionmethod = \"".$templates->get("post_subscription_method")."\";"); - - if($mybb->settings['enableattachments'] != 0 && $forumpermissions['canpostattachments'] != 0) - { // Get a listing of the current attachments, if there are any - $attachcount = 0; - if($mybb->input['action'] == "editdraft" || ($mybb->input['tid'] && $mybb->input['pid'])) - { - $attachwhere = "pid='$pid'"; - } - else - { - $attachwhere = "posthash='".$db->escape_string($posthash)."'"; - } - $query = $db->simple_select("attachments", "*", $attachwhere); - $attachments = ''; - while($attachment = $db->fetch_array($query)) - { - $attachment['size'] = get_friendly_size($attachment['filesize']); - $attachment['icon'] = get_attachment_icon(get_extension($attachment['filename'])); - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - - if($mybb->settings['bbcodeinserter'] != 0 && $forum['allowmycode'] != 0 && (!$mybb->user['uid'] || $mybb->user['showcodebuttons'] != 0)) - { - eval("\$postinsert = \"".$templates->get("post_attachments_attachment_postinsert")."\";"); - } - - eval("\$attach_rem_options = \"".$templates->get("post_attachments_attachment_remove")."\";"); - - $attach_mod_options = ''; - if($attachment['visible'] != 1) - { - eval("\$attachments .= \"".$templates->get("post_attachments_attachment_unapproved")."\";"); - } - else - { - eval("\$attachments .= \"".$templates->get("post_attachments_attachment")."\";"); - } - $attachcount++; - } - $query = $db->simple_select("attachments", "SUM(filesize) AS ausage", "uid='".$mybb->user['uid']."'"); - $usage = $db->fetch_array($query); - if($usage['ausage'] > ($mybb->usergroup['attachquota']*1024) && $mybb->usergroup['attachquota'] != 0) - { - $noshowattach = 1; - } - if($mybb->usergroup['attachquota'] == 0) - { - $friendlyquota = $lang->unlimited; - } - else - { - $friendlyquota = get_friendly_size($mybb->usergroup['attachquota']*1024); - } - $friendlyusage = get_friendly_size($usage['ausage']); - $lang->attach_quota = $lang->sprintf($lang->attach_quota, $friendlyusage, $friendlyquota); - if($mybb->settings['maxattachments'] == 0 || ($mybb->settings['maxattachments'] != 0 && $attachcount < $mybb->settings['maxattachments']) && !isset($noshowattach)) - { - eval("\$attach_add_options = \"".$templates->get("post_attachments_add")."\";"); - } - - if(($mybb->usergroup['caneditattachments'] || $forumpermissions['caneditattachments']) && $attachcount > 0) - { - eval("\$attach_update_options = \"".$templates->get("post_attachments_update")."\";"); - } - - if($attach_add_options || $attach_update_options) - { - eval("\$newattach = \"".$templates->get("post_attachments_new")."\";"); - } - eval("\$attachbox = \"".$templates->get("post_attachments")."\";"); - - $bgcolor = alt_trow(); - } - - if($mybb->user['uid']) - { - eval("\$savedraftbutton = \"".$templates->get("post_savedraftbutton", 1, 0)."\";"); - } - - $captcha = ''; - - // Show captcha image for guests if enabled - if($mybb->settings['captchaimage'] && !$mybb->user['uid']) - { - $correct = false; - require_once MYBB_ROOT.'inc/class_captcha.php'; - $post_captcha = new captcha(false, "post_captcha"); - - if((!empty($mybb->input['previewpost']) || $hide_captcha == true) && $post_captcha->type == 1) - { - // If previewing a post - check their current captcha input - if correct, hide the captcha input area - // ... but only if it's a default one, reCAPTCHA and Are You a Human must be filled in every time due to draconian limits - if($post_captcha->validate_captcha() == true) - { - $correct = true; - - // Generate a hidden list of items for our captcha - $captcha = $post_captcha->build_hidden_captcha(); - } - } - - if(!$correct) - { - if($post_captcha->type == 1) - { - $post_captcha->build_captcha(); - } - elseif($post_captcha->type == 2 || $post_captcha->type == 4) - { - $post_captcha->build_recaptcha(); - } - - if($post_captcha->html) - { - $captcha = $post_captcha->html; - } - } - else if($correct && ($post_captcha->type == 2 || $post_captcha->type == 4)) - { - $post_captcha->build_recaptcha(); - - if($post_captcha->html) - { - $captcha = $post_captcha->html; - } - } - } - - if($forumpermissions['canpostpolls'] != 0) - { - $lang->max_options = $lang->sprintf($lang->max_options, $mybb->settings['maxpolloptions']); - eval("\$pollbox = \"".$templates->get("newthread_postpoll")."\";"); - } - - // Do we have any forum rules to show for this forum? - $forumrules = ''; - if($forum['rulestype'] >= 2 && $forum['rules']) - { - if(!$forum['rulestitle']) - { - $forum['rulestitle'] = $lang->sprintf($lang->forum_rules, $forum['name']); - } - - if(!$parser) - { - require_once MYBB_ROOT.'inc/class_parser.php'; - $parser = new postParser; - } - - $rules_parser = array( - "allow_html" => 1, - "allow_mycode" => 1, - "allow_smilies" => 1, - "allow_imgcode" => 1 - ); - - $forum['rules'] = $parser->parse_message($forum['rules'], $rules_parser); - $foruminfo = $forum; - - if($forum['rulestype'] == 3) - { - eval("\$forumrules = \"".$templates->get("forumdisplay_rules")."\";"); - } - else if($forum['rulestype'] == 2) - { - eval("\$forumrules = \"".$templates->get("forumdisplay_rules_link")."\";"); - } - } - - $moderation_notice = ''; - if(!is_moderator($forum['fid'], "canapproveunapproveattachs")) - { - if($forumpermissions['modattachments'] == 1 && $forumpermissions['canpostattachments'] != 0) - { - $moderation_text = $lang->moderation_forum_attachments; - eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); - } - } - - if(!is_moderator($forum['fid'], "canapproveunapprovethreads")) - { - if($forumpermissions['modthreads'] == 1) - { - $moderation_text = $lang->moderation_forum_thread; - eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); - } - } - - if(!is_moderator($forum['fid'], "canapproveunapproveposts")) - { - if($mybb->user['moderateposts'] == 1) - { - $moderation_text = $lang->moderation_user_posts; - eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); - } - } - - $plugins->run_hooks("newthread_end"); - - $forum['name'] = strip_tags($forum['name']); - $lang->newthread_in = $lang->sprintf($lang->newthread_in, $forum['name']); - - eval("\$newthread = \"".$templates->get("newthread")."\";"); - output_page($newthread); -} - diff --git a/html/forums/online.php b/html/forums/online.php deleted file mode 100644 index 9a52528..0000000 --- a/html/forums/online.php +++ /dev/null @@ -1,284 +0,0 @@ -load("online"); - -if($mybb->usergroup['canviewonline'] == 0) -{ - error_no_permission(); -} - -// Make navigation -add_breadcrumb($lang->nav_online, "online.php"); - -if($mybb->get_input('action') == "today") -{ - add_breadcrumb($lang->nav_onlinetoday); - - $plugins->run_hooks("online_today_start"); - - $threshold = TIME_NOW-(60*60*24); - $query = $db->simple_select("users", "COUNT(uid) AS users", "lastactive > '{$threshold}'"); - $todaycount = $db->fetch_field($query, "users"); - - $query = $db->simple_select("users", "COUNT(uid) AS users", "lastactive > '{$threshold}' AND invisible = '1'"); - $invis_count = $db->fetch_field($query, "users"); - - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - // Add pagination - $perpage = $mybb->settings['threadsperpage']; - - if($mybb->get_input('page', MyBB::INPUT_INT) > 0) - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($page-1) * $perpage; - $pages = ceil($todaycount / $perpage); - if($page > $pages) - { - $start = 0; - $page = 1; - } - } - else - { - $start = 0; - $page = 1; - } - - $query = $db->simple_select("users", "*", "lastactive > '{$threshold}'", array("order_by" => "lastactive", "order_dir" => "desc", "limit" => $perpage, "limit_start" => $start)); - - $todayrows = ''; - while($online = $db->fetch_array($query)) - { - $invisiblemark = ''; - if($online['invisible'] == 1) - { - $invisiblemark = "*"; - } - - if($online['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $online['uid'] == $mybb->user['uid']) - { - $username = format_name(htmlspecialchars_uni($online['username']), $online['usergroup'], $online['displaygroup']); - $online['profilelink'] = build_profile_link($username, $online['uid']); - $onlinetime = my_date($mybb->settings['timeformat'], $online['lastactive']); - - eval("\$todayrows .= \"".$templates->get("online_today_row")."\";"); - } - } - - $todaycount = my_number_format($todaycount); - $invis_count = my_number_format($invis_count); - - if($todaycount == 1) - { - $onlinetoday = $lang->member_online_today; - } - else - { - $onlinetoday = $lang->sprintf($lang->members_were_online_today, $todaycount); - } - - if($invis_count) - { - $string = $lang->members_online_hidden; - - if($invis_count == 1) - { - $string = $lang->member_online_hidden; - } - - $onlinetoday .= $lang->sprintf($string, $invis_count); - } - - $multipage = multipage($todaycount, $perpage, $page, "online.php?action=today"); - - $plugins->run_hooks("online_today_end"); - - eval("\$today = \"".$templates->get("online_today")."\";"); - output_page($today); -} -else -{ - $plugins->run_hooks("online_start"); - - // Custom sorting options - if($mybb->get_input('sortby') == "username") - { - $sql = "u.username ASC, s.time DESC"; - $refresh_string = "?sortby=username"; - } - elseif($mybb->get_input('sortby') == "location") - { - $sql = "s.location, s.time DESC"; - $refresh_string = "?sortby=location"; - } - // Otherwise sort by last refresh - else - { - switch($db->type) - { - case "sqlite": - case "pgsql": - $sql = "s.time DESC"; - break; - default: - $sql = "IF( s.uid >0, 1, 0 ) DESC, s.time DESC"; - break; - } - $refresh_string = ''; - } - - $timesearch = TIME_NOW - $mybb->settings['wolcutoffmins']*60; - - // Exactly how many users are currently online? - switch($db->type) - { - case "sqlite": - $sessions = array(); - $query = $db->simple_select("sessions", "sid", "time > {$timesearch}"); - while($sid = $db->fetch_field($query, "sid")) - { - $sessions[$sid] = 1; - } - $online_count = count($sessions); - unset($sessions); - break; - case "pgsql": - default: - $query = $db->simple_select("sessions", "COUNT(sid) as online", "time > {$timesearch}"); - $online_count = $db->fetch_field($query, "online"); - break; - } - - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - // How many pages are there? - $perpage = $mybb->settings['threadsperpage']; - - if($mybb->get_input('page', MyBB::INPUT_INT) > 0) - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($page-1) * $perpage; - $pages = ceil($online_count / $perpage); - if($page > $pages) - { - $start = 0; - $page = 1; - } - } - else - { - $start = 0; - $page = 1; - } - - // Assemble page URL - $multipage = multipage($online_count, $perpage, $page, "online.php".$refresh_string); - - // Query for active sessions - $query = $db->query(" - SELECT DISTINCT s.sid, s.ip, s.uid, s.time, s.location, u.username, s.nopermission, u.invisible, u.usergroup, u.displaygroup - FROM ".TABLE_PREFIX."sessions s - LEFT JOIN ".TABLE_PREFIX."users u ON (s.uid=u.uid) - WHERE s.time>'$timesearch' - ORDER BY $sql - LIMIT {$start}, {$perpage} - "); - - // Fetch spiders - $spiders = $cache->read("spiders"); - - while($user = $db->fetch_array($query)) - { - $plugins->run_hooks("online_user"); - - // Fetch the WOL activity - $user['activity'] = fetch_wol_activity($user['location'], $user['nopermission']); - - $botkey = my_strtolower(str_replace("bot=", '', $user['sid'])); - - // Have a registered user - if($user['uid'] > 0) - { - if(empty($users[$user['uid']]) || $users[$user['uid']]['time'] < $user['time']) - { - $users[$user['uid']] = $user; - } - } - // Otherwise this session is a bot - else if(my_strpos($user['sid'], "bot=") !== false && $spiders[$botkey]) - { - $user['bot'] = $spiders[$botkey]['name']; - $user['usergroup'] = $spiders[$botkey]['usergroup']; - $guests[] = $user; - } - // Or a guest - else - { - $guests[] = $user; - } - } - - // Now we build the actual online rows - we do this separately because we need to query all of the specific activity and location information - $online_rows = ''; - if(isset($users) && is_array($users)) - { - reset($users); - foreach($users as $user) - { - $online_rows .= build_wol_row($user); - } - } - if(isset($guests) && is_array($guests)) - { - reset($guests); - foreach($guests as $user) - { - $online_rows .= build_wol_row($user); - } - } - - // Fetch the most online information - $most_online = $cache->read("mostonline"); - $record_count = $most_online['numusers']; - $record_date = my_date('relative', $most_online['time']); - - // Set automatic refreshing if enabled - if($mybb->settings['refreshwol'] > 0) - { - $refresh_time = $mybb->settings['refreshwol'] * 60; - eval("\$refresh = \"".$templates->get("online_refresh")."\";"); - } - - $plugins->run_hooks("online_end"); - - eval("\$online = \"".$templates->get("online")."\";"); - output_page($online); -} diff --git a/html/forums/polls.php b/html/forums/polls.php deleted file mode 100644 index 7caaeb5..0000000 --- a/html/forums/polls.php +++ /dev/null @@ -1,1204 +0,0 @@ -load("polls"); - -$plugins->run_hooks("polls_start"); - -if($mybb->user['uid'] != 0) -{ - $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); - eval("\$loginbox = \"".$templates->get("changeuserbox")."\";"); -} -else -{ - eval("\$loginbox = \"".$templates->get("loginbox")."\";"); -} - -$mybb->input['action'] = $mybb->get_input('action'); -if(!empty($mybb->input['updateoptions'])) -{ - if($mybb->input['action'] == "do_editpoll") - { - $mybb->input['action'] = "editpoll"; - } - else - { - $mybb->input['action'] = "newpoll"; - } -} -if($mybb->input['action'] == "newpoll") -{ - // Form for new poll - $tid = $mybb->get_input('tid', MyBB::INPUT_INT); - - $plugins->run_hooks("polls_newpoll_start"); - - $thread = get_thread($mybb->get_input('tid', MyBB::INPUT_INT)); - if(!$thread) - { - error($lang->error_invalidthread); - } - - // Is the currently logged in user a moderator of this forum? - $ismod = is_moderator($thread['fid']); - - // Make sure we are looking at a real thread here. - if(($thread['visible'] != 1 && $ismod == false) || ($thread['visible'] > 1 && $ismod == true)) - { - error($lang->error_invalidthread); - } - - $fid = $thread['fid']; - $forumpermissions = forum_permissions($fid); - - // Get forum info - $forum = get_forum($fid); - if(!$forum) - { - error($lang->error_invalidforum); - } - else - { - // Is our forum closed? - if($forum['open'] == 0 && !is_moderator($fid, "canmanagepolls")) - { - // Doesn't look like it is - error($lang->error_closedinvalidforum); - } - } - // Make navigation - build_forum_breadcrumb($fid); - add_breadcrumb(htmlspecialchars_uni($thread['subject']), get_thread_link($thread['tid'])); - add_breadcrumb($lang->nav_postpoll); - - // No permission if: Not thread author; not moderator; no forum perms to view, post threads, post polls - if(($thread['uid'] != $mybb->user['uid'] && !is_moderator($fid, "canmanagepolls")) || ($forumpermissions['canview'] == 0 || $forumpermissions['canpostthreads'] == 0 || $forumpermissions['canpostpolls'] == 0)) - { - error_no_permission(); - } - - if($thread['poll']) - { - error($lang->error_pollalready); - } - - $time = TIME_NOW; - if($thread['dateline'] < ($time-($mybb->settings['polltimelimit']*60*60)) && $mybb->settings['polltimelimit'] != 0 && $ismod == false) - { - $lang->poll_time_limit = $lang->sprintf($lang->poll_time_limit, $mybb->settings['polltimelimit']); - error($lang->poll_time_limit); - } - - // Sanitize number of poll options - if($mybb->get_input('numpolloptions', MyBB::INPUT_INT) > 0) - { - $mybb->input['polloptions'] = $mybb->get_input('numpolloptions', MyBB::INPUT_INT); - } - if($mybb->settings['maxpolloptions'] && $mybb->get_input('polloptions', MyBB::INPUT_INT) > $mybb->settings['maxpolloptions']) - { // Too big - $polloptions = $mybb->settings['maxpolloptions']; - } - elseif($mybb->get_input('polloptions', MyBB::INPUT_INT) < 2) - { // Too small - $polloptions = 2; - } - else - { // Just right - $polloptions = $mybb->get_input('polloptions', MyBB::INPUT_INT); - } - - $question = htmlspecialchars_uni($mybb->get_input('question')); - - $postoptionschecked = array('public' => '', 'multiple' => ''); - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_INT); - if(isset($postoptions['multiple']) && $postoptions['multiple'] == 1) - { - $postoptionschecked['multiple'] = 'checked="checked"'; - } - if(isset($postoptions['public']) && $postoptions['public'] == 1) - { - $postoptionschecked['public'] = 'checked="checked"'; - } - - $options = $mybb->get_input('options', MyBB::INPUT_ARRAY); - $optionbits = ''; - for($i = 1; $i <= $polloptions; ++$i) - { - if(!isset($options[$i])) - { - $options[$i] = ''; - } - $option = $options[$i]; - $option = htmlspecialchars_uni($option); - eval("\$optionbits .= \"".$templates->get("polls_newpoll_option")."\";"); - $option = ""; - } - - if($mybb->get_input('timeout', MyBB::INPUT_INT) > 0) - { - $timeout = $mybb->get_input('timeout', MyBB::INPUT_INT); - } - else - { - $timeout = 0; - } - - if($mybb->get_input('maxoptions', MyBB::INPUT_INT) > 0 && $mybb->get_input('maxoptions', MyBB::INPUT_INT) < $polloptions) - { - $maxoptions = $mybb->get_input('maxoptions', MyBB::INPUT_INT); - } - else - { - $maxoptions = 0; - } - - $plugins->run_hooks("polls_newpoll_end"); - - eval("\$newpoll = \"".$templates->get("polls_newpoll")."\";"); - output_page($newpoll); -} -if($mybb->input['action'] == "do_newpoll" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("polls_do_newpoll_start"); - - $thread = get_thread($mybb->get_input('tid', MyBB::INPUT_INT)); - if(!$thread) - { - error($lang->error_invalidthread); - } - - $fid = $thread['fid']; - $forumpermissions = forum_permissions($fid); - - // Get forum info - $forum = get_forum($fid); - if(!$forum) - { - error($lang->error_invalidforum); - } - else - { - // Is our forum closed? - if($forum['open'] == 0 && !is_moderator($fid, "canmanagepolls")) - { - // Doesn't look like it is - error($lang->error_closedinvalidforum); - } - } - - // No permission if: Not thread author; not moderator; no forum perms to view, post threads, post polls - if(($thread['uid'] != $mybb->user['uid'] && !is_moderator($fid, "canmanagepolls")) || ($forumpermissions['canview'] == 0 || $forumpermissions['canpostthreads'] == 0 || $forumpermissions['canpostpolls'] == 0)) - { - error_no_permission(); - } - - if($thread['poll']) - { - error($lang->error_pollalready); - } - - $polloptions = $mybb->get_input('polloptions', MyBB::INPUT_INT); - if($mybb->settings['maxpolloptions'] && $polloptions > $mybb->settings['maxpolloptions']) - { - $polloptions = $mybb->settings['maxpolloptions']; - } - - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - if(!isset($postoptions['multiple']) || $postoptions['multiple'] != '1') - { - $postoptions['multiple'] = 0; - } - - if(!isset($postoptions['public']) || $postoptions['public'] != '1') - { - $postoptions['public'] = 0; - } - - if($polloptions < 2) - { - $polloptions = "2"; - } - $optioncount = "0"; - $options = $mybb->get_input('options', MyBB::INPUT_ARRAY); - - for($i = 1; $i <= $polloptions; ++$i) - { - if(!isset($options[$i])) - { - $options[$i] = ''; - } - - if($mybb->settings['polloptionlimit'] != 0 && my_strlen($options[$i]) > $mybb->settings['polloptionlimit']) - { - $lengtherror = 1; - break; - } - - if(strpos($options[$i], '||~|~||') !== false) - { - $sequenceerror = 1; - break; - } - - if(trim($options[$i]) != "") - { - $optioncount++; - } - } - - if(isset($lengtherror)) - { - error($lang->error_polloptiontoolong); - } - - if(isset($sequenceerror)) - { - error($lang->error_polloptionsequence); - } - - $mybb->input['question'] = $mybb->get_input('question'); - - if(trim($mybb->input['question']) == '' || $optioncount < 2) - { - error($lang->error_noquestionoptions); - } - - $optionslist = ''; - $voteslist = ''; - for($i = 1; $i <= $polloptions; ++$i) - { - if(trim($options[$i]) != '') - { - if($optionslist != '') - { - $optionslist .= '||~|~||'; - $voteslist .= '||~|~||'; - } - $optionslist .= trim($options[$i]); - $voteslist .= '0'; - } - } - - if($mybb->get_input('timeout', MyBB::INPUT_INT) > 0) - { - $timeout = $mybb->get_input('timeout', MyBB::INPUT_INT); - } - else - { - $timeout = 0; - } - - if($mybb->get_input('maxoptions', MyBB::INPUT_INT) > 0 && $mybb->get_input('maxoptions', MyBB::INPUT_INT) < $polloptions) - { - $maxoptions = $mybb->get_input('maxoptions', MyBB::INPUT_INT); - } - else - { - $maxoptions = 0; - } - - $newpoll = array( - "tid" => $thread['tid'], - "question" => $db->escape_string($mybb->input['question']), - "dateline" => TIME_NOW, - "options" => $db->escape_string($optionslist), - "votes" => $db->escape_string($voteslist), - "numoptions" => (int)$optioncount, - "numvotes" => 0, - "timeout" => $timeout, - "closed" => 0, - "multiple" => $postoptions['multiple'], - "public" => $postoptions['public'], - "maxoptions" => $maxoptions - ); - - $plugins->run_hooks("polls_do_newpoll_process"); - - $pid = $db->insert_query("polls", $newpoll); - - $db->update_query("threads", array('poll' => $pid), "tid='".$thread['tid']."'"); - - $plugins->run_hooks("polls_do_newpoll_end"); - - if($thread['visible'] == 1) - { - redirect(get_thread_link($thread['tid']), $lang->redirect_pollposted); - } - else - { - redirect(get_forum_link($thread['fid']), $lang->redirect_pollpostedmoderated); - } -} - -if($mybb->input['action'] == "editpoll") -{ - $pid = $mybb->get_input('pid', MyBB::INPUT_INT); - - $plugins->run_hooks("polls_editpoll_start"); - - $query = $db->simple_select("polls", "*", "pid='$pid'"); - $poll = $db->fetch_array($query); - - if(!$poll) - { - error($lang->error_invalidpoll); - } - - $query = $db->simple_select("threads", "*", "poll='$pid'"); - $thread = $db->fetch_array($query); - if(!$thread) - { - error($lang->error_invalidthread); - } - - $tid = $thread['tid']; - $fid = $thread['fid']; - - // Make navigation - build_forum_breadcrumb($fid); - add_breadcrumb(htmlspecialchars_uni($thread['subject']), get_thread_link($thread['tid'])); - add_breadcrumb($lang->nav_editpoll); - - $forumpermissions = forum_permissions($fid); - - // Get forum info - $forum = get_forum($fid); - if(!$forum) - { - error($lang->error_invalidforum); - } - else - { - // Is our forum closed? - if($forum['open'] == 0 && !is_moderator($fid, "canmanagepolls")) - { - // Doesn't look like it is - error($lang->error_closedinvalidforum); - } - } - - if(!is_moderator($fid, "canmanagepolls")) - { - error_no_permission(); - } - - $postoptionschecked = array('closed' => '', 'multiple' => '', 'public' => ''); - - $polldate = my_date($mybb->settings['dateformat'], $poll['dateline']); - if(empty($mybb->input['updateoptions'])) - { - if($poll['closed'] == 1) - { - $postoptionschecked['closed'] = 'checked="checked"'; - } - - if($poll['multiple'] == 1) - { - $postoptionschecked['multiple'] = 'checked="checked"'; - } - - if($poll['public'] == 1) - { - $postoptionschecked['public'] = 'checked="checked"'; - } - - $optionsarray = explode("||~|~||", $poll['options']); - $votesarray = explode("||~|~||", $poll['votes']); - - $poll['totvotes'] = 0; - for($i = 1; $i <= $poll['numoptions']; ++$i) - { - $poll['totvotes'] = $poll['totvotes'] + $votesarray[$i-1]; - } - - $question = htmlspecialchars_uni($poll['question']); - $numoptions = $poll['numoptions']; - $optionbits = ""; - for($i = 0; $i < $numoptions; ++$i) - { - $counter = $i + 1; - $option = $optionsarray[$i]; - $option = htmlspecialchars_uni($option); - $optionvotes = (int)$votesarray[$i]; - - if(!$optionvotes) - { - $optionvotes = 0; - } - - eval("\$optionbits .= \"".$templates->get("polls_editpoll_option")."\";"); - $option = ""; - $optionvotes = ""; - } - - if(!$poll['timeout']) - { - $timeout = 0; - } - else - { - $timeout = $poll['timeout']; - } - - if(!$poll['maxoptions']) - { - $maxoptions = 0; - } - else - { - $maxoptions = $poll['maxoptions']; - } - } - else - { - if($mybb->settings['maxpolloptions'] && $mybb->get_input('numoptions', MyBB::INPUT_INT) > $mybb->settings['maxpolloptions']) - { - $numoptions = $mybb->settings['maxpolloptions']; - } - elseif($mybb->get_input('numoptions', MyBB::INPUT_INT) < 2) - { - $numoptions = 2; - } - else - { - $numoptions = $mybb->get_input('numoptions', MyBB::INPUT_INT); - } - $question = htmlspecialchars_uni($mybb->input['question']); - - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - if(isset($postoptions['multiple']) && $postoptions['multiple'] == 1) - { - $postoptionschecked['multiple'] = 'checked="checked"'; - } - - if(isset($postoptions['public']) && $postoptions['public'] == 1) - { - $postoptionschecked['public'] = 'checked="checked"'; - } - - if(isset($postoptions['closed']) && $postoptions['closed'] == 1) - { - $postoptionschecked['closed'] = 'checked="checked"'; - } - - $options = $mybb->get_input('options', MyBB::INPUT_ARRAY); - $votes = $mybb->get_input('votes', MyBB::INPUT_ARRAY); - $optionbits = ''; - for($i = 1; $i <= $numoptions; ++$i) - { - $counter = $i; - if(!isset($options[$i])) - { - $options[$i] = ''; - } - $option = htmlspecialchars_uni($options[$i]); - if(!isset($votes[$i])) - { - $votes[$i] = 0; - } - $optionvotes = (int)$votes[$i]; - - if(!$optionvotes) - { - $optionvotes = 0; - } - - eval("\$optionbits .= \"".$templates->get("polls_editpoll_option")."\";"); - $option = ""; - } - - if($mybb->get_input('timeout', MyBB::INPUT_INT) > 0) - { - $timeout = $mybb->get_input('timeout', MyBB::INPUT_INT); - } - else - { - $timeout = 0; - } - - if(!$poll['maxoptions']) - { - $maxoptions = 0; - } - else - { - $maxoptions = $poll['maxoptions']; - } - } - - $plugins->run_hooks("polls_editpoll_end"); - - eval("\$editpoll = \"".$templates->get("polls_editpoll")."\";"); - output_page($editpoll); -} - -if($mybb->input['action'] == "do_editpoll" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("polls_do_editpoll_start"); - - $query = $db->simple_select("polls", "*", "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - $poll = $db->fetch_array($query); - - if(!$poll) - { - error($lang->error_invalidpoll); - } - - $query = $db->simple_select("threads", "*", "poll='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - $thread = $db->fetch_array($query); - if(!$thread) - { - error($lang->error_invalidthread); - } - - $forumpermissions = forum_permissions($thread['fid']); - - // Get forum info - $forum = get_forum($thread['fid']); - $fid = $thread['fid']; - if(!$forum) - { - error($lang->error_invalidforum); - } - else - { - // Is our forum closed? - if($forum['open'] == 0 && !is_moderator($fid, "canmanagepolls")) - { - // Doesn't look like it is - error($lang->error_closedinvalidforum); - } - } - - if(!is_moderator($thread['fid'], "canmanagepolls")) - { - error_no_permission(); - } - - if($mybb->settings['maxpolloptions'] && $mybb->get_input('numoptions', MyBB::INPUT_INT) > $mybb->settings['maxpolloptions']) - { - $numoptions = $mybb->settings['maxpolloptions']; - } - elseif($mybb->get_input('numoptions', MyBB::INPUT_INT) < 2) - { - $numoptions = 2; - } - else - { - $numoptions = $mybb->get_input('numoptions', MyBB::INPUT_INT); - } - - $postoptions = $mybb->get_input('postoptions', MyBB::INPUT_ARRAY); - if(!isset($postoptions['multiple']) || $postoptions['multiple'] != '1') - { - $postoptions['multiple'] = 0; - } - - if(!isset($postoptions['public']) || $postoptions['public'] != '1') - { - $postoptions['public'] = 0; - } - - if(!isset($postoptions['closed']) || $postoptions['closed'] != '1') - { - $postoptions['closed'] = 0; - } - $optioncount = "0"; - $options = $mybb->input['options']; - - for($i = 1; $i <= $numoptions; ++$i) - { - if(!isset($options[$i])) - { - $options[$i] = ''; - } - - if($mybb->settings['polloptionlimit'] != 0 && my_strlen($options[$i]) > $mybb->settings['polloptionlimit']) - { - $lengtherror = 1; - break; - } - - if(strpos($options[$i], '||~|~||') !== false) - { - $sequenceerror = 1; - break; - } - - if(trim($options[$i]) != "") - { - $optioncount++; - } - } - - if(isset($lengtherror)) - { - error($lang->error_polloptiontoolong); - } - - if(isset($sequenceerror)) - { - error($lang->error_polloptionsequence); - } - - $mybb->input['question'] = $mybb->get_input('question'); - if(trim($mybb->input['question']) == '' || $optioncount < 2) - { - error($lang->error_noquestionoptions); - } - - $optionslist = ''; - $voteslist = ''; - $numvotes = ''; - $votes = $mybb->input['votes']; - for($i = 1; $i <= $numoptions; ++$i) - { - if(trim($options[$i]) != '') - { - if($optionslist != '') - { - $optionslist .= "||~|~||"; - $voteslist .= "||~|~||"; - } - - $optionslist .= trim($options[$i]); - if(!isset($votes[$i]) || (int)$votes[$i] <= 0) - { - $votes[$i] = "0"; - } - $voteslist .= $votes[$i]; - $numvotes = $numvotes + $votes[$i]; - } - } - - if($mybb->get_input('timeout', MyBB::INPUT_INT) > 0) - { - $timeout = $mybb->get_input('timeout', MyBB::INPUT_INT); - } - else - { - $timeout = 0; - } - - if($mybb->get_input('maxoptions', MyBB::INPUT_INT) > 0 && $mybb->get_input('maxoptions', MyBB::INPUT_INT) < $numoptions) - { - $maxoptions = $mybb->get_input('maxoptions', MyBB::INPUT_INT); - } - else - { - $maxoptions = 0; - } - - $updatedpoll = array( - "question" => $db->escape_string($mybb->input['question']), - "options" => $db->escape_string($optionslist), - "votes" => $db->escape_string($voteslist), - "numoptions" => (int)$optioncount, - "numvotes" => $numvotes, - "timeout" => $timeout, - "closed" => $postoptions['closed'], - "multiple" => $postoptions['multiple'], - "public" => $postoptions['public'], - "maxoptions" => $maxoptions - ); - - $plugins->run_hooks("polls_do_editpoll_process"); - - $db->update_query("polls", $updatedpoll, "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - - $plugins->run_hooks("polls_do_editpoll_end"); - - $modlogdata['fid'] = $thread['fid']; - $modlogdata['tid'] = $thread['tid']; - log_moderator_action($modlogdata, $lang->poll_edited); - - redirect(get_thread_link($thread['tid']), $lang->redirect_pollupdated); -} - -if($mybb->input['action'] == "showresults") -{ - $query = $db->simple_select("polls", "*", "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - $poll = $db->fetch_array($query); - - if(!$poll) - { - error($lang->error_invalidpoll); - } - - $tid = $poll['tid']; - $thread = get_thread($tid); - if(!$thread) - { - error($lang->error_invalidthread); - } - - $fid = $thread['fid']; - - // Get forum info - $forum = get_forum($fid); - if(!$forum) - { - error($lang->error_invalidforum); - } - - $forumpermissions = forum_permissions($forum['fid']); - - $plugins->run_hooks("polls_showresults_start"); - - if($forumpermissions['canviewthreads'] == 0 || $forumpermissions['canview'] == 0 || (isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0 && $thread['uid'] != $mybb->user['uid'])) - { - error_no_permission(); - } - - // Make navigation - build_forum_breadcrumb($fid); - add_breadcrumb(htmlspecialchars_uni($thread['subject']), get_thread_link($thread['tid'])); - add_breadcrumb($lang->nav_pollresults); - - $voters = $votedfor = array(); - - // Calculate votes - $query = $db->query(" - SELECT v.*, u.username - FROM ".TABLE_PREFIX."pollvotes v - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=v.uid) - WHERE v.pid='{$poll['pid']}' - ORDER BY u.username - "); - while($voter = $db->fetch_array($query)) - { - // Mark for current user's vote - if($mybb->user['uid'] == $voter['uid'] && $mybb->user['uid']) - { - $votedfor[$voter['voteoption']] = 1; - } - - // Count number of guests and users without a username (assumes they've been deleted) - if($voter['uid'] == 0 || $voter['username'] == '') - { - // Add one to the number of voters for guests - ++$guest_voters[$voter['voteoption']]; - } - else - { - $voters[$voter['voteoption']][$voter['uid']] = htmlspecialchars_uni($voter['username']); - } - } - - $optionsarray = explode("||~|~||", $poll['options']); - $votesarray = explode("||~|~||", $poll['votes']); - $poll['totvotes'] = 0; - for($i = 1; $i <= $poll['numoptions']; ++$i) - { - $poll['totvotes'] = $poll['totvotes'] + $votesarray[$i-1]; - } - - $polloptions = ''; - for($i = 1; $i <= $poll['numoptions']; ++$i) - { - $parser_options = array( - "allow_html" => $forum['allowhtml'], - "allow_mycode" => $forum['allowmycode'], - "allow_smilies" => $forum['allowsmilies'], - "allow_imgcode" => $forum['allowimgcode'], - "allow_videocode" => $forum['allowvideocode'], - "filter_badwords" => 1 - ); - $option = $parser->parse_message($optionsarray[$i-1], $parser_options); - - $votes = $votesarray[$i-1]; - $number = $i; - // Make the mark for current user's voted option - if(!empty($votedfor[$number])) - { - $optionbg = 'trow2'; - $votestar = '*'; - } - else - { - $optionbg = 'trow1'; - $votestar = ''; - } - - if($votes == 0) - { - $percent = 0; - } - else - { - $percent = number_format($votes / $poll['totvotes'] * 100, 2); - } - - $imagewidth = round($percent); - $comma = ''; - $guest_comma = ''; - $userlist = ''; - $guest_count = 0; - if($poll['public'] == 1 || is_moderator($fid, "canmanagepolls")) - { - if(isset($voters[$number]) && is_array($voters[$number])) - { - foreach($voters[$number] as $uid => $username) - { - $userlist .= $comma.build_profile_link($username, $uid); - $comma = $guest_comma = $lang->comma; - } - } - - if(isset($guest_voters[$number]) && $guest_voters[$number] > 0) - { - if($guest_voters[$number] == 1) - { - $userlist .= $guest_comma.$lang->guest_count; - } - else - { - $userlist .= $guest_comma.$lang->sprintf($lang->guest_count_multiple, $guest_voters[$number]); - } - } - } - eval("\$polloptions .= \"".$templates->get("polls_showresults_resultbit")."\";"); - } - - if($poll['totvotes']) - { - $totpercent = '100%'; - } - else - { - $totpercent = '0%'; - } - - $plugins->run_hooks("polls_showresults_end"); - - $poll['question'] = htmlspecialchars_uni($poll['question']); - eval("\$showresults = \"".$templates->get("polls_showresults")."\";"); - output_page($showresults); -} -if($mybb->input['action'] == "vote" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $query = $db->simple_select("polls", "*", "pid='".$mybb->get_input('pid')."'"); - $poll = $db->fetch_array($query); - - if(!$poll) - { - error($lang->error_invalidpoll); - } - - $plugins->run_hooks("polls_vote_start"); - - $poll['timeout'] = $poll['timeout']*60*60*24; - - $query = $db->simple_select("threads", "*", "poll='".(int)$poll['pid']."'"); - $thread = $db->fetch_array($query); - - if(!$thread || $thread['visible'] == 0) - { - error($lang->error_invalidthread); - } - - $fid = $thread['fid']; - $forumpermissions = forum_permissions($fid); - if($forumpermissions['canvotepolls'] == 0) - { - error_no_permission(); - } - - // Get forum info - $forum = get_forum($fid); - if(!$forum) - { - error($lang->error_invalidforum); - } - else - { - // Is our forum closed? - if($forum['open'] == 0) - { - // Doesn't look like it is - error($lang->error_closedinvalidforum); - } - } - - $expiretime = $poll['dateline'] + $poll['timeout']; - $now = TIME_NOW; - if($poll['closed'] == 1 || $thread['closed'] == 1 || ($expiretime < $now && $poll['timeout'])) - { - error($lang->error_pollclosed); - } - - if(!isset($mybb->input['option'])) - { - error($lang->error_nopolloptions); - } - - // Check if the user has voted before... - if($mybb->user['uid']) - { - $query = $db->simple_select("pollvotes", "*", "uid='".$mybb->user['uid']."' AND pid='".$poll['pid']."'"); - $votecheck = $db->fetch_array($query); - } - - if($votecheck['vid'] || (isset($mybb->cookies['pollvotes'][$poll['pid']]) && $mybb->cookies['pollvotes'][$poll['pid']] !== "")) - { - error($lang->error_alreadyvoted); - } - elseif(!$mybb->user['uid']) - { - // Give a cookie to guests to inhibit revotes - if(is_array($mybb->input['option'])) - { - // We have multiple options here... - $votes_cookie = implode(',', array_keys($mybb->input['option'])); - } - else - { - $votes_cookie = $mybb->input['option']; - } - - my_setcookie("pollvotes[{$poll['pid']}]", $votes_cookie); - } - - $votesql = ''; - $now = TIME_NOW; - $votesarray = explode("||~|~||", $poll['votes']); - $option = $mybb->input['option']; - $numvotes = (int)$poll['numvotes']; - if($poll['multiple'] == 1) - { - if(is_array($option)) - { - $total_options = 0; - - foreach($option as $voteoption => $vote) - { - if($vote == 1 && isset($votesarray[$voteoption-1])) - { - if($votesql) - { - $votesql .= ","; - } - $votesql .= "('".$poll['pid']."','".$mybb->user['uid']."','".$db->escape_string($voteoption)."','$now')"; - $votesarray[$voteoption-1]++; - $numvotes = $numvotes+1; - $total_options++; - } - } - - if($total_options > $poll['maxoptions'] && $poll['maxoptions'] != 0) - { - error($lang->sprintf($lang->error_maxpolloptions, $poll['maxoptions'])); - } - } - } - else - { - if(is_array($option) || !isset($votesarray[$option-1])) - { - error($lang->error_nopolloptions); - } - $votesql = "('".$poll['pid']."','".$mybb->user['uid']."','".$db->escape_string($option)."','$now')"; - $votesarray[$option-1]++; - $numvotes = $numvotes+1; - } - - if(!$votesql) - { - error($lang->error_nopolloptions); - } - - $db->write_query(" - INSERT INTO - ".TABLE_PREFIX."pollvotes (pid,uid,voteoption,dateline) - VALUES $votesql - "); - $voteslist = ''; - for($i = 1; $i <= $poll['numoptions']; ++$i) - { - if($i > 1) - { - $voteslist .= "||~|~||"; - } - $voteslist .= $votesarray[$i-1]; - } - $updatedpoll = array( - "votes" => $db->escape_string($voteslist), - "numvotes" => (int)$numvotes, - ); - - $plugins->run_hooks("polls_vote_process"); - - $db->update_query("polls", $updatedpoll, "pid='".$poll['pid']."'"); - - $plugins->run_hooks("polls_vote_end"); - - redirect(get_thread_link($poll['tid']), $lang->redirect_votethanks); -} - -if($mybb->input['action'] == "do_undovote") -{ - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->usergroup['canundovotes'] != 1) - { - error_no_permission(); - } - - $query = $db->simple_select("polls", "*", "pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - $poll = $db->fetch_array($query); - - if(!$poll['pid']) - { - error($lang->error_invalidpoll); - } - - $plugins->run_hooks("polls_do_undovote_start"); - - $poll['numvotes'] = (int)$poll['numvotes']; - - // We do not have $forum_cache available here since no forums permissions are checked in undo vote - // Get thread ID and then get forum info - $thread = get_thread($poll['tid']); - if(!$thread || $thread['visible'] == 0) - { - error($lang->error_invalidthread); - } - - $fid = $thread['fid']; - - // Get forum info - $forum = get_forum($fid); - if(!$forum) - { - error($lang->error_invalidforum); - } - else - { - // Is our forum closed? - if($forum['open'] == 0) - { - // Doesn't look like it is - error($lang->error_closedinvalidforum); - } - } - - $poll['timeout'] = $poll['timeout']*60*60*24; - - - $expiretime = $poll['dateline'] + $poll['timeout']; - if($poll['closed'] == 1 || $thread['closed'] == 1 || ($expiretime < TIME_NOW && $poll['timeout'])) - { - error($lang->error_pollclosed); - } - - // Check if the user has voted before... - $vote_options = array(); - if($mybb->user['uid']) - { - $query = $db->simple_select("pollvotes", "vid,voteoption", "uid='".$mybb->user['uid']."' AND pid='".$poll['pid']."'"); - while($voteoption = $db->fetch_array($query)) - { - $vote_options[$voteoption['vid']] = $voteoption['voteoption']; - } - } - elseif(isset($mybb->cookies['pollvotes'][$poll['pid']])) - { - // for Guests, we simply see if they've got the cookie - $vote_options = explode(',', $mybb->cookies['pollvotes'][$poll['pid']]); - } - - if(empty($vote_options)) - { - error($lang->error_notvoted); - } - else if(!$mybb->user['uid']) - { - // clear cookie for Guests - my_setcookie("pollvotes[{$poll['pid']}]", ""); - } - - // Note, this is not thread safe! - $votesarray = explode("||~|~||", $poll['votes']); - if(count($votesarray) > $poll['numoptions']) - { - $votesarray = array_slice(0, $poll['numoptions']); - } - - if($poll['multiple'] == 1) - { - foreach($vote_options as $vote) - { - if(isset($votesarray[$vote-1])) - { - --$votesarray[$vote-1]; - --$poll['numvotes']; - } - } - } - else - { - $voteoption = reset($vote_options); - if(isset($votesarray[$voteoption-1])) - { - --$votesarray[$voteoption-1]; - --$poll['numvotes']; - } - } - - // check if anything < 0 - possible if Guest vote undoing is allowed (generally Guest unvoting should be disabled >_>) - if($poll['numvotes'] < 0) - { - $poll['numvotes'] = 0; - } - - foreach($votesarray as $i => $votes) - { - if($votes < 0) - { - $votesarray[$i] = 0; - } - } - - $voteslist = implode("||~|~||", $votesarray); - $updatedpoll = array( - "votes" => $db->escape_string($voteslist), - "numvotes" => (int)$poll['numvotes'], - ); - - $plugins->run_hooks("polls_do_undovote_process"); - - $db->delete_query("pollvotes", "uid='".$mybb->user['uid']."' AND pid='".$poll['pid']."'"); - $db->update_query("polls", $updatedpoll, "pid='".$poll['pid']."'"); - - $plugins->run_hooks("polls_do_undovote_end"); - - redirect(get_thread_link($poll['tid']), $lang->redirect_unvoted); -} - diff --git a/html/forums/portal.php b/html/forums/portal.php deleted file mode 100644 index 8c40890..0000000 --- a/html/forums/portal.php +++ /dev/null @@ -1,712 +0,0 @@ -load("portal"); - -if($mybb->settings['portal'] == 0) -{ - error($lang->portal_disabled); -} - -// Fetch the current URL -$portal_url = get_current_location(); -$file_name = strtok(my_strtolower(basename($portal_url)), '?'); - -add_breadcrumb($lang->nav_portal, $file_name); - -$plugins->run_hooks("portal_start"); - -$tunviewwhere = $unviewwhere = ''; -// get forums user cannot view -$unviewable = get_unviewable_forums(true); -if($unviewable) -{ - $unviewwhere = " AND fid NOT IN ($unviewable)"; - $tunviewwhere = " AND t.fid NOT IN ($unviewable)"; -} - -// get inactive forums -$inactive = get_inactive_forums(); -if($inactive) -{ - $unviewwhere .= " AND fid NOT IN ($inactive)"; - $tunviewwhere .= " AND t.fid NOT IN ($inactive)"; -} - -$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); - -$welcome = ''; -// If user is known, welcome them -if($mybb->settings['portal_showwelcome'] != 0) -{ - if($mybb->user['uid'] != 0) - { - // Get number of new posts, threads, announcements - $query = $db->simple_select("posts", "COUNT(pid) AS newposts", "visible=1 AND dateline>'".$mybb->user['lastvisit']."'{$unviewwhere}"); - $newposts = $db->fetch_field($query, "newposts"); - if($newposts) - { - // If there aren't any new posts, there is no point in wasting two more queries - $query = $db->simple_select("threads", "COUNT(tid) AS newthreads", "visible=1 AND dateline>'".$mybb->user['lastvisit']."'{$unviewwhere}"); - $newthreads = $db->fetch_field($query, "newthreads"); - - $newann = 0; - if(!empty($mybb->settings['portal_announcementsfid'])) - { - $annfidswhere = ''; - if($mybb->settings['portal_announcementsfid'] != -1) - { - $announcementsfids = explode(',', (string)$mybb->settings['portal_announcementsfid']); - if(is_array($announcementsfids)) - { - foreach($announcementsfids as &$fid) - { - $fid = (int)$fid; - } - unset($fid); - - $announcementsfids = implode(',', $announcementsfids); - - $annfidswhere = " AND fid IN (".$announcementsfids.")"; - } - } - - $query = $db->simple_select("threads", "COUNT(tid) AS newann", "visible=1 AND dateline>'".$mybb->user['lastvisit']."'{$annfidswhere}{$unviewwhere}"); - $newann = $db->fetch_field($query, "newann"); - } - } - else - { - $newposts = 0; - $newthreads = 0; - $newann = 0; - } - - // Make the text - if($newann == 1) - { - $lang->new_announcements = $lang->new_announcement; - } - else - { - $lang->new_announcements = $lang->sprintf($lang->new_announcements, $newann); - } - if($newthreads == 1) - { - $lang->new_threads = $lang->new_thread; - } - else - { - $lang->new_threads = $lang->sprintf($lang->new_threads, $newthreads); - } - if($newposts == 1) - { - $lang->new_posts = $lang->new_post; - } - else - { - $lang->new_posts = $lang->sprintf($lang->new_posts, $newposts); - } - eval("\$welcometext = \"".$templates->get("portal_welcome_membertext")."\";"); - - } - else - { - $lang->guest_welcome_registration = $lang->sprintf($lang->guest_welcome_registration, $mybb->settings['bburl'].'/member.php?action=register'); - $mybb->user['username'] = $lang->guest; - switch($mybb->settings['username_method']) - { - case 0: - $username = $lang->username; - break; - case 1: - $username = $lang->username1; - break; - case 2: - $username = $lang->username2; - break; - default: - $username = $lang->username; - break; - } - eval("\$welcometext = \"".$templates->get("portal_welcome_guesttext")."\";"); - } - $lang->welcome = $lang->sprintf($lang->welcome, $mybb->user['username']); - eval("\$welcome = \"".$templates->get("portal_welcome")."\";"); -} - -$pms = ''; -// Private messages box -if($mybb->settings['portal_showpms'] != 0) -{ - if($mybb->user['uid'] != 0 && $mybb->user['receivepms'] != 0 && $mybb->usergroup['canusepms'] != 0 && $mybb->settings['enablepms'] != 0) - { - $messages['pms_total'] = $mybb->user['pms_total']; - $messages['pms_unread'] = $mybb->user['pms_unread']; - - $lang->pms_received_new = $lang->sprintf($lang->pms_received_new, $mybb->user['username'], $messages['pms_unread']); - eval("\$pms = \"".$templates->get("portal_pms")."\";"); - } -} - -$stats = ''; -// Get Forum Statistics -if($mybb->settings['portal_showstats'] != 0) -{ - $stats = $cache->read("stats"); - $stats['numthreads'] = my_number_format($stats['numthreads']); - $stats['numposts'] = my_number_format($stats['numposts']); - $stats['numusers'] = my_number_format($stats['numusers']); - if(!$stats['lastusername']) - { - eval("\$newestmember = \"".$templates->get("portal_stats_nobody")."\";"); - } - else - { - $newestmember = build_profile_link($stats['lastusername'], $stats['lastuid']); - } - eval("\$stats = \"".$templates->get("portal_stats")."\";"); -} - -$search = ''; -// Search box -if($mybb->settings['portal_showsearch'] != 0) -{ - eval("\$search = \"".$templates->get("portal_search")."\";"); -} - -$whosonline = ''; -// Get the online users -if($mybb->settings['portal_showwol'] != 0 && $mybb->usergroup['canviewonline'] != 0) -{ - if($mybb->settings['wolorder'] == 'username') - { - $order_by = 'u.username ASC'; - $order_by2 = 's.time DESC'; - } - else - { - $order_by = 's.time DESC'; - $order_by2 = 'u.username ASC'; - } - - $timesearch = TIME_NOW - $mybb->settings['wolcutoff']; - $comma = ''; - $guestcount = $membercount = $botcount = $anoncount = 0; - $onlinemembers = ''; - $doneusers = array(); - $query = $db->query(" - SELECT s.sid, s.ip, s.uid, s.time, s.location, u.username, u.invisible, u.usergroup, u.displaygroup - FROM ".TABLE_PREFIX."sessions s - LEFT JOIN ".TABLE_PREFIX."users u ON (s.uid=u.uid) - WHERE s.time>'$timesearch' - ORDER BY {$order_by}, {$order_by2} - "); - while($user = $db->fetch_array($query)) - { - - // Create a key to test if this user is a search bot. - $botkey = my_strtolower(str_replace("bot=", '', $user['sid'])); - - if($user['uid'] == "0") - { - ++$guestcount; - } - elseif(my_strpos($user['sid'], "bot=") !== false && $session->bots[$botkey]) - { - // The user is a search bot. - $onlinemembers .= $comma.format_name($session->bots[$botkey], $session->botgroup); - $comma = $lang->comma; - ++$botcount; - } - else - { - if(empty($doneusers[$user['uid']]) || $doneusers[$user['uid']] < $user['time']) - { - ++$membercount; - - $doneusers[$user['uid']] = $user['time']; - - // If the user is logged in anonymously, update the count for that. - if($user['invisible'] == 1) - { - ++$anoncount; - } - - if($user['invisible'] == 1) - { - $invisiblemark = "*"; - } - else - { - $invisiblemark = ''; - } - - if(($user['invisible'] == 1 && ($mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid'])) || $user['invisible'] != 1) - { - $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); - $user['profilelink'] = get_profile_link($user['uid']); - eval("\$onlinemembers .= \"".$templates->get("portal_whosonline_memberbit", 1, 0)."\";"); - $comma = $lang->comma; - } - } - } - } - - $onlinecount = $membercount + $guestcount + $botcount; - - // If we can see invisible users add them to the count - if($mybb->usergroup['canviewwolinvis'] == 1) - { - $onlinecount += $anoncount; - } - - // If we can't see invisible users but the user is an invisible user incriment the count by one - if($mybb->usergroup['canviewwolinvis'] != 1 && isset($mybb->user['invisible']) && $mybb->user['invisible'] == 1) - { - ++$onlinecount; - } - - // Most users online - $mostonline = $cache->read("mostonline"); - if($onlinecount > $mostonline['numusers']) - { - $time = TIME_NOW; - $mostonline['numusers'] = $onlinecount; - $mostonline['time'] = $time; - $cache->update("mostonline", $mostonline); - } - $recordcount = $mostonline['numusers']; - $recorddate = my_date('relative', $mostonline['time']); - - if($onlinecount == 1) - { - $lang->online_users = $lang->online_user; - } - else - { - $lang->online_users = $lang->sprintf($lang->online_users, $onlinecount); - } - $lang->online_counts = $lang->sprintf($lang->online_counts, $membercount, $guestcount); - eval("\$whosonline = \"".$templates->get("portal_whosonline")."\";"); -} - -$latestthreads = ''; -// Latest forum discussions -if($mybb->settings['portal_showdiscussions'] != 0 && $mybb->settings['portal_showdiscussionsnum'] && $mybb->settings['portal_excludediscussion'] != -1) -{ - $altbg = alt_trow(); - $threadlist = ''; - - $excludeforums = ''; - if(!empty($mybb->settings['portal_excludediscussion'])) - { - $excludeforums = "AND t.fid NOT IN ({$mybb->settings['portal_excludediscussion']})"; - } - - $query = $db->query(" - SELECT t.tid, t.fid, t.uid, t.lastpost, t.lastposteruid, t.lastposter, t.subject, t.replies, t.views, u.username - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=t.uid) - WHERE 1=1 {$excludeforums}{$tunviewwhere} AND t.visible='1' AND t.closed NOT LIKE 'moved|%' - ORDER BY t.lastpost DESC - LIMIT 0, ".$mybb->settings['portal_showdiscussionsnum'] - ); - while($thread = $db->fetch_array($query)) - { - $forumpermissions[$thread['fid']] = forum_permissions($thread['fid']); - - // Make sure we can view this thread - if(isset($forumpermissions[$thread['fid']]['canonlyviewownthreads']) && $forumpermissions[$thread['fid']]['canonlyviewownthreads'] == 1 && $thread['uid'] != $mybb->user['uid']) - { - continue; - } - - $lastpostdate = my_date('relative', $thread['lastpost']); - $lastposter = htmlspecialchars_uni($thread['lastposter']); - $thread['replies'] = my_number_format($thread['replies']); - $thread['views'] = my_number_format($thread['views']); - - // Don't link to guest's profiles (they have no profile). - if($thread['lastposteruid'] == 0) - { - $lastposterlink = $lastposter; - } - else - { - $lastposterlink = build_profile_link($lastposter, $thread['lastposteruid']); - } - - $thread['subject'] = $thread['fullsubject'] = $parser->parse_badwords($thread['subject']); - if(my_strlen($thread['subject']) > 25) - { - $thread['subject'] = my_substr($thread['subject'], 0, 25) . "..."; - } - $thread['subject'] = htmlspecialchars_uni($thread['subject']); - $thread['fullsubject'] = htmlspecialchars_uni($thread['fullsubject']); - - $thread['threadlink'] = get_thread_link($thread['tid']); - $thread['lastpostlink'] = get_thread_link($thread['tid'], 0, "lastpost"); - $thread['forumlink'] = get_forum_link($thread['fid']); - $thread['forumname'] = $forum_cache[$thread['fid']]['name']; - eval("\$threadlist .= \"".$templates->get("portal_latestthreads_thread")."\";"); - $altbg = alt_trow(); - } - if($threadlist) - { - // Show the table only if there are threads - eval("\$latestthreads = \"".$templates->get("portal_latestthreads")."\";"); - } -} - -$announcements = ''; -if(!empty($mybb->settings['portal_announcementsfid'])) -{ - // Get latest news announcements - // Build where clause - $annfidswhere = ''; - $announcementcount = 0; - if($mybb->settings['portal_announcementsfid'] != -1) - { - // First validate announcement fids: - $announcementsfids = explode(',', (string)$mybb->settings['portal_announcementsfid']); - if(is_array($announcementsfids)) - { - foreach($announcementsfids as $fid) - { - $fid_array[] = (int)$fid; - } - unset($fid); - - $announcementsfids = implode(',', $fid_array); - - $annfidswhere = " AND t.fid IN ($announcementsfids)"; - } - } - - // And get them! - foreach($forum_cache as $fid => $f) - { - if(empty($fid_array) || (is_array($fid_array) && in_array($fid, $fid_array))) - { - $forum[$fid] = $f; - } - } - - $query = $db->simple_select("threads t", "COUNT(t.tid) AS threads", "t.visible='1'{$annfidswhere}{$tunviewwhere} AND t.closed NOT LIKE 'moved|%'", array('limit' => 1)); - $announcementcount = $db->fetch_field($query, "threads"); - - $numannouncements = (int)$mybb->settings['portal_numannouncements']; - if(!$numannouncements) - { - $numannouncements = 10; // Default back to 10 - } - - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $pages = $announcementcount / $numannouncements; - $pages = ceil($pages); - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $numannouncements; - } - else - { - $start = 0; - $page = 1; - } - - $multipage = multipage($announcementcount, $numannouncements, $page, $file_name); - - $pids = ''; - $tids = ''; - $comma = ''; - $posts = array(); - $attachmentcount = array(); - $query = $db->query(" - SELECT p.pid, p.message, p.tid, p.smilieoff, t.attachmentcount - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE t.visible='1'{$annfidswhere}{$tunviewwhere} AND t.closed NOT LIKE 'moved|%' AND t.firstpost=p.pid - ORDER BY t.dateline DESC - LIMIT {$start}, {$numannouncements}" - ); - while($getid = $db->fetch_array($query)) - { - $attachmentcount[$getid['tid']] = $getid['attachmentcount']; - foreach($attachmentcount as $tid => $attach_count) - { - if($attach_count > 0) - { - $pids .= ",'{$getid['pid']}'"; - } - - $posts[$getid['tid']] = $getid; - } - - $tids .= ",'{$getid['tid']}'"; - } - if(!empty($posts)) - { - if($pids != '' && $mybb->settings['enableattachments'] == 1) - { - $pids = "pid IN(0{$pids})"; - // Now lets fetch all of the attachments for these posts - $query = $db->simple_select("attachments", "*", $pids); - while($attachment = $db->fetch_array($query)) - { - $attachcache[$attachment['pid']][$attachment['aid']] = $attachment; - } - } - - if(is_array($forum)) - { - foreach($forum as $fid => $forumrow) - { - $forumpermissions[$fid] = forum_permissions($fid); - } - } - - $icon_cache = $cache->read("posticons"); - - $query = $db->query(" - SELECT t.*, t.username AS threadusername, u.username, u.avatar, u.avatardimensions - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid = t.uid) - WHERE t.tid IN (0{$tids}){$annfidswhere}{$tunviewwhere} AND t.visible='1' AND t.closed NOT LIKE 'moved|%' - ORDER BY t.dateline DESC - LIMIT 0, {$numannouncements}" - ); - while($announcement = $db->fetch_array($query)) - { - // Make sure we can view this announcement - if(isset($forumpermissions[$announcement['fid']]['canonlyviewownthreads']) && $forumpermissions[$announcement['fid']]['canonlyviewownthreads'] == 1 && $announcement['uid'] != $mybb->user['uid']) - { - continue; - } - - $announcement['message'] = $posts[$announcement['tid']]['message']; - $announcement['pid'] = $posts[$announcement['tid']]['pid']; - $announcement['smilieoff'] = $posts[$announcement['tid']]['smilieoff']; - $announcement['threadlink'] = get_thread_link($announcement['tid']); - $announcement['forumlink'] = get_forum_link($announcement['fid']); - $announcement['forumname'] = $forum_cache[$announcement['fid']]['name']; - - $announcement['username'] = htmlspecialchars_uni($announcement['username']); - $announcement['threadusername'] = htmlspecialchars_uni($announcement['threadusername']); - - if($announcement['uid'] == 0) - { - $profilelink = $announcement['threadusername']; - } - else - { - $profilelink = build_profile_link($announcement['username'], $announcement['uid']); - } - - if(!$announcement['username']) - { - $announcement['username'] = $announcement['threadusername']; - } - $announcement['subject'] = htmlspecialchars_uni($parser->parse_badwords($announcement['subject'])); - if($announcement['icon'] > 0 && $icon_cache[$announcement['icon']]) - { - $icon = $icon_cache[$announcement['icon']]; - $icon['path'] = str_replace("{theme}", $theme['imgdir'], $icon['path']); - $icon['path'] = htmlspecialchars_uni($icon['path']); - $icon['name'] = htmlspecialchars_uni($icon['name']); - eval("\$icon = \"".$templates->get("portal_announcement_icon")."\";"); - } - else - { - $icon = " "; - } - - $useravatar = format_avatar($announcement['avatar'], $announcement['avatardimensions']); - eval("\$avatar = \"".$templates->get("portal_announcement_avatar")."\";"); - - $anndate = my_date('relative', $announcement['dateline']); - - if($announcement['replies']) - { - eval("\$numcomments = \"".$templates->get("portal_announcement_numcomments")."\";"); - } - else - { - eval("\$numcomments = \"".$templates->get("portal_announcement_numcomments_no")."\";"); - $lastcomment = ''; - } - - $senditem = ''; - if($mybb->user['uid'] > 0 && $mybb->usergroup['cansendemail'] == 1) - { - eval("\$senditem = \"".$templates->get("portal_announcement_send_item")."\";"); - } - - $plugins->run_hooks("portal_announcement"); - - $parser_options = array( - "allow_html" => $forum[$announcement['fid']]['allowhtml'], - "allow_mycode" => $forum[$announcement['fid']]['allowmycode'], - "allow_smilies" => $forum[$announcement['fid']]['allowsmilies'], - "allow_imgcode" => $forum[$announcement['fid']]['allowimgcode'], - "allow_videocode" => $forum[$announcement['fid']]['allowvideocode'], - "filter_badwords" => 1 - ); - if($announcement['smilieoff'] == 1) - { - $parser_options['allow_smilies'] = 0; - } - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_imgcode'] = 0; - } - - if($mybb->user['showvideos'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestvideos'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_videocode'] = 0; - } - - $message = $parser->parse_message($announcement['message'], $parser_options); - - $post['attachments'] = ''; - if($mybb->settings['enableattachments'] == 1 && isset($attachcache[$announcement['pid']]) && is_array($attachcache[$announcement['pid']])) - { // This post has 1 or more attachments - $validationcount = 0; - $id = $announcement['pid']; - $post['attachmentlist'] = $post['thumblist'] = $post['imagelist'] = $post['attachedthumbs'] = $post['attachedimages'] = ''; - foreach($attachcache[$id] as $aid => $attachment) - { - if($attachment['visible']) - { // There is an attachment thats visible! - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - $attachment['filesize'] = get_friendly_size($attachment['filesize']); - $ext = get_extension($attachment['filename']); - if($ext == "jpeg" || $ext == "gif" || $ext == "bmp" || $ext == "png" || $ext == "jpg") - { - $isimage = true; - } - else - { - $isimage = false; - } - $attachment['icon'] = get_attachment_icon($ext); - // Support for [attachment=id] code - if(stripos($message, "[attachment=".$attachment['aid']."]") !== false) - { - if($attachment['thumbnail'] != "SMALL" && $attachment['thumbnail'] != '') - { // We have a thumbnail to show (and its not the "SMALL" enough image - eval("\$attbit = \"".$templates->get("postbit_attachments_thumbnails_thumbnail")."\";"); - } - elseif($attachment['thumbnail'] == "SMALL" && $forumpermissions[$announcement['fid']]['candlattachments'] == 1) - { - // Image is small enough to show - no thumbnail - eval("\$attbit = \"".$templates->get("postbit_attachments_images_image")."\";"); - } - else - { - // Show standard link to attachment - eval("\$attbit = \"".$templates->get("postbit_attachments_attachment")."\";"); - } - $message = preg_replace("#\[attachment=".$attachment['aid']."]#si", $attbit, $message); - } - else - { - if($attachment['thumbnail'] != "SMALL" && $attachment['thumbnail'] != '') - { // We have a thumbnail to show - eval("\$post['thumblist'] .= \"".$templates->get("postbit_attachments_thumbnails_thumbnail")."\";"); - if($tcount == 5) - { - $thumblist .= "
    "; - $tcount = 0; - } - ++$tcount; - } - elseif($attachment['thumbnail'] == "SMALL" && $forumpermissions[$announcement['fid']]['candlattachments'] == 1) - { - // Image is small enough to show - no thumbnail - eval("\$post['imagelist'] .= \"".$templates->get("postbit_attachments_images_image")."\";"); - } - else - { - eval("\$post['attachmentlist'] .= \"".$templates->get("postbit_attachments_attachment")."\";"); - } - } - } - else - { - $validationcount++; - } - } - if($post['thumblist']) - { - eval("\$post['attachedthumbs'] = \"".$templates->get("postbit_attachments_thumbnails")."\";"); - } - if($post['imagelist']) - { - eval("\$post['attachedimages'] = \"".$templates->get("postbit_attachments_images")."\";"); - } - if($post['attachmentlist'] || $post['thumblist'] || $post['imagelist']) - { - eval("\$post['attachments'] = \"".$templates->get("postbit_attachments")."\";"); - } - } - - eval("\$announcements .= \"".$templates->get("portal_announcement")."\";"); - unset($post); - } - } -} - -$plugins->run_hooks("portal_end"); - -eval("\$portal = \"".$templates->get("portal")."\";"); -output_page($portal); \ No newline at end of file diff --git a/html/forums/printthread.php b/html/forums/printthread.php deleted file mode 100644 index fb2afb8..0000000 --- a/html/forums/printthread.php +++ /dev/null @@ -1,261 +0,0 @@ -load("printthread"); - -$plugins->run_hooks("printthread_start"); - -$thread = get_thread($mybb->get_input('tid', MyBB::INPUT_INT)); - -if(!$thread) -{ - error($lang->error_invalidthread); -} - -$plugins->run_hooks("printthread_start"); - -$thread['threadprefix'] = $thread['displaystyle'] = ''; -if($thread['prefix']) -{ - $threadprefix = build_prefixes($thread['prefix']); - if(!empty($threadprefix)) - { - $thread['threadprefix'] = $threadprefix['prefix']; - $thread['displaystyle'] = $threadprefix['displaystyle']; - } -} - -$thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); - -$fid = $thread['fid']; -$tid = $thread['tid']; - -// Is the currently logged in user a moderator of this forum? -$ismod = is_moderator($fid); - -// Make sure we are looking at a real thread here. -if(($thread['visible'] != 1 && $ismod == false) || ($thread['visible'] > 1 && $ismod == true)) -{ - error($lang->error_invalidthread); -} - -// Get forum info -$forum = get_forum($fid); -if(!$forum) -{ - error($lang->error_invalidforum); -} - -$breadcrumb = makeprintablenav(); - -$parentsexp = explode(",", $forum['parentlist']); -$numparents = count($parentsexp); -$tdepth = "-"; -for($i = 0; $i < $numparents; ++$i) -{ - $tdepth .= "-"; -} -$forumpermissions = forum_permissions($forum['fid']); - -if($forum['type'] != "f") -{ - error($lang->error_invalidforum); -} -if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0 || (isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0 && $thread['uid'] != $mybb->user['uid'])) -{ - error_no_permission(); -} - -// Check if this forum is password protected and we have a valid password -check_forum_password($forum['fid']); - -$page = $mybb->get_input('page', MyBB::INPUT_INT); - -// Paginate this thread -if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) -{ - $mybb->settings['postsperpage'] = 20; -} -$perpage = $mybb->settings['postsperpage']; -$postcount = (int)$thread['replies']+1; -$pages = ceil($postcount/$perpage); - -if($page > $pages) -{ - $page = 1; -} -if($page > 0) -{ - $start = ($page-1) * $perpage; -} -else -{ - $start = 0; - $page = 1; -} - -if($postcount > $perpage) -{ - $multipage = printthread_multipage($postcount, $perpage, $page, "printthread.php?tid={$tid}"); -} -else -{ - $multipage = ''; -} - -$thread['threadlink'] = get_thread_link($tid); - -$postrows = ''; -if(is_moderator($forum['fid'], "canviewunapprove")) -{ - $visible = "AND (p.visible='0' OR p.visible='1')"; -} -else -{ - $visible = "AND p.visible='1'"; -} -$query = $db->query(" - SELECT u.*, u.username AS userusername, p.* - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.tid='$tid' {$visible} - ORDER BY p.dateline - LIMIT {$start}, {$perpage} -"); -while($postrow = $db->fetch_array($query)) -{ - $parser_options = array( - "allow_html" => $forum['allowhtml'], - "allow_mycode" => $forum['allowmycode'], - "allow_smilies" => $forum['allowsmilies'], - "allow_imgcode" => $forum['allowimgcode'], - "allow_videocode" => $forum['allowvideocode'], - "me_username" => $postrow['username'], - "shorten_urls" => 0, - "filter_badwords" => 1 - ); - if($postrow['smilieoff'] == 1) - { - $parser_options['allow_smilies'] = 0; - } - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_imgcode'] = 0; - } - - if($mybb->user['showvideos'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestvideos'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_videocode'] = 0; - } - - if($postrow['userusername']) - { - $postrow['username'] = $postrow['userusername']; - } - $postrow['username'] = htmlspecialchars_uni($postrow['username']); - $postrow['subject'] = htmlspecialchars_uni($parser->parse_badwords($postrow['subject'])); - $postrow['date'] = my_date($mybb->settings['dateformat'], $postrow['dateline'], null, 0); - $postrow['profilelink'] = build_profile_link($postrow['username'], $postrow['uid']); - - $postrow['message'] = $parser->parse_message($postrow['message'], $parser_options); - $plugins->run_hooks("printthread_post"); - eval("\$postrows .= \"".$templates->get("printthread_post")."\";"); -} - -$plugins->run_hooks("printthread_end"); - -eval("\$printable = \"".$templates->get("printthread")."\";"); -output_page($printable); - -/** - * @param int $pid - * @param string $depth - * - * @return string - */ -function makeprintablenav($pid=0, $depth="--") -{ - global $mybb, $db, $pforumcache, $fid, $forum, $lang, $templates; - if(!is_array($pforumcache)) - { - $parlist = build_parent_list($fid, "fid", "OR", $forum['parentlist']); - $query = $db->simple_select("forums", "name, fid, pid", "$parlist", array('order_by' => 'pid, disporder')); - while($forumnav = $db->fetch_array($query)) - { - $pforumcache[$forumnav['pid']][$forumnav['fid']] = $forumnav; - } - unset($forumnav); - } - $forums = ''; - if(is_array($pforumcache[$pid])) - { - foreach($pforumcache[$pid] as $key => $forumnav) - { - $forumnav['link'] = get_forum_link($forumnav['fid']); - eval("\$forums .= \"".$templates->get("printthread_nav")."\";"); - if(!empty($pforumcache[$forumnav['fid']])) - { - $newdepth = $depth."-"; - $forums .= makeprintablenav($forumnav['fid'], $newdepth); - } - } - } - return $forums; -} - -/** - * Output multipage navigation. - * - * @param int $count The total number of items. - * @param int $perpage The items per page. - * @param int $current_page The current page. - * @param string $url The URL base. - * - * @return string -*/ -function printthread_multipage($count, $perpage, $current_page, $url) -{ - global $lang, $templates; - $multipage = ""; - if($count > $perpage) - { - $pages = $count / $perpage; - $pages = ceil($pages); - - $mppage = null; - for($page = 1; $page <= $pages; ++$page) - { - if($page == $current_page) - { - eval("\$mppage .= \"".$templates->get("printthread_multipage_page_current")."\";"); - } - else - { - eval("\$mppage .= \"".$templates->get("printthread_multipage_page")."\";"); - } - } - - eval("\$multipage = \"".$templates->get("printthread_multipage")."\";"); - } - return $multipage; -} - diff --git a/html/forums/private.php b/html/forums/private.php deleted file mode 100644 index fba58c8..0000000 --- a/html/forums/private.php +++ /dev/null @@ -1,2475 +0,0 @@ -load("private"); - -if($mybb->settings['enablepms'] == 0) -{ - error($lang->pms_disabled); -} - -if($mybb->user['uid'] == '/' || $mybb->user['uid'] == 0 || $mybb->usergroup['canusepms'] == 0) -{ - error_no_permission(); -} - -if(!$mybb->user['pmfolders']) -{ - $mybb->user['pmfolders'] = "1**$%%$2**$%%$3**$%%$4**"; - - $sql_array = array( - "pmfolders" => $mybb->user['pmfolders'] - ); - $db->update_query("users", $sql_array, "uid = ".$mybb->user['uid']); -} - -$mybb->input['fid'] = $mybb->get_input('fid', MyBB::INPUT_INT); - -$folder_id = $folder_name = ''; - -$foldernames = array(); -$foldersexploded = explode("$%%$", $mybb->user['pmfolders']); -foreach($foldersexploded as $key => $folders) -{ - $folderinfo = explode("**", $folders, 2); - if($mybb->input['fid'] == $folderinfo[0]) - { - $sel = ' selected="selected"'; - } - else - { - $sel = ''; - } - $folderinfo[1] = get_pm_folder_name($folderinfo[0], $folderinfo[1]); - $foldernames[$folderinfo[0]] = $folderinfo[1]; - - $folder_id = $folderinfo[0]; - $folder_name = $folderinfo[1]; - - eval("\$folderjump_folder .= \"".$templates->get("private_jump_folders_folder")."\";"); - eval("\$folderoplist_folder .= \"".$templates->get("private_jump_folders_folder")."\";"); - eval("\$foldersearch_folder .= \"".$templates->get("private_jump_folders_folder")."\";"); -} - -eval("\$folderjump = \"".$templates->get("private_jump_folders")."\";"); -eval("\$folderoplist = \"".$templates->get("private_move")."\";"); -eval("\$foldersearch = \"".$templates->get("private_advanced_search_folders")."\";"); - -usercp_menu(); - -$plugins->run_hooks("private_start"); - -// Make navigation -add_breadcrumb($lang->nav_pms, "private.php"); - -$mybb->input['action'] = $mybb->get_input('action'); -switch($mybb->input['action']) -{ - case "send": - add_breadcrumb($lang->nav_send); - break; - case "tracking": - add_breadcrumb($lang->nav_tracking); - break; - case "folders": - add_breadcrumb($lang->nav_folders); - break; - case "empty": - add_breadcrumb($lang->nav_empty); - break; - case "export": - add_breadcrumb($lang->nav_export); - break; - case "advanced_search": - add_breadcrumb($lang->nav_search); - break; - case "results": - add_breadcrumb($lang->nav_results); - break; -} - -if(!empty($mybb->input['preview'])) -{ - $mybb->input['action'] = "send"; -} - -if(($mybb->input['action'] == "do_search" || $mybb->input['action'] == "do_stuff" && ($mybb->get_input('quick_search') || !$mybb->get_input('hop') && !$mybb->get_input('moveto') && !$mybb->get_input('delete'))) && $mybb->request_method == "post") -{ - $plugins->run_hooks("private_do_search_start"); - - // Simulate coming from our advanced search form with some preset options - if($mybb->get_input('quick_search')) - { - $mybb->input['action'] = "do_search"; - $mybb->input['subject'] = 1; - $mybb->input['message'] = 1; - $mybb->input['folder'] = $mybb->input['fid']; - unset($mybb->input['jumpto']); - unset($mybb->input['fromfid']); - } - - // Check if search flood checking is enabled and user is not admin - if($mybb->settings['searchfloodtime'] > 0 && $mybb->usergroup['cancp'] != 1) - { - // Fetch the time this user last searched - $timecut = TIME_NOW-$mybb->settings['searchfloodtime']; - $query = $db->simple_select("searchlog", "*", "uid='{$mybb->user['uid']}' AND dateline > '$timecut'", array('order_by' => "dateline", 'order_dir' => "DESC")); - $last_search = $db->fetch_array($query); - // Users last search was within the flood time, show the error - if($last_search['sid']) - { - $remaining_time = $mybb->settings['searchfloodtime']-(TIME_NOW-$last_search['dateline']); - if($remaining_time == 1) - { - $lang->error_searchflooding = $lang->sprintf($lang->error_searchflooding_1, $mybb->settings['searchfloodtime']); - } - else - { - $lang->error_searchflooding = $lang->sprintf($lang->error_searchflooding, $mybb->settings['searchfloodtime'], $remaining_time); - } - error($lang->error_searchflooding); - } - } - - if($mybb->get_input('subject', MyBB::INPUT_INT) != 1 && $mybb->get_input('message', MyBB::INPUT_INT) != 1) - { - error($lang->error_nosearchresults); - } - - if($mybb->get_input('message', MyBB::INPUT_INT) == 1) - { - $resulttype = "pmmessages"; - } - else - { - $resulttype = "pmsubjects"; - } - - $search_data = array( - "keywords" => $mybb->get_input('keywords'), - "subject" => $mybb->get_input('subject', MyBB::INPUT_INT), - "message" => $mybb->get_input('message', MyBB::INPUT_INT), - "sender" => $mybb->get_input('sender'), - "status" => $mybb->get_input('status', MyBB::INPUT_ARRAY), - "folder" => $mybb->get_input('folder', MyBB::INPUT_ARRAY) - ); - - if($db->can_search == true) - { - require_once MYBB_ROOT."inc/functions_search.php"; - - $search_results = privatemessage_perform_search_mysql($search_data); - } - else - { - error($lang->error_no_search_support); - } - $sid = md5(uniqid(microtime(), true)); - $searcharray = array( - "sid" => $db->escape_string($sid), - "uid" => $mybb->user['uid'], - "dateline" => TIME_NOW, - "ipaddress" => $db->escape_binary($session->packedip), - "threads" => '', - "posts" => '', - "resulttype" => $resulttype, - "querycache" => $search_results['querycache'], - "keywords" => $db->escape_string($mybb->get_input('keywords')), - ); - $plugins->run_hooks("private_do_search_process"); - - $db->insert_query("searchlog", $searcharray); - - // Sender sort won't work yet - $sortby = array('subject', 'sender', 'dateline'); - - if(in_array($mybb->get_input('sort'), $sortby)) - { - $sortby = $mybb->get_input('sort'); - } - else - { - $sortby = "dateline"; - } - - if(my_strtolower($mybb->get_input('sortordr')) == "asc") - { - $sortorder = "asc"; - } - else - { - $sortorder = "desc"; - } - - $plugins->run_hooks("private_do_search_end"); - redirect("private.php?action=results&sid=".$sid."&sortby=".$sortby."&order=".$sortorder, $lang->redirect_searchresults); -} - -if($mybb->input['action'] == "results") -{ - $sid = $mybb->get_input('sid'); - $query = $db->simple_select("searchlog", "*", "sid='".$db->escape_string($sid)."' AND uid='{$mybb->user['uid']}'"); - $search = $db->fetch_array($query); - - if(!$search) - { - error($lang->error_invalidsearch); - } - - $plugins->run_hooks("private_results_start"); - - // Decide on our sorting fields and sorting order. - $order = my_strtolower($mybb->get_input('order')); - $sortby = my_strtolower($mybb->get_input('sortby')); - - $sortby_accepted = array('subject', 'username', 'dateline'); - - if(in_array($sortby, $sortby_accepted)) - { - $query_sortby = $sortby; - - if($query_sortby == "username") - { - $query_sortby = "fromusername"; - } - } - else - { - $sortby = $query_sortby = "dateline"; - } - - if($order != "asc") - { - $order = "desc"; - } - - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - // Work out pagination, which page we're at, as well as the limits. - $perpage = $mybb->settings['threadsperpage']; - $page = $mybb->get_input('page', MyBB::INPUT_INT); - if($page > 0) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - $end = $start + $perpage; - $lower = $start+1; - $upper = $end; - - // Work out if we have terms to highlight - $highlight = ""; - if($search['keywords']) - { - $highlight = "&highlight=".urlencode($search['keywords']); - } - - // Do Multi Pages - $query = $db->simple_select("privatemessages", "COUNT(*) AS total", "pmid IN(".$db->escape_string($search['querycache']).")"); - $pmscount = $db->fetch_array($query); - - if($upper > $pmscount) - { - $upper = $pmscount; - } - $multipage = multipage($pmscount['total'], $perpage, $page, "private.php?action=results&sid=".htmlspecialchars_uni($mybb->get_input('sid'))."&sortby={$sortby}&order={$order}"); - $messagelist = ''; - - $icon_cache = $cache->read("posticons"); - - // Cache users in multiple recipients for sent & drafts folder - // Get all recipients into an array - $cached_users = $get_users = array(); - $users_query = $db->simple_select("privatemessages", "recipients", "pmid IN(".$db->escape_string($search['querycache']).")", array('limit_start' => $start, 'limit' => $perpage, 'order_by' => $query_sortby, 'order_dir' => $order)); - while($row = $db->fetch_array($users_query)) - { - $recipients = my_unserialize($row['recipients']); - if(is_array($recipients['to']) && count($recipients['to'])) - { - $get_users = array_merge($get_users, $recipients['to']); - } - - if(isset($recipients['bcc']) && is_array($recipients['bcc']) && count($recipients['bcc'])) - { - $get_users = array_merge($get_users, $recipients['bcc']); - } - } - - $get_users = implode(',', array_unique($get_users)); - - // Grab info - if($get_users) - { - $users_query = $db->simple_select("users", "uid, username, usergroup, displaygroup", "uid IN ({$get_users})"); - while($user = $db->fetch_array($users_query)) - { - $cached_users[$user['uid']] = $user; - } - } - - $query = $db->query(" - SELECT pm.*, fu.username AS fromusername, tu.username as tousername - FROM ".TABLE_PREFIX."privatemessages pm - LEFT JOIN ".TABLE_PREFIX."users fu ON (fu.uid=pm.fromid) - LEFT JOIN ".TABLE_PREFIX."users tu ON (tu.uid=pm.toid) - WHERE pm.pmid IN(".$db->escape_string($search['querycache']).") AND pm.uid='{$mybb->user['uid']}' - ORDER BY pm.{$query_sortby} {$order} - LIMIT {$start}, {$perpage} - "); - while($message = $db->fetch_array($query)) - { - $msgalt = $msgstatus = ''; - - // Determine Folder Icon - if($message['status'] == 0) - { - $msgstatus = 'new_pm'; - $msgalt = $lang->new_pm; - } - else if($message['status'] == 1) - { - $msgstatus = 'old_pm'; - $msgalt = $lang->old_pm; - } - else if($message['status'] == 3) - { - $msgstatus = 're_pm'; - $msgalt = $lang->reply_pm; - } - else if($message['status'] == 4) - { - $msgstatus = 'fw_pm'; - $msgalt = $lang->fwd_pm; - } - - $folder = $message['folder']; - - $tofromuid = 0; - if($folder == 2 || $folder == 3) - { - // Sent Items or Drafts Folder Check - $recipients = my_unserialize($message['recipients']); - $to_users = $bcc_users = ''; - if(count($recipients['to']) > 1 || (count($recipients['to']) == 1 && isset($recipients['bcc']) && count($recipients['bcc']) > 0)) - { - foreach($recipients['to'] as $uid) - { - $profilelink = get_profile_link($uid); - $user = $cached_users[$uid]; - $user['username'] = htmlspecialchars_uni($user['username']); - $username = format_name($user['username'], $user['usergroup'], $user['displaygroup']); - eval("\$to_users .= \"".$templates->get("private_multiple_recipients_user")."\";"); - } - if(isset($recipients['bcc']) && is_array($recipients['bcc']) && count($recipients['bcc'])) - { - eval("\$bcc_users = \"".$templates->get("private_multiple_recipients_bcc")."\";"); - foreach($recipients['bcc'] as $uid) - { - $profilelink = get_profile_link($uid); - $user = $cached_users[$uid]; - $user['username'] = htmlspecialchars_uni($user['username']); - $username = format_name($user['username'], $user['usergroup'], $user['displaygroup']); - eval("\$bcc_users .= \"".$templates->get("private_multiple_recipients_user")."\";"); - } - } - - eval("\$tofromusername = \"".$templates->get("private_multiple_recipients")."\";"); - } - else if($message['toid']) - { - $tofromusername = htmlspecialchars_uni($message['tousername']); - $tofromuid = $message['toid']; - } - else - { - $tofromusername = $lang->not_sent; - } - } - else - { - $tofromusername = htmlspecialchars_uni($message['fromusername']); - $tofromuid = $message['fromid']; - if($tofromuid == 0) - { - $tofromusername = $lang->mybb_engine; - } - } - - $tofromusername = build_profile_link($tofromusername, $tofromuid); - - $denyreceipt = ''; - - if($message['icon'] > 0 && $icon_cache[$message['icon']]) - { - $icon = $icon_cache[$message['icon']]; - $icon['path'] = str_replace("{theme}", $theme['imgdir'], $icon['path']); - $icon['path'] = htmlspecialchars_uni($icon['path']); - $icon['name'] = htmlspecialchars_uni($icon['name']); - eval("\$icon = \"".$templates->get("private_messagebit_icon")."\";"); - } - else - { - $icon = ' '; - } - - if(!trim($message['subject'])) - { - $message['subject'] = $lang->pm_no_subject; - } - - $message['subject'] = $parser->parse_badwords($message['subject']); - - if(my_strlen($message['subject']) > 50) - { - $message['subject'] = htmlspecialchars_uni(my_substr($message['subject'], 0, 50)."..."); - } - else - { - $message['subject'] = htmlspecialchars_uni($message['subject']); - } - - if($message['folder'] != "3") - { - $senddate = my_date('relative', $message['dateline']); - } - else - { - $senddate = $lang->not_sent; - } - - $foldername = $foldernames[$message['folder']]; - - // What we do here is parse the post using our post parser, then strip the tags from it - $parser_options = array( - 'allow_html' => 0, - 'allow_mycode' => 1, - 'allow_smilies' => 0, - 'allow_imgcode' => 0, - 'filter_badwords' => 1 - ); - $message['message'] = strip_tags($parser->parse_message($message['message'], $parser_options)); - if(my_strlen($message['message']) > 200) - { - $message['message'] = my_substr($message['message'], 0, 200)."..."; - } - - eval("\$messagelist .= \"".$templates->get("private_search_messagebit")."\";"); - } - - if($db->num_rows($query) == 0) - { - eval("\$messagelist = \"".$templates->get("private_search_results_nomessages")."\";"); - } - - $plugins->run_hooks("private_results_end"); - - eval("\$results = \"".$templates->get("private_search_results")."\";"); - output_page($results); -} - -if($mybb->input['action'] == "advanced_search") -{ - $plugins->run_hooks("private_advanced_search"); - - eval("\$advanced_search = \"".$templates->get("private_advanced_search")."\";"); - - output_page($advanced_search); -} - -// Dismissing a new/unread PM notice -if($mybb->input['action'] == "dismiss_notice") -{ - if($mybb->user['pmnotice'] != 2) - { - exit; - } - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $updated_user = array( - "pmnotice" => 1 - ); - $db->update_query("users", $updated_user, "uid='{$mybb->user['uid']}'"); - - if(!empty($mybb->input['ajax'])) - { - echo 1; - exit; - } - else - { - header("Location: index.php"); - exit; - } -} - -$send_errors = ''; - -if($mybb->input['action'] == "do_send" && $mybb->request_method == "post") -{ - if($mybb->usergroup['cansendpms'] == 0) - { - error_no_permission(); - } - - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("private_send_do_send"); - - // Attempt to see if this PM is a duplicate or not - $to = array_map("trim", explode(",", $mybb->get_input('to'))); - $to_escaped = implode("','", array_map(array($db, 'escape_string'), array_map('my_strtolower', $to))); - $time_cutoff = TIME_NOW - (5 * 60 * 60); - $query = $db->query(" - SELECT pm.pmid - FROM ".TABLE_PREFIX."privatemessages pm - LEFT JOIN ".TABLE_PREFIX."users u ON(u.uid=pm.toid) - WHERE LOWER(u.username) IN ('{$to_escaped}') AND pm.dateline > {$time_cutoff} AND pm.fromid='{$mybb->user['uid']}' AND pm.subject='".$db->escape_string($mybb->get_input('subject'))."' AND pm.message='".$db->escape_string($mybb->get_input('message'))."' AND pm.folder!='3' - LIMIT 0, 1 - "); - $duplicate_check = $db->fetch_field($query, "pmid"); - if($duplicate_check) - { - error($lang->error_pm_already_submitted); - } - - require_once MYBB_ROOT."inc/datahandlers/pm.php"; - $pmhandler = new PMDataHandler(); - - $pm = array( - "subject" => $mybb->get_input('subject'), - "message" => $mybb->get_input('message'), - "icon" => $mybb->get_input('icon', MyBB::INPUT_INT), - "fromid" => $mybb->user['uid'], - "do" => $mybb->get_input('do'), - "pmid" => $mybb->get_input('pmid', MyBB::INPUT_INT), - "ipaddress" => $session->packedip - ); - - // Split up any recipients we have - $pm['to'] = $to; - if(!empty($mybb->input['bcc'])) - { - $pm['bcc'] = explode(",", $mybb->get_input('bcc')); - $pm['bcc'] = array_map("trim", $pm['bcc']); - } - - $mybb->input['options'] = $mybb->get_input('options', MyBB::INPUT_ARRAY); - - if(!$mybb->usergroup['cantrackpms']) - { - $mybb->input['options']['readreceipt'] = false; - } - - $pm['options'] = array(); - if(isset($mybb->input['options']['signature']) && $mybb->input['options']['signature'] == 1) - { - $pm['options']['signature'] = 1; - } - else - { - $pm['options']['signature'] = 0; - } - if(isset($mybb->input['options']['disablesmilies'])) - { - $pm['options']['disablesmilies'] = $mybb->input['options']['disablesmilies']; - } - if(isset($mybb->input['options']['savecopy']) && $mybb->input['options']['savecopy'] == 1) - { - $pm['options']['savecopy'] = 1; - } - else - { - $pm['options']['savecopy'] = 0; - } - if(isset($mybb->input['options']['readreceipt'])) - { - $pm['options']['readreceipt'] = $mybb->input['options']['readreceipt']; - } - - if(!empty($mybb->input['saveasdraft'])) - { - $pm['saveasdraft'] = 1; - } - $pmhandler->set_data($pm); - - // Now let the pm handler do all the hard work. - if(!$pmhandler->validate_pm()) - { - $pm_errors = $pmhandler->get_friendly_errors(); - $send_errors = inline_error($pm_errors); - $mybb->input['action'] = "send"; - } - else - { - $pminfo = $pmhandler->insert_pm(); - $plugins->run_hooks("private_do_send_end"); - - if(isset($pminfo['draftsaved'])) - { - redirect("private.php", $lang->redirect_pmsaved); - } - else - { - redirect("private.php", $lang->redirect_pmsent); - } - } -} - -if($mybb->input['action'] == "send") -{ - if($mybb->usergroup['cansendpms'] == 0) - { - error_no_permission(); - } - - $plugins->run_hooks("private_send_start"); - - $smilieinserter = $codebuttons = ''; - - if($mybb->settings['bbcodeinserter'] != 0 && $mybb->settings['pmsallowmycode'] != 0 && $mybb->user['showcodebuttons'] != 0) - { - $codebuttons = build_mycode_inserter("message", $mybb->settings['pmsallowsmilies']); - if($mybb->settings['pmsallowsmilies'] != 0) - { - $smilieinserter = build_clickable_smilies(); - } - } - - $lang->post_icon = $lang->message_icon; - - $posticons = get_post_icons(); - $message = htmlspecialchars_uni($parser->parse_badwords($mybb->get_input('message'))); - $subject = htmlspecialchars_uni($parser->parse_badwords($mybb->get_input('subject'))); - - $optionschecked = array('signature' => '', 'disablesmilies' => '', 'savecopy' => '', 'readreceipt' => ''); - $to = $bcc = ''; - - if(!empty($mybb->input['preview']) || $send_errors) - { - $options = $mybb->get_input('options', MyBB::INPUT_ARRAY); - if(isset($options['signature']) && $options['signature'] == 1) - { - $optionschecked['signature'] = 'checked="checked"'; - } - if(isset($options['disablesmilies']) && $options['disablesmilies'] == 1) - { - $optionschecked['disablesmilies'] = 'checked="checked"'; - } - if(isset($options['savecopy']) && $options['savecopy'] != 0) - { - $optionschecked['savecopy'] = 'checked="checked"'; - } - if(isset($options['readreceipt']) && $options['readreceipt'] != 0) - { - $optionschecked['readreceipt'] = 'checked="checked"'; - } - $to = htmlspecialchars_uni($mybb->get_input('to')); - $bcc = htmlspecialchars_uni($mybb->get_input('bcc')); - } - - $preview = ''; - // Preview - if(!empty($mybb->input['preview'])) - { - $options = $mybb->get_input('options', MyBB::INPUT_ARRAY); - $query = $db->query(" - SELECT u.username AS userusername, u.*, f.* - FROM ".TABLE_PREFIX."users u - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - WHERE u.uid='".$mybb->user['uid']."' - "); - - $post = $db->fetch_array($query); - - $post['userusername'] = $mybb->user['username']; - $post['postusername'] = $mybb->user['username']; - $post['message'] = $mybb->get_input('message'); - $post['subject'] = htmlspecialchars_uni($mybb->get_input('subject')); - $post['icon'] = $mybb->get_input('icon', MyBB::INPUT_INT); - if(!isset($options['disablesmilies'])) - { - $options['disablesmilies'] = 0; - } - $post['smilieoff'] = $options['disablesmilies']; - $post['dateline'] = TIME_NOW; - - if(!isset($options['signature'])) - { - $post['includesig'] = 0; - } - else - { - $post['includesig'] = 1; - } - - // Merge usergroup data from the cache - $data_key = array( - 'title' => 'grouptitle', - 'usertitle' => 'groupusertitle', - 'stars' => 'groupstars', - 'starimage' => 'groupstarimage', - 'image' => 'groupimage', - 'namestyle' => 'namestyle', - 'usereputationsystem' => 'usereputationsystem' - ); - - foreach($data_key as $field => $key) - { - $post[$key] = $groupscache[$post['usergroup']][$field]; - } - - $postbit = build_postbit($post, 2); - eval("\$preview = \"".$templates->get("previewpost")."\";"); - } - else if(!$send_errors) - { - // New PM, so load default settings - if($mybb->user['signature'] != '') - { - $optionschecked['signature'] = 'checked="checked"'; - } - if($mybb->usergroup['cantrackpms'] == 1) - { - $optionschecked['readreceipt'] = 'checked="checked"'; - } - $optionschecked['savecopy'] = 'checked="checked"'; - } - - // Draft, reply, forward - if($mybb->get_input('pmid') && empty($mybb->input['preview']) && !$send_errors) - { - $query = $db->query(" - SELECT pm.*, u.username AS quotename - FROM ".TABLE_PREFIX."privatemessages pm - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=pm.fromid) - WHERE pm.pmid='".$mybb->get_input('pmid', MyBB::INPUT_INT)."' AND pm.uid='{$mybb->user['uid']}' - "); - - $pm = $db->fetch_array($query); - $message = htmlspecialchars_uni($parser->parse_badwords($pm['message'])); - $subject = htmlspecialchars_uni($parser->parse_badwords($pm['subject'])); - - if($pm['folder'] == "3") - { - // message saved in drafts - $mybb->input['uid'] = $pm['toid']; - - if($pm['includesig'] == 1) - { - $optionschecked['signature'] = 'checked="checked"'; - } - if($pm['smilieoff'] == 1) - { - $optionschecked['disablesmilies'] = 'checked="checked"'; - } - if($pm['receipt']) - { - $optionschecked['readreceipt'] = 'checked="checked"'; - } - - // Get list of recipients - $recipients = my_unserialize($pm['recipients']); - $comma = $recipientids = ''; - if(isset($recipients['to']) && is_array($recipients['to'])) - { - foreach($recipients['to'] as $recipient) - { - $recipient_list['to'][] = $recipient; - $recipientids .= $comma.$recipient; - $comma = ','; - } - } - - if(isset($recipients['bcc']) && is_array($recipients['bcc'])) - { - foreach($recipients['bcc'] as $recipient) - { - $recipient_list['bcc'][] = $recipient; - $recipientids .= $comma.$recipient; - $comma = ','; - } - } - - if(!empty($recipientids)) - { - $query = $db->simple_select("users", "uid, username", "uid IN ({$recipientids})"); - while($user = $db->fetch_array($query)) - { - if(isset($recipients['bcc']) && is_array($recipients['bcc']) && in_array($user['uid'], $recipient_list['bcc'])) - { - $bcc .= htmlspecialchars_uni($user['username']).', '; - } - else - { - $to .= htmlspecialchars_uni($user['username']).', '; - } - } - } - } - else - { - // forward/reply - $subject = preg_replace("#(FW|RE):( *)#is", '', $subject); - $message = "[quote='{$pm['quotename']}']\n$message\n[/quote]"; - $message = preg_replace('#^/me (.*)$#im', "* ".$pm['quotename']." \\1", $message); - - require_once MYBB_ROOT."inc/functions_posting.php"; - - if($mybb->settings['maxpmquotedepth'] != '0') - { - $message = remove_message_quotes($message, $mybb->settings['maxpmquotedepth']); - } - - if($mybb->input['do'] == 'forward') - { - $subject = "Fw: $subject"; - } - elseif($mybb->input['do'] == 'reply') - { - $subject = "Re: $subject"; - $uid = $pm['fromid']; - if($mybb->user['uid'] == $uid) - { - $to = $mybb->user['username']; - } - else - { - $query = $db->simple_select('users', 'username', "uid='{$uid}'"); - $to = $db->fetch_field($query, 'username'); - } - $to = htmlspecialchars_uni($to); - } - else if($mybb->input['do'] == 'replyall') - { - $subject = "Re: $subject"; - - // Get list of recipients - $recipients = my_unserialize($pm['recipients']); - $recipientids = $pm['fromid']; - if(isset($recipients['to']) && is_array($recipients['to'])) - { - foreach($recipients['to'] as $recipient) - { - if($recipient == $mybb->user['uid']) - { - continue; - } - $recipientids .= ','.$recipient; - } - } - $comma = ''; - $query = $db->simple_select('users', 'uid, username', "uid IN ({$recipientids})"); - while($user = $db->fetch_array($query)) - { - $to .= $comma.htmlspecialchars_uni($user['username']); - $comma = $lang->comma; - } - } - } - } - - // New PM with recipient preset - if($mybb->get_input('uid', MyBB::INPUT_INT) && empty($mybb->input['preview'])) - { - $query = $db->simple_select('users', 'username', "uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"); - $to = htmlspecialchars_uni($db->fetch_field($query, 'username')).', '; - } - - $max_recipients = ''; - if($mybb->usergroup['maxpmrecipients'] > 0) - { - $max_recipients = $lang->sprintf($lang->max_recipients, $mybb->usergroup['maxpmrecipients']); - } - - if($send_errors) - { - $to = htmlspecialchars_uni($mybb->get_input('to')); - $bcc = htmlspecialchars_uni($mybb->get_input('bcc')); - } - - // Load the auto complete javascript if it is enabled. - eval("\$autocompletejs = \"".$templates->get("private_send_autocomplete")."\";"); - - $pmid = $mybb->get_input('pmid', MyBB::INPUT_INT); - $do = $mybb->get_input('do'); - if($do != "forward" && $do != "reply" && $do != "replyall") - { - $do = ''; - } - - $buddy_select_to = $buddy_select_bcc = ''; - // See if it's actually worth showing the buddylist icon. - if($mybb->user['buddylist'] != '' && $mybb->settings['use_xmlhttprequest'] == 1) - { - $buddy_select = 'to'; - eval("\$buddy_select_to = \"".$templates->get("private_send_buddyselect")."\";"); - $buddy_select = 'bcc'; - eval("\$buddy_select_bcc = \"".$templates->get("private_send_buddyselect")."\";"); - } - - // Hide tracking option if no permission - $private_send_tracking = ''; - if($mybb->usergroup['cantrackpms']) - { - eval("\$private_send_tracking = \"".$templates->get("private_send_tracking")."\";"); - } - - $plugins->run_hooks("private_send_end"); - - eval("\$send = \"".$templates->get("private_send")."\";"); - output_page($send); -} - -if($mybb->input['action'] == "read") -{ - $plugins->run_hooks("private_read"); - - $pmid = $mybb->get_input('pmid', MyBB::INPUT_INT); - - $query = $db->query(" - SELECT pm.*, u.*, f.* - FROM ".TABLE_PREFIX."privatemessages pm - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=pm.fromid) - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - WHERE pm.pmid='{$pmid}' AND pm.uid='".$mybb->user['uid']."' - "); - $pm = $db->fetch_array($query); - - if(!$pm) - { - error($lang->error_invalidpm); - } - - if($pm['folder'] == 3) - { - header("Location: private.php?action=send&pmid={$pm['pmid']}"); - exit; - } - - // If we've gotten a PM, attach the group info - $data_key = array( - 'title' => 'grouptitle', - 'usertitle' => 'groupusertitle', - 'stars' => 'groupstars', - 'starimage' => 'groupstarimage', - 'image' => 'groupimage', - 'namestyle' => 'namestyle' - ); - - foreach($data_key as $field => $key) - { - $pm[$key] = $groupscache[$pm['usergroup']][$field]; - } - - if($pm['receipt'] == 1) - { - if($mybb->usergroup['candenypmreceipts'] == 1 && $mybb->get_input('denyreceipt', MyBB::INPUT_INT) == 1) - { - $receiptadd = 0; - } - else - { - $receiptadd = 2; - } - } - - $action_time = ''; - if($pm['status'] == 0) - { - $time = TIME_NOW; - $updatearray = array( - 'status' => 1, - 'readtime' => $time - ); - - if(isset($receiptadd)) - { - $updatearray['receipt'] = $receiptadd; - } - - $db->update_query('privatemessages', $updatearray, "pmid='{$pmid}'"); - - // Update the unread count - it has now changed. - update_pm_count($mybb->user['uid'], 6); - - // Update PM notice value if this is our last unread PM - if($mybb->user['unreadpms']-1 <= 0 && $mybb->user['pmnotice'] == 2) - { - $updated_user = array( - "pmnotice" => 1 - ); - $db->update_query("users", $updated_user, "uid='{$mybb->user['uid']}'"); - } - } - // Replied PM? - else if($pm['status'] == 3 && $pm['statustime']) - { - $reply_string = $lang->you_replied_on; - $reply_date = my_date('relative', $pm['statustime']); - - if((TIME_NOW - $pm['statustime']) < 3600) - { - // Relative string for the first hour - $reply_string = $lang->you_replied; - } - - $actioned_on = $lang->sprintf($reply_string, $reply_date); - eval("\$action_time = \"".$templates->get("private_read_action")."\";"); - } - else if($pm['status'] == 4 && $pm['statustime']) - { - $forward_string = $lang->you_forwarded_on; - $forward_date = my_date('relative', $pm['statustime']); - - if((TIME_NOW - $pm['statustime']) < 3600) - { - $forward_string = $lang->you_forwarded; - } - - $actioned_on = $lang->sprintf($forward_string, $forward_date); - eval("\$action_time = \"".$templates->get("private_read_action")."\";"); - } - - $pm['userusername'] = $pm['username']; - $pm['subject'] = htmlspecialchars_uni($parser->parse_badwords($pm['subject'])); - - if($pm['fromid'] == 0) - { - $pm['username'] = $lang->mybb_engine; - } - - if(!$pm['username']) - { - $pm['username'] = $lang->na; - } - - // Fetch the recipients for this message - $pm['recipients'] = my_unserialize($pm['recipients']); - - if(is_array($pm['recipients']['to'])) - { - $uid_sql = implode(',', $pm['recipients']['to']); - } - else - { - $uid_sql = $pm['toid']; - $pm['recipients']['to'] = array($pm['toid']); - } - - $show_bcc = 0; - - // If we have any BCC recipients and this user is an Administrator, add them on to the query - if(isset($pm['recipients']['bcc']) && count($pm['recipients']['bcc']) > 0 && $mybb->usergroup['cancp'] == 1) - { - $show_bcc = 1; - $uid_sql .= ','.implode(',', $pm['recipients']['bcc']); - } - - // Fetch recipient names from the database - $bcc_recipients = $to_recipients = $bcc_form_val = array(); - $query = $db->simple_select('users', 'uid, username', "uid IN ({$uid_sql})"); - while($recipient = $db->fetch_array($query)) - { - // User is a BCC recipient - $recipient['username'] = htmlspecialchars_uni($recipient['username']); - if($show_bcc && in_array($recipient['uid'], $pm['recipients']['bcc'])) - { - $bcc_recipients[] = build_profile_link($recipient['username'], $recipient['uid']); - $bcc_form_val[] = $recipient['username']; - } - // User is a normal recipient - else if(in_array($recipient['uid'], $pm['recipients']['to'])) - { - $to_recipients[] = build_profile_link($recipient['username'], $recipient['uid']); - } - } - - $bcc = ''; - if(count($bcc_recipients) > 0) - { - $bcc_recipients = implode(', ', $bcc_recipients); - $bcc_form_val = implode(',', $bcc_form_val); - eval("\$bcc = \"".$templates->get("private_read_bcc")."\";"); - } - else - { - $bcc_form_val = ''; - } - - $replyall = false; - if(count($to_recipients) > 1) - { - $replyall = true; - } - - if(count($to_recipients) > 0) - { - $to_recipients = implode($lang->comma, $to_recipients); - } - else - { - $to_recipients = $lang->nobody; - } - - eval("\$pm['subject_extra'] = \"".$templates->get("private_read_to")."\";"); - - add_breadcrumb($pm['subject']); - $message = build_postbit($pm, 2); - - // Decide whether or not to show quick reply. - $quickreply = ''; - if($mybb->settings['pmquickreply'] != 0 && $mybb->user['showquickreply'] != 0 && $mybb->usergroup['cansendpms'] != 0 && $pm['fromid'] != 0 && $pm['folder'] != 3) - { - $trow = alt_trow(); - - $optionschecked = array('savecopy' => 'checked="checked"'); - if(!empty($mybb->user['signature'])) - { - $optionschecked['signature'] = 'checked="checked"'; - } - if($mybb->usergroup['cantrackpms'] == 1) - { - $optionschecked['readreceipt'] = 'checked="checked"'; - } - - require_once MYBB_ROOT.'inc/functions_posting.php'; - - $quoted_message = array( - 'message' => htmlspecialchars_uni($parser->parse_badwords($pm['message'])), - 'username' => $pm['username'], - 'quote_is_pm' => true - ); - $quoted_message = parse_quoted_message($quoted_message); - - if($mybb->settings['maxpmquotedepth'] != '0') - { - $quoted_message = remove_message_quotes($quoted_message, $mybb->settings['maxpmquotedepth']); - } - - $subject = preg_replace("#(FW|RE):( *)#is", '', $pm['subject']); - - if($mybb->user['uid'] == $pm['fromid']) - { - $to = htmlspecialchars_uni($mybb->user['username']); - } - else - { - $query = $db->simple_select('users', 'username', "uid='{$pm['fromid']}'"); - $to = htmlspecialchars_uni($db->fetch_field($query, 'username')); - } - - $private_send_tracking = ''; - if($mybb->usergroup['cantrackpms']) - { - $lang->options_read_receipt = $lang->quickreply_read_receipt; - - eval("\$private_send_tracking = \"".$templates->get("private_send_tracking")."\";"); - } - - eval("\$quickreply = \"".$templates->get("private_quickreply")."\";"); - } - - $plugins->run_hooks("private_read_end"); - - eval("\$read = \"".$templates->get("private_read")."\";"); - output_page($read); -} - -if($mybb->input['action'] == "tracking") -{ - if(!$mybb->usergroup['cantrackpms']) - { - error_no_permission(); - } - - $plugins->run_hooks("private_tracking_start"); - $readmessages = ''; - $unreadmessages = ''; - - if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) - { - $mybb->settings['postsperpage'] = 20; - } - - // Figure out if we need to display multiple pages. - $perpage = $mybb->settings['postsperpage']; - - $query = $db->simple_select("privatemessages", "COUNT(pmid) as readpms", "receipt='2' AND folder!='3' AND status!='0' AND fromid='".$mybb->user['uid']."'"); - $postcount = $db->fetch_field($query, "readpms"); - - $page = $mybb->get_input('read_page', MyBB::INPUT_INT); - $pages = $postcount / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('read_page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $read_multipage = multipage($postcount, $perpage, $page, "private.php?action=tracking&read_page={page}"); - - $query = $db->query(" - SELECT pm.pmid, pm.subject, pm.toid, pm.readtime, u.username as tousername - FROM ".TABLE_PREFIX."privatemessages pm - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=pm.toid) - WHERE pm.receipt='2' AND pm.folder!='3' AND pm.status!='0' AND pm.fromid='".$mybb->user['uid']."' - ORDER BY pm.readtime DESC - LIMIT {$start}, {$perpage} - "); - while($readmessage = $db->fetch_array($query)) - { - $readmessage['subject'] = htmlspecialchars_uni($parser->parse_badwords($readmessage['subject'])); - $readmessage['tousername'] = htmlspecialchars_uni($readmessage['tousername']); - $readmessage['profilelink'] = build_profile_link($readmessage['tousername'], $readmessage['toid']); - $readdate = my_date('relative', $readmessage['readtime']); - eval("\$readmessages .= \"".$templates->get("private_tracking_readmessage")."\";"); - } - - $stoptrackingread = ''; - if(!empty($readmessages)) - { - eval("\$stoptrackingread = \"".$templates->get("private_tracking_readmessage_stop")."\";"); - } - - if(!$readmessages) - { - eval("\$readmessages = \"".$templates->get("private_tracking_nomessage")."\";"); - } - - $query = $db->simple_select("privatemessages", "COUNT(pmid) as unreadpms", "receipt='1' AND folder!='3' AND status='0' AND fromid='".$mybb->user['uid']."'"); - $postcount = $db->fetch_field($query, "unreadpms"); - - $page = $mybb->get_input('unread_page', MyBB::INPUT_INT); - $pages = $postcount / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('unread_page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $unread_multipage = multipage($postcount, $perpage, $page, "private.php?action=tracking&unread_page={page}"); - - $query = $db->query(" - SELECT pm.pmid, pm.subject, pm.toid, pm.dateline, u.username as tousername - FROM ".TABLE_PREFIX."privatemessages pm - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=pm.toid) - WHERE pm.receipt='1' AND pm.folder!='3' AND pm.status='0' AND pm.fromid='".$mybb->user['uid']."' - ORDER BY pm.dateline DESC - LIMIT {$start}, {$perpage} - "); - while($unreadmessage = $db->fetch_array($query)) - { - $unreadmessage['subject'] = htmlspecialchars_uni($parser->parse_badwords($unreadmessage['subject'])); - $unreadmessage['tousername'] = htmlspecialchars_uni($unreadmessage['tousername']); - $unreadmessage['profilelink'] = build_profile_link($unreadmessage['tousername'], $unreadmessage['toid']); - $senddate = my_date('relative', $unreadmessage['dateline']); - eval("\$unreadmessages .= \"".$templates->get("private_tracking_unreadmessage")."\";"); - } - - $stoptrackingunread = ''; - if(!empty($unreadmessages)) - { - eval("\$stoptrackingunread = \"".$templates->get("private_tracking_unreadmessage_stop")."\";"); - } - - if(!$unreadmessages) - { - $lang->no_readmessages = $lang->no_unreadmessages; - eval("\$unreadmessages = \"".$templates->get("private_tracking_nomessage")."\";"); - } - - $plugins->run_hooks("private_tracking_end"); - - eval("\$tracking = \"".$templates->get("private_tracking")."\";"); - output_page($tracking); -} - -if($mybb->input['action'] == "do_tracking" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("private_do_tracking_start"); - - if(!empty($mybb->input['stoptracking'])) - { - $mybb->input['readcheck'] = $mybb->get_input('readcheck', MyBB::INPUT_ARRAY); - if(!empty($mybb->input['readcheck'])) - { - foreach($mybb->input['readcheck'] as $key => $val) - { - $sql_array = array( - "receipt" => 0 - ); - $db->update_query("privatemessages", $sql_array, "pmid=".(int)$key." AND fromid=".$mybb->user['uid']); - } - } - $plugins->run_hooks("private_do_tracking_end"); - redirect("private.php?action=tracking", $lang->redirect_pmstrackingstopped); - } - elseif(!empty($mybb->input['stoptrackingunread'])) - { - $mybb->input['unreadcheck'] = $mybb->get_input('unreadcheck', MyBB::INPUT_ARRAY); - if(!empty($mybb->input['unreadcheck'])) - { - foreach($mybb->input['unreadcheck'] as $key => $val) - { - $sql_array = array( - "receipt" => 0 - ); - $db->update_query("privatemessages", $sql_array, "pmid=".(int)$key." AND fromid=".$mybb->user['uid']); - } - } - $plugins->run_hooks("private_do_tracking_end"); - redirect("private.php?action=tracking", $lang->redirect_pmstrackingstopped); - } - elseif(!empty($mybb->input['cancel'])) - { - $mybb->input['unreadcheck'] = $mybb->get_input('unreadcheck', MyBB::INPUT_ARRAY); - if(!empty($mybb->input['unreadcheck'])) - { - foreach($mybb->input['unreadcheck'] as $pmid => $val) - { - $pmids[$pmid] = (int)$pmid; - } - - $pmids = implode(",", $pmids); - $query = $db->simple_select("privatemessages", "uid", "pmid IN ($pmids) AND fromid='".$mybb->user['uid']."'"); - while($pm = $db->fetch_array($query)) - { - $pmuids[$pm['uid']] = $pm['uid']; - } - - $db->delete_query("privatemessages", "pmid IN ($pmids) AND receipt='1' AND status='0' AND fromid='".$mybb->user['uid']."'"); - foreach($pmuids as $uid) - { - // Message is canceled, update PM count for this user - update_pm_count($uid); - } - } - $plugins->run_hooks("private_do_tracking_end"); - redirect("private.php?action=tracking", $lang->redirect_pmstrackingcanceled); - } -} - -if($mybb->input['action'] == "stopalltracking") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("private_stopalltracking_start"); - - $sql_array = array( - "receipt" => 0 - ); - $db->update_query("privatemessages", $sql_array, "receipt='2' AND folder!='3' AND status!='0' AND fromid=".$mybb->user['uid']); - - $plugins->run_hooks("private_stopalltracking_end"); - redirect("private.php?action=tracking", $lang->redirect_allpmstrackingstopped); -} - -if($mybb->input['action'] == "folders") -{ - $plugins->run_hooks("private_folders_start"); - - $folderlist = ''; - $foldersexploded = explode("$%%$", $mybb->user['pmfolders']); - foreach($foldersexploded as $key => $folders) - { - $folderinfo = explode("**", $folders, 2); - $foldername = $folderinfo[1]; - $fid = $folderinfo[0]; - $foldername = get_pm_folder_name($fid, $foldername); - - if($folderinfo[0] == "1" || $folderinfo[0] == "2" || $folderinfo[0] == "3" || $folderinfo[0] == "4") - { - $foldername2 = get_pm_folder_name($fid); - eval("\$folderlist .= \"".$templates->get("private_folders_folder_unremovable")."\";"); - unset($name); - } - else - { - eval("\$folderlist .= \"".$templates->get("private_folders_folder")."\";"); - } - } - - $newfolders = ''; - for($i = 1; $i <= 5; ++$i) - { - $fid = "new$i"; - $foldername = ''; - eval("\$newfolders .= \"".$templates->get("private_folders_folder")."\";"); - } - - $plugins->run_hooks("private_folders_end"); - - eval("\$folders = \"".$templates->get("private_folders")."\";"); - output_page($folders); -} - -if($mybb->input['action'] == "do_folders" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("private_do_folders_start"); - - $highestid = 2; - $folders = ''; - $donefolders = array(); - $mybb->input['folder'] = $mybb->get_input('folder', MyBB::INPUT_ARRAY); - foreach($mybb->input['folder'] as $key => $val) - { - if(empty($donefolders[$val]) )// Probably was a check for duplicate folder names, but doesn't seem to be used now - { - if(my_substr($key, 0, 3) == "new") // Create a new folder - { - ++$highestid; - $fid = (int)$highestid; - } - else // Editing an existing folder - { - if($key > $highestid) - { - $highestid = $key; - } - - $fid = (int)$key; - // Use default language strings if empty or value is language string - switch($fid) - { - case 1: - if($val == $lang->folder_inbox || trim($val) == '') - { - $val = ''; - } - break; - case 2: - if($val == $lang->folder_sent_items || trim($val) == '') - { - $val = ''; - } - break; - case 3: - if($val == $lang->folder_drafts || trim($val) == '') - { - $val = ''; - } - break; - case 4: - if($val == $lang->folder_trash || trim($val) == '') - { - $val = ''; - } - break; - } - } - - if($val != '' && trim($val) == '' && !($key >= 1 && $key <= 4)) - { - // If the name only contains whitespace and it's not a default folder, print an error - error($lang->error_emptypmfoldername); - } - - if($val != '' || ($key >= 1 && $key <= 4)) - { - // If there is a name or if this is a default folder, save it - $foldername = $db->escape_string(htmlspecialchars_uni($val)); - - if(my_strpos($foldername, "$%%$") === false) - { - if($folders != '') - { - $folders .= "$%%$"; - } - $folders .= "$fid**$foldername"; - } - else - { - error($lang->error_invalidpmfoldername); - } - } - else - { - // Delete PMs from the folder - $db->delete_query("privatemessages", "folder='$fid' AND uid='".$mybb->user['uid']."'"); - } - } - } - - $sql_array = array( - "pmfolders" => $folders - ); - $db->update_query("users", $sql_array, "uid='".$mybb->user['uid']."'"); - - // Update PM count - update_pm_count(); - - $plugins->run_hooks("private_do_folders_end"); - - redirect("private.php", $lang->redirect_pmfoldersupdated); -} - -if($mybb->input['action'] == "empty") -{ - if($mybb->user['totalpms'] == 0) - { - error($lang->error_nopms); - } - - $plugins->run_hooks("private_empty_start"); - - $foldersexploded = explode("$%%$", $mybb->user['pmfolders']); - $folderlist = ''; - foreach($foldersexploded as $key => $folders) - { - $folderinfo = explode("**", $folders, 2); - $fid = $folderinfo[0]; - $foldername = get_pm_folder_name($fid, $folderinfo[1]); - $query = $db->simple_select("privatemessages", "COUNT(*) AS pmsinfolder", " folder='$fid' AND uid='".$mybb->user['uid']."'"); - $thing = $db->fetch_array($query); - $foldercount = my_number_format($thing['pmsinfolder']); - eval("\$folderlist .= \"".$templates->get("private_empty_folder")."\";"); - } - - $plugins->run_hooks("private_empty_end"); - - eval("\$folders = \"".$templates->get("private_empty")."\";"); - output_page($folders); -} - -if($mybb->input['action'] == "do_empty" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("private_do_empty_start"); - - $emptyq = ''; - $mybb->input['empty'] = $mybb->get_input('empty', MyBB::INPUT_ARRAY); - $keepunreadq = ''; - if($mybb->get_input('keepunread', MyBB::INPUT_INT) == 1) - { - $keepunreadq = " AND status!='0'"; - } - if(!empty($mybb->input['empty'])) - { - foreach($mybb->input['empty'] as $key => $val) - { - if($val == 1) - { - $key = (int)$key; - if($emptyq) - { - $emptyq .= " OR "; - } - $emptyq .= "folder='$key'"; - } - } - - if($emptyq != '') - { - $db->delete_query("privatemessages", "($emptyq) AND uid='".$mybb->user['uid']."'{$keepunreadq}"); - } - } - - // Update PM count - update_pm_count(); - - $plugins->run_hooks("private_do_empty_end"); - redirect("private.php", $lang->redirect_pmfoldersemptied); -} - -if($mybb->input['action'] == "do_stuff" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("private_do_stuff"); - - if(!empty($mybb->input['hop'])) - { - header("Location: private.php?fid=".$mybb->get_input('jumpto')); - } - elseif(!empty($mybb->input['moveto'])) - { - $mybb->input['check'] = $mybb->get_input('check', MyBB::INPUT_ARRAY); - if(!empty($mybb->input['check'])) - { - foreach($mybb->input['check'] as $key => $val) - { - $sql_array = array( - "folder" => $mybb->input['fid'] - ); - $db->update_query("privatemessages", $sql_array, "pmid='".(int)$key."' AND uid='".$mybb->user['uid']."'"); - } - } - // Update PM count - update_pm_count(); - - if(!empty($mybb->input['fromfid'])) - { - redirect("private.php?fid=".$mybb->get_input('fromfid', MyBB::INPUT_INT), $lang->redirect_pmsmoved); - } - else - { - redirect("private.php", $lang->redirect_pmsmoved); - } - } - elseif(!empty($mybb->input['delete'])) - { - $mybb->input['check'] = $mybb->get_input('check', MyBB::INPUT_ARRAY); - if(!empty($mybb->input['check'])) - { - $pmssql = ''; - foreach($mybb->input['check'] as $key => $val) - { - if($pmssql) - { - $pmssql .= ","; - } - $pmssql .= "'".(int)$key."'"; - } - - $deletepms = array(); - $query = $db->simple_select("privatemessages", "pmid, folder", "pmid IN ($pmssql) AND uid='".$mybb->user['uid']."' AND folder='4'", array('order_by' => 'pmid')); - while($delpm = $db->fetch_array($query)) - { - $deletepms[$delpm['pmid']] = 1; - } - - foreach($mybb->input['check'] as $key => $val) - { - $key = (int)$key; - if(!empty($deletepms[$key])) - { - $db->delete_query("privatemessages", "pmid='$key' AND uid='".$mybb->user['uid']."'"); - } - else - { - $sql_array = array( - "folder" => 4, - "deletetime" => TIME_NOW - ); - $db->update_query("privatemessages", $sql_array, "pmid='".$key."' AND uid='".$mybb->user['uid']."'"); - } - } - } - // Update PM count - update_pm_count(); - - if(!empty($mybb->input['fromfid'])) - { - redirect("private.php?fid=".$mybb->get_input('fromfid', MyBB::INPUT_INT), $lang->redirect_pmsdeleted); - } - else - { - redirect("private.php", $lang->redirect_pmsdeleted); - } - } -} - -if($mybb->input['action'] == "delete") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("private_delete_start"); - - $query = $db->simple_select("privatemessages", "*", "pmid='".$mybb->get_input('pmid', MyBB::INPUT_INT)."' AND uid='".$mybb->user['uid']."' AND folder='4'", array('order_by' => 'pmid')); - if($db->num_rows($query) == 1) - { - $db->delete_query("privatemessages", "pmid='".$mybb->get_input('pmid', MyBB::INPUT_INT)."'"); - } - else - { - $sql_array = array( - "folder" => 4, - "deletetime" => TIME_NOW - ); - $db->update_query("privatemessages", $sql_array, "pmid='".$mybb->get_input('pmid', MyBB::INPUT_INT)."' AND uid='".$mybb->user['uid']."'"); - } - - // Update PM count - update_pm_count(); - - $plugins->run_hooks("private_delete_end"); - redirect("private.php", $lang->redirect_pmsdeleted); -} - -if($mybb->input['action'] == "export") -{ - if($mybb->user['totalpms'] == 0) - { - error($lang->error_nopms); - } - - $plugins->run_hooks("private_export_start"); - - $foldersexploded = explode("$%%$", $mybb->user['pmfolders']); - $folder_name = $folder_id = ''; - foreach($foldersexploded as $key => $folders) - { - $folderinfo = explode("**", $folders, 2); - $folderinfo[1] = get_pm_folder_name($folderinfo[0], $folderinfo[1]); - - $folder_id = $folderinfo[0]; - $folder_name = $folderinfo[1]; - - eval("\$folderlist_folder .= \"".$templates->get("private_archive_folders_folder")."\";"); - } - - eval("\$folderlist = \"".$templates->get("private_archive_folders")."\";"); - - $plugins->run_hooks("private_export_end"); - - eval("\$archive = \"".$templates->get("private_archive")."\";"); - - output_page($archive); -} - -if($mybb->input['action'] == "do_export" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("private_do_export_start"); - - $lang->private_messages_for = $lang->sprintf($lang->private_messages_for, htmlspecialchars_uni($mybb->user['username'])); - $exdate = my_date($mybb->settings['dateformat'], TIME_NOW, 0, 0); - $extime = my_date($mybb->settings['timeformat'], TIME_NOW, 0, 0); - $lang->exported_date = $lang->sprintf($lang->exported_date, $exdate, $extime); - $foldersexploded = explode("$%%$", $mybb->user['pmfolders']); - foreach($foldersexploded as $key => $folders) - { - $folderinfo = explode("**", $folders, 2); - $folderinfo[1] = get_pm_folder_name($folderinfo[0], $folderinfo[1]); - $foldersexploded[$key] = implode("**", $folderinfo); - } - - if($mybb->get_input('pmid', MyBB::INPUT_INT)) - { - $wsql = "pmid='".$mybb->get_input('pmid', MyBB::INPUT_INT)."' AND uid='".$mybb->user['uid']."'"; - } - else - { - if($mybb->get_input('daycut', MyBB::INPUT_INT) && ($mybb->get_input('dayway') != "disregard")) - { - $datecut = TIME_NOW-($mybb->get_input('daycut', MyBB::INPUT_INT) * 86400); - $wsql = "pm.dateline"; - if($mybb->get_input('dayway') == "older") - { - $wsql .= "<="; - } - else - { - $wsql .= ">="; - } - $wsql .= "'$datecut'"; - } - else - { - $wsql = "1=1"; - } - - $mybb->input['exportfolders'] = $mybb->get_input('exportfolders', MyBB::INPUT_ARRAY); - if(!empty($mybb->input['exportfolders'])) - { - $folderlst = ''; - foreach($mybb->input['exportfolders'] as $key => $val) - { - $val = $db->escape_string($val); - if($val == "all") - { - $folderlst = ''; - break; - } - else - { - if(!$folderlst) - { - $folderlst = " AND pm.folder IN ('$val'"; - } - else - { - $folderlst .= ",'$val'"; - } - } - } - if($folderlst) - { - $folderlst .= ")"; - } - $wsql .= "$folderlst"; - } - else - { - error($lang->error_pmnoarchivefolders); - } - - if($mybb->get_input('exportunread', MyBB::INPUT_INT) != 1) - { - $wsql .= " AND pm.status!='0'"; - } - } - $query = $db->query(" - SELECT pm.*, fu.username AS fromusername, tu.username AS tousername - FROM ".TABLE_PREFIX."privatemessages pm - LEFT JOIN ".TABLE_PREFIX."users fu ON (fu.uid=pm.fromid) - LEFT JOIN ".TABLE_PREFIX."users tu ON (tu.uid=pm.toid) - WHERE $wsql AND pm.uid='".$mybb->user['uid']."' - ORDER BY pm.folder ASC, pm.dateline DESC - "); - $numpms = $db->num_rows($query); - if(!$numpms) - { - error($lang->error_nopmsarchive); - } - - $mybb->input['exporttype'] = $mybb->get_input('exporttype'); - - $pmsdownload = $ids = ''; - while($message = $db->fetch_array($query)) - { - if($message['folder'] == 2 || $message['folder'] == 3) - { // Sent Items or Drafts Folder Check - if($message['toid']) - { - $tofromuid = $message['toid']; - if($mybb->input['exporttype'] == "txt") - { - $tofromusername = $message['tousername']; - } - else - { - $tofromusername = build_profile_link($message['tousername'], $tofromuid); - } - } - else - { - $tofromusername = $lang->not_sent; - } - $tofrom = $lang->to; - } - else - { - $tofromuid = $message['fromid']; - if($mybb->input['exporttype'] == "txt") - { - $tofromusername = $message['fromusername']; - } - else - { - $tofromusername = build_profile_link($message['fromusername'], $tofromuid); - } - - if($tofromuid == 0) - { - $tofromusername = $lang->mybb_engine; - } - $tofrom = $lang->from; - } - - if($tofromuid == 0) - { - $message['fromusername'] = $lang->mybb_engine; - } - - if(!$message['toid'] && $message['folder'] == 3) - { - $message['tousername'] = $lang->not_sent; - } - - $message['subject'] = $parser->parse_badwords($message['subject']); - if($message['folder'] != "3") - { - $senddate = my_date($mybb->settings['dateformat'], $message['dateline'], "", false); - $sendtime = my_date($mybb->settings['timeformat'], $message['dateline'], "", false); - $senddate .= " $lang->at $sendtime"; - } - else - { - $senddate = $lang->not_sent; - } - - if($mybb->input['exporttype'] == "html") - { - $parser_options = array( - "allow_html" => $mybb->settings['pmsallowhtml'], - "allow_mycode" => $mybb->settings['pmsallowmycode'], - "allow_smilies" => 0, - "allow_imgcode" => $mybb->settings['pmsallowimgcode'], - "allow_videocode" => $mybb->settings['pmsallowvideocode'], - "me_username" => $mybb->user['username'], - "filter_badwords" => 1 - ); - - $message['message'] = $parser->parse_message($message['message'], $parser_options); - $message['subject'] = htmlspecialchars_uni($message['subject']); - } - - if($mybb->input['exporttype'] == "txt" || $mybb->input['exporttype'] == "csv") - { - $message['message'] = str_replace("\r\n", "\n", $message['message']); - $message['message'] = str_replace("\n", "\r\n", $message['message']); - } - - if($mybb->input['exporttype'] == "csv") - { - $message['message'] = my_escape_csv($message['message']); - $message['subject'] = my_escape_csv($message['subject']); - $message['tousername'] = my_escape_csv($message['tousername']); - $message['fromusername'] = my_escape_csv($message['fromusername']); - } - - if(empty($donefolder[$message['folder']])) - { - reset($foldersexploded); - foreach($foldersexploded as $key => $val) - { - $folderinfo = explode("**", $val, 2); - if($folderinfo[0] == $message['folder']) - { - $foldername = $folderinfo[1]; - if($mybb->input['exporttype'] != "csv") - { - if($mybb->input['exporttype'] != "html") - { - $mybb->input['exporttype'] == "txt"; - } - eval("\$pmsdownload .= \"".$templates->get("private_archive_".$mybb->input['exporttype']."_folderhead", 1, 0)."\";"); - } - else - { - $foldername = my_escape_csv($folderinfo[1]); - } - $donefolder[$message['folder']] = 1; - } - } - } - - eval("\$pmsdownload .= \"".$templates->get("private_archive_".$mybb->input['exporttype']."_message", 1, 0)."\";"); - $ids .= ",'{$message['pmid']}'"; - } - - if($mybb->input['exporttype'] == "html") - { - // Gather global stylesheet for HTML - $query = $db->simple_select("themestylesheets", "stylesheet", "sid = '1'", array('limit' => 1)); - $css = $db->fetch_field($query, "stylesheet"); - } - - $plugins->run_hooks("private_do_export_end"); - - eval("\$archived = \"".$templates->get("private_archive_".$mybb->input['exporttype'], 1, 0)."\";"); - if($mybb->get_input('deletepms', MyBB::INPUT_INT) == 1) - { // delete the archived pms - $db->delete_query("privatemessages", "pmid IN ('0'$ids)"); - // Update PM count - update_pm_count(); - } - - if($mybb->input['exporttype'] == "html") - { - $filename = "pm-archive.html"; - $contenttype = "text/html"; - } - elseif($mybb->input['exporttype'] == "csv") - { - $filename = "pm-archive.csv"; - $contenttype = "application/octet-stream"; - } - else - { - $filename = "pm-archive.txt"; - $contenttype = "text/plain"; - } - - $archived = str_replace("\\\'","'",$archived); - header("Content-disposition: filename=$filename"); - header("Content-type: ".$contenttype); - - if($mybb->input['exporttype'] == "html") - { - output_page($archived); - } - else - { - echo "\xEF\xBB\xBF"; // UTF-8 BOM - echo $archived; - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("private_inbox"); - - if(!$mybb->input['fid'] || !array_key_exists($mybb->input['fid'], $foldernames)) - { - $mybb->input['fid'] = 1; - } - - $folder = $mybb->input['fid']; - $foldername = $foldernames[$folder]; - - if($folder == 2 || $folder == 3) - { // Sent Items Folder - $sender = $lang->sentto; - } - else - { - $sender = $lang->sender; - } - - $mybb->input['order'] = htmlspecialchars_uni($mybb->get_input('order')); - $ordersel = array('asc' => '', 'desc'); - switch(my_strtolower($mybb->input['order'])) - { - case "asc": - $sortordernow = "asc"; - $ordersel['asc'] = "selected=\"selected\""; - $oppsort = $lang->desc; - $oppsortnext = "desc"; - break; - default: - $sortordernow = "desc"; - $ordersel['desc'] = "selected=\"selected\""; - $oppsort = $lang->asc; - $oppsortnext = "asc"; - break; - } - - // Sort by which field? - $sortby = htmlspecialchars_uni($mybb->get_input('sortby')); - switch($mybb->get_input('sortby')) - { - case "subject": - $sortfield = "subject"; - break; - case "username": - $sortfield = "username"; - break; - default: - $sortby = "dateline"; - $sortfield = "dateline"; - $mybb->input['sortby'] = "dateline"; - break; - } - $orderarrow = $sortsel = array('subject' => '', 'username' => '', 'dateline' => ''); - $sortsel[$sortby] = "selected=\"selected\""; - - eval("\$orderarrow['$sortby'] = \"".$templates->get("private_orderarrow")."\";"); - - // Do Multi Pages - $query = $db->simple_select("privatemessages", "COUNT(*) AS total", "uid='".$mybb->user['uid']."' AND folder='$folder'"); - $pmscount = $db->fetch_array($query); - - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - $perpage = $mybb->settings['threadsperpage']; - $page = $mybb->get_input('page', MyBB::INPUT_INT); - - if($page > 0) - { - $start = ($page-1) *$perpage; - } - else - { - $start = 0; - $page = 1; - } - - $end = $start + $perpage; - $lower = $start+1; - $upper = $end; - - if($upper > $pmscount) - { - $upper = $pmscount; - } - - if($mybb->input['order'] || ($sortby && $sortby != "dateline")) - { - $page_url = "private.php?fid={$folder}&sortby={$sortby}&order={$sortordernow}"; - } - else - { - $page_url = "private.php?fid={$folder}"; - } - - $multipage = multipage($pmscount['total'], $perpage, $page, $page_url); - $messagelist = ''; - - $icon_cache = $cache->read("posticons"); - - // Cache users in multiple recipients for sent & drafts folder - if($folder == 2 || $folder == 3) - { - if($sortfield == "username") - { - $u = "u."; - } - else - { - $u = "pm."; - } - - // Get all recipients into an array - $cached_users = $get_users = array(); - $users_query = $db->query(" - SELECT pm.recipients - FROM ".TABLE_PREFIX."privatemessages pm - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=pm.toid) - WHERE pm.folder='{$folder}' AND pm.uid='{$mybb->user['uid']}' - ORDER BY {$u}{$sortfield} {$sortordernow} - LIMIT {$start}, {$perpage} - "); - while($row = $db->fetch_array($users_query)) - { - $recipients = my_unserialize($row['recipients']); - if(is_array($recipients['to']) && count($recipients['to'])) - { - $get_users = array_merge($get_users, $recipients['to']); - } - - if(isset($recipients['bcc']) && is_array($recipients['bcc']) && count($recipients['bcc'])) - { - $get_users = array_merge($get_users, $recipients['bcc']); - } - } - - $get_users = implode(',', array_unique($get_users)); - - // Grab info - if($get_users) - { - $users_query = $db->simple_select("users", "uid, username, usergroup, displaygroup", "uid IN ({$get_users})"); - while($user = $db->fetch_array($users_query)) - { - $cached_users[$user['uid']] = $user; - } - } - } - - if($folder == 2 || $folder == 3) - { - if($sortfield == "username") - { - $pm = "tu."; - } - else - { - $pm = "pm."; - } - } - else - { - if($sortfield == "username") - { - $pm = "fu."; - } - else - { - $pm = "pm."; - } - } - - $query = $db->query(" - SELECT pm.*, fu.username AS fromusername, tu.username as tousername - FROM ".TABLE_PREFIX."privatemessages pm - LEFT JOIN ".TABLE_PREFIX."users fu ON (fu.uid=pm.fromid) - LEFT JOIN ".TABLE_PREFIX."users tu ON (tu.uid=pm.toid) - WHERE pm.folder='$folder' AND pm.uid='".$mybb->user['uid']."' - ORDER BY {$pm}{$sortfield} {$sortordernow} - LIMIT $start, $perpage - "); - - if($db->num_rows($query) > 0) - { - while($message = $db->fetch_array($query)) - { - $msgalt = $msgstatus = ''; - - // Determine Folder Icon - if($message['status'] == 0) - { - $msgstatus = 'new_pm'; - $msgalt = $lang->new_pm; - } - else if($message['status'] == 1) - { - $msgstatus = 'old_pm'; - $msgalt = $lang->old_pm; - } - else if($message['status'] == 3) - { - $msgstatus = 're_pm'; - $msgalt = $lang->reply_pm; - } - else if($message['status'] == 4) - { - $msgstatus = 'fw_pm'; - $msgalt = $lang->fwd_pm; - } - - $tofromuid = 0; - if($folder == 2 || $folder == 3) - { // Sent Items or Drafts Folder Check - $recipients = my_unserialize($message['recipients']); - $to_users = $bcc_users = ''; - if(count($recipients['to']) > 1 || (count($recipients['to']) == 1 && isset($recipients['bcc']) && count($recipients['bcc']) > 0)) - { - foreach($recipients['to'] as $uid) - { - $profilelink = get_profile_link($uid); - $user = $cached_users[$uid]; - $user['username'] = htmlspecialchars_uni($user['username']); - $username = format_name($user['username'], $user['usergroup'], $user['displaygroup']); - if(!$user['username']) - { - $username = $lang->na; - } - eval("\$to_users .= \"".$templates->get("private_multiple_recipients_user")."\";"); - } - if(isset($recipients['bcc']) && is_array($recipients['bcc']) && count($recipients['bcc'])) - { - eval("\$bcc_users = \"".$templates->get("private_multiple_recipients_bcc")."\";"); - foreach($recipients['bcc'] as $uid) - { - $profilelink = get_profile_link($uid); - $user = $cached_users[$uid]; - $user['username'] = htmlspecialchars_uni($user['username']); - $username = format_name($user['username'], $user['usergroup'], $user['displaygroup']); - if(!$user['username']) - { - $username = $lang->na; - } - eval("\$bcc_users .= \"".$templates->get("private_multiple_recipients_user")."\";"); - } - } - - eval("\$tofromusername = \"".$templates->get("private_multiple_recipients")."\";"); - } - else if($message['toid']) - { - $tofromusername = htmlspecialchars_uni($message['tousername']); - $tofromuid = $message['toid']; - } - else - { - $tofromusername = $lang->not_sent; - } - } - else - { - $tofromusername = htmlspecialchars_uni($message['fromusername']); - $tofromuid = $message['fromid']; - if($tofromuid == 0) - { - $tofromusername = $lang->mybb_engine; - } - - if(!$tofromusername) - { - $tofromuid = 0; - $tofromusername = $lang->na; - } - } - - $tofromusername = build_profile_link($tofromusername, $tofromuid); - - if($mybb->usergroup['candenypmreceipts'] == 1 && $message['receipt'] == '1' && $message['folder'] != '3' && $message['folder'] != 2) - { - eval("\$denyreceipt = \"".$templates->get("private_messagebit_denyreceipt")."\";"); - } - else - { - $denyreceipt = ''; - } - - if($message['icon'] > 0 && $icon_cache[$message['icon']]) - { - $icon = $icon_cache[$message['icon']]; - $icon['path'] = str_replace("{theme}", $theme['imgdir'], $icon['path']); - $icon['path'] = htmlspecialchars_uni($icon['path']); - $icon['name'] = htmlspecialchars_uni($icon['name']); - eval("\$icon = \"".$templates->get("private_messagebit_icon")."\";"); - } - else - { - $icon = ' '; - } - - if(!trim($message['subject'])) - { - $message['subject'] = $lang->pm_no_subject; - } - - $message['subject'] = htmlspecialchars_uni($parser->parse_badwords($message['subject'])); - if($message['folder'] != "3") - { - $senddate = my_date('relative', $message['dateline']); - } - else - { - $senddate = $lang->not_sent; - } - - $plugins->run_hooks("private_message"); - - eval("\$messagelist .= \"".$templates->get("private_messagebit")."\";"); - } - } - else - { - eval("\$messagelist .= \"".$templates->get("private_nomessages")."\";"); - } - - $pmspacebar = ''; - if($mybb->usergroup['pmquota'] != '0' && $mybb->usergroup['cancp'] != 1) - { - $query = $db->simple_select("privatemessages", "COUNT(*) AS total", "uid='".$mybb->user['uid']."'"); - $pmscount = $db->fetch_array($query); - if($pmscount['total'] == 0) - { - $spaceused = 0; - } - else - { - $spaceused = $pmscount['total'] / $mybb->usergroup['pmquota'] * 100; - } - $spaceused2 = 100 - $spaceused; - $belowhalf = $overhalf = ''; - if($spaceused <= "50") - { - $spaceused_severity = "low"; - $belowhalf = round($spaceused, 0)."%"; - if((int)$belowhalf > 100) - { - $belowhalf = "100%"; - } - } - else - { - if($spaceused <= "75") - { - $spaceused_severity = "medium"; - } - - else - { - $spaceused_severity = "high"; - } - - $overhalf = round($spaceused, 0)."%"; - if((int)$overhalf > 100) - { - $overhalf = "100%"; - } - } - - if($spaceused > 100) - { - $spaceused = 100; - $spaceused2 = 0; - } - - eval("\$pmspacebar = \"".$templates->get("private_pmspace")."\";"); - } - - $composelink = ''; - if($mybb->usergroup['cansendpms'] == 1) - { - eval("\$composelink = \"".$templates->get("private_composelink")."\";"); - } - - $emptyexportlink = ''; - if($mybb->user['totalpms'] > 0) - { - eval("\$emptyexportlink = \"".$templates->get("private_emptyexportlink")."\";"); - } - - $limitwarning = ''; - if($mybb->usergroup['pmquota'] != "0" && $pmscount['total'] >= $mybb->usergroup['pmquota'] && $mybb->usergroup['cancp'] != 1) - { - eval("\$limitwarning = \"".$templates->get("private_limitwarning")."\";"); - } - - $plugins->run_hooks("private_end"); - - eval("\$folder = \"".$templates->get("private")."\";"); - output_page($folder); -} diff --git a/html/forums/ratethread.php b/html/forums/ratethread.php deleted file mode 100644 index 23c54ea..0000000 --- a/html/forums/ratethread.php +++ /dev/null @@ -1,156 +0,0 @@ -get_input('my_post_key')); - -$lang->load("ratethread"); - -$tid = $mybb->get_input('tid'); -$thread = get_thread($tid); -if(!$thread) -{ - error($lang->error_invalidthread); -} - -// Is the currently logged in user a moderator of this forum? -$ismod = is_moderator($thread['fid']); - -// Make sure we are looking at a real thread here. -if(($thread['visible'] != 1 && $ismod == false) || ($thread['visible'] > 1 && $ismod == true)) -{ - error($lang->error_invalidthread); -} - -if($thread['uid'] == $mybb->user['uid']) -{ - error($lang->error_cannotrateownthread); -} - -$forumpermissions = forum_permissions($thread['fid']); -if($forumpermissions['canview'] == 0 || $forumpermissions['canratethreads'] == 0 || $mybb->usergroup['canratethreads'] == 0 || $mybb->settings['allowthreadratings'] == 0 || (isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0)) -{ - error_no_permission(); -} - -// Get forum info -$fid = $thread['fid']; -$forum = get_forum($fid); -if(!$forum) -{ - error($lang->error_invalidforum); -} - -// Get forum info -$forum = get_forum($fid); -if(!$forum) -{ - error($lang->error_invalidforum); -} -else -{ - // Is our forum closed? - if($forum['open'] == 0) - { - // Doesn't look like it is - error($lang->error_closedinvalidforum); - } -} - -// Check if this forum is password protected and we have a valid password -check_forum_password($forum['fid']); - -if($forum['allowtratings'] == 0) -{ - error_no_permission(); -} -$mybb->input['rating'] = $mybb->get_input('rating', MyBB::INPUT_INT); -if($mybb->input['rating'] < 1 || $mybb->input['rating'] > 5) -{ - error($lang->error_invalidrating); -} -$plugins->run_hooks("ratethread_start"); - -if($mybb->user['uid'] != 0) -{ - $whereclause = "uid='{$mybb->user['uid']}'"; -} -else -{ - $whereclause = "ipaddress=".$db->escape_binary($session->packedip); -} -$query = $db->simple_select("threadratings", "*", "{$whereclause} AND tid='{$tid}'"); -$ratecheck = $db->fetch_array($query); - -if($ratecheck['rid'] || isset($mybb->cookies['mybbratethread'][$tid])) -{ - error($lang->error_alreadyratedthread); -} -else -{ - $plugins->run_hooks("ratethread_process"); - - $db->write_query(" - UPDATE ".TABLE_PREFIX."threads - SET numratings=numratings+1, totalratings=totalratings+'{$mybb->input['rating']}' - WHERE tid='{$tid}' - "); - if($mybb->user['uid'] != 0) - { - $insertarray = array( - 'tid' => $tid, - 'uid' => $mybb->user['uid'], - 'rating' => $mybb->input['rating'], - 'ipaddress' => $db->escape_binary($session->packedip) - ); - $db->insert_query("threadratings", $insertarray); - } - else - { - $insertarray = array( - 'tid' => $tid, - 'rating' => $mybb->input['rating'], - 'ipaddress' => $db->escape_binary($session->packedip) - ); - $db->insert_query("threadratings", $insertarray); - $time = TIME_NOW; - my_setcookie("mybbratethread[{$tid}]", $mybb->input['rating']); - } -} -$plugins->run_hooks("ratethread_end"); - -if(!empty($mybb->input['ajax'])) -{ - $json = array("success" => $lang->rating_added); - $query = $db->simple_select("threads", "totalratings, numratings", "tid='$tid'", array('limit' => 1)); - $fetch = $db->fetch_array($query); - $width = 0; - if($fetch['numratings'] >= 0) - { - $averagerating = (float)round($fetch['totalratings']/$fetch['numratings'], 2); - $width = (int)round($averagerating)*20; - $fetch['numratings'] = (int)$fetch['numratings']; - $ratingvotesav = $lang->sprintf($lang->rating_votes_average, $fetch['numratings'], $averagerating); - $json = $json + array("average" => $ratingvotesav); - } - $json = $json + array("width" => $width); - - @header("Content-type: application/json; charset={$lang->settings['charset']}"); - echo json_encode($json); - exit; -} - -redirect(get_thread_link($thread['tid']), $lang->redirect_threadrated); diff --git a/html/forums/report.php b/html/forums/report.php deleted file mode 100644 index b551fc5..0000000 --- a/html/forums/report.php +++ /dev/null @@ -1,286 +0,0 @@ -load("report"); - -if(!$mybb->user['uid']) -{ - error_no_permission(); -} - -$plugins->run_hooks("report_start"); - -$report = array(); -$verified = false; -$report_type = 'post'; -$error = $report_type_db = ''; - -if(!empty($mybb->input['type'])) -{ - $report_type = htmlspecialchars_uni($mybb->get_input('type')); -} - -$report_title = $lang->report_content; -$report_string = "report_reason_{$report_type}"; - -if(isset($lang->$report_string)) -{ - $report_title = $lang->$report_string; -} - -$id = 0; -if($report_type == 'post') -{ - if($mybb->usergroup['canview'] == 0) - { - error_no_permission(); - } - - // Do we have a valid post? - $post = get_post($mybb->get_input('pid', MyBB::INPUT_INT)); - - if(!$post) - { - $error = $lang->error_invalid_report; - } - else - { - $id = $post['pid']; - $id2 = $post['tid']; - $report_type_db = "(type = 'post' OR type = '')"; - - // Check for a valid forum - $forum = get_forum($post['fid']); - - if(!isset($forum['fid'])) - { - $error = $lang->error_invalid_report; - } - else - { - $verified = true; - } - - // Password protected forums ......... yhummmmy! - $id3 = $forum['fid']; - check_forum_password($forum['parentlist']); - } -} -else if($report_type == 'profile') -{ - $user = get_user($mybb->get_input('pid', MyBB::INPUT_INT)); - - if(!isset($user['uid'])) - { - $error = $lang->error_invalid_report; - } - else - { - $id2 = $id3 = 0; // We don't use these on the profile - $id = $user['uid']; // id is the profile user - $permissions = user_permissions($user['uid']); - - if(empty($permissions['canbereported'])) - { - $error = $lang->error_invalid_report; - } - else - { - $verified = true; - $report_type_db = "type = 'profile'"; - } - } -} -else if($report_type == 'reputation') -{ - // Any member can report a reputation comment but let's make sure it exists first - $query = $db->simple_select("reputation", "*", "rid = '".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - - if(!$db->num_rows($query)) - { - $error = $lang->error_invalid_report; - } - else - { - $verified = true; - $reputation = $db->fetch_array($query); - - $id = $reputation['rid']; // id is the reputation id - $id2 = $reputation['adduid']; // id2 is the user who gave the comment - $id3 = $reputation['uid']; // id3 is the user who received the comment - - $report_type_db = "type = 'reputation'"; - } -} - -$plugins->run_hooks("report_type"); - -// Check for an existing report -if(!empty($report_type_db)) -{ - $query = $db->simple_select("reportedcontent", "*", "reportstatus != '1' AND id = '{$id}' AND {$report_type_db}"); - - if($db->num_rows($query)) - { - // Existing report - $report = $db->fetch_array($query); - $report['reporters'] = my_unserialize($report['reporters']); - - if($mybb->user['uid'] == $report['uid'] || is_array($report['reporters']) && in_array($mybb->user['uid'], $report['reporters'])) - { - $error = $lang->success_report_voted; - } - } -} - -$mybb->input['action'] = $mybb->get_input('action'); - -if(empty($error) && $verified == true && $mybb->input['action'] == "do_report" && $mybb->request_method == "post") -{ - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("report_do_report_start"); - - // Is this an existing report or a new offender? - if(!empty($report)) - { - // Existing report, add vote - $report['reporters'][] = $mybb->user['uid']; - update_report($report); - - $plugins->run_hooks("report_do_report_end"); - - eval("\$report_thanks = \"".$templates->get("report_thanks")."\";"); - echo $report_thanks; - exit; - } - else - { - // Bad user! - $new_report = array( - 'id' => $id, - 'id2' => $id2, - 'id3' => $id3, - 'uid' => $mybb->user['uid'] - ); - - // Figure out the reason - $rid = $mybb->get_input('reason', MyBB::INPUT_INT); - $query = $db->simple_select("reportreasons", "*", "rid = '{$rid}'"); - - if(!$db->num_rows($query)) - { - $error = $lang->error_invalid_report_reason; - $verified = false; - } - else - { - $reason = $db->fetch_array($query); - - $new_report['reasonid'] = $reason['rid']; - - if($reason['extra']) - { - $comment = trim($mybb->get_input('comment')); - if(empty($comment) || $comment == '') - { - $error = $lang->error_comment_required; - $verified = false; - } - else - { - if(my_strlen($comment) < 3) - { - $error = $lang->error_report_length; - $verified = false; - } - else - { - $new_report['reason'] = $comment; - } - } - } - } - - if(empty($error)) - { - add_report($new_report, $report_type); - - $plugins->run_hooks("report_do_report_end"); - - eval("\$report_thanks = \"".$templates->get("report_thanks")."\";"); - echo $report_thanks; - exit; - } - } -} - -if(!empty($error) || $verified == false) -{ - $mybb->input['action'] = ''; - - if($verified == false && empty($error)) - { - $error = $lang->error_invalid_report; - } -} - -if(!$mybb->input['action']) -{ - if(!empty($error)) - { - if($mybb->input['no_modal']) - { - eval("\$report_reasons = \"".$templates->get("report_error_nomodal")."\";"); - } - else - { - eval("\$report_reasons = \"".$templates->get("report_error")."\";"); - } - } - else - { - if(!empty($report)) - { - eval("\$report_reasons = \"".$templates->get("report_duplicate")."\";"); - } - else - { - $reportreasons = $cache->read('reportreasons'); - $reasons = $reportreasons[$report_type]; - $reasonslist = ''; - foreach($reasons as $reason) - { - $reason['title'] = htmlspecialchars_uni($lang->parse($reason['title'])); - eval("\$reasonslist .= \"".$templates->get("report_reason")."\";"); - } - eval("\$report_reasons = \"".$templates->get("report_reasons")."\";"); - } - } - - if($mybb->input['no_modal']) - { - echo $report_reasons; - exit; - } - - $plugins->run_hooks("report_end"); - - eval("\$report = \"".$templates->get("report", 1, 0)."\";"); - echo $report; - exit; -} diff --git a/html/forums/reputation.php b/html/forums/reputation.php deleted file mode 100644 index 49d41d9..0000000 --- a/html/forums/reputation.php +++ /dev/null @@ -1,1063 +0,0 @@ -load("reputation"); - -$plugins->run_hooks("reputation_start"); - -// Check if the reputation system is globally disabled or not. -if($mybb->settings['enablereputation'] != 1) -{ - error($lang->reputation_disabled); -} - -// Does this user have permission to view the board? -if($mybb->usergroup['canview'] != 1) -{ - error_no_permission(); -} - -// If we have a specified incoming username, validate it and fetch permissions for it -$uid = $mybb->get_input('uid', MyBB::INPUT_INT); -$user = get_user($uid); -if(!$user) -{ - error($lang->add_no_uid); -} -$user_permissions = user_permissions($uid); - -$mybb->input['action'] = $mybb->get_input('action'); - -// Here we perform our validation when adding a reputation to see if the user -// has permission or not. This is done here to save duplicating the same code. -if($mybb->input['action'] == "add" || $mybb->input['action'] == "do_add") -{ - // This user doesn't have permission to give reputations. - if($mybb->usergroup['cangivereputations'] != 1) - { - $message = $lang->add_no_permission; - if($mybb->input['nomodal']) - { - eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";"); - } - else - { - eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";"); - } - echo $error; - exit; - } - - // The user we're trying to give a reputation to doesn't have permission to receive reps. - if($user_permissions['usereputationsystem'] != 1) - { - $message = $lang->add_disabled; - if($mybb->input['nomodal']) - { - eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";"); - } - else - { - eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";"); - } - echo $error; - exit; - } - - // Is this user trying to give themself a reputation? - if($uid == $mybb->user['uid']) - { - $message = $lang->add_yours; - if($mybb->input['nomodal']) - { - eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";"); - } - else - { - eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";"); - } - echo $error; - exit; - } - - // If a post has been given but post ratings have been disabled, set the post to 0. This will mean all subsequent code will think no post was given. - if($mybb->settings['postrep'] != 1) - { - $mybb->input['pid'] = 0; - } - - if($mybb->get_input('pid', MyBB::INPUT_INT)) - { - // Make sure that this post exists, and that the author of the post we're giving this reputation for corresponds with the user the rep is being given to. - $post = get_post($mybb->get_input('pid', MyBB::INPUT_INT)); - if($post) - { - $thread = get_thread($post['tid']); - $forum = get_forum($thread['fid']); - $forumpermissions = forum_permissions($forum['fid']); - - // Post doesn't belong to that user or isn't visible - if($uid != $post['uid'] || $post['visible'] != 1) - { - $mybb->input['pid'] = 0; - } - - // Thread isn't visible - elseif($thread['visible'] != 1) - { - $mybb->input['pid'] = 0; - } - - // Current user can't see the forum - elseif($forumpermissions['canview'] == 0 || $forumpermissions['canpostreplys'] == 0 || $mybb->user['suspendposting'] == 1) - { - $mybb->input['pid'] = 0; - } - - // Current user can't see that thread - elseif(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] == 1 && $thread['uid'] != $mybb->user['uid']) - { - $mybb->input['pid'] = 0; - } - } - else - { - $mybb->input['pid'] = 0; - } - } - - $rid = 0; - - // Fetch the existing reputation for this user given by our current user if there is one. - // If multiple reputations is allowed, then this isn't needed - if($mybb->settings['multirep'] != 1 && $mybb->get_input('pid', MyBB::INPUT_INT) == 0) - { - $query = $db->simple_select("reputation", "*", "adduid='".$mybb->user['uid']."' AND uid='{$uid}' AND pid='0'"); - $existing_reputation = $db->fetch_array($query); - $rid = $existing_reputation['rid']; - $was_post = false; - } - if($mybb->get_input('pid', MyBB::INPUT_INT) != 0) - { - $query = $db->simple_select("reputation", "*", "adduid='".$mybb->user['uid']."' AND uid='{$uid}' AND pid = '".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - $existing_reputation = $db->fetch_array($query); - $rid = $existing_reputation['rid']; - $was_post = true; - } - - if($rid == 0 && ($mybb->input['action'] != "do_add" || ($mybb->input['action'] == "do_add" && empty($mybb->input['delete'])))) - { - $message = ''; - - // Check if this user has reached their "maximum reputations per day" quota - if($mybb->usergroup['maxreputationsday'] != 0) - { - $timesearch = TIME_NOW - (60 * 60 * 24); - $query = $db->simple_select("reputation", "*", "adduid='{$mybb->user['uid']}' AND dateline>'$timesearch'"); - $numtoday = $db->num_rows($query); - - // Reached the quota - error. - if($numtoday >= $mybb->usergroup['maxreputationsday']) - { - $message = $lang->add_maxperday; - } - } - - // Is the user giving too much reputation to another? - if(!$message && $mybb->usergroup['maxreputationsperuser'] != 0) - { - $timesearch = TIME_NOW - (60 * 60 * 24); - $query = $db->simple_select("reputation", "*", "uid='{$uid}' AND adduid='{$mybb->user['uid']}' AND dateline>'$timesearch'"); - $numtoday = $db->num_rows($query); - - if($numtoday >= $mybb->usergroup['maxreputationsperuser']) - { - $message = $lang->add_maxperuser; - } - } - - // We have the correct post, but has the user given too much reputation to another in the same thread? - if(!$message && $was_post && $mybb->usergroup['maxreputationsperthread'] != 0) - { - $timesearch = TIME_NOW - (60 * 60 * 24); - $query = $db->query(" - SELECT COUNT(p.pid) AS posts - FROM ".TABLE_PREFIX."reputation r - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid = r.pid) - WHERE r.uid = '{$uid}' AND r.adduid = '{$mybb->user['uid']}' AND p.tid = '{$post['tid']}' AND r.dateline > '{$timesearch}' - "); - - $numtoday = $db->fetch_field($query, 'posts'); - - if($numtoday >= $mybb->usergroup['maxreputationsperthread']) - { - $message = $lang->add_maxperthread; - } - } - - if($message) - { - if($mybb->input['nomodal']) - { - eval('$error = "'.$templates->get("reputation_add_error_nomodal", 1, 0).'";'); - } - else - { - eval('$error = "'.$templates->get("reputation_add_error", 1, 0).'";'); - } - echo $error; - exit; - } - } -} - -// Saving the new reputation -if($mybb->input['action'] == "do_add" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("reputation_do_add_start"); - - // Check if the reputation power they're trying to give is within their "power limit" - $reputation = abs($mybb->get_input('reputation', MyBB::INPUT_INT)); - - // Deleting our current reputation of this user. - if(!empty($mybb->input['delete'])) - { - // Only administrators, super moderators, as well as users who gave a specifc vote can delete one. - if($mybb->usergroup['issupermod'] != 1 && ($mybb->usergroup['candeletereputations'] != 1 || $existing_reputation['adduid'] != $mybb->user['uid'] || $mybb->user['uid'] == 0)) - { - error_no_permission(); - } - - if($mybb->get_input('pid', MyBB::INPUT_INT) != 0) - { - $db->delete_query("reputation", "uid='{$uid}' AND adduid='".$mybb->user['uid']."' AND pid = '".$mybb->get_input('pid', MyBB::INPUT_INT)."'"); - } - else - { - $db->delete_query("reputation", "rid='{$rid}' AND uid='{$uid}' AND adduid='".$mybb->user['uid']."'"); - } - - // Recount the reputation of this user - keep it in sync. - $query = $db->simple_select("reputation", "SUM(reputation) AS reputation_count", "uid='{$uid}'"); - $reputation_value = $db->fetch_field($query, "reputation_count"); - - $db->update_query("users", array('reputation' => (int)$reputation_value), "uid='{$uid}'"); - eval("\$error = \"".$templates->get("reputation_deleted", 1, 0)."\";"); - echo $error; - exit; - } - - $mybb->input['comments'] = trim($mybb->get_input('comments')); // Trim whitespace to check for length - if(my_strlen($mybb->input['comments']) < $mybb->settings['minreplength'] && $mybb->get_input('pid', MyBB::INPUT_INT) == 0) - { - $message = $lang->add_no_comment; - if($mybb->input['nomodal']) - { - eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";"); - } - else - { - eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";"); - } - echo $error; - exit; - } - - // The power for the reputation they specified was invalid. - if($reputation > $mybb->usergroup['reputationpower']) - { - $message = $lang->add_invalidpower; - if($mybb->input['nomodal']) - { - eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";"); - } - else - { - eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";"); - } - echo $error; - exit; - } - - // The user is trying to give a negative reputation, but negative reps have been disabled. - if($mybb->get_input('reputation', MyBB::INPUT_INT) < 0 && $mybb->settings['negrep'] != 1) - { - $message = $lang->add_negative_disabled; - if($mybb->input['nomodal']) - { - eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";"); - } - else - { - eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";"); - } - echo $error; - exit; - } - - // This user is trying to give a neutral reputation, but neutral reps have been disabled. - if($mybb->get_input('reputation', MyBB::INPUT_INT) == 0 && $mybb->settings['neurep'] != 1) - { - $message = $lang->add_neutral_disabled; - if($mybb->input['nomodal']) - { - eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";"); - } - else - { - eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";"); - } - echo $error; - exit; - } - - // This user is trying to give a positive reputation, but positive reps have been disabled. - if($mybb->get_input('reputation', MyBB::INPUT_INT) > 0 && $mybb->settings['posrep'] != 1) - { - $message = $lang->add_positive_disabled; - if($mybb->input['nomodal']) - { - eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";"); - } - else - { - eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";"); - } - echo $error; - exit; - } - - // The length of the comment is too long - if(my_strlen($mybb->input['comments']) > $mybb->settings['maxreplength']) - { - $message = $lang->sprintf($lang->add_toolong, $mybb->settings['maxreplength']); - if($mybb->input['nomodal']) - { - eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";"); - } - else - { - eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";"); - } - echo $error; - exit; - } - - // Build array of reputation data. - $reputation = array( - "uid" => $uid, - "adduid" => $mybb->user['uid'], - "pid" => $mybb->get_input('pid', MyBB::INPUT_INT), - "reputation" => $mybb->get_input('reputation', MyBB::INPUT_INT), - "dateline" => TIME_NOW, - "comments" => $db->escape_string($mybb->input['comments']) - ); - - $plugins->run_hooks("reputation_do_add_process"); - - // Updating an existing reputation - if(!empty($existing_reputation['uid'])) - { - $db->update_query("reputation", $reputation, "rid='".$existing_reputation['rid']."'"); - - // Recount the reputation of this user - keep it in sync. - $query = $db->simple_select("reputation", "SUM(reputation) AS reputation_count", "uid='{$uid}'"); - $reputation_value = $db->fetch_field($query, "reputation_count"); - - $db->update_query("users", array('reputation' => (int)$reputation_value), "uid='{$uid}'"); - - $lang->vote_added = $lang->vote_updated; - $lang->vote_added_message = $lang->vote_updated_message; - } - // Insert a new reputation - else - { - $db->insert_query("reputation", $reputation); - - // Recount the reputation of this user - keep it in sync. - $query = $db->simple_select("reputation", "SUM(reputation) AS reputation_count", "uid='{$uid}'"); - $reputation_value = $db->fetch_field($query, "reputation_count"); - - $db->update_query("users", array('reputation' => (int)$reputation_value), "uid='{$uid}'"); - } - - $plugins->run_hooks("reputation_do_add_end"); - - eval("\$reputation = \"".$templates->get("reputation_added", 1, 0)."\";"); - echo $reputation; - exit; -} - -// Adding a new reputation -if($mybb->input['action'] == "add") -{ - $plugins->run_hooks("reputation_add_start"); - - // If we have an existing reputation for this user, the user can modify or delete it. - $user['username'] = htmlspecialchars_uni($user['username']); - if(!empty($existing_reputation['uid'])) - { - $vote_title = $lang->sprintf($lang->update_reputation_vote, $user['username']); - $vote_button = $lang->update_vote; - $comments = htmlspecialchars_uni($existing_reputation['comments']); - - if($mybb->usergroup['issupermod'] == 1 || ($mybb->usergroup['candeletereputations'] == 1 && $existing_reputation['adduid'] == $mybb->user['uid'] && $mybb->user['uid'] != 0)) - { - eval("\$delete_button = \"".$templates->get("reputation_add_delete")."\";"); - } - } - // Otherwise we're adding an entirely new reputation for this user. - else - { - $vote_title = $lang->sprintf($lang->add_reputation_vote, $user['username']); - $vote_button = $lang->add_vote; - $comments = ''; - $delete_button = ''; - } - $lang->user_comments = $lang->sprintf($lang->user_comments, $user['username']); - - if($mybb->get_input('pid', MyBB::INPUT_INT)) - { - $post_rep_info = $lang->sprintf($lang->add_reputation_to_post, $user['username']); - $lang->user_comments = $lang->no_comment_needed; - } - else - { - $post_rep_info = ''; - } - - // Draw the "power" options - if($mybb->settings['negrep'] || $mybb->settings['neurep'] || $mybb->settings['posrep']) - { - $vote_check = array(); - $positive_power = ''; - $negative_power = ''; - $reputationpower = (int)$mybb->usergroup['reputationpower']; - - foreach(range(-$mybb->usergroup['reputationpower'], $mybb->usergroup['reputationpower']) as $value) - { - $vote_check[$value] = ''; - } - - if(!empty($existing_reputation['uid']) && !$was_post) - { - $vote_check[$existing_reputation['reputation']] = " selected=\"selected\""; - } - - if($mybb->settings['neurep']) - { - $neutral_title = $lang->power_neutral; - eval("\$neutral_power = \"".$templates->get("reputation_add_neutral")."\";"); - } - - for($value = 1; $value <= $reputationpower; ++$value) - { - if($mybb->settings['posrep']) - { - $positive_title = $lang->sprintf($lang->power_positive, "+".$value); - eval("\$positive_power = \"".$templates->get("reputation_add_positive")."\";"); - } - - if($mybb->settings['negrep']) - { - $negative_title = $lang->sprintf($lang->power_negative, "-".$value); - $neg_value = "-{$value}"; - eval("\$negative_power .= \"".$templates->get("reputation_add_negative")."\";"); - } - } - - $mybb->input['pid'] = $mybb->get_input('pid', MyBB::INPUT_INT); - - $plugins->run_hooks("reputation_add_end"); - eval("\$reputation_add = \"".$templates->get("reputation_add", 1, 0)."\";"); - } - else - { - $message = $lang->add_all_rep_disabled; - - $plugins->run_hooks("reputation_add_end_error"); - if($mybb->input['nomodal']) - { - eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";"); - } - else - { - eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";"); - } - } - - echo $reputation_add; - exit; -} - -// Delete a specific reputation from a user. -if($mybb->input['action'] == "delete") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - // Fetch the existing reputation for this user given by our current user if there is one. - $query = $db->query(" - SELECT r.*, u.username - FROM ".TABLE_PREFIX."reputation r - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=r.adduid) - WHERE rid = '".$mybb->get_input('rid', MyBB::INPUT_INT)."' - "); - $existing_reputation = $db->fetch_array($query); - - // Only administrators, super moderators, as well as users who gave a specifc vote can delete one. - if($mybb->usergroup['issupermod'] != 1 && ($mybb->usergroup['candeletereputations'] != 1 || $existing_reputation['adduid'] != $mybb->user['uid'] || $mybb->user['uid'] == 0)) - { - error_no_permission(); - } - - // Delete the specified reputation - $db->delete_query("reputation", "uid='{$uid}' AND rid='".$mybb->get_input('rid', MyBB::INPUT_INT)."'"); - - // Recount the reputation of this user - keep it in sync. - $query = $db->simple_select("reputation", "SUM(reputation) AS reputation_count", "uid='{$uid}'"); - $reputation_value = $db->fetch_field($query, "reputation_count"); - - // Create moderator log - log_moderator_action(array("uid" => $user['uid'], "username" => $user['username']), $lang->sprintf($lang->delete_reputation_log, $existing_reputation['username'], $existing_reputation['adduid'])); - - $db->update_query("users", array('reputation' => (int)$reputation_value), "uid='{$uid}'"); - - redirect("reputation.php?uid={$uid}", $lang->vote_deleted_message); -} - -// Otherwise, show a listing of reputations for the given user. -if(!$mybb->input['action']) -{ - if($mybb->usergroup['canviewprofiles'] == 0) - { - // Reputation page is a part of a profile - error_no_permission(); - } - - // Set display group to their user group if they don't have a display group. - if(!$user['displaygroup']) - { - $user['displaygroup'] = $user['usergroup']; - } - - // Fetch display group properties. - $displaygroupfields = array('title', 'description', 'namestyle', 'usertitle', 'stars', 'starimage', 'image', 'usereputationsystem'); - $display_group = usergroup_displaygroup($user['displaygroup']); - - if($user_permissions['usereputationsystem'] != 1 || $display_group['title'] && $display_group['usereputationsystem'] == 0) - { - // Group has reputation disabled or user has a display group that has reputation disabled - error($lang->reputations_disabled_group); - } - - $user['username'] = htmlspecialchars_uni($user['username']); - $lang->nav_profile = $lang->sprintf($lang->nav_profile, $user['username']); - $lang->reputation_report = $lang->sprintf($lang->reputation_report, $user['username']); - - // Format the user name using the group username style - $username = format_name($user['username'], $user['usergroup'], $user['displaygroup']); - - // Set display group to their user group if they don't have a display group. - if(!$user['displaygroup']) - { - $user['displaygroup'] = $user['usergroup']; - } - - $usertitle = ''; - - // This user has a custom user title - if(trim($user['usertitle']) != '') - { - $usertitle = $user['usertitle']; - } - // Using our display group's user title - elseif(trim($display_group['usertitle']) != '') - { - $usertitle = $display_group['usertitle']; - } - // Otherwise, fetch it from our titles table for the number of posts this user has - else - { - $usertitles = $cache->read('usertitles'); - foreach($usertitles as $title) - { - if($title['posts'] <= $user['postnum']) - { - $usertitle = $title['title']; - break; - } - } - unset($usertitles, $title); - } - - $usertitle = htmlspecialchars_uni($usertitle); - - // If the user has permission to add reputations - show the image - if($mybb->usergroup['cangivereputations'] == 1 && $mybb->user['uid'] != $user['uid'] && ($mybb->settings['posrep'] || $mybb->settings['neurep'] || $mybb->settings['negrep'])) - { - eval("\$add_reputation = \"".$templates->get("reputation_addlink")."\";"); - } - else - { - $add_reputation = ''; - } - - // Build navigation menu - add_breadcrumb($lang->nav_profile, get_profile_link($user['uid'])); - add_breadcrumb($lang->nav_reputation); - - // Check our specified conditionals for what type of reputations to show - $show_selected = array('all' => '', 'positive' => '', 'neutral' => '', 'negative' => ''); - switch($mybb->get_input('show')) - { - case "positive": - $s_url = "&show=positive"; - $conditions = 'AND r.reputation>0'; - $show_selected['positive'] = 'selected="selected"'; - break; - case "neutral": - $s_url = "&show=neutral"; - $conditions = 'AND r.reputation=0'; - $show_selected['neutral'] = 'selected="selected"'; - break; - case "negative": - $s_url = "&show=negative"; - $conditions = 'AND r.reputation<0'; - $show_selected['negative'] = 'selected="selected"'; - break; - default: - $s_url = '&show=all'; - $conditions = ''; - $show_select['all'] = 'selected="selected"'; - break; - } - - // Check the sorting options for the reputation list - $sort_selected = array('username' => '', 'last_ipdated' => ''); - switch($mybb->get_input('sort')) - { - case "username": - $s_url .= "&sort=username"; - $order = "u.username ASC"; - $sort_selected['username'] = 'selected="selected"'; - break; - default: - $s_url .= '&sort=dateline'; - $order = "r.dateline DESC"; - $sort_selected['last_updated'] = 'selected="selected"'; - break; - } - - if(empty($mybb->input['show']) && empty($mybb->input['sort'])) - { - $s_url = ''; - } - - // Fetch the total number of reputations for this user - $query = $db->simple_select("reputation r", "COUNT(r.rid) AS reputation_count", "r.uid='{$user['uid']}' $conditions"); - $reputation_count = $db->fetch_field($query, "reputation_count"); - - // If the user has no reputation, suspect 0... - if(!$user['reputation']) - { - $user['reputation'] = 0; - } - - // Quickly check to see if we're in sync... - $query = $db->simple_select("reputation", "SUM(reputation) AS reputation, COUNT(rid) AS total_reputation", "uid = '".$user['uid']."'"); - $reputation = $db->fetch_array($query); - - $sync_reputation = (int)$reputation['reputation']; - $total_reputation = $reputation['total_reputation']; - - if($sync_reputation != $user['reputation']) - { - // We're out of sync! Oh noes! - $db->update_query("users", array("reputation" => $sync_reputation), "uid = '".$user['uid']."'"); - $user['reputation'] = $sync_reputation; - } - - // Set default count variables to 0 - $positive_count = $negative_count = $neutral_count = 0; - $positive_week = $negative_week = $neutral_week = 0; - $positive_month = $negative_month = $neutral_month = 0; - $positive_6months = $negative_6months = $neutral_6months = 0; - - // Unix timestamps for when this week, month and last 6 months started - $last_week = TIME_NOW-604800; - $last_month = TIME_NOW-2678400; - $last_6months = TIME_NOW-16070400; - - // Query reputations for the "reputation card" - $query = $db->simple_select("reputation", "reputation, dateline", "uid='{$user['uid']}'"); - while($reputation_vote = $db->fetch_array($query)) - { - // This is a positive reputation - if($reputation_vote['reputation'] > 0) - { - $positive_count++; - if($reputation_vote['dateline'] >= $last_week) - { - $positive_week++; - } - if($reputation_vote['dateline'] >= $last_month) - { - $positive_month++; - } - if($reputation_vote['dateline'] >= $last_6months) - { - $positive_6months++; - } - } - // Negative reputation given - else if($reputation_vote['reputation'] < 0) - { - $negative_count++; - if($reputation_vote['dateline'] >= $last_week) - { - $negative_week++; - } - if($reputation_vote['dateline'] >= $last_month) - { - $negative_month++; - } - if($reputation_vote['dateline'] >= $last_6months) - { - $negative_6months++; - } - } - // Neutral reputation given - else - { - $neutral_count++; - if($reputation_vote['dateline'] >= $last_week) - { - $neutral_week++; - } - if($reputation_vote['dateline'] >= $last_month) - { - $neutral_month++; - } - if($reputation_vote['dateline'] >= $last_6months) - { - $neutral_6months++; - } - } - } - - // Format all reputation numbers - $rep_total = my_number_format($user['reputation']); - $f_positive_count = my_number_format($positive_count); - $f_negative_count = my_number_format($negative_count); - $f_neutral_count = my_number_format($neutral_count); - $f_positive_week = my_number_format($positive_week); - $f_negative_week = my_number_format($negative_week); - $f_neutral_week = my_number_format($neutral_week); - $f_positive_month = my_number_format($positive_month); - $f_negative_month = my_number_format($negative_month); - $f_neutral_month = my_number_format($neutral_month); - $f_positive_6months = my_number_format($positive_6months); - $f_negative_6months = my_number_format($negative_6months); - $f_neutral_6months = my_number_format($neutral_6months); - - // Format the user's 'total' reputation - if($user['reputation'] < 0) - { - $total_class = "_minus"; - } - elseif($user['reputation'] > 0) - { - $total_class = "_plus"; - } - else - { - $total_class = "_neutral"; - } - - // Figure out how many reps have come from posts / 'general' - // Posts - $query = $db->simple_select("reputation", "COUNT(rid) AS rep_posts", "uid = '".$user['uid']."' AND pid > 0"); - $rep_post_count = $db->fetch_field($query, "rep_posts"); - $rep_posts = my_number_format($rep_post_count); - - // General - // We count how many reps in total, then subtract the reps from posts - $rep_members = my_number_format($total_reputation - $rep_post_count); - - // Is negative reputation disabled? If so, tell the user - if($mybb->settings['negrep'] == 0) - { - $neg_rep_info = $lang->neg_rep_disabled; - } - - if($mybb->settings['posrep'] == 0) - { - $pos_rep_info = $lang->pos_rep_disabled; - } - - if($mybb->settings['neurep'] == 0) - { - $neu_rep_info = $lang->neu_rep_disabled; - } - - $perpage = (int)$mybb->settings['repsperpage']; - if($perpage < 1) - { - $perpage = 15; - } - - // Check if we're browsing a specific page of results - if($mybb->get_input('page', MyBB::INPUT_INT) > 0) - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - $start = ($page-1) * $perpage; - $pages = $reputation_count / $perpage; - $pages = ceil($pages); - if($page > $pages) - { - $start = 0; - $page = 1; - } - } - else - { - $start = 0; - $page = 1; - } - - $multipage = ''; - - // Build out multipage navigation - if($reputation_count > 0) - { - $multipage = multipage($reputation_count, $perpage, $page, "reputation.php?uid={$user['uid']}".$s_url); - } - - // Fetch the reputations which will be displayed on this page - $query = $db->query(" - SELECT r.*, r.uid AS rated_uid, u.uid, u.username, u.reputation AS user_reputation, u.usergroup AS user_usergroup, u.displaygroup AS user_displaygroup - FROM ".TABLE_PREFIX."reputation r - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=r.adduid) - WHERE r.uid='{$user['uid']}' $conditions - ORDER BY $order - LIMIT $start, {$perpage} - "); - - // Gather a list of items that have post reputation - $reputation_cache = $post_cache = $post_reputation = array(); - - while($reputation_vote = $db->fetch_array($query)) - { - $reputation_cache[] = $reputation_vote; - - // If this is a post, hold it and gather some information about it - if($reputation_vote['pid'] && !isset($post_cache[$reputation_vote['pid']])) - { - $post_cache[$reputation_vote['pid']] = $reputation_vote['pid']; - } - } - - if(!empty($post_cache)) - { - $pids = implode(',', $post_cache); - - $sql = array("p.pid IN ({$pids})"); - - // get forums user cannot view - $unviewable = get_unviewable_forums(true); - if($unviewable) - { - $sql[] = "p.fid NOT IN ({$unviewable})"; - } - - // get inactive forums - $inactive = get_inactive_forums(); - if($inactive) - { - $sql[] = "p.fid NOT IN ({$inactive})"; - } - - if(!$mybb->user['ismoderator']) - { - $sql[] = "p.visible='1'"; - $sql[] = "t.visible='1'"; - } - - $sql = implode(' AND ', $sql); - - $query = $db->query(" - SELECT p.pid, p.uid, p.fid, p.visible, p.message, t.tid, t.subject, t.visible AS thread_visible - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE {$sql} - "); - - $forumpermissions = array(); - - while($post = $db->fetch_array($query)) - { - if(($post['visible'] == 0 || $post['thread_visible'] == 0) && !is_moderator($post['fid'], 'canviewunapprove')) - { - continue; - } - - if(($post['visible'] == -1 || $post['thread_visible'] == -1) && !is_moderator($post['fid'], 'canviewdeleted')) - { - continue; - } - - if(!isset($forumpermissions[$post['fid']])) - { - $forumpermissions[$post['fid']] = forum_permissions($post['fid']); - } - - // Make sure we can view this post - if(isset($forumpermissions[$post['fid']]['canonlyviewownthreads']) && $forumpermissions[$post['fid']]['canonlyviewownthreads'] == 1 && $post['uid'] != $mybb->user['uid']) - { - continue; - } - - $post_reputation[$post['pid']] = $post; - } - } - - $reputation_votes = ''; - - foreach($reputation_cache as $reputation_vote) - { - // Get the reputation for the user who posted this comment - if($reputation_vote['adduid'] == 0) - { - $reputation_vote['user_reputation'] = 0; - } - - $reputation_vote['user_reputation'] = get_reputation($reputation_vote['user_reputation'], $reputation_vote['adduid']); - - // Format the username of this poster - if(!$reputation_vote['username']) - { - $reputation_vote['username'] = $lang->na; - $reputation_vote['user_reputation'] = ''; - } - else - { - $reputation_vote['username'] = format_name(htmlspecialchars_uni($reputation_vote['username']), $reputation_vote['user_usergroup'], $reputation_vote['user_displaygroup']); - $reputation_vote['username'] = build_profile_link($reputation_vote['username'], $reputation_vote['uid']); - $reputation_vote['user_reputation'] = "({$reputation_vote['user_reputation']})"; - } - - $vote_reputation = (int)$reputation_vote['reputation']; - - // This is a negative reputation - if($vote_reputation < 0) - { - $status_class = "trow_reputation_negative"; - $vote_type_class = "reputation_negative"; - $vote_type = $lang->negative; - } - // This is a neutral reputation - else if($vote_reputation == 0) - { - $status_class = "trow_reputation_neutral"; - $vote_type_class = "reputation_neutral"; - $vote_type = $lang->neutral; - } - // Otherwise, this is a positive reputation - else - { - $vote_reputation = "+{$vote_reputation}"; - $status_class = "trow_reputation_positive"; - $vote_type_class = "reputation_positive"; - $vote_type = $lang->positive; - } - - $vote_reputation = "({$vote_reputation})"; - - // Format the date this reputation was last modified - $last_updated_date = my_date('relative', $reputation_vote['dateline']); - $last_updated = $lang->sprintf($lang->last_updated, $last_updated_date); - - $user['username'] = htmlspecialchars_uni($user['username']); - - // Is this rating specific to a post? - $postrep_given = ''; - if($reputation_vote['pid']) - { - $postrep_given = $lang->sprintf($lang->postrep_given_nolink, $user['username']); - if(isset($post_reputation[$reputation_vote['pid']])) - { - $thread_link = get_thread_link($post_reputation[$reputation_vote['pid']]['tid']); - $subject = htmlspecialchars_uni($parser->parse_badwords($post_reputation[$reputation_vote['pid']]['subject'])); - - $thread_link = $lang->sprintf($lang->postrep_given_thread, $thread_link, $subject); - $link = get_post_link($reputation_vote['pid'])."#pid{$reputation_vote['pid']}"; - - $postrep_given = $lang->sprintf($lang->postrep_given, $link, $user['username'], $thread_link); - } - } - - // Does the current user have permission to delete this reputation? Show delete link - $delete_link = ''; - if($mybb->usergroup['issupermod'] == 1 || ($mybb->usergroup['candeletereputations'] == 1 && $reputation_vote['adduid'] == $mybb->user['uid'] && $mybb->user['uid'] != 0)) - { - eval("\$delete_link = \"".$templates->get("reputation_vote_delete")."\";"); - } - - $report_link = ''; - if($mybb->user['uid'] != 0) - { - eval("\$report_link = \"".$templates->get("reputation_vote_report")."\";"); - } - - // Parse smilies in the reputation vote - $reputation_parser = array( - "allow_html" => 0, - "allow_mycode" => 0, - "allow_smilies" => 1, - "allow_imgcode" => 0, - "filter_badwords" => 1 - ); - - $reputation_vote['comments'] = $parser->parse_message($reputation_vote['comments'], $reputation_parser); - if($reputation_vote['comments'] == '') - { - $reputation_vote['comments'] = $lang->no_comment; - } - - $plugins->run_hooks("reputation_vote"); - - eval("\$reputation_votes .= \"".$templates->get("reputation_vote")."\";"); - } - - // If we don't have any reputations display a nice message. - if(!$reputation_votes) - { - eval("\$reputation_votes = \"".$templates->get("reputation_no_votes")."\";"); - } - - $plugins->run_hooks("reputation_end"); - eval("\$reputation = \"".$templates->get("reputation")."\";"); - output_page($reputation); -} diff --git a/html/forums/rss.php b/html/forums/rss.php deleted file mode 100644 index b0ebb07..0000000 --- a/html/forums/rss.php +++ /dev/null @@ -1,19 +0,0 @@ -load("search"); - -add_breadcrumb($lang->nav_search, "search.php"); - -$mybb->input['action'] = $mybb->get_input('action'); -switch($mybb->input['action']) -{ - case "results": - add_breadcrumb($lang->nav_results); - break; - default: - break; -} - -if($mybb->usergroup['cansearch'] == 0) -{ - error_no_permission(); -} - -$now = TIME_NOW; -$mybb->input['keywords'] = trim($mybb->get_input('keywords')); - -$limitsql = ""; -if((int)$mybb->settings['searchhardlimit'] > 0) -{ - $limitsql = "LIMIT ".(int)$mybb->settings['searchhardlimit']; -} - -if($mybb->input['action'] == "results") -{ - $sid = $db->escape_string($mybb->get_input('sid')); - $query = $db->simple_select("searchlog", "*", "sid='$sid'"); - $search = $db->fetch_array($query); - - if(!$search['sid']) - { - error($lang->error_invalidsearch); - } - - $plugins->run_hooks("search_results_start"); - - // Decide on our sorting fields and sorting order. - $order = my_strtolower(htmlspecialchars_uni($mybb->get_input('order'))); - $sortby = my_strtolower(htmlspecialchars_uni($mybb->get_input('sortby'))); - - switch($sortby) - { - case "replies": - $sortfield = "t.replies"; - break; - case "views": - $sortfield = "t.views"; - break; - case "subject": - if($search['resulttype'] == "threads") - { - $sortfield = "t.subject"; - } - else - { - $sortfield = "p.subject"; - } - break; - case "forum": - $sortfield = "t.fid"; - break; - case "starter": - if($search['resulttype'] == "threads") - { - $sortfield = "t.username"; - } - else - { - $sortfield = "p.username"; - } - break; - case "lastpost": - default: - if($search['resulttype'] == "threads") - { - $sortfield = "t.lastpost"; - $sortby = "lastpost"; - } - else - { - $sortfield = "p.dateline"; - $sortby = "dateline"; - } - break; - } - - if($order != "asc") - { - $order = "desc"; - $oppsortnext = "asc"; - $oppsort = $lang->asc; - } - else - { - $oppsortnext = "desc"; - $oppsort = $lang->desc; - } - - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - // Work out pagination, which page we're at, as well as the limits. - $perpage = $mybb->settings['threadsperpage']; - $page = $mybb->get_input('page'); - if($page > 0) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - $end = $start + $perpage; - $lower = $start+1; - $upper = $end; - - // Work out if we have terms to highlight - $highlight = ""; - if($search['keywords']) - { - if($mybb->seo_support == true) - { - $highlight = "?highlight=".urlencode($search['keywords']); - } - else - { - $highlight = "&highlight=".urlencode($search['keywords']); - } - } - - $sorturl = "search.php?action=results&sid={$sid}"; - $thread_url = ""; - $post_url = ""; - - $orderarrow = array('replies' => '', 'views' => '', 'subject' => '', 'forum' => '', 'starter' => '', 'lastpost' => '', 'dateline' => ''); - - eval("\$orderarrow['$sortby'] = \"".$templates->get("search_orderarrow")."\";"); - - // Read some caches we will be using - $forumcache = $cache->read("forums"); - $icon_cache = $cache->read("posticons"); - - $threads = array(); - - if($mybb->user['uid'] == 0) - { - // Build a forum cache. - $query = $db->query(" - SELECT fid - FROM ".TABLE_PREFIX."forums - WHERE active != 0 - ORDER BY pid, disporder - "); - - $forumsread = my_unserialize($mybb->cookies['mybb']['forumread']); - } - else - { - // Build a forum cache. - $query = $db->query(" - SELECT f.fid, fr.dateline AS lastread - FROM ".TABLE_PREFIX."forums f - LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}') - WHERE f.active != 0 - ORDER BY pid, disporder - "); - } - - while($forum = $db->fetch_array($query)) - { - if($mybb->user['uid'] == 0) - { - if($forumsread[$forum['fid']]) - { - $forum['lastread'] = $forumsread[$forum['fid']]; - } - } - $readforums[$forum['fid']] = $forum['lastread']; - } - $fpermissions = forum_permissions(); - - // Inline Mod Column for moderators - $inlinemodcol = $inlinecookie = ''; - $is_mod = $is_supermod = false; - if($mybb->usergroup['issupermod']) - { - $is_supermod = true; - } - if($is_supermod || is_moderator()) - { - eval("\$inlinemodcol = \"".$templates->get("search_results_inlinemodcol")."\";"); - $inlinecookie = "inlinemod_search".$sid; - $inlinecount = 0; - $is_mod = true; - $return_url = 'search.php?'.htmlspecialchars_uni($_SERVER['QUERY_STRING']); - } - - // Show search results as 'threads' - if($search['resulttype'] == "threads") - { - $threadcount = 0; - - // Moderators can view unapproved threads - $query = $db->simple_select("moderators", "fid, canviewunapprove, canviewdeleted", "(id='{$mybb->user['uid']}' AND isgroup='0') OR (id='{$mybb->user['usergroup']}' AND isgroup='1')"); - if($mybb->usergroup['issupermod'] == 1) - { - // Super moderators (and admins) - $unapproved_where = "t.visible>=-1"; - } - elseif($db->num_rows($query)) - { - // Normal moderators - $unapprove_forums = array(); - $deleted_forums = array(); - $unapproved_where = '(t.visible = 1'; - while($moderator = $db->fetch_array($query)) - { - if($moderator['canviewunapprove'] == 1) - { - $unapprove_forums[] = $moderator['fid']; - } - - if($moderator['canviewdeleted'] == 1) - { - $deleted_forums[] = $moderator['fid']; - } - } - - if(!empty($unapprove_forums)) - { - $unapproved_where .= " OR (t.visible = 0 AND t.fid IN(".implode(',', $unapprove_forums)."))"; - } - if(!empty($deleted_forums)) - { - $unapproved_where .= " OR (t.visible = -1 AND t.fid IN(".implode(',', $deleted_forums)."))"; - } - $unapproved_where .= ')'; - } - else - { - // Normal users - $unapproved_where = 't.visible>0'; - } - - // If we have saved WHERE conditions, execute them - if($search['querycache'] != "") - { - $where_conditions = $search['querycache']; - $query = $db->simple_select("threads t", "t.tid", $where_conditions. " AND {$unapproved_where} AND t.closed NOT LIKE 'moved|%' ORDER BY t.lastpost DESC {$limitsql}"); - while($thread = $db->fetch_array($query)) - { - $threads[$thread['tid']] = $thread['tid']; - $threadcount++; - } - // Build our list of threads. - if($threadcount > 0) - { - $search['threads'] = implode(",", $threads); - } - // No results. - else - { - error($lang->error_nosearchresults); - } - $where_conditions = "t.tid IN (".$search['threads'].")"; - } - // This search doesn't use a query cache, results stored in search table. - else - { - $where_conditions = "t.tid IN (".$search['threads'].")"; - $query = $db->simple_select("threads t", "COUNT(t.tid) AS resultcount", $where_conditions. " AND {$unapproved_where} AND t.closed NOT LIKE 'moved|%' {$limitsql}"); - $count = $db->fetch_array($query); - - if(!$count['resultcount']) - { - error($lang->error_nosearchresults); - } - $threadcount = $count['resultcount']; - } - - $permsql = ""; - $onlyusfids = array(); - - // Check group permissions if we can't view threads not started by us - $group_permissions = forum_permissions(); - foreach($group_permissions as $fid => $forum_permissions) - { - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $fid; - } - } - if(!empty($onlyusfids)) - { - $permsql .= "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; - } - - $unsearchforums = get_unsearchable_forums(); - if($unsearchforums) - { - $permsql .= " AND t.fid NOT IN ($unsearchforums)"; - } - $inactiveforums = get_inactive_forums(); - if($inactiveforums) - { - $permsql .= " AND t.fid NOT IN ($inactiveforums)"; - } - - // Begin selecting matching threads, cache them. - $sqlarray = array( - 'order_by' => $sortfield, - 'order_dir' => $order, - 'limit_start' => $start, - 'limit' => $perpage - ); - $query = $db->query(" - SELECT t.*, u.username AS userusername - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=t.uid) - WHERE $where_conditions AND {$unapproved_where} {$permsql} AND t.closed NOT LIKE 'moved|%' - ORDER BY $sortfield $order - LIMIT $start, $perpage - "); - - $threadprefixes = build_prefixes(); - $thread_cache = array(); - while($thread = $db->fetch_array($query)) - { - $thread['threadprefix'] = ''; - if($thread['prefix'] && !empty($threadprefixes[$thread['prefix']])) - { - $thread['threadprefix'] = $threadprefixes[$thread['prefix']]['displaystyle']; - } - $thread_cache[$thread['tid']] = $thread; - } - $thread_ids = implode(",", array_keys($thread_cache)); - - if(empty($thread_ids)) - { - error($lang->error_nosearchresults); - } - - // Fetch dot icons if enabled - if($mybb->settings['dotfolders'] != 0 && $mybb->user['uid'] && $thread_cache) - { - $p_unapproved_where = str_replace('t.', '', $unapproved_where); - $query = $db->simple_select("posts", "DISTINCT tid,uid", "uid='{$mybb->user['uid']}' AND tid IN({$thread_ids}) AND {$p_unapproved_where}"); - while($thread = $db->fetch_array($query)) - { - $thread_cache[$thread['tid']]['dot_icon'] = 1; - } - } - - // Fetch the read threads. - if($mybb->user['uid'] && $mybb->settings['threadreadcut'] > 0) - { - $query = $db->simple_select("threadsread", "tid,dateline", "uid='".$mybb->user['uid']."' AND tid IN(".$thread_ids.")"); - while($readthread = $db->fetch_array($query)) - { - $thread_cache[$readthread['tid']]['lastread'] = $readthread['dateline']; - } - } - - if(!$mybb->settings['maxmultipagelinks']) - { - $mybb->settings['maxmultipagelinks'] = 5; - } - - $results = ''; - - foreach($thread_cache as $thread) - { - $bgcolor = alt_trow(); - $folder = ''; - $prefix = ''; - - // Unapproved colour - if($thread['visible'] == 0) - { - $bgcolor = 'trow_shaded'; - } - elseif($thread['visible'] == -1) - { - $bgcolor = 'trow_shaded trow_deleted'; - } - - if($thread['userusername']) - { - $thread['username'] = $thread['userusername']; - } - $thread['username'] = htmlspecialchars_uni($thread['username']); - $thread['profilelink'] = build_profile_link($thread['username'], $thread['uid']); - - // If this thread has a prefix, insert a space between prefix and subject - if($thread['prefix'] != 0) - { - $thread['threadprefix'] .= ' '; - } - - $thread['subject'] = $parser->parse_badwords($thread['subject']); - $thread['subject'] = htmlspecialchars_uni($thread['subject']); - - if(isset($icon_cache[$thread['icon']])) - { - $posticon = $icon_cache[$thread['icon']]; - $posticon['path'] = str_replace("{theme}", $theme['imgdir'], $posticon['path']); - $posticon['path'] = htmlspecialchars_uni($posticon['path']); - $posticon['name'] = htmlspecialchars_uni($posticon['name']); - eval("\$icon = \"".$templates->get("search_results_icon")."\";"); - } - else - { - $icon = " "; - } - if($thread['poll']) - { - $prefix = $lang->poll_prefix; - } - - // Determine the folder - $folder = ''; - $folder_label = ''; - if(isset($thread['dot_icon'])) - { - $folder = "dot_"; - $folder_label .= $lang->icon_dot; - } - $gotounread = ''; - $isnew = 0; - $donenew = 0; - $last_read = 0; - - if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid']) - { - $forum_read = $readforums[$thread['fid']]; - - $read_cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - if($forum_read == 0 || $forum_read < $read_cutoff) - { - $forum_read = $read_cutoff; - } - } - else - { - $forum_read = $forumsread[$thread['fid']]; - } - - if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid'] && $thread['lastpost'] > $forum_read) - { - if($thread['lastread']) - { - $last_read = $thread['lastread']; - } - else - { - $last_read = $read_cutoff; - } - } - else - { - $last_read = my_get_array_cookie("threadread", $thread['tid']); - } - - if($forum_read > $last_read) - { - $last_read = $forum_read; - } - - if($thread['lastpost'] > $last_read && $last_read) - { - $folder .= "new"; - $new_class = "subject_new"; - $folder_label .= $lang->icon_new; - $thread['newpostlink'] = get_thread_link($thread['tid'], 0, "newpost").$highlight; - eval("\$gotounread = \"".$templates->get("forumdisplay_thread_gotounread")."\";"); - $unreadpost = 1; - } - else - { - $new_class = 'subject_old'; - $folder_label .= $lang->icon_no_new; - } - - if($thread['replies'] >= $mybb->settings['hottopic'] || $thread['views'] >= $mybb->settings['hottopicviews']) - { - $folder .= "hot"; - $folder_label .= $lang->icon_hot; - } - if($thread['closed'] == 1) - { - $folder .= "lock"; - $folder_label .= $lang->icon_lock; - } - $folder .= "folder"; - - if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) - { - $mybb->settings['postsperpage'] = 20; - } - - $thread['pages'] = 0; - $thread['multipage'] = ''; - $threadpages = ''; - $morelink = ''; - $thread['posts'] = $thread['replies'] + 1; - if(is_moderator($thread['fid'], "canviewunapprove")) - { - $thread['posts'] += $thread['unapprovedposts']; - } - if(is_moderator($thread['fid'], "canviewdeleted")) - { - $thread['posts'] += $thread['deletedposts']; - } - - if($thread['posts'] > $mybb->settings['postsperpage']) - { - $thread['pages'] = $thread['posts'] / $mybb->settings['postsperpage']; - $thread['pages'] = ceil($thread['pages']); - if($thread['pages'] > $mybb->settings['maxmultipagelinks']) - { - $pagesstop = $mybb->settings['maxmultipagelinks'] - 1; - $page_link = get_thread_link($thread['tid'], $thread['pages']).$highlight; - eval("\$morelink = \"".$templates->get("forumdisplay_thread_multipage_more")."\";"); - } - else - { - $pagesstop = $thread['pages']; - } - for($i = 1; $i <= $pagesstop; ++$i) - { - $page_link = get_thread_link($thread['tid'], $i).$highlight; - eval("\$threadpages .= \"".$templates->get("forumdisplay_thread_multipage_page")."\";"); - } - eval("\$thread['multipage'] = \"".$templates->get("forumdisplay_thread_multipage")."\";"); - } - else - { - $threadpages = ''; - $morelink = ''; - $thread['multipage'] = ''; - } - $lastpostdate = my_date('relative', $thread['lastpost']); - $lastposter = htmlspecialchars_uni($thread['lastposter']); - $thread['lastpostlink'] = get_thread_link($thread['tid'], 0, "lastpost"); - $lastposteruid = $thread['lastposteruid']; - $thread_link = get_thread_link($thread['tid']); - - // Don't link to guest's profiles (they have no profile). - if($lastposteruid == 0) - { - $lastposterlink = $lastposter; - } - else - { - $lastposterlink = build_profile_link($lastposter, $lastposteruid); - } - - $thread['replies'] = my_number_format($thread['replies']); - $thread['views'] = my_number_format($thread['views']); - - $thread['forumlink'] = ''; - if($forumcache[$thread['fid']]) - { - $thread['forumlink_link'] = get_forum_link($thread['fid']); - $thread['forumlink_name'] = $forumcache[$thread['fid']]['name']; - eval("\$thread['forumlink'] = \"".$templates->get("search_results_threads_forumlink")."\";"); - } - - // If this user is the author of the thread and it is not closed or they are a moderator, they can edit - if(($thread['uid'] == $mybb->user['uid'] && $thread['closed'] != 1 && $mybb->user['uid'] != 0 && $fpermissions[$thread['fid']]['caneditposts'] == 1) || is_moderator($thread['fid'], "caneditposts")) - { - $inline_edit_class = "subject_editable"; - } - else - { - $inline_edit_class = ""; - } - - // If this thread has 1 or more attachments show the papperclip - if($mybb->settings['enableattachments'] == 1 && $thread['attachmentcount'] > 0) - { - if($thread['attachmentcount'] > 1) - { - $attachment_count = $lang->sprintf($lang->attachment_count_multiple, $thread['attachmentcount']); - } - else - { - $attachment_count = $lang->attachment_count; - } - - eval("\$attachment_count = \"".$templates->get("forumdisplay_thread_attachment_count")."\";"); - } - else - { - $attachment_count = ''; - } - - $inline_edit_tid = $thread['tid']; - - // Inline thread moderation - $inline_mod_checkbox = ''; - if($is_supermod || is_moderator($thread['fid'])) - { - if(isset($mybb->cookies[$inlinecookie]) && my_strpos($mybb->cookies[$inlinecookie], "|{$thread['tid']}|")) - { - $inlinecheck = "checked=\"checked\""; - ++$inlinecount; - } - else - { - $inlinecheck = ''; - } - eval("\$inline_mod_checkbox = \"".$templates->get("search_results_threads_inlinecheck")."\";"); - } - elseif($is_mod) - { - eval("\$inline_mod_checkbox = \"".$templates->get("search_results_threads_nocheck")."\";"); - } - - $plugins->run_hooks("search_results_thread"); - eval("\$results .= \"".$templates->get("search_results_threads_thread")."\";"); - } - if(!$results) - { - error($lang->error_nosearchresults); - } - $multipage = multipage($threadcount, $perpage, $page, "search.php?action=results&sid=$sid&sortby=$sortby&order=$order&uid=".$mybb->get_input('uid', MyBB::INPUT_INT)); - if($upper > $threadcount) - { - $upper = $threadcount; - } - - // Inline Thread Moderation Options - if($is_mod) - { - // If user has moderation tools available, prepare the Select All feature - $lang->page_selected = $lang->sprintf($lang->page_selected, count($thread_cache)); - $lang->all_selected = $lang->sprintf($lang->all_selected, (int)$threadcount); - $lang->select_all = $lang->sprintf($lang->select_all, (int)$threadcount); - eval("\$selectall = \"".$templates->get("search_threads_inlinemoderation_selectall")."\";"); - - $customthreadtools = ''; - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("modtools", "tid, name", "type='t' AND (','||forums||',' LIKE '%,-1,%' OR forums='')"); - break; - default: - $query = $db->simple_select("modtools", "tid, name", "type='t' AND (CONCAT(',',forums,',') LIKE '%,-1,%' OR forums='')"); - } - - while($tool = $db->fetch_array($query)) - { - eval("\$customthreadtools .= \"".$templates->get("search_results_threads_inlinemoderation_custom_tool")."\";"); - } - // Build inline moderation dropdown - if(!empty($customthreadtools)) - { - eval("\$customthreadtools = \"".$templates->get("search_results_threads_inlinemoderation_custom")."\";"); - } - eval("\$inlinemod = \"".$templates->get("search_results_threads_inlinemoderation")."\";"); - } - - $plugins->run_hooks("search_results_end"); - - eval("\$searchresults = \"".$templates->get("search_results_threads")."\";"); - output_page($searchresults); - } - else // Displaying results as posts - { - if(!$search['posts']) - { - error($lang->error_nosearchresults); - } - - $postcount = 0; - - // Moderators can view unapproved threads - $query = $db->simple_select("moderators", "fid, canviewunapprove, canviewdeleted", "(id='{$mybb->user['uid']}' AND isgroup='0') OR (id='{$mybb->user['usergroup']}' AND isgroup='1')"); - if($mybb->usergroup['issupermod'] == 1) - { - // Super moderators (and admins) - $unapproved_where = "visible >= -1"; - } - elseif($db->num_rows($query)) - { - // Normal moderators - $unapprove_forums = array(); - $deleted_forums = array(); - $unapproved_where = '(visible = 1'; - - while($moderator = $db->fetch_array($query)) - { - if($moderator['canviewunapprove'] == 1) - { - $unapprove_forums[] = $moderator['fid']; - } - - if($moderator['canviewdeleted'] == 1) - { - $deleted_forums[] = $moderator['fid']; - } - } - - if(!empty($unapprove_forums)) - { - $unapproved_where .= " OR (visible = 0 AND fid IN(".implode(',', $unapprove_forums)."))"; - } - if(!empty($deleted_forums)) - { - $unapproved_where .= " OR (visible = -1 AND fid IN(".implode(',', $deleted_forums)."))"; - } - $unapproved_where .= ')'; - } - else - { - // Normal users - $unapproved_where = 'visible = 1'; - } - - $post_cache_options = array(); - if((int)$mybb->settings['searchhardlimit'] > 0) - { - $post_cache_options['limit'] = (int)$mybb->settings['searchhardlimit']; - } - - if(strpos($sortfield, 'p.') !== false) - { - $post_cache_options['order_by'] = str_replace('p.', '', $sortfield); - $post_cache_options['order_dir'] = $order; - } - - $tids = array(); - $pids = array(); - // Make sure the posts we're viewing we have permission to view. - $query = $db->simple_select("posts", "pid, tid", "pid IN(".$db->escape_string($search['posts']).") AND {$unapproved_where}", $post_cache_options); - while($post = $db->fetch_array($query)) - { - $pids[$post['pid']] = $post['tid']; - $tids[$post['tid']][$post['pid']] = $post['pid']; - } - - if(!empty($pids)) - { - $temp_pids = array(); - - $group_permissions = forum_permissions(); - $permsql = ''; - $onlyusfids = array(); - - foreach($group_permissions as $fid => $forum_permissions) - { - if(!empty($forum_permissions['canonlyviewownthreads'])) - { - $onlyusfids[] = $fid; - } - } - - if($onlyusfids) - { - $permsql .= " OR (fid IN(".implode(',', $onlyusfids).") AND uid!={$mybb->user['uid']})"; - } - $unsearchforums = get_unsearchable_forums(); - if($unsearchforums) - { - $permsql .= " OR fid IN ($unsearchforums)"; - } - $inactiveforums = get_inactive_forums(); - if($inactiveforums) - { - $permsql .= " OR fid IN ($inactiveforums)"; - } - - // Check the thread records as well. If we don't have permissions, remove them from the listing. - $query = $db->simple_select("threads", "tid", "tid IN(".$db->escape_string(implode(',', $pids)).") AND ({$unapproved_where}{$permsql} OR closed LIKE 'moved|%')"); - while($thread = $db->fetch_array($query)) - { - if(array_key_exists($thread['tid'], $tids) != true) - { - $temp_pids = $tids[$thread['tid']]; - foreach($temp_pids as $pid) - { - unset($pids[$pid]); - unset($tids[$thread['tid']]); - } - } - } - unset($temp_pids); - } - - // Declare our post count - $postcount = count($pids); - - if(!$postcount) - { - error($lang->error_nosearchresults); - } - - // And now we have our sanatized post list - $search['posts'] = implode(',', array_keys($pids)); - - $tids = implode(",", array_keys($tids)); - - // Read threads - if($mybb->user['uid'] && $mybb->settings['threadreadcut'] > 0) - { - $query = $db->simple_select("threadsread", "tid, dateline", "uid='".$mybb->user['uid']."' AND tid IN(".$db->escape_string($tids).")"); - while($readthread = $db->fetch_array($query)) - { - $readthreads[$readthread['tid']] = $readthread['dateline']; - } - } - - $dot_icon = array(); - if($mybb->settings['dotfolders'] != 0 && $mybb->user['uid'] != 0) - { - $query = $db->simple_select("posts", "DISTINCT tid,uid", "uid='{$mybb->user['uid']}' AND tid IN({$db->escape_string($tids)}) AND {$unapproved_where}"); - while($post = $db->fetch_array($query)) - { - $dot_icon[$post['tid']] = true; - } - } - - $results = ''; - - $query = $db->query(" - SELECT p.*, u.username AS userusername, t.subject AS thread_subject, t.replies AS thread_replies, t.views AS thread_views, t.lastpost AS thread_lastpost, t.closed AS thread_closed, t.uid as thread_uid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE p.pid IN (".$db->escape_string($search['posts']).") - ORDER BY $sortfield $order - LIMIT $start, $perpage - "); - while($post = $db->fetch_array($query)) - { - $bgcolor = alt_trow(); - if($post['visible'] == 0) - { - $bgcolor = 'trow_shaded'; - } - elseif($post['visible'] == -1) - { - $bgcolor = 'trow_shaded trow_deleted'; - } - if($post['userusername']) - { - $post['username'] = $post['userusername']; - } - $post['username'] = htmlspecialchars_uni($post['username']); - $post['profilelink'] = build_profile_link($post['username'], $post['uid']); - $post['subject'] = $parser->parse_badwords($post['subject']); - $post['thread_subject'] = $parser->parse_badwords($post['thread_subject']); - $post['thread_subject'] = htmlspecialchars_uni($post['thread_subject']); - - if(isset($icon_cache[$post['icon']])) - { - $posticon = $icon_cache[$post['icon']]; - $posticon['path'] = str_replace("{theme}", $theme['imgdir'], $posticon['path']); - $posticon['path'] = htmlspecialchars_uni($posticon['path']); - $posticon['name'] = htmlspecialchars_uni($posticon['name']); - eval("\$icon = \"".$templates->get("search_results_icon")."\";"); - } - else - { - $icon = " "; - } - - $post['forumlink'] = ''; - if(!empty($forumcache[$thread['fid']])) - { - $post['forumlink_link'] = get_forum_link($post['fid']); - $post['forumlink_name'] = $forumcache[$post['fid']]['name']; - eval("\$post['forumlink'] = \"".$templates->get("search_results_posts_forumlink")."\";"); - } - - // Determine the folder - $folder = ''; - $folder_label = ''; - $gotounread = ''; - $isnew = 0; - $donenew = 0; - $last_read = 0; - $post['thread_lastread'] = $readthreads[$post['tid']]; - - if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid']) - { - $forum_read = $readforums[$post['fid']]; - - $read_cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - if($forum_read == 0 || $forum_read < $read_cutoff) - { - $forum_read = $read_cutoff; - } - } - else - { - $forum_read = $forumsread[$post['fid']]; - } - - if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid'] && $post['thread_lastpost'] > $forum_read) - { - $cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - if($post['thread_lastpost'] > $cutoff) - { - if($post['thread_lastread']) - { - $last_read = $post['thread_lastread']; - } - else - { - $last_read = 1; - } - } - } - - if(isset($dot_icon[$post['tid']])) - { - $folder = "dot_"; - $folder_label .= $lang->icon_dot; - } - - if(!$last_read) - { - $readcookie = $threadread = my_get_array_cookie("threadread", $post['tid']); - if($readcookie > $forum_read) - { - $last_read = $readcookie; - } - elseif($forum_read > $mybb->user['lastvisit']) - { - $last_read = $forum_read; - } - else - { - $last_read = $mybb->user['lastvisit']; - } - } - - if($post['thread_lastpost'] > $last_read && $last_read) - { - $folder .= "new"; - $folder_label .= $lang->icon_new; - eval("\$gotounread = \"".$templates->get("forumdisplay_thread_gotounread")."\";"); - $unreadpost = 1; - } - else - { - $folder_label .= $lang->icon_no_new; - } - - if($post['thread_replies'] >= $mybb->settings['hottopic'] || $post['thread_views'] >= $mybb->settings['hottopicviews']) - { - $folder .= "hot"; - $folder_label .= $lang->icon_hot; - } - if($post['thread_closed'] == 1) - { - $folder .= "lock"; - $folder_label .= $lang->icon_lock; - } - $folder .= "folder"; - - $post['thread_replies'] = my_number_format($post['thread_replies']); - $post['thread_views'] = my_number_format($post['thread_views']); - - $post['forumlink'] = ''; - if($forumcache[$post['fid']]) - { - $post['forumlink_link'] = get_forum_link($post['fid']); - $post['forumlink_name'] = $forumcache[$post['fid']]['name']; - eval("\$post['forumlink'] = \"".$templates->get("search_results_posts_forumlink")."\";"); - } - - if(!$post['subject']) - { - $post['subject'] = $post['message']; - } - if(my_strlen($post['subject']) > 50) - { - $post['subject'] = htmlspecialchars_uni(my_substr($post['subject'], 0, 50)."..."); - } - else - { - $post['subject'] = htmlspecialchars_uni($post['subject']); - } - // What we do here is parse the post using our post parser, then strip the tags from it - $parser_options = array( - 'allow_html' => 0, - 'allow_mycode' => 1, - 'allow_smilies' => 0, - 'allow_imgcode' => 0, - 'filter_badwords' => 1 - ); - $post['message'] = strip_tags($parser->parse_message($post['message'], $parser_options)); - if(my_strlen($post['message']) > 200) - { - $prev = my_substr($post['message'], 0, 200)."..."; - } - else - { - $prev = $post['message']; - } - $posted = my_date('relative', $post['dateline']); - - $thread_url = get_thread_link($post['tid']); - $post_url = get_post_link($post['pid'], $post['tid']); - - // Inline post moderation - $inline_mod_checkbox = ''; - if($is_supermod || is_moderator($post['fid'])) - { - if(isset($mybb->cookies[$inlinecookie]) && my_strpos($mybb->cookies[$inlinecookie], "|{$post['pid']}|")) - { - $inlinecheck = "checked=\"checked\""; - ++$inlinecount; - } - else - { - $inlinecheck = ''; - } - eval("\$inline_mod_checkbox = \"".$templates->get("search_results_posts_inlinecheck")."\";"); - } - elseif($is_mod) - { - eval("\$inline_mod_checkbox = \"".$templates->get("search_results_posts_nocheck")."\";"); - } - - $plugins->run_hooks("search_results_post"); - eval("\$results .= \"".$templates->get("search_results_posts_post")."\";"); - } - if(!$results) - { - error($lang->error_nosearchresults); - } - $multipage = multipage($postcount, $perpage, $page, "search.php?action=results&sid=".htmlspecialchars_uni($mybb->get_input('sid'))."&sortby=$sortby&order=$order&uid=".$mybb->get_input('uid', MyBB::INPUT_INT)); - if($upper > $postcount) - { - $upper = $postcount; - } - - // Inline Post Moderation Options - if($is_mod) - { - // If user has moderation tools available, prepare the Select All feature - $num_results = $db->num_rows($query); - $lang->page_selected = $lang->sprintf($lang->page_selected, (int)$num_results); - $lang->select_all = $lang->sprintf($lang->select_all, (int)$postcount); - $lang->all_selected = $lang->sprintf($lang->all_selected, (int)$postcount); - eval("\$selectall = \"".$templates->get("search_posts_inlinemoderation_selectall")."\";"); - - $customthreadtools = $customposttools = ''; - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->simple_select("modtools", "tid, name, type", "type='p' AND (','||forums||',' LIKE '%,-1,%' OR forums='')"); - break; - default: - $query = $db->simple_select("modtools", "tid, name, type", "type='p' AND (CONCAT(',',forums,',') LIKE '%,-1,%' OR forums='')"); - } - - while($tool = $db->fetch_array($query)) - { - eval("\$customposttools .= \"".$templates->get("search_results_posts_inlinemoderation_custom_tool")."\";"); - } - // Build inline moderation dropdown - if(!empty($customposttools)) - { - eval("\$customposttools = \"".$templates->get("search_results_posts_inlinemoderation_custom")."\";"); - } - eval("\$inlinemod = \"".$templates->get("search_results_posts_inlinemoderation")."\";"); - } - - $plugins->run_hooks("search_results_end"); - - eval("\$searchresults = \"".$templates->get("search_results_posts")."\";"); - output_page($searchresults); - } -} -elseif($mybb->input['action'] == "findguest") -{ - $where_sql = "uid='0'"; - - $unsearchforums = get_unsearchable_forums(); - if($unsearchforums) - { - $where_sql .= " AND fid NOT IN ($unsearchforums)"; - } - $inactiveforums = get_inactive_forums(); - if($inactiveforums) - { - $where_sql .= " AND fid NOT IN ($inactiveforums)"; - } - - $permsql = ""; - $onlyusfids = array(); - - // Check group permissions if we can't view threads not started by us - $group_permissions = forum_permissions(); - foreach($group_permissions as $fid => $forum_permissions) - { - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $fid; - } - } - if(!empty($onlyusfids)) - { - $where_sql .= " AND fid NOT IN(".implode(',', $onlyusfids).")"; - } - - $options = array( - 'order_by' => 'dateline', - 'order_dir' => 'desc' - ); - - // Do we have a hard search limit? - if($mybb->settings['searchhardlimit'] > 0) - { - $options['limit'] = (int)$mybb->settings['searchhardlimit']; - } - - $pids = ''; - $comma = ''; - $query = $db->simple_select("posts", "pid", "{$where_sql}", $options); - while($pid = $db->fetch_field($query, "pid")) - { - $pids .= $comma.$pid; - $comma = ','; - } - - $tids = ''; - $comma = ''; - $query = $db->simple_select("threads", "tid", $where_sql); - while($tid = $db->fetch_field($query, "tid")) - { - $tids .= $comma.$tid; - $comma = ','; - } - - $sid = md5(uniqid(microtime(), true)); - $searcharray = array( - "sid" => $db->escape_string($sid), - "uid" => $mybb->user['uid'], - "dateline" => TIME_NOW, - "ipaddress" => $db->escape_binary($session->packedip), - "threads" => $db->escape_string($tids), - "posts" => $db->escape_string($pids), - "resulttype" => "posts", - "querycache" => '', - "keywords" => '' - ); - $plugins->run_hooks("search_do_search_process"); - $db->insert_query("searchlog", $searcharray); - redirect("search.php?action=results&sid=".$sid, $lang->redirect_searchresults); -} -elseif($mybb->input['action'] == "finduser") -{ - $where_sql = "uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"; - - $unsearchforums = get_unsearchable_forums(); - if($unsearchforums) - { - $where_sql .= " AND fid NOT IN ($unsearchforums)"; - } - $inactiveforums = get_inactive_forums(); - if($inactiveforums) - { - $where_sql .= " AND fid NOT IN ($inactiveforums)"; - } - - $permsql = ""; - $onlyusfids = array(); - - // Check group permissions if we can't view threads not started by us - $group_permissions = forum_permissions(); - foreach($group_permissions as $fid => $forum_permissions) - { - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $fid; - } - } - if(!empty($onlyusfids)) - { - $where_sql .= "AND ((fid IN(".implode(',', $onlyusfids).") AND uid='{$mybb->user['uid']}') OR fid NOT IN(".implode(',', $onlyusfids)."))"; - } - - $options = array( - 'order_by' => 'dateline', - 'order_dir' => 'desc' - ); - - // Do we have a hard search limit? - if($mybb->settings['searchhardlimit'] > 0) - { - $options['limit'] = (int)$mybb->settings['searchhardlimit']; - } - - $pids = ''; - $comma = ''; - $query = $db->simple_select("posts", "pid", "{$where_sql}", $options); - while($pid = $db->fetch_field($query, "pid")) - { - $pids .= $comma.$pid; - $comma = ','; - } - - $tids = ''; - $comma = ''; - $query = $db->simple_select("threads", "tid", $where_sql); - while($tid = $db->fetch_field($query, "tid")) - { - $tids .= $comma.$tid; - $comma = ','; - } - - $sid = md5(uniqid(microtime(), true)); - $searcharray = array( - "sid" => $db->escape_string($sid), - "uid" => $mybb->user['uid'], - "dateline" => TIME_NOW, - "ipaddress" => $db->escape_binary($session->packedip), - "threads" => $db->escape_string($tids), - "posts" => $db->escape_string($pids), - "resulttype" => "posts", - "querycache" => '', - "keywords" => '' - ); - $plugins->run_hooks("search_do_search_process"); - $db->insert_query("searchlog", $searcharray); - redirect("search.php?action=results&sid=".$sid, $lang->redirect_searchresults); -} -elseif($mybb->input['action'] == "finduserthreads") -{ - $where_sql = "t.uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"; - - $unsearchforums = get_unsearchable_forums(); - if($unsearchforums) - { - $where_sql .= " AND t.fid NOT IN ($unsearchforums)"; - } - $inactiveforums = get_inactive_forums(); - if($inactiveforums) - { - $where_sql .= " AND t.fid NOT IN ($inactiveforums)"; - } - - $permsql = ""; - $onlyusfids = array(); - - // Check group permissions if we can't view threads not started by us - $group_permissions = forum_permissions(); - foreach($group_permissions as $fid => $forum_permissions) - { - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $fid; - } - } - if(!empty($onlyusfids)) - { - $where_sql .= "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; - } - - $sid = md5(uniqid(microtime(), true)); - $searcharray = array( - "sid" => $db->escape_string($sid), - "uid" => $mybb->user['uid'], - "dateline" => TIME_NOW, - "ipaddress" => $db->escape_binary($session->packedip), - "threads" => '', - "posts" => '', - "resulttype" => "threads", - "querycache" => $db->escape_string($where_sql), - "keywords" => '' - ); - $plugins->run_hooks("search_do_search_process"); - $db->insert_query("searchlog", $searcharray); - redirect("search.php?action=results&sid=".$sid, $lang->redirect_searchresults); -} -elseif($mybb->input['action'] == "getnew") -{ - - $where_sql = "t.lastpost >= '".(int)$mybb->user['lastvisit']."'"; - - if($mybb->get_input('fid', MyBB::INPUT_INT)) - { - $where_sql .= " AND t.fid='".$mybb->get_input('fid', MyBB::INPUT_INT)."'"; - } - else if($mybb->get_input('fids')) - { - $fids = explode(',', $mybb->get_input('fids')); - foreach($fids as $key => $fid) - { - $fids[$key] = (int)$fid; - } - - if(!empty($fids)) - { - $where_sql .= " AND t.fid IN (".implode(',', $fids).")"; - } - } - - $unsearchforums = get_unsearchable_forums(); - if($unsearchforums) - { - $where_sql .= " AND t.fid NOT IN ($unsearchforums)"; - } - $inactiveforums = get_inactive_forums(); - if($inactiveforums) - { - $where_sql .= " AND t.fid NOT IN ($inactiveforums)"; - } - - $permsql = ""; - $onlyusfids = array(); - - // Check group permissions if we can't view threads not started by us - $group_permissions = forum_permissions(); - foreach($group_permissions as $fid => $forum_permissions) - { - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $fid; - } - } - if(!empty($onlyusfids)) - { - $where_sql .= "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; - } - - $sid = md5(uniqid(microtime(), true)); - $searcharray = array( - "sid" => $db->escape_string($sid), - "uid" => $mybb->user['uid'], - "dateline" => TIME_NOW, - "ipaddress" => $db->escape_binary($session->packedip), - "threads" => '', - "posts" => '', - "resulttype" => "threads", - "querycache" => $db->escape_string($where_sql), - "keywords" => '' - ); - - $plugins->run_hooks("search_do_search_process"); - $db->insert_query("searchlog", $searcharray); - redirect("search.php?action=results&sid=".$sid, $lang->redirect_searchresults); -} -elseif($mybb->input['action'] == "getdaily") -{ - if($mybb->get_input('days', MyBB::INPUT_INT) < 1) - { - $days = 1; - } - else - { - $days = $mybb->get_input('days', MyBB::INPUT_INT); - } - $datecut = TIME_NOW-(86400*$days); - - $where_sql = "t.lastpost >='".$datecut."'"; - - if($mybb->get_input('fid', MyBB::INPUT_INT)) - { - $where_sql .= " AND t.fid='".$mybb->get_input('fid', MyBB::INPUT_INT)."'"; - } - else if($mybb->get_input('fids')) - { - $fids = explode(',', $mybb->get_input('fids')); - foreach($fids as $key => $fid) - { - $fids[$key] = (int)$fid; - } - - if(!empty($fids)) - { - $where_sql .= " AND t.fid IN (".implode(',', $fids).")"; - } - } - - $unsearchforums = get_unsearchable_forums(); - if($unsearchforums) - { - $where_sql .= " AND t.fid NOT IN ($unsearchforums)"; - } - $inactiveforums = get_inactive_forums(); - if($inactiveforums) - { - $where_sql .= " AND t.fid NOT IN ($inactiveforums)"; - } - - $permsql = ""; - $onlyusfids = array(); - - // Check group permissions if we can't view threads not started by us - $group_permissions = forum_permissions(); - foreach($group_permissions as $fid => $forum_permissions) - { - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $fid; - } - } - if(!empty($onlyusfids)) - { - $where_sql .= "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; - } - - $sid = md5(uniqid(microtime(), true)); - $searcharray = array( - "sid" => $db->escape_string($sid), - "uid" => $mybb->user['uid'], - "dateline" => TIME_NOW, - "ipaddress" => $db->escape_binary($session->packedip), - "threads" => '', - "posts" => '', - "resulttype" => "threads", - "querycache" => $db->escape_string($where_sql), - "keywords" => '' - ); - - $plugins->run_hooks("search_do_search_process"); - $db->insert_query("searchlog", $searcharray); - redirect("search.php?action=results&sid=".$sid, $lang->redirect_searchresults); -} -elseif($mybb->input['action'] == "do_search" && $mybb->request_method == "post") -{ - $plugins->run_hooks("search_do_search_start"); - - // Check if search flood checking is enabled and user is not admin - if($mybb->settings['searchfloodtime'] > 0 && $mybb->usergroup['cancp'] != 1) - { - // Fetch the time this user last searched - if($mybb->user['uid']) - { - $conditions = "uid='{$mybb->user['uid']}'"; - } - else - { - $conditions = "uid='0' AND ipaddress=".$db->escape_binary($session->packedip); - } - $timecut = TIME_NOW-$mybb->settings['searchfloodtime']; - $query = $db->simple_select("searchlog", "*", "$conditions AND dateline > '$timecut'", array('order_by' => "dateline", 'order_dir' => "DESC")); - $last_search = $db->fetch_array($query); - // Users last search was within the flood time, show the error - if($last_search['sid']) - { - $remaining_time = $mybb->settings['searchfloodtime']-(TIME_NOW-$last_search['dateline']); - if($remaining_time == 1) - { - $lang->error_searchflooding = $lang->sprintf($lang->error_searchflooding_1, $mybb->settings['searchfloodtime']); - } - else - { - $lang->error_searchflooding = $lang->sprintf($lang->error_searchflooding, $mybb->settings['searchfloodtime'], $remaining_time); - } - error($lang->error_searchflooding); - } - } - if($mybb->get_input('showresults') == "threads") - { - $resulttype = "threads"; - } - else - { - $resulttype = "posts"; - } - - $search_data = array( - "keywords" => $mybb->input['keywords'], - "author" => $mybb->get_input('author'), - "postthread" => $mybb->get_input('postthread', MyBB::INPUT_INT), - "matchusername" => $mybb->get_input('matchusername', MyBB::INPUT_INT), - "postdate" => $mybb->get_input('postdate', MyBB::INPUT_INT), - "pddir" => $mybb->get_input('pddir', MyBB::INPUT_INT), - "forums" => $mybb->input['forums'], - "findthreadst" => $mybb->get_input('findthreadst', MyBB::INPUT_INT), - "numreplies" => $mybb->get_input('numreplies', MyBB::INPUT_INT), - "threadprefix" => $mybb->get_input('threadprefix', MyBB::INPUT_ARRAY) - ); - - if(is_moderator() && !empty($mybb->input['visible'])) - { - $search_data['visible'] = $mybb->get_input('visible', MyBB::INPUT_INT); - } - - if($db->can_search == true) - { - if($mybb->settings['searchtype'] == "fulltext" && $db->supports_fulltext_boolean("posts") && $db->is_fulltext("posts")) - { - $search_results = perform_search_mysql_ft($search_data); - } - else - { - $search_results = perform_search_mysql($search_data); - } - } - else - { - error($lang->error_no_search_support); - } - $sid = md5(uniqid(microtime(), true)); - $searcharray = array( - "sid" => $db->escape_string($sid), - "uid" => $mybb->user['uid'], - "dateline" => $now, - "ipaddress" => $db->escape_binary($session->packedip), - "threads" => $search_results['threads'], - "posts" => $search_results['posts'], - "resulttype" => $resulttype, - "querycache" => $search_results['querycache'], - "keywords" => $db->escape_string($mybb->input['keywords']), - ); - $plugins->run_hooks("search_do_search_process"); - - $db->insert_query("searchlog", $searcharray); - - if(my_strtolower($mybb->get_input('sortordr')) == "asc" || my_strtolower($mybb->get_input('sortordr') == "desc")) - { - $sortorder = $mybb->get_input('sortordr'); - } - else - { - $sortorder = "desc"; - } - $sortby = htmlspecialchars_uni($mybb->get_input('sortby')); - $plugins->run_hooks("search_do_search_end"); - redirect("search.php?action=results&sid=".$sid."&sortby=".$sortby."&order=".$sortorder, $lang->redirect_searchresults); -} -else if($mybb->input['action'] == "thread") -{ - // Fetch thread info - $thread = get_thread($mybb->get_input('tid', MyBB::INPUT_INT)); - $ismod = is_moderator($thread['fid']); - - if(!$thread || ($thread['visible'] != 1 && $ismod == false && ($thread['visible'] != -1 || $mybb->settings['soft_delete'] != 1 || !$mybb->user['uid'] || $mybb->user['uid'] != $thread['uid'])) || ($thread['visible'] > 1 && $ismod == true)) - { - error($lang->error_invalidthread); - } - - // Get forum info - $forum = get_forum($thread['fid']); - if(!$forum) - { - error($lang->error_invalidforum); - } - - $forum_permissions = forum_permissions($forum['fid']); - - if($forum['open'] == 0 || $forum['type'] != "f") - { - error($lang->error_closedinvalidforum); - } - if($forum_permissions['canview'] == 0 || $forum_permissions['canviewthreads'] != 1 || (isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] != 0 && $thread['uid'] != $mybb->user['uid'])) - { - error_no_permission(); - } - - $plugins->run_hooks("search_thread_start"); - - // Check if search flood checking is enabled and user is not admin - if($mybb->settings['searchfloodtime'] > 0 && $mybb->usergroup['cancp'] != 1) - { - // Fetch the time this user last searched - if($mybb->user['uid']) - { - $conditions = "uid='{$mybb->user['uid']}'"; - } - else - { - $conditions = "uid='0' AND ipaddress=".$db->escape_binary($session->packedip); - } - $timecut = TIME_NOW-$mybb->settings['searchfloodtime']; - $query = $db->simple_select("searchlog", "*", "$conditions AND dateline > '$timecut'", array('order_by' => "dateline", 'order_dir' => "DESC")); - $last_search = $db->fetch_array($query); - - // We shouldn't show remaining time if time is 0 or under. - $remaining_time = $mybb->settings['searchfloodtime']-(TIME_NOW-$last_search['dateline']); - // Users last search was within the flood time, show the error. - if($last_search['sid'] && $remaining_time > 0) - { - if($remaining_time == 1) - { - $lang->error_searchflooding = $lang->sprintf($lang->error_searchflooding_1, $mybb->settings['searchfloodtime']); - } - else - { - $lang->error_searchflooding = $lang->sprintf($lang->error_searchflooding, $mybb->settings['searchfloodtime'], $remaining_time); - } - error($lang->error_searchflooding); - } - } - - $search_data = array( - "keywords" => $mybb->input['keywords'], - "postthread" => 1, - "tid" => $mybb->get_input('tid', MyBB::INPUT_INT) - ); - - if($db->can_search == true) - { - if($mybb->settings['searchtype'] == "fulltext" && $db->supports_fulltext_boolean("posts") && $db->is_fulltext("posts")) - { - $search_results = perform_search_mysql_ft($search_data); - } - else - { - $search_results = perform_search_mysql($search_data); - } - } - else - { - error($lang->error_no_search_support); - } - $sid = md5(uniqid(microtime(), true)); - $searcharray = array( - "sid" => $db->escape_string($sid), - "uid" => $mybb->user['uid'], - "dateline" => $now, - "ipaddress" => $db->escape_binary($session->packedip), - "threads" => $search_results['threads'], - "posts" => $search_results['posts'], - "resulttype" => 'posts', - "querycache" => $search_results['querycache'], - "keywords" => $db->escape_string($mybb->input['keywords']) - ); - $plugins->run_hooks("search_thread_process"); - - $db->insert_query("searchlog", $searcharray); - - $plugins->run_hooks("search_do_search_end"); - redirect("search.php?action=results&sid=".$sid, $lang->redirect_searchresults); -} -else -{ - $plugins->run_hooks("search_start"); - $srchlist = make_searchable_forums(); - $prefixselect = build_prefix_select('all', 'any', 1); - - $rowspan = 5; - - $moderator_options = ''; - if(is_moderator()) - { - $rowspan += 2; - eval("\$moderator_options = \"".$templates->get("search_moderator_options")."\";"); - } - - $plugins->run_hooks("search_end"); - - eval("\$search = \"".$templates->get("search")."\";"); - output_page($search); -} - - diff --git a/html/forums/sendthread.php b/html/forums/sendthread.php deleted file mode 100644 index 236b68f..0000000 --- a/html/forums/sendthread.php +++ /dev/null @@ -1,294 +0,0 @@ -load("sendthread"); - -// Get thread info -$tid = $mybb->get_input('tid', MyBB::INPUT_INT); -$thread = get_thread($tid); - -// Invalid thread -if(!$thread || $thread['visible'] != 1) -{ - error($lang->error_invalidthread); -} - -// Get thread prefix -$breadcrumbprefix = ''; -$threadprefix = array('prefix' => ''); -if($thread['prefix']) -{ - $threadprefix = build_prefixes($thread['prefix']); - if(!empty($threadprefix['displaystyle'])) - { - $breadcrumbprefix = $threadprefix['displaystyle'].' '; - } -} - -$thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); - -// Make navigation -build_forum_breadcrumb($thread['fid']); -add_breadcrumb($breadcrumbprefix.$thread['subject'], get_thread_link($thread['tid'])); -add_breadcrumb($lang->nav_sendthread); - -// Get forum info -$forum = get_forum($thread['fid']); -$forumpermissions = forum_permissions($forum['fid']); - -// Invalid forum? -if(!$forum['fid'] || $forum['type'] != "f") -{ - error($lang->error_invalidforum); -} - -// This user can't view this forum or this thread -if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0 || (isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0 && $thread['uid'] != $mybb->user['uid'])) -{ - error_no_permission(); -} - -// Check if this forum is password protected and we have a valid password -check_forum_password($forum['fid']); - -if($mybb->usergroup['cansendemail'] == 0) -{ - error_no_permission(); -} - -// Check group limits -if($mybb->usergroup['maxemails'] > 0) -{ - if($mybb->user['uid'] > 0) - { - $user_check = "fromuid='{$mybb->user['uid']}'"; - } - else - { - $user_check = "ipaddress=".$db->escape_binary($session->packedip); - } - - $query = $db->simple_select("maillogs", "COUNT(*) AS sent_count", "{$user_check} AND dateline >= '".(TIME_NOW - (60*60*24))."'"); - $sent_count = $db->fetch_field($query, "sent_count"); - if($sent_count >= $mybb->usergroup['maxemails']) - { - $lang->error_max_emails_day = $lang->sprintf($lang->error_max_emails_day, $mybb->usergroup['maxemails']); - error($lang->error_max_emails_day); - } -} - -// Check email flood control -if($mybb->usergroup['emailfloodtime'] > 0) -{ - if($mybb->user['uid'] > 0) - { - $user_check = "fromuid='{$mybb->user['uid']}'"; - } - else - { - $user_check = "ipaddress=".$db->escape_binary($session->packedip); - } - - $timecut = TIME_NOW-$mybb->usergroup['emailfloodtime']*60; - - $query = $db->simple_select("maillogs", "mid, dateline", "{$user_check} AND dateline > '{$timecut}'", array('order_by' => "dateline", 'order_dir' => "DESC")); - $last_email = $db->fetch_array($query); - - // Users last email was within the flood time, show the error - if($last_email['mid']) - { - $remaining_time = ($mybb->usergroup['emailfloodtime']*60)-(TIME_NOW-$last_email['dateline']); - - if($remaining_time == 1) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_1_second, $mybb->usergroup['emailfloodtime']); - } - elseif($remaining_time < 60) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_seconds, $mybb->usergroup['emailfloodtime'], $remaining_time); - } - elseif($remaining_time > 60 && $remaining_time < 120) - { - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_1_minute, $mybb->usergroup['emailfloodtime']); - } - else - { - $remaining_time_minutes = ceil($remaining_time/60); - $lang->error_emailflooding = $lang->sprintf($lang->error_emailflooding_minutes, $mybb->usergroup['emailfloodtime'], $remaining_time_minutes); - } - - error($lang->error_emailflooding); - } -} - -$errors = array(); - -$mybb->input['action'] = $mybb->get_input('action'); -if($mybb->input['action'] == "do_sendtofriend" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->input['my_post_key']); - - $plugins->run_hooks("sendthread_do_sendtofriend_start"); - - if(!validate_email_format($mybb->input['email'])) - { - $errors[] = $lang->error_invalidemail; - } - - if($mybb->user['uid']) - { - $mybb->input['fromemail'] = $mybb->user['email']; - $mybb->input['fromname'] = $mybb->user['username']; - } - - if(!validate_email_format($mybb->input['fromemail'])) - { - $errors[] = $lang->error_invalidfromemail; - } - - if(empty($mybb->input['fromname'])) - { - $errors[] = $lang->error_noname; - } - - if(empty($mybb->input['subject'])) - { - $errors[] = $lang->error_nosubject; - } - - if(empty($mybb->input['message'])) - { - $errors[] = $lang->error_nomessage; - } - - if($mybb->settings['captchaimage'] && $mybb->user['uid'] == 0) - { - require_once MYBB_ROOT.'inc/class_captcha.php'; - $captcha = new captcha; - - if($captcha->validate_captcha() == false) - { - // CAPTCHA validation failed - foreach($captcha->get_errors() as $error) - { - $errors[] = $error; - } - } - } - - // No errors detected - if(count($errors) == 0) - { - if($mybb->settings['mail_handler'] == 'smtp') - { - $from = $mybb->input['fromemail']; - } - else - { - $from = "{$mybb->input['fromname']} <{$mybb->input['fromemail']}>"; - } - - $threadlink = get_thread_link($thread['tid']); - - $message = $lang->sprintf($lang->email_sendtofriend, $mybb->input['fromname'], $mybb->settings['bbname'], $mybb->settings['bburl']."/".$threadlink, $mybb->input['message']); - - // Send the actual message - my_mail($mybb->input['email'], $mybb->input['subject'], $message, $from, "", "", false, "text", "", $mybb->input['fromemail']); - - if($mybb->settings['mail_logging'] > 0) - { - // Log the message - $log_entry = array( - "subject" => $db->escape_string($mybb->input['subject']), - "message" => $db->escape_string($message), - "dateline" => TIME_NOW, - "fromuid" => $mybb->user['uid'], - "fromemail" => $db->escape_string($mybb->input['fromemail']), - "touid" => 0, - "toemail" => $db->escape_string($mybb->input['email']), - "tid" => $thread['tid'], - "ipaddress" => $db->escape_binary($session->packedip), - "type" => 2 - ); - $db->insert_query("maillogs", $log_entry); - } - - $plugins->run_hooks("sendthread_do_sendtofriend_end"); - redirect(get_thread_link($thread['tid']), $lang->redirect_emailsent); - } - else - { - $mybb->input['action'] = ''; - } -} - -if(!$mybb->input['action']) -{ - $plugins->run_hooks("sendthread_start"); - - // Do we have some errors? - if(count($errors) >= 1) - { - $errors = inline_error($errors); - $email = htmlspecialchars_uni($mybb->input['email']); - $fromname = htmlspecialchars_uni($mybb->input['fromname']); - $fromemail = htmlspecialchars_uni($mybb->input['fromemail']); - $subject = htmlspecialchars_uni($mybb->input['subject']); - $message = htmlspecialchars_uni($mybb->input['message']); - } - else - { - $errors = ''; - $email = ''; - $fromname = ''; - $fromemail = ''; - $subject = $lang->sprintf($lang->emailsubject_sendtofriend, $mybb->settings['bbname']); - $message = ''; - } - - // Generate CAPTCHA? - if($mybb->settings['captchaimage'] && $mybb->user['uid'] == 0) - { - require_once MYBB_ROOT.'inc/class_captcha.php'; - $post_captcha = new captcha(true, "post_captcha"); - - if($post_captcha->html) - { - $captcha = $post_captcha->html; - } - } - else - { - $captcha = ''; - } - - $from_email = ''; - if($mybb->user['uid'] == 0) - { - eval("\$from_email = \"".$templates->get("sendthread_fromemail")."\";"); - } - - $plugins->run_hooks("sendthread_end"); - - eval("\$sendtofriend = \"".$templates->get("sendthread")."\";"); - output_page($sendtofriend); -} diff --git a/html/forums/showteam.php b/html/forums/showteam.php deleted file mode 100644 index 5442b8b..0000000 --- a/html/forums/showteam.php +++ /dev/null @@ -1,208 +0,0 @@ -load('showteam'); - -add_breadcrumb($lang->nav_showteam); - -$plugins->run_hooks('showteam_start'); - -$timecut = TIME_NOW - $mybb->settings['wolcutoff']; - -$usergroups = array(); -$moderators = array(); -$users = array(); - -// Fetch the list of groups which are to be shown on the page -$query = $db->simple_select("usergroups", "gid, title, usertitle", "showforumteam=1", array('order_by' => 'disporder')); -while($usergroup = $db->fetch_array($query)) -{ - $usergroups[$usergroup['gid']] = $usergroup; -} - -if(empty($usergroups)) -{ - error($lang->error_noteamstoshow); -} - -// Fetch specific forum moderator details -if($usergroups[6]['gid']) -{ - $query = $db->query(" - SELECT m.*, f.name - FROM ".TABLE_PREFIX."moderators m - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=m.id) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=m.fid) - WHERE f.active = 1 AND m.isgroup = 0 - ORDER BY u.username - "); - while($moderator = $db->fetch_array($query)) - { - $moderators[$moderator['id']][] = $moderator; - } -} - -// Now query the users of those specific groups -$groups_in = implode(",", array_keys($usergroups)); -$users_in = implode(",", array_keys($moderators)); -if(!$groups_in) -{ - $groups_in = 0; -} -if(!$users_in) -{ - $users_in = 0; -} -$forum_permissions = forum_permissions(); - -$query = $db->simple_select("users", "uid, username, displaygroup, usergroup, ignorelist, hideemail, receivepms, lastactive, lastvisit, invisible, away", "displaygroup IN ($groups_in) OR (displaygroup='0' AND usergroup IN ($groups_in)) OR uid IN ($users_in)", array('order_by' => 'username')); -while($user = $db->fetch_array($query)) -{ - // If this user is a moderator - if(isset($moderators[$user['uid']])) - { - foreach($moderators[$user['uid']] as $forum) - { - if($forum_permissions[$forum['fid']]['canview'] == 1) - { - $forum_url = get_forum_link($forum['fid']); - eval("\$forumlist .= \"".$templates->get("showteam_moderators_forum")."\";"); - } - } - $user['forumlist'] = $forumlist; - $forumlist = ''; - $usergroups[6]['user_list'][$user['uid']] = $user; - } - - if($user['displaygroup'] == '6' || $user['usergroup'] == '6') - { - $usergroups[6]['user_list'][$user['uid']] = $user; - } - - // Are they also in another group which is being shown on the list? - if($user['displaygroup'] != 0) - { - $group = $user['displaygroup']; - } - else - { - $group = $user['usergroup']; - } - - if($usergroups[$group] && $group != 6) - { - $usergroups[$group]['user_list'][$user['uid']] = $user; - } -} - -// Now we have all of our user details we can display them. -$grouplist = ''; -foreach($usergroups as $usergroup) -{ - $usergrouprows = $modrows = ''; - - // If we have no users - don't show this group - if(!isset($usergroup['user_list'])) - { - continue; - } - - $bgcolor = ''; - foreach($usergroup['user_list'] as $user) - { - $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); - $user['profilelink'] = get_profile_link($user['uid']); - - // For the postbit templates - $post['uid'] = $user['uid']; - $emailcode = $pmcode = ''; - if($user['hideemail'] != 1) - { - eval("\$emailcode = \"".$templates->get("postbit_email")."\";"); - } - - if($user['receivepms'] != 0 && $mybb->settings['enablepms'] != 0 && my_strpos(",".$user['ignorelist'].",", ",".$mybb->user['uid'].",") === false) - { - eval("\$pmcode = \"".$templates->get("postbit_pm")."\";"); - } - - // For the online image - if($user['lastactive'] > $timecut && ($user['invisible'] == 0 || $mybb->usergroup['canviewwolinvis'] == 1) && $user['lastvisit'] != $user['lastactive']) - { - $status = "online"; - } - elseif($user['away'] == 1 && $mybb->settings['allowaway'] != 0) - { - $status = "away"; - } - else - { - $status = "offline"; - } - - if($user['invisible'] == 1 && $mybb->usergroup['canviewwolinvis'] != 1 && $user['uid'] != $mybb->user['uid']) - { - if($user['lastactive']) - { - $user['lastvisit'] = $lang->lastvisit_hidden; - } - else - { - $user['lastvisit'] = $lang->lastvisit_never; - } - } - else - { - $user['lastvisit'] = my_date('relative', $user['lastactive']); - } - - $bgcolor = alt_trow(); - - $plugins->run_hooks('showteam_user'); - - // If the current group is a moderator group - if($usergroup['gid'] == 6 && !empty($user['forumlist'])) - { - $forumslist = $user['forumlist']; - eval("\$modrows .= \"".$templates->get("showteam_moderators_mod")."\";"); - } - else - { - eval("\$usergrouprows .= \"".$templates->get("showteam_usergroup_user")."\";"); - } - } - - if($modrows && $usergroup['gid'] == 6) - { - eval("\$grouplist .= \"".$templates->get("showteam_moderators")."\";"); - } - - if($usergrouprows) - { - eval("\$grouplist .= \"".$templates->get("showteam_usergroup")."\";"); - } -} - -if(empty($grouplist)) -{ - error($lang->error_noteamstoshow); -} - -$plugins->run_hooks("showteam_end"); - -eval("\$showteam = \"".$templates->get("showteam")."\";"); -output_page($showteam); diff --git a/html/forums/showthread.php b/html/forums/showthread.php deleted file mode 100644 index 89ea001..0000000 --- a/html/forums/showthread.php +++ /dev/null @@ -1,1584 +0,0 @@ -load("showthread"); - -// If there is no tid but a pid, trick the system into thinking there was a tid anyway. -if(!empty($mybb->input['pid']) && !isset($mybb->input['tid'])) -{ - // see if we already have the post information - if(isset($style) && $style['pid'] == $mybb->get_input('pid', MyBB::INPUT_INT) && $style['tid']) - { - $mybb->input['tid'] = $style['tid']; - unset($style['tid']); // stop the thread caching code from being tricked - } - else - { - $options = array( - "limit" => 1 - ); - $query = $db->simple_select("posts", "fid,tid,visible", "pid=".$mybb->get_input('pid', MyBB::INPUT_INT), $options); - $post = $db->fetch_array($query); - - if(empty($post) || ($post['visible'] == 0 && !is_moderator($post['fid'], 'canviewunapprove')) || ($post['visible'] == -1 && !is_moderator($post['fid'], 'canviewdeleted'))) - { - // post does not exist --> show corresponding error - error($lang->error_invalidpost); - } - - $mybb->input['tid'] = $post['tid']; - } -} - -// Get the thread details from the database. -$thread = get_thread($mybb->get_input('tid', MyBB::INPUT_INT)); - -if(!$thread || substr($thread['closed'], 0, 6) == "moved|") -{ - error($lang->error_invalidthread); -} - -// Get thread prefix if there is one. -$thread['threadprefix'] = ''; -$thread['displayprefix'] = ''; -if($thread['prefix'] != 0) -{ - $threadprefix = build_prefixes($thread['prefix']); - - if(!empty($threadprefix['prefix'])) - { - $thread['threadprefix'] = htmlspecialchars_uni($threadprefix['prefix']).' '; - $thread['displayprefix'] = $threadprefix['displaystyle'].' '; - } -} - -$reply_subject = $parser->parse_badwords($thread['subject']); -$thread['subject'] = htmlspecialchars_uni($reply_subject); -// Subject too long? Shorten it to avoid error message -if(my_strlen($reply_subject) > 85) -{ - $reply_subject = my_substr($reply_subject, 0, 82).'...'; -} -$reply_subject = htmlspecialchars_uni($reply_subject); -$tid = $thread['tid']; -$fid = $thread['fid']; - -if(!$thread['username']) -{ - $thread['username'] = $lang->guest; -} -$thread['username'] = htmlspecialchars_uni($thread['username']); - -// Is the currently logged in user a moderator of this forum? -if(is_moderator($fid)) -{ - $ismod = true; - if(is_moderator($fid, "canviewdeleted") == true || is_moderator($fid, "canviewunapprove") == true) - { - if(is_moderator($fid, "canviewunapprove") == true && is_moderator($fid, "canviewdeleted") == false) - { - $visibleonly = " AND visible IN (0,1)"; - $visibleonly2 = "AND p.visible IN (0,1) AND t.visible IN (0,1)"; - } - elseif(is_moderator($fid, "canviewdeleted") == true && is_moderator($fid, "canviewunapprove") == false) - { - $visibleonly = " AND visible IN (-1,1)"; - $visibleonly2 = "AND p.visible IN (-1,1) AND t.visible IN (-1,1)"; - } - else - { - $visibleonly = " AND visible IN (-1,0,1)"; - $visibleonly2 = "AND p.visible IN (-1,0,1) AND t.visible IN (-1,0,1)"; - } - } -} -else -{ - $ismod = false; - $visibleonly = " AND visible=1"; - $visibleonly2 = "AND p.visible=1 AND t.visible=1"; -} - -// Make sure we are looking at a real thread here. -if(($thread['visible'] != 1 && $ismod == false) || ($thread['visible'] == 0 && !is_moderator($fid, "canviewunapprove")) || ($thread['visible'] == -1 && !is_moderator($fid, "canviewdeleted"))) -{ - error($lang->error_invalidthread); -} - -$forumpermissions = forum_permissions($thread['fid']); - -// Does the user have permission to view this thread? -if($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1) -{ - error_no_permission(); -} - -if(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] == 1 && $thread['uid'] != $mybb->user['uid']) -{ - error_no_permission(); -} - -$archive_url = build_archive_link("thread", $tid); - -// Does the thread belong to a valid forum? -$forum = get_forum($fid); -if(!$forum || $forum['type'] != "f") -{ - error($lang->error_invalidforum); -} - -$threadnoteslink = ''; -if(is_moderator($fid, "canmanagethreads") && !empty($thread['notes'])) -{ - eval('$threadnoteslink = "'.$templates->get('showthread_threadnoteslink').'";'); -} - -// Check if this forum is password protected and we have a valid password -check_forum_password($forum['fid']); - -// If there is no specific action, we must be looking at the thread. -if(!$mybb->get_input('action')) -{ - $mybb->input['action'] = "thread"; -} - -// Jump to the unread posts. -if($mybb->input['action'] == "newpost") -{ - // First, figure out what time the thread or forum were last read - $query = $db->simple_select("threadsread", "dateline", "uid='{$mybb->user['uid']}' AND tid='{$thread['tid']}'"); - $thread_read = $db->fetch_field($query, "dateline"); - - if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid']) - { - $query = $db->simple_select("forumsread", "dateline", "fid='{$fid}' AND uid='{$mybb->user['uid']}'"); - $forum_read = $db->fetch_field($query, "dateline"); - - $read_cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - if($forum_read == 0 || $forum_read < $read_cutoff) - { - $forum_read = $read_cutoff; - } - } - else - { - $forum_read = (int)my_get_array_cookie("forumread", $fid); - } - - if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid'] && $thread['lastpost'] > $forum_read) - { - $cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - if($thread['lastpost'] > $cutoff) - { - if($thread_read) - { - $lastread = $thread_read; - } - else - { - // Set $lastread to zero to make sure 'lastpost' is invoked in the last IF - $lastread = 0; - } - } - } - - if(!$lastread) - { - $readcookie = $threadread = (int)my_get_array_cookie("threadread", $thread['tid']); - if($readcookie > $forum_read) - { - $lastread = $readcookie; - } - else - { - $lastread = $forum_read; - } - } - - if($cutoff && $lastread < $cutoff) - { - $lastread = $cutoff; - } - - // Next, find the proper pid to link to. - $options = array( - "limit_start" => 0, - "limit" => 1, - "order_by" => "dateline", - "order_dir" => "asc" - ); - - $lastread = (int)$lastread; - $query = $db->simple_select("posts", "pid", "tid='{$tid}' AND dateline > '{$lastread}' {$visibleonly}", $options); - $newpost = $db->fetch_array($query); - - if($newpost['pid'] && $lastread) - { - $highlight = ''; - if($mybb->get_input('highlight')) - { - $string = "&"; - if($mybb->seo_support == true) - { - $string = "?"; - } - - $highlight = $string."highlight=".$mybb->get_input('highlight'); - } - - header("Location: ".htmlspecialchars_decode(get_post_link($newpost['pid'], $tid)).$highlight."#pid{$newpost['pid']}"); - } - else - { - // show them to the last post - $mybb->input['action'] = "lastpost"; - } -} - -// Jump to the last post. -if($mybb->input['action'] == "lastpost") -{ - if(my_strpos($thread['closed'], "moved|")) - { - $query = $db->query(" - SELECT p.pid - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON(p.tid=t.tid) - WHERE t.fid='".$thread['fid']."' AND t.closed NOT LIKE 'moved|%' {$visibleonly2} - ORDER BY p.dateline DESC - LIMIT 1 - "); - $pid = $db->fetch_field($query, "pid"); - } - else - { - $options = array( - 'order_by' => 'dateline', - 'order_dir' => 'desc', - 'limit_start' => 0, - 'limit' => 1 - ); - $query = $db->simple_select('posts', 'pid', "tid={$tid} {$visibleonly}", $options); - $pid = $db->fetch_field($query, "pid"); - } - header("Location: ".htmlspecialchars_decode(get_post_link($pid, $tid))."#pid{$pid}"); - exit; -} - -// Jump to the next newest posts. -if($mybb->input['action'] == "nextnewest") -{ - $options = array( - "limit_start" => 0, - "limit" => 1, - "order_by" => "lastpost" - ); - $query = $db->simple_select('threads', '*', "fid={$thread['fid']} AND lastpost > {$thread['lastpost']} {$visibleonly} AND closed NOT LIKE 'moved|%'", $options); - $nextthread = $db->fetch_array($query); - - // Are there actually next newest posts? - if(!$nextthread['tid']) - { - error($lang->error_nonextnewest); - } - $options = array( - "limit_start" => 0, - "limit" => 1, - "order_by" => "dateline", - "order_dir" => "desc" - ); - $query = $db->simple_select('posts', 'pid', "tid='{$nextthread['tid']}'", $options); - - // Redirect to the proper page. - $pid = $db->fetch_field($query, "pid"); - header("Location: ".htmlspecialchars_decode(get_post_link($pid, $nextthread['tid']))."#pid{$pid}"); - exit; -} - -// Jump to the next oldest posts. -if($mybb->input['action'] == "nextoldest") -{ - $options = array( - "limit" => 1, - "limit_start" => 0, - "order_by" => "lastpost", - "order_dir" => "desc" - ); - $query = $db->simple_select("threads", "*", "fid=".$thread['fid']." AND lastpost < ".$thread['lastpost']." {$visibleonly} AND closed NOT LIKE 'moved|%'", $options); - $nextthread = $db->fetch_array($query); - - // Are there actually next oldest posts? - if(!$nextthread['tid']) - { - error($lang->error_nonextoldest); - } - $options = array( - "limit_start" => 0, - "limit" => 1, - "order_by" => "dateline", - "order_dir" => "desc" - ); - $query = $db->simple_select("posts", "pid", "tid='".$nextthread['tid']."'", $options); - - // Redirect to the proper page. - $pid = $db->fetch_field($query, "pid"); - header("Location: ".htmlspecialchars_decode(get_post_link($pid, $nextthread['tid']))."#pid{$pid}"); - exit; -} - -$pid = $mybb->input['pid'] = $mybb->get_input('pid', MyBB::INPUT_INT); - -// Forumdisplay cache -$forum_stats = $cache->read("forumsdisplay"); - -$breadcrumb_multipage = array(); -if($mybb->settings['showforumpagesbreadcrumb']) -{ - // How many pages are there? - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - $query = $db->simple_select("forums", "threads, unapprovedthreads", "fid = '{$fid}'", array('limit' => 1)); - $forum_threads = $db->fetch_array($query); - $threadcount = $forum_threads['threads']; - - if(is_moderator($fid, "canviewunapprove") == true) - { - $threadcount += $forum_threads['unapprovedthreads']; - } - - // Limit to only our own threads - $uid_only = ''; - if(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] == 1) - { - $uid_only = " AND uid = '".$mybb->user['uid']."'"; - - $query = $db->simple_select("threads", "COUNT(tid) AS threads", "fid = '$fid' $visibleonly $uid_only", array('limit' => 1)); - $threadcount = $db->fetch_field($query, "threads"); - } - - // If we have 0 threads double check there aren't any "moved" threads - if($threadcount == 0) - { - $query = $db->simple_select("threads", "COUNT(tid) AS threads", "fid = '$fid' $visibleonly $uid_only", array('limit' => 1)); - $threadcount = $db->fetch_field($query, "threads"); - } - - $stickybit = " OR sticky=1"; - if($thread['sticky'] == 1) - { - $stickybit = " AND sticky=1"; - } - - // Figure out what page the thread is actually on - switch($db->type) - { - case "pgsql": - $query = $db->query(" - SELECT COUNT(tid) as threads - FROM ".TABLE_PREFIX."threads - WHERE fid = '$fid' AND (lastpost >= '".(int)$thread['lastpost']."'{$stickybit}) {$visibleonly} {$uid_only} - GROUP BY lastpost - ORDER BY lastpost DESC - "); - break; - default: - $query = $db->simple_select("threads", "COUNT(tid) as threads", "fid = '$fid' AND (lastpost >= '".(int)$thread['lastpost']."'{$stickybit}) {$visibleonly} {$uid_only}", array('order_by' => 'lastpost', 'order_dir' => 'desc')); - } - - $thread_position = $db->fetch_field($query, "threads"); - $thread_page = ceil(($thread_position/$mybb->settings['threadsperpage'])); - - $breadcrumb_multipage = array( - "num_threads" => $threadcount, - "current_page" => $thread_page - ); -} - -// Build the navigation. -build_forum_breadcrumb($fid, $breadcrumb_multipage); -add_breadcrumb($thread['displayprefix'].$thread['subject'], get_thread_link($thread['tid'])); - -$plugins->run_hooks("showthread_start"); - -// Show the entire thread (taking into account pagination). -if($mybb->input['action'] == "thread") -{ - if($thread['firstpost'] == 0) - { - update_first_post($tid); - } - - // Does this thread have a poll? - if($thread['poll']) - { - $options = array( - "limit" => 1 - ); - $query = $db->simple_select("polls", "*", "pid='".$thread['poll']."'", $options); - $poll = $db->fetch_array($query); - $poll['timeout'] = $poll['timeout']*60*60*24; - $expiretime = $poll['dateline'] + $poll['timeout']; - $now = TIME_NOW; - - // If the poll or the thread is closed or if the poll is expired, show the results. - if($poll['closed'] == 1 || $thread['closed'] == 1 || ($expiretime < $now && $poll['timeout'] > 0) || $forumpermissions['canvotepolls'] != 1) - { - $showresults = 1; - } - - // If the user is not a guest, check if he already voted. - if($mybb->user['uid'] != 0) - { - $query = $db->simple_select("pollvotes", "*", "uid='".$mybb->user['uid']."' AND pid='".$poll['pid']."'"); - while($votecheck = $db->fetch_array($query)) - { - $alreadyvoted = 1; - $votedfor[$votecheck['voteoption']] = 1; - } - } - else - { - if(isset($mybb->cookies['pollvotes'][$poll['pid']]) && $mybb->cookies['pollvotes'][$poll['pid']] !== "") - { - $alreadyvoted = 1; - } - } - $optionsarray = explode("||~|~||", $poll['options']); - $votesarray = explode("||~|~||", $poll['votes']); - $poll['question'] = htmlspecialchars_uni($poll['question']); - $polloptions = ''; - $totalvotes = 0; - $poll['totvotes'] = 0; - - for($i = 1; $i <= $poll['numoptions']; ++$i) - { - $poll['totvotes'] = $poll['totvotes'] + $votesarray[$i-1]; - } - - // Loop through the poll options. - for($i = 1; $i <= $poll['numoptions']; ++$i) - { - // Set up the parser options. - $parser_options = array( - "allow_html" => $forum['allowhtml'], - "allow_mycode" => $forum['allowmycode'], - "allow_smilies" => $forum['allowsmilies'], - "allow_imgcode" => $forum['allowimgcode'], - "allow_videocode" => $forum['allowvideocode'], - "filter_badwords" => 1 - ); - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_imgcode'] = 0; - } - - if($mybb->user['showvideos'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestvideos'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_videocode'] = 0; - } - - $option = $parser->parse_message($optionsarray[$i-1], $parser_options); - $votes = $votesarray[$i-1]; - $totalvotes += $votes; - $number = $i; - - // Mark the option the user voted for. - if(!empty($votedfor[$number])) - { - $optionbg = "trow2"; - $votestar = "*"; - } - else - { - $optionbg = "trow1"; - $votestar = ""; - } - - // If the user already voted or if the results need to be shown, do so; else show voting screen. - if(isset($alreadyvoted) || isset($showresults)) - { - if((int)$votes == "0") - { - $percent = "0"; - } - else - { - $percent = number_format($votes / $poll['totvotes'] * 100, 2); - } - $imagewidth = round($percent); - eval("\$polloptions .= \"".$templates->get("showthread_poll_resultbit")."\";"); - } - else - { - if($poll['multiple'] == 1) - { - eval("\$polloptions .= \"".$templates->get("showthread_poll_option_multiple")."\";"); - } - else - { - eval("\$polloptions .= \"".$templates->get("showthread_poll_option")."\";"); - } - } - } - - // If there are any votes at all, all votes together will be 100%; if there are no votes, all votes together will be 0%. - if($poll['totvotes']) - { - $totpercent = "100%"; - } - else - { - $totpercent = "0%"; - } - - // Check if user is allowed to edit posts; if so, show "edit poll" link. - $edit_poll = ''; - if(is_moderator($fid, 'canmanagepolls')) - { - eval("\$edit_poll = \"".$templates->get("showthread_poll_editpoll")."\";"); - } - - // Decide what poll status to show depending on the status of the poll and whether or not the user voted already. - if(isset($alreadyvoted) || isset($showresults)) - { - if($alreadyvoted) - { - $pollstatus = $lang->already_voted; - - if($mybb->usergroup['canundovotes'] == 1) - { - eval("\$pollstatus .= \"".$templates->get("showthread_poll_undovote")."\";"); - } - } - else - { - $pollstatus = $lang->poll_closed; - } - $lang->total_votes = $lang->sprintf($lang->total_votes, $totalvotes); - eval("\$pollbox = \"".$templates->get("showthread_poll_results")."\";"); - $plugins->run_hooks("showthread_poll_results"); - } - else - { - $closeon = ' '; - if($poll['timeout'] != 0) - { - $closeon = $lang->sprintf($lang->poll_closes, my_date($mybb->settings['dateformat'], $expiretime)); - } - - $publicnote = ' '; - if($poll['public'] == 1) - { - $publicnote = $lang->public_note; - } - - eval("\$pollbox = \"".$templates->get("showthread_poll")."\";"); - $plugins->run_hooks("showthread_poll"); - } - - } - else - { - $pollbox = ""; - } - - // Create the forum jump dropdown box. - if($mybb->settings['enableforumjump'] != 0) - { - $forumjump = build_forum_jump("", $fid, 1); - } - - // Fetch some links - $next_oldest_link = get_thread_link($tid, 0, "nextoldest"); - $next_newest_link = get_thread_link($tid, 0, "nextnewest"); - - // Mark this thread as read - mark_thread_read($tid, $fid); - - // If the forum is not open, show closed newreply button unless the user is a moderator of this forum. - $newthread = $newreply = ''; - if($forum['open'] != 0 && $forum['type'] == "f") - { - if($forumpermissions['canpostthreads'] != 0 && $mybb->user['suspendposting'] != 1) - { - eval("\$newthread = \"".$templates->get("showthread_newthread")."\";"); - } - - // Show the appropriate reply button if this thread is open or closed - if($forumpermissions['canpostreplys'] != 0 && $mybb->user['suspendposting'] != 1 && ($thread['closed'] != 1 || is_moderator($fid, "canpostclosedthreads")) && ($thread['uid'] == $mybb->user['uid'] || $forumpermissions['canonlyreplyownthreads'] != 1)) - { - eval("\$newreply = \"".$templates->get("showthread_newreply")."\";"); - } - elseif($thread['closed'] == 1) - { - eval("\$newreply = \"".$templates->get("showthread_newreply_closed")."\";"); - } - } - - // Create the admin tools dropdown box. - if($ismod == true) - { - $closelinkch = $stickch = ''; - - if($thread['closed'] == 1) - { - $closelinkch = ' checked="checked"'; - } - - if($thread['sticky']) - { - $stickch = ' checked="checked"'; - } - - if(is_moderator($thread['fid'], "canopenclosethreads")) - { - eval("\$closeoption .= \"".$templates->get("showthread_quickreply_options_close")."\";"); - } - - if(is_moderator($thread['fid'], "canstickunstickthreads")) - { - eval("\$closeoption .= \"".$templates->get("showthread_quickreply_options_stick")."\";"); - } - - $inlinecount = "0"; - $inlinecookie = "inlinemod_thread".$tid; - - $plugins->run_hooks("showthread_ismod"); - } - else - { - $modoptions = " "; - $inlinemod = $closeoption = ''; - } - - // Increment the thread view. - if($mybb->settings['delayedthreadviews'] == 1) - { - $db->shutdown_query("INSERT INTO ".TABLE_PREFIX."threadviews (tid) VALUES('{$tid}')"); - } - else - { - $db->shutdown_query("UPDATE ".TABLE_PREFIX."threads SET views=views+1 WHERE tid='{$tid}'"); - } - ++$thread['views']; - - // Work out the thread rating for this thread. - $rating = ''; - if($mybb->settings['allowthreadratings'] != 0 && $forum['allowtratings'] != 0) - { - $rated = 0; - $lang->load("ratethread"); - if($thread['numratings'] <= 0) - { - $thread['width'] = 0; - $thread['averagerating'] = 0; - $thread['numratings'] = 0; - } - else - { - $thread['averagerating'] = (float)round($thread['totalratings']/$thread['numratings'], 2); - $thread['width'] = (int)round($thread['averagerating'])*20; - $thread['numratings'] = (int)$thread['numratings']; - } - - if($thread['numratings']) - { - // At least >someone< has rated this thread, was it me? - // Check if we have already voted on this thread - it won't show hover effect then. - $query = $db->simple_select("threadratings", "uid", "tid='{$tid}' AND uid='{$mybb->user['uid']}'"); - $rated = $db->fetch_field($query, 'uid'); - } - - $not_rated = ''; - if(!$rated) - { - $not_rated = ' star_rating_notrated'; - } - - $ratingvotesav = $lang->sprintf($lang->rating_average, $thread['numratings'], $thread['averagerating']); - eval("\$ratethread = \"".$templates->get("showthread_ratethread")."\";"); - } - // Work out if we are showing unapproved posts as well (if the user is a moderator etc.) - if($ismod && is_moderator($fid, "canviewdeleted") == true && is_moderator($fid, "canviewunapprove") == false) - { - $visible = "AND p.visible IN (-1,1)"; - } - elseif($ismod && is_moderator($fid, "canviewdeleted") == false && is_moderator($fid, "canviewunapprove") == true) - { - $visible = "AND p.visible IN (0,1)"; - } - elseif($ismod && is_moderator($fid, "canviewdeleted") == true && is_moderator($fid, "canviewunapprove") == true) - { - $visible = "AND p.visible IN (-1,0,1)"; - } - elseif($forumpermissions['canviewdeletionnotice'] != 0 && $ismod == false) - { - $visible = "AND p.visible IN (-1,1)"; - } - else - { - $visible = "AND p.visible='1'"; - } - - // Can this user perform searches? If so, we can show them the "Search thread" form - if($forumpermissions['cansearch'] != 0) - { - eval("\$search_thread = \"".$templates->get("showthread_search")."\";"); - } - - // Fetch the ignore list for the current user if they have one - $ignored_users = array(); - if($mybb->user['uid'] > 0 && $mybb->user['ignorelist'] != "") - { - $ignore_list = explode(',', $mybb->user['ignorelist']); - foreach($ignore_list as $uid) - { - $ignored_users[$uid] = 1; - } - } - - // Fetch profile fields to display on postbit - $pfcache = $cache->read('profilefields'); - - if(is_array($pfcache)) - { - foreach($pfcache as $profilefield) - { - if($profilefield['postbit'] != 1) - { - continue; - } - - $profile_fields[$profilefield['fid']] = $profilefield; - } - } - - // Which thread mode is our user using by default? - if(!empty($mybb->user['threadmode'])) - { - $defaultmode = $mybb->user['threadmode']; - } - else if($mybb->settings['threadusenetstyle'] == 1) - { - $defaultmode = 'threaded'; - } - else - { - $defaultmode = 'linear'; - } - - // If mode is unset, set the default mode - if(!isset($mybb->input['mode'])) - { - $mybb->input['mode'] = $defaultmode; - } - - // Threaded or linear display? - $threadexbox = ''; - if($mybb->get_input('mode') == 'threaded') - { - $isfirst = 1; - - // Are we linked to a specific pid? - if($mybb->input['pid']) - { - $where = "AND p.pid='".$mybb->input['pid']."'"; - } - else - { - $where = " ORDER BY dateline LIMIT 0, 1"; - } - $query = $db->query(" - SELECT u.*, u.username AS userusername, p.*, f.*, eu.username AS editusername - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - LEFT JOIN ".TABLE_PREFIX."users eu ON (eu.uid=p.edituid) - WHERE p.tid='$tid' $visible $where - "); - $showpost = $db->fetch_array($query); - - // Choose what pid to display. - if(!$mybb->input['pid']) - { - $mybb->input['pid'] = $showpost['pid']; - } - - // Is there actually a pid to display? - if(!$showpost['pid']) - { - error($lang->error_invalidpost); - } - - $attachcache = array(); - if($mybb->settings['enableattachments'] == 1 && $thread['attachmentcount'] > 0 || is_moderator($fid, 'caneditposts')) - { - // Get the attachments for this post. - $query = $db->simple_select("attachments", "*", "pid=".$mybb->input['pid']); - while($attachment = $db->fetch_array($query)) - { - $attachcache[$attachment['pid']][$attachment['aid']] = $attachment; - } - } - - // Build the threaded post display tree. - $query = $db->query(" - SELECT p.username, p.uid, p.pid, p.replyto, p.subject, p.dateline - FROM ".TABLE_PREFIX."posts p - WHERE p.tid='$tid' - $visible - ORDER BY p.dateline - "); - while($post = $db->fetch_array($query)) - { - if(!$postsdone[$post['pid']]) - { - if($post['pid'] == $mybb->input['pid'] || ($isfirst && !$mybb->input['pid'])) - { - $postcounter = count($postsdone); - $isfirst = 0; - } - $tree[$post['replyto']][$post['pid']] = $post; - $postsdone[$post['pid']] = 1; - } - } - - $threadedbits = buildtree(); - $posts = build_postbit($showpost); - eval("\$threadexbox = \"".$templates->get("showthread_threadedbox")."\";"); - $plugins->run_hooks("showthread_threaded"); - } - else // Linear display - { - $threadexbox = ''; - if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) - { - $mybb->settings['postsperpage'] = 20; - } - - // Figure out if we need to display multiple pages. - $page = 1; - $perpage = $mybb->settings['postsperpage']; - if($mybb->get_input('page', MyBB::INPUT_INT) && $mybb->get_input('page') != "last") - { - $page = $mybb->get_input('page', MyBB::INPUT_INT); - } - - if(!empty($mybb->input['pid'])) - { - $post = get_post($mybb->input['pid']); - if(empty($post) || ($post['visible'] == 0 && !is_moderator($post['fid'], 'canviewunapprove')) || ($post['visible'] == -1 && !is_moderator($post['fid'], 'canviewdeleted'))) - { - $footer .= ''; - } - else - { - $query = $db->query(" - SELECT COUNT(p.dateline) AS count FROM ".TABLE_PREFIX."posts p - WHERE p.tid = '{$tid}' - AND p.dateline <= '{$post['dateline']}' - {$visible} - "); - $result = $db->fetch_field($query, "count"); - if(($result % $perpage) == 0) - { - $page = $result / $perpage; - } - else - { - $page = (int)($result / $perpage) + 1; - } - } - } - - // Recount replies if user is a moderator to take into account unapproved posts. - if($ismod) - { - $query = $db->simple_select("posts p", "COUNT(*) AS replies", "p.tid='$tid' $visible"); - $cached_replies = $thread['replies']+$thread['unapprovedposts']+$thread['deletedposts']; - $thread['replies'] = $db->fetch_field($query, 'replies')-1; - - // The counters are wrong? Rebuild them - // This doesn't cover all cases however it is a good addition to the manual rebuild function - if($thread['replies'] != $cached_replies) - { - require_once MYBB_ROOT."/inc/functions_rebuild.php"; - rebuild_thread_counters($thread['tid']); - } - } - - $postcount = (int)$thread['replies']+1; - $pages = $postcount / $perpage; - $pages = ceil($pages); - - if($mybb->get_input('page') == "last") - { - $page = $pages; - } - - if($page > $pages || $page <= 0) - { - $page = 1; - } - - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - $upper = $start+$perpage; - - // Work out if we have terms to highlight - $highlight = ""; - $threadmode = ""; - if($mybb->seo_support == true) - { - if($mybb->get_input('highlight')) - { - $highlight = "?highlight=".urlencode($mybb->get_input('highlight')); - } - - if($defaultmode != "linear") - { - if($mybb->get_input('highlight')) - { - $threadmode = "&mode=linear"; - } - else - { - $threadmode = "?mode=linear"; - } - } - } - else - { - if(!empty($mybb->input['highlight'])) - { - if(is_array($mybb->input['highlight'])) - { - foreach($mybb->input['highlight'] as $highlight_word) - { - $highlight .= "&highlight[]=".urlencode($highlight_word); - } - } - else - { - $highlight = "&highlight=".urlencode($mybb->get_input('highlight')); - } - } - - if($defaultmode != "linear") - { - $threadmode = "&mode=linear"; - } - } - - $multipage = multipage($postcount, $perpage, $page, str_replace("{tid}", $tid, THREAD_URL_PAGED.$highlight.$threadmode)); - - // Lets get the pids of the posts on this page. - $pids = ""; - $comma = ''; - $query = $db->simple_select("posts p", "p.pid", "p.tid='$tid' $visible", array('order_by' => 'p.dateline', 'limit_start' => $start, 'limit' => $perpage)); - while($getid = $db->fetch_array($query)) - { - // Set the ID of the first post on page to $pid if it doesn't hold any value - // to allow this value to be used for Thread Mode/Linear Mode links - // and ensure the user lands on the correct page after changing view mode - if(empty($pid)) - { - $pid = $getid['pid']; - } - // Gather a comma separated list of post IDs - $pids .= "$comma'{$getid['pid']}'"; - $comma = ","; - } - if($pids) - { - $pids = "pid IN($pids)"; - - $attachcache = array(); - if($mybb->settings['enableattachments'] == 1 && $thread['attachmentcount'] > 0 || is_moderator($fid, 'caneditposts')) - { - // Now lets fetch all of the attachments for these posts. - $query = $db->simple_select("attachments", "*", $pids); - while($attachment = $db->fetch_array($query)) - { - $attachcache[$attachment['pid']][$attachment['aid']] = $attachment; - } - } - } - else - { - // If there are no pid's the thread is probably awaiting approval. - error($lang->error_invalidthread); - } - - // Get the actual posts from the database here. - $posts = ''; - $query = $db->query(" - SELECT u.*, u.username AS userusername, p.*, f.*, eu.username AS editusername - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - LEFT JOIN ".TABLE_PREFIX."userfields f ON (f.ufid=u.uid) - LEFT JOIN ".TABLE_PREFIX."users eu ON (eu.uid=p.edituid) - WHERE $pids - ORDER BY p.dateline - "); - while($post = $db->fetch_array($query)) - { - if($thread['firstpost'] == $post['pid'] && $thread['visible'] == 0) - { - $post['visible'] = 0; - } - $posts .= build_postbit($post); - $post = ''; - } - $plugins->run_hooks("showthread_linear"); - } - - // Show the similar threads table if wanted. - $similarthreads = ''; - if($mybb->settings['showsimilarthreads'] != 0) - { - $own_perm = ''; - if($forumpermissions['canonlyviewownthreads'] == 1) - { - $own_perm = " AND t.uid={$mybb->user['uid']}"; - } - - switch($db->type) - { - case "pgsql": - $query = $db->query(" - SELECT t.*, t.username AS threadusername, u.username - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid = t.uid), plainto_tsquery ('".$db->escape_string($thread['subject'])."') AS query - WHERE t.fid='{$thread['fid']}' AND t.tid!='{$thread['tid']}' AND t.visible='1' AND t.closed NOT LIKE 'moved|%' AND t.subject @@ query{$own_perm} - ORDER BY t.lastpost DESC - OFFSET 0 LIMIT {$mybb->settings['similarlimit']} - "); - break; - default: - $query = $db->query(" - SELECT t.*, t.username AS threadusername, u.username, MATCH (t.subject) AGAINST ('".$db->escape_string($thread['subject'])."') AS relevance - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid = t.uid) - WHERE t.fid='{$thread['fid']}' AND t.tid!='{$thread['tid']}' AND t.visible='1' AND t.closed NOT LIKE 'moved|%'{$own_perm} AND MATCH (t.subject) AGAINST ('".$db->escape_string($thread['subject'])."') >= '{$mybb->settings['similarityrating']}' - ORDER BY t.lastpost DESC - LIMIT 0, {$mybb->settings['similarlimit']} - "); - } - - $count = 0; - $similarthreadbits = ''; - $icon_cache = $cache->read("posticons"); - while($similar_thread = $db->fetch_array($query)) - { - ++$count; - $trow = alt_trow(); - if($similar_thread['icon'] > 0 && $icon_cache[$similar_thread['icon']]) - { - $icon = $icon_cache[$similar_thread['icon']]; - $icon['path'] = str_replace("{theme}", $theme['imgdir'], $icon['path']); - $icon['path'] = htmlspecialchars_uni($icon['path']); - $icon['name'] = htmlspecialchars_uni($icon['name']); - eval("\$icon = \"".$templates->get("forumdisplay_thread_icon")."\";"); - } - else - { - $icon = " "; - } - if(!$similar_thread['username']) - { - $similar_thread['username'] = $similar_thread['profilelink'] = htmlspecialchars_uni($similar_thread['threadusername']); - } - else - { - $similar_thread['username'] = htmlspecialchars_uni($similar_thread['username']); - $similar_thread['profilelink'] = build_profile_link($similar_thread['username'], $similar_thread['uid']); - } - - // If this thread has a prefix, insert a space between prefix and subject - if($similar_thread['prefix'] != 0) - { - $prefix = build_prefixes($similar_thread['prefix']); - if(!empty($prefix)) - { - $similar_thread['threadprefix'] = $prefix['displaystyle'].' '; - } - } - - $similar_thread['subject'] = $parser->parse_badwords($similar_thread['subject']); - $similar_thread['subject'] = htmlspecialchars_uni($similar_thread['subject']); - $similar_thread['threadlink'] = get_thread_link($similar_thread['tid']); - $similar_thread['lastpostlink'] = get_thread_link($similar_thread['tid'], 0, "lastpost"); - - $lastpostdate = my_date('relative', $similar_thread['lastpost']); - $lastposter = $similar_thread['lastposter']; - $lastposteruid = $similar_thread['lastposteruid']; - - // Don't link to guest's profiles (they have no profile). - if($lastposteruid == 0) - { - $lastposterlink = $lastposter; - } - else - { - $lastposterlink = build_profile_link($lastposter, $lastposteruid); - } - $similar_thread['replies'] = my_number_format($similar_thread['replies']); - $similar_thread['views'] = my_number_format($similar_thread['views']); - eval("\$similarthreadbits .= \"".$templates->get("showthread_similarthreads_bit")."\";"); - } - if($count) - { - eval("\$similarthreads = \"".$templates->get("showthread_similarthreads")."\";"); - } - } - - // Decide whether or not to show quick reply. - $quickreply = ''; - if($forumpermissions['canpostreplys'] != 0 && $mybb->user['suspendposting'] != 1 && ($thread['closed'] != 1 || is_moderator($fid, "canpostclosedthreads")) && $mybb->settings['quickreply'] != 0 && $mybb->user['showquickreply'] != '0' && $forum['open'] != 0 && ($thread['uid'] == $mybb->user['uid'] || $forumpermissions['canonlyreplyownthreads'] != 1)) - { - $query = $db->simple_select("posts", "pid", "tid='{$tid}'", array("order_by" => "pid", "order_dir" => "desc", "limit" => 1)); - $last_pid = $db->fetch_field($query, "pid"); - - // Show captcha image for guests if enabled - $captcha = ''; - if($mybb->settings['captchaimage'] && !$mybb->user['uid']) - { - require_once MYBB_ROOT.'inc/class_captcha.php'; - $post_captcha = new captcha(true, "post_captcha"); - - if($post_captcha->html) - { - $captcha = $post_captcha->html; - } - } - - $postoptionschecked = array('signature' => '', 'emailnotify' => ''); - if($mybb->user['signature']) - { - $postoptionschecked['signature'] = 'checked="checked"'; - } - - // Hide signature option if no permission - $option_signature = ''; - if($mybb->usergroup['canusesig'] && !$mybb->user['suspendsignature']) - { - eval("\$option_signature = \"".$templates->get('showthread_quickreply_options_signature')."\";"); - } - - if(isset($mybb->user['emailnotify']) && $mybb->user['emailnotify'] == 1) - { - $postoptionschecked['emailnotify'] = 'checked="checked"'; - } - - $trow = alt_trow(); - if($thread['closed'] == 1) - { - $trow = 'trow_shaded'; - } - - $moderation_notice = ''; - if(!is_moderator($forum['fid'], "canapproveunapproveposts")) - { - if($forumpermissions['modposts'] == 1) - { - $moderation_text = $lang->moderation_forum_posts; - eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); - } - - if($mybb->user['moderateposts'] == 1) - { - $moderation_text = $lang->moderation_user_posts; - eval('$moderation_notice = "'.$templates->get('global_moderation_notice').'";'); - } - } - - $posthash = md5($mybb->user['uid'].random_str()); - eval("\$quickreply = \"".$templates->get("showthread_quickreply")."\";"); - } - - $moderationoptions = ''; - - // If the user is a moderator, show the moderation tools. - if($ismod) - { - $customthreadtools = $customposttools = $standardthreadtools = $standardposttools = ''; - - $threadnotesbox = $viewnotes = ''; - if(!empty($thread['notes'])) - { - $thread['notes'] = nl2br(htmlspecialchars_uni($thread['notes'])); - - if(strlen($thread['notes']) > 200) - { - eval("\$viewnotes = \"".$templates->get("showthread_threadnotes_viewnotes")."\";"); - $thread['notes'] = my_substr($thread['notes'], 0, 200)."... {$viewnotes}"; - } - - eval("\$threadnotesbox = \"".$templates->get("showthread_threadnotes")."\";"); - } - - if(is_moderator($forum['fid'], "canusecustomtools") && (!empty($forum_stats[-1]['modtools']) || !empty($forum_stats[$forum['fid']]['modtools']))) - { - $gids = explode(',', $mybb->user['additionalgroups']); - $gids[] = $mybb->user['usergroup']; - $gids = array_filter(array_unique($gids)); - switch($db->type) - { - case "pgsql": - case "sqlite": - foreach($gids as $gid) - { - $gid = (int)$gid; - $gidswhere .= " OR ','||groups||',' LIKE '%,{$gid},%'"; - } - $query = $db->simple_select("modtools", 'tid, name, type', "(','||forums||',' LIKE '%,$fid,%' OR ','||forums||',' LIKE '%,-1,%' OR forums='') AND (groups='' OR ','||groups||',' LIKE '%,-1,%'{$gidswhere})"); - break; - default: - foreach($gids as $gid) - { - $gid = (int)$gid; - $gidswhere .= " OR CONCAT(',',groups,',') LIKE '%,{$gid},%'"; - } - $query = $db->simple_select("modtools", 'tid, name, type', "(CONCAT(',',forums,',') LIKE '%,$fid,%' OR CONCAT(',',forums,',') LIKE '%,-1,%' OR forums='') AND (groups='' OR CONCAT(',',groups,',') LIKE '%,-1,%'{$gidswhere})"); - break; - } - - while($tool = $db->fetch_array($query)) - { - if($tool['type'] == 'p') - { - eval("\$customposttools .= \"".$templates->get("showthread_inlinemoderation_custom_tool")."\";"); - } - else - { - eval("\$customthreadtools .= \"".$templates->get("showthread_moderationoptions_custom_tool")."\";"); - } - } - - // Build inline moderation dropdown - if(!empty($customposttools)) - { - eval("\$customposttools = \"".$templates->get("showthread_inlinemoderation_custom")."\";"); - } - } - - $inlinemodsoftdelete = $inlinemodrestore = $inlinemoddelete = $inlinemodmanage = $inlinemodapprove = ''; - - if(is_moderator($forum['fid'], "cansoftdeleteposts")) - { - eval("\$inlinemodsoftdelete = \"".$templates->get("showthread_inlinemoderation_softdelete")."\";"); - } - - if(is_moderator($forum['fid'], "canrestoreposts")) - { - eval("\$inlinemodrestore = \"".$templates->get("showthread_inlinemoderation_restore")."\";"); - } - - if(is_moderator($forum['fid'], "candeleteposts")) - { - eval("\$inlinemoddelete = \"".$templates->get("showthread_inlinemoderation_delete")."\";"); - } - - if(is_moderator($forum['fid'], "canmanagethreads")) - { - eval("\$inlinemodmanage = \"".$templates->get("showthread_inlinemoderation_manage")."\";"); - } - - if(is_moderator($forum['fid'], "canapproveunapproveposts")) - { - eval("\$inlinemodapprove = \"".$templates->get("showthread_inlinemoderation_approve")."\";"); - } - - if(!empty($inlinemodsoftdelete) || !empty($inlinemodrestore) || !empty($inlinemoddelete) || !empty($inlinemodmanage) || !empty($inlinemodapprove)) - { - eval("\$standardposttools = \"".$templates->get("showthread_inlinemoderation_standard")."\";"); - } - - // Only show inline mod menu if there's options to show - if(!empty($standardposttools) || !empty($customposttools)) - { - eval("\$inlinemod = \"".$templates->get("showthread_inlinemoderation")."\";"); - } - - // Build thread moderation dropdown - if(!empty($customthreadtools)) - { - eval("\$customthreadtools = \"".$templates->get("showthread_moderationoptions_custom")."\";"); - } - - $openclosethread = $stickunstickthread = $deletethread = $threadnotes = $managethread = $adminpolloptions = $approveunapprovethread = $softdeletethread = ''; - - if(is_moderator($forum['fid'], "canopenclosethreads")) - { - eval("\$openclosethread = \"".$templates->get("showthread_moderationoptions_openclose")."\";"); - } - - if(is_moderator($forum['fid'], "canstickunstickthreads")) - { - eval("\$stickunstickthread = \"".$templates->get("showthread_moderationoptions_stickunstick")."\";"); - } - - if(is_moderator($forum['fid'], "candeletethreads")) - { - eval("\$deletethread = \"".$templates->get("showthread_moderationoptions_delete")."\";"); - } - - if(is_moderator($forum['fid'], "canmanagethreads")) - { - eval("\$threadnotes = \"".$templates->get("showthread_moderationoptions_threadnotes")."\";"); - eval("\$managethread = \"".$templates->get("showthread_moderationoptions_manage")."\";"); - } - - if($pollbox && is_moderator($forum['fid'], "canmanagepolls")) - { - eval("\$adminpolloptions = \"".$templates->get("showthread_moderationoptions_deletepoll")."\";"); - } - - if(is_moderator($forum['fid'], "canapproveunapprovethreads")) - { - if($thread['visible'] == 0) - { - eval("\$approveunapprovethread = \"".$templates->get("showthread_moderationoptions_approve")."\";"); - } - else - { - eval("\$approveunapprovethread = \"".$templates->get("showthread_moderationoptions_unapprove")."\";"); - } - } - - if(is_moderator($forum['fid'], "cansoftdeletethreads") && $thread['visible'] != -1) - { - eval("\$softdeletethread = \"".$templates->get("showthread_moderationoptions_softdelete")."\";"); - } - elseif(is_moderator($forum['fid'], "canrestorethreads") && $thread['visible'] == -1) - { - eval("\$softdeletethread = \"".$templates->get("showthread_moderationoptions_restore")."\";"); - } - - if(!empty($openclosethread) || !empty($stickunstickthread) || !empty($deletethread) || !empty($managethread) || !empty($adminpolloptions) || !empty($approveunapprovethread) || !empty($softdeletethread)) - { - eval("\$standardthreadtools = \"".$templates->get("showthread_moderationoptions_standard")."\";"); - } - - // Only show mod menu if there's any options to show - if(!empty($standardthreadtools) || !empty($customthreadtools)) - { - eval("\$moderationoptions = \"".$templates->get("showthread_moderationoptions")."\";"); - } - } - - // Display 'send thread' link if permissions allow - $sendthread = ''; - if($mybb->usergroup['cansendemail'] == 1) - { - eval("\$sendthread = \"".$templates->get("showthread_send_thread")."\";"); - } - - // Display 'add poll' link to thread creator (or mods) if thread doesn't have a poll already - $addpoll = ''; - $time = TIME_NOW; - if(!$thread['poll'] && ($thread['uid'] == $mybb->user['uid'] || $ismod == true) && $forumpermissions['canpostpolls'] == 1 && $forum['open'] != 0 && $thread['closed'] != 1 && ($ismod == true || $thread['dateline'] > ($time-($mybb->settings['polltimelimit']*60*60)) || $mybb->settings['polltimelimit'] == 0)) - { - eval("\$addpoll = \"".$templates->get("showthread_add_poll")."\";"); - } - - // Subscription status - $add_remove_subscription = 'add'; - $add_remove_subscription_text = $lang->subscribe_thread; - - if($mybb->user['uid']) - { - $query = $db->simple_select("threadsubscriptions", "tid", "tid='".(int)$tid."' AND uid='".(int)$mybb->user['uid']."'", array('limit' => 1)); - - if($db->fetch_field($query, 'tid')) - { - $add_remove_subscription = 'remove'; - $add_remove_subscription_text = $lang->unsubscribe_thread; - } - - eval("\$addremovesubscription = \"".$templates->get("showthread_subscription")."\";"); - } - - $classic_header = ''; - if($mybb->settings['postlayout'] == "classic") - { - eval("\$classic_header = \"".$templates->get("showthread_classic_header")."\";"); - } - - // Get users viewing this thread - if($mybb->settings['browsingthisthread'] != 0) - { - $timecut = TIME_NOW - $mybb->settings['wolcutoff']; - - $comma = ''; - $guestcount = 0; - $membercount = 0; - $inviscount = 0; - $onlinemembers = ''; - $doneusers = array(); - - $query = $db->query(" - SELECT s.ip, s.uid, s.time, u.username, u.invisible, u.usergroup, u.displaygroup - FROM ".TABLE_PREFIX."sessions s - LEFT JOIN ".TABLE_PREFIX."users u ON (s.uid=u.uid) - WHERE s.time > '$timecut' AND location2='$tid' AND nopermission != 1 - ORDER BY u.username ASC, s.time DESC - "); - - while($user = $db->fetch_array($query)) - { - if($user['uid'] == 0) - { - ++$guestcount; - } - else if(empty($doneusers[$user['uid']]) || $doneusers[$user['uid']] < $user['time']) - { - ++$membercount; - $doneusers[$user['uid']] = $user['time']; - - $invisiblemark = ''; - if($user['invisible'] == 1) - { - $invisiblemark = "*"; - ++$inviscount; - } - - if($user['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid']) - { - $user['profilelink'] = get_profile_link($user['uid']); - $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); - $user['reading'] = my_date($mybb->settings['timeformat'], $user['time']); - - eval("\$onlinemembers .= \"".$templates->get("showthread_usersbrowsing_user", 1, 0)."\";"); - $comma = $lang->comma; - } - } - } - - $guestsonline = ''; - if($guestcount) - { - $guestsonline = $lang->sprintf($lang->users_browsing_thread_guests, $guestcount); - } - - $invisonline = ''; - if($mybb->user['invisible'] == 1) - { - // the user was counted as invisible user --> correct the inviscount - $inviscount -= 1; - } - if($inviscount && $mybb->usergroup['canviewwolinvis'] != 1) - { - $invisonline = $lang->sprintf($lang->users_browsing_forum_invis, $inviscount); - } - - $onlinesep = ''; - if($invisonline != '' && $onlinemembers) - { - $onlinesep = $lang->comma; - } - - $onlinesep2 = ''; - if($invisonline != '' && $guestcount || $onlinemembers && $guestcount) - { - $onlinesep2 = $lang->comma; - } - - eval("\$usersbrowsing = \"".$templates->get("showthread_usersbrowsing")."\";"); - } - - $plugins->run_hooks("showthread_end"); - - eval("\$showthread = \"".$templates->get("showthread")."\";"); - output_page($showthread); -} - -/** - * Build a navigation tree for threaded display. - * - * @param int $replyto - * @param int $indent - * @return string - */ -function buildtree($replyto=0, $indent=0) -{ - global $tree, $mybb, $theme, $mybb, $pid, $tid, $templates, $parser, $lang; - - $indentsize = 13 * $indent; - - ++$indent; - $posts = ''; - if(is_array($tree[$replyto])) - { - foreach($tree[$replyto] as $key => $post) - { - $postdate = my_date('relative', $post['dateline']); - $post['subject'] = htmlspecialchars_uni($parser->parse_badwords($post['subject'])); - - if(!$post['subject']) - { - $post['subject'] = "[".$lang->no_subject."]"; - } - - $post['username'] = htmlspecialchars_uni($post['username']); - $post['profilelink'] = build_profile_link($post['username'], $post['uid']); - - if($mybb->input['pid'] == $post['pid']) - { - eval("\$posts .= \"".$templates->get("showthread_threaded_bitactive")."\";"); - } - else - { - eval("\$posts .= \"".$templates->get("showthread_threaded_bit")."\";"); - } - - if($tree[$post['pid']]) - { - $posts .= buildtree($post['pid'], $indent); - } - } - --$indent; - } - return $posts; -} diff --git a/html/forums/stats.php b/html/forums/stats.php deleted file mode 100644 index 9522fb3..0000000 --- a/html/forums/stats.php +++ /dev/null @@ -1,225 +0,0 @@ -load("stats"); - -add_breadcrumb($lang->nav_stats); - -$stats = $cache->read("stats"); - -if($stats['numthreads'] < 1 || $stats['numusers'] < 1) -{ - error($lang->not_enough_info_stats); -} - -if($mybb->settings['statsenabled'] != 1) -{ - error($lang->stats_disabled); -} - -$plugins->run_hooks("stats_start"); - -$repliesperthread = my_number_format(round((($stats['numposts'] - $stats['numthreads']) / $stats['numthreads']), 2)); -$postspermember = my_number_format(round(($stats['numposts'] / $stats['numusers']), 2)); -$threadspermember = my_number_format(round(($stats['numthreads'] / $stats['numusers']), 2)); - -// Get number of days since board start (might need improvement) -$query = $db->simple_select("users", "regdate", "", array('order_by' => 'regdate', 'limit' => 1)); -$result = $db->fetch_array($query); -$days = (TIME_NOW - $result['regdate']) / 86400; -if($days < 1) -{ - $days = 1; -} -// Get "per day" things -$postsperday = my_number_format(round(($stats['numposts'] / $days), 2)); -$threadsperday = my_number_format(round(($stats['numthreads'] / $days), 2)); -$membersperday = my_number_format(round(($stats['numusers'] / $days), 2)); - -// Get forum permissions -$unviewableforums = get_unviewable_forums(true); -$inactiveforums = get_inactive_forums(); -$unviewablefids = $inactivefids = array(); -$fidnot = ''; - -if($unviewableforums) -{ - $fidnot .= "AND fid NOT IN ($unviewableforums)"; - $unviewablefids = explode(',', $unviewableforums); -} -if($inactiveforums) -{ - $fidnot .= "AND fid NOT IN ($inactiveforums)"; - $inactivefids = explode(',', $inactiveforums); -} - -$unviewableforumsarray = array_merge($unviewablefids, $inactivefids); - -// Check group permissions if we can't view threads not started by us -$group_permissions = forum_permissions(); -$onlyusfids = array(); -foreach($group_permissions as $gpfid => $forum_permissions) -{ - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $gpfid; - } -} - -// Most replied-to threads -$most_replied = $cache->read("most_replied_threads"); - -if(!$most_replied) -{ - $cache->update_most_replied_threads(); - $most_replied = $cache->read("most_replied_threads", true); -} - -$mostreplies = ''; -if(!empty($most_replied)) -{ - foreach($most_replied as $key => $thread) - { - if( - !in_array($thread['fid'], $unviewableforumsarray) && - (!in_array($thread['fid'], $onlyusfids) || ($mybb->user['uid'] && $thread['uid'] == $mybb->user['uid'])) - ) - { - $thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); - $numberbit = my_number_format($thread['replies']); - $numbertype = $lang->replies; - $thread['threadlink'] = get_thread_link($thread['tid']); - eval("\$mostreplies .= \"".$templates->get("stats_thread")."\";"); - } - } -} - -// Most viewed threads -$most_viewed = $cache->read("most_viewed_threads"); - -if(!$most_viewed) -{ - $cache->update_most_viewed_threads(); - $most_viewed = $cache->read("most_viewed_threads", true); -} - -$mostviews = ''; -if(!empty($most_viewed)) -{ - foreach($most_viewed as $key => $thread) - { - if( - !in_array($thread['fid'], $unviewableforumsarray) && - (!in_array($thread['fid'], $onlyusfids) || ($mybb->user['uid'] && $thread['uid'] == $mybb->user['uid'])) - ) - { - $thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); - $numberbit = my_number_format($thread['views']); - $numbertype = $lang->views; - $thread['threadlink'] = get_thread_link($thread['tid']); - eval("\$mostviews .= \"".$templates->get("stats_thread")."\";"); - } - } -} - -$statistics = $cache->read('statistics'); -$mybb->settings['statscachetime'] = (int)$mybb->settings['statscachetime']; - -if($mybb->settings['statscachetime'] < 1) -{ - $mybb->settings['statscachetime'] = 0; -} - -$interval = $mybb->settings['statscachetime']*3600; - -if(!$statistics || $interval == 0 || TIME_NOW - $interval > $statistics['time']) -{ - $cache->update_statistics(); - $statistics = $cache->read('statistics'); -} - -// Top forum -$query = $db->simple_select('forums', 'fid, name, threads, posts', "type='f'$fidnot", array('order_by' => 'posts', 'order_dir' => 'DESC', 'limit' => 1)); -$forum = $db->fetch_array($query); - -if(empty($forum['fid'])) -{ - $topforum = $lang->none; - $topforumposts = $lang->no; - $topforumthreads = $lang->no; -} -else -{ - $forum['name'] = htmlspecialchars_uni(strip_tags($forum['name'])); - $forum['link'] = get_forum_link($forum['fid']); - eval("\$topforum = \"".$templates->get("stats_topforum")."\";"); - $topforumposts = $forum['posts']; - $topforumthreads = $forum['threads']; -} - -// Top referrer defined for the templates even if we don't use it -$top_referrer = ''; -if($mybb->settings['statstopreferrer'] == 1 && isset($statistics['top_referrer']['uid'])) -{ - // Only show this if we have anything more the 0 referrals - if($statistics['top_referrer']['referrals'] > 0) - { - $toprefuser = build_profile_link(htmlspecialchars_uni($statistics['top_referrer']['username']), $statistics['top_referrer']['uid']); - $top_referrer = $lang->sprintf($lang->top_referrer, $toprefuser, my_number_format($statistics['top_referrer']['referrals'])); - } -} - -// Today's top poster -if(!isset($statistics['top_poster']['uid'])) -{ - $topposter = $lang->nobody; - $topposterposts = $lang->no_posts; -} -else -{ - if(!$statistics['top_poster']['uid']) - { - $topposter = $lang->guest; - } - else - { - $topposter = build_profile_link(htmlspecialchars_uni($statistics['top_poster']['username']), $statistics['top_poster']['uid']); - } - - $topposterposts = $statistics['top_poster']['poststoday']; -} - -// What percent of members have posted? -$posters = $statistics['posters']; -$havepostedpercent = my_number_format(round((($posters / $stats['numusers']) * 100), 2)) . "%"; - -$lang->todays_top_poster = $lang->sprintf($lang->todays_top_poster, $topposter, my_number_format($topposterposts)); -$lang->popular_forum = $lang->sprintf($lang->popular_forum, $topforum, my_number_format($topforumposts), my_number_format($topforumthreads)); - -$stats['numposts'] = my_number_format($stats['numposts']); -$stats['numthreads'] = my_number_format($stats['numthreads']); -$stats['numusers'] = my_number_format($stats['numusers']); -$stats['newest_user'] = build_profile_link($stats['lastusername'], $stats['lastuid']); - -$plugins->run_hooks("stats_end"); - -eval("\$stats = \"".$templates->get("stats")."\";"); -output_page($stats); diff --git a/html/forums/syndication.php b/html/forums/syndication.php deleted file mode 100644 index 2233569..0000000 --- a/html/forums/syndication.php +++ /dev/null @@ -1,235 +0,0 @@ -load("syndication"); - -// Load syndication class. -require_once MYBB_ROOT."inc/class_feedgeneration.php"; -$feedgenerator = new FeedGenerator(); - -// Load the post parser -require_once MYBB_ROOT."inc/class_parser.php"; -$parser = new postParser; - -// Find out the thread limit. -if($mybb->get_input('portal') && $mybb->settings['portal'] != 0) -{ - $thread_limit = $mybb->settings['portal_numannouncements']; -} -else -{ - $thread_limit = $mybb->get_input('limit', MyBB::INPUT_INT); -} - -if($thread_limit > 50) -{ - $thread_limit = 50; -} -else if(!$thread_limit || $thread_limit < 0) -{ - $thread_limit = 20; -} - -// Syndicate a specific forum or all viewable? -if($mybb->get_input('portal') && $mybb->settings['portal'] != 0) -{ - if($mybb->settings['portal_announcementsfid'] != '-1') - { - $forumlist = explode(',', $mybb->settings['portal_announcementsfid']); - } -} -elseif($mybb->get_input('fid')) -{ - $forumlist = explode(',', $mybb->get_input('fid')); -} - -// Get the forums the user is not allowed to see. -$unviewableforums = get_unviewable_forums(true); -$inactiveforums = get_inactive_forums(); - -$unviewable = ''; - -$plugins->run_hooks('syndication_start'); - -// If there are any, add SQL to exclude them. -if($unviewableforums) -{ - $unviewable .= " AND fid NOT IN($unviewableforums)"; -} - -if($inactiveforums) -{ - $unviewable .= " AND fid NOT IN($inactiveforums)"; -} - -// If there are no forums to syndicate, syndicate all viewable. -if(!empty($forumlist)) -{ - $forum_ids = "'-1'"; - foreach($forumlist as $fid) - { - $forum_ids .= ",'".(int)$fid."'"; - } - $forumlist = "AND fid IN ($forum_ids) $unviewable"; -} -else -{ - $forumlist = $unviewable; - $all_forums = 1; -} - -// Find out which title to add to the feed. -$title = $mybb->settings['bbname']; -$query = $db->simple_select("forums", "name, fid, allowhtml, allowmycode, allowsmilies, allowimgcode, allowvideocode", "1=1 ".$forumlist); -$comma = " - "; -while($forum = $db->fetch_array($query)) -{ - if(!$mybb->get_input('portal') || $mybb->settings['portal'] == 0) - { - $title .= $comma.$forum['name']; - $comma = $lang->comma; - } - $forumcache[$forum['fid']] = $forum; -} - -if($mybb->get_input('portal') && $mybb->settings['portal'] != 0) -{ - $title .= $comma.$lang->portal; -} - -// If syndicating all forums then cut the title back to "All Forums" -if(isset($all_forums)) -{ - if($mybb->get_input('portal') && $mybb->settings['portal'] != 0) - { - $title = $mybb->settings['bbname']." - ".$lang->portal; - } - else - { - $title = $mybb->settings['bbname']." - ".$lang->all_forums; - } -} - -// Set the feed type. -$feedgenerator->set_feed_format($mybb->get_input('type')); - -// Set the channel header. -$channel = array( - "title" => $title, - "link" => $mybb->settings['bburl']."/", - "date" => TIME_NOW, - "description" => $mybb->settings['bbname']." - ".$mybb->settings['bburl'] -); -$feedgenerator->set_channel($channel); - -$permsql = ""; -$onlyusfids = array(); - -// Check group permissions if we can't view threads not started by us -$group_permissions = forum_permissions(); -foreach($group_permissions as $fid => $forum_permissions) -{ - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $fid; - } -} -if(!empty($onlyusfids)) -{ - $permsql .= "AND ((fid IN(".implode(',', $onlyusfids).") AND uid='{$mybb->user['uid']}') OR fid NOT IN(".implode(',', $onlyusfids)."))"; -} - -// Get the threads to syndicate. -$query = $db->simple_select("threads", "subject, tid, dateline, firstpost", "visible='1' AND closed NOT LIKE 'moved|%' {$permsql} {$forumlist}", array('order_by' => 'dateline', 'order_dir' => 'DESC', 'limit' => $thread_limit)); -// Loop through all the threads. -while($thread = $db->fetch_array($query)) -{ - $items[$thread['tid']] = array( - "title" => $parser->parse_badwords($thread['subject']), - "link" => $channel['link'].get_thread_link($thread['tid']), - "date" => $thread['dateline'], - ); - - $firstposts[] = $thread['firstpost']; -} - -$plugins->run_hooks('syndication_get_posts'); - -if(!empty($firstposts)) -{ - $firstpostlist = "pid IN(".$db->escape_string(implode(',', $firstposts)).")"; - - if($mybb->settings['enableattachments'] == 1) - { - $attachments = array(); - $query = $db->simple_select("attachments", "*", $firstpostlist); - while($attachment = $db->fetch_array($query)) - { - if(!isset($attachments[$attachment['pid']])) - { - $attachments[$attachment['pid']] = array(); - } - $attachments[$attachment['pid']][] = $attachment; - } - } - - $query = $db->simple_select("posts", "message, edittime, tid, fid, pid", $firstpostlist, array('order_by' => 'dateline', 'order_dir' => 'desc')); - while($post = $db->fetch_array($query)) - { - $parser_options = array( - "allow_html" => $forumcache[$post['fid']]['allowhtml'], - "allow_mycode" => $forumcache[$post['fid']]['allowmycode'], - "allow_smilies" => $forumcache[$post['fid']]['allowsmilies'], - "allow_imgcode" => $forumcache[$post['fid']]['allowimgcode'], - "allow_videocode" => $forumcache[$post['fid']]['allowvideocode'], - "filter_badwords" => 1, - "filter_cdata" => 1 - ); - - $parsed_message = $parser->parse_message($post['message'], $parser_options); - - if($mybb->settings['enableattachments'] == 1 && isset($attachments[$post['pid']]) && is_array($attachments[$post['pid']])) - { - foreach($attachments[$post['pid']] as $attachment) - { - $ext = get_extension($attachment['filename']); - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - $attachment['filesize'] = get_friendly_size($attachment['filesize']); - $attachment['icon'] = get_attachment_icon($ext); - eval("\$attbit = \"".$templates->get("postbit_attachments_attachment")."\";"); - if(stripos($parsed_message, "[attachment=".$attachment['aid']."]") !== false) - { - $parsed_message = preg_replace("#\[attachment=".$attachment['aid']."]#si", $attbit, $parsed_message); - } - else - { - $parsed_message .= "
    ".$attbit; - } - } - } - - $items[$post['tid']]['description'] = $parsed_message; - $items[$post['tid']]['updated'] = $post['edittime']; - $feedgenerator->add_item($items[$post['tid']]); - } -} - -// Then output the feed XML. -$feedgenerator->output_feed(); diff --git a/html/forums/task.php b/html/forums/task.php deleted file mode 100644 index 8295957..0000000 --- a/html/forums/task.php +++ /dev/null @@ -1,73 +0,0 @@ -set_language($mybb->settings['bblanguage']); -$lang->load("global"); -$lang->load("messages"); - -if(function_exists('mb_internal_encoding') && !empty($lang->settings['charset'])) -{ - @mb_internal_encoding($lang->settings['charset']); -} - -require_once MYBB_ROOT."inc/functions_task.php"; - -// Are tasks set to run via cron instead & are we accessing this file via the CLI? -// php task.php [tid] -if(PHP_SAPI == "cli") -{ - // Passing a specific task ID - if($_SERVER['argc'] == 2) - { - $query = $db->simple_select("tasks", "tid", "tid='".(int)$_SERVER['argv'][1]."'"); - $tid = $db->fetch_field($query, "tid"); - } - - if($tid) - { - run_task($tid); - } - else - { - run_task(); - } -} -// Otherwise false GIF image, only supports running next available task -else -{ - // Send our fake gif image (clear 1x1 transparent image) - header("Content-type: image/gif"); - header("Expires: Sat, 1 Jan 2000 01:00:00 GMT"); - header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); - header("Cache-Control: no-cache, must-revalidate"); - header("Pragma: no-cache"); - echo base64_decode("R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="); - - // If the use shutdown functionality is turned off, run any shutdown related items now. - if($mybb->use_shutdown == true) - { - add_shutdown("run_task"); - } - else - { - run_task(); - } -} diff --git a/html/forums/uploads/avatars/index.html b/html/forums/uploads/avatars/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/uploads/avatars/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/uploads/index.html b/html/forums/uploads/index.html deleted file mode 100644 index efd2f36..0000000 --- a/html/forums/uploads/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -  - - \ No newline at end of file diff --git a/html/forums/usercp.php b/html/forums/usercp.php deleted file mode 100644 index 40caf74..0000000 --- a/html/forums/usercp.php +++ /dev/null @@ -1,4155 +0,0 @@ -load("usercp"); - -if($mybb->user['uid'] == 0 || $mybb->usergroup['canusercp'] == 0) -{ - error_no_permission(); -} - -if(!$mybb->user['pmfolders']) -{ - $mybb->user['pmfolders'] = '1**$%%$2**$%%$3**$%%$4**'; - $db->update_query('users', array('pmfolders' => $mybb->user['pmfolders']), "uid = {$mybb->user['uid']}"); -} - -$errors = ''; - -$mybb->input['action'] = $mybb->get_input('action'); - -usercp_menu(); - -$plugins->run_hooks("usercp_start"); -if($mybb->input['action'] == "do_editsig" && $mybb->request_method == "post") -{ - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler(); - - $data = array( - 'uid' => $mybb->user['uid'], - 'signature' => $mybb->get_input('signature'), - ); - - $userhandler->set_data($data); - - if(!$userhandler->verify_signature()) - { - $error = inline_error($userhandler->get_friendly_errors()); - } - - if(isset($error) || !empty($mybb->input['preview'])) - { - $mybb->input['action'] = "editsig"; - } -} - -// Make navigation -add_breadcrumb($lang->nav_usercp, "usercp.php"); - -switch($mybb->input['action']) -{ - case "profile": - case "do_profile": - add_breadcrumb($lang->ucp_nav_profile); - break; - case "options": - case "do_options": - add_breadcrumb($lang->nav_options); - break; - case "email": - case "do_email": - add_breadcrumb($lang->nav_email); - break; - case "password": - case "do_password": - add_breadcrumb($lang->nav_password); - break; - case "changename": - case "do_changename": - add_breadcrumb($lang->nav_changename); - break; - case "subscriptions": - add_breadcrumb($lang->ucp_nav_subscribed_threads); - break; - case "forumsubscriptions": - add_breadcrumb($lang->ucp_nav_forum_subscriptions); - break; - case "editsig": - case "do_editsig": - add_breadcrumb($lang->nav_editsig); - break; - case "avatar": - case "do_avatar": - add_breadcrumb($lang->nav_avatar); - break; - case "notepad": - case "do_notepad": - add_breadcrumb($lang->ucp_nav_notepad); - break; - case "editlists": - case "do_editlists": - add_breadcrumb($lang->ucp_nav_editlists); - break; - case "drafts": - add_breadcrumb($lang->ucp_nav_drafts); - break; - case "usergroups": - add_breadcrumb($lang->ucp_nav_usergroups); - break; - case "attachments": - add_breadcrumb($lang->ucp_nav_attachments); - break; -} - -if($mybb->input['action'] == "do_profile" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("usercp_do_profile_start"); - - if($mybb->get_input('away', MyBB::INPUT_INT) == 1 && $mybb->settings['allowaway'] != 0) - { - $awaydate = TIME_NOW; - if(!empty($mybb->input['awayday'])) - { - // If the user has indicated that they will return on a specific day, but not month or year, assume it is current month and year - if(!$mybb->get_input('awaymonth', MyBB::INPUT_INT)) - { - $mybb->input['awaymonth'] = my_date('n', $awaydate); - } - if(!$mybb->get_input('awayyear', MyBB::INPUT_INT)) - { - $mybb->input['awayyear'] = my_date('Y', $awaydate); - } - - $return_month = (int)substr($mybb->get_input('awaymonth'), 0, 2); - $return_day = (int)substr($mybb->get_input('awayday'), 0, 2); - $return_year = min((int)$mybb->get_input('awayyear'), 9999); - - // Check if return date is after the away date. - $returntimestamp = gmmktime(0, 0, 0, $return_month, $return_day, $return_year); - $awaytimestamp = gmmktime(0, 0, 0, my_date('n', $awaydate), my_date('j', $awaydate), my_date('Y', $awaydate)); - if($return_year < my_date('Y', $awaydate) || ($returntimestamp < $awaytimestamp && $return_year == my_date('Y', $awaydate))) - { - error($lang->error_usercp_return_date_past); - } - - $returndate = "{$return_day}-{$return_month}-{$return_year}"; - } - else - { - $returndate = ""; - } - $away = array( - "away" => 1, - "date" => $awaydate, - "returndate" => $returndate, - "awayreason" => $mybb->get_input('awayreason') - ); - } - else - { - $away = array( - "away" => 0, - "date" => '', - "returndate" => '', - "awayreason" => '' - ); - } - - $bday = array( - "day" => $mybb->get_input('bday1', MyBB::INPUT_INT), - "month" => $mybb->get_input('bday2', MyBB::INPUT_INT), - "year" => $mybb->get_input('bday3', MyBB::INPUT_INT) - ); - - // Set up user handler. - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler("update"); - - $user = array( - "uid" => $mybb->user['uid'], - "postnum" => $mybb->user['postnum'], - "usergroup" => $mybb->user['usergroup'], - "additionalgroups" => $mybb->user['additionalgroups'], - "birthday" => $bday, - "birthdayprivacy" => $mybb->get_input('birthdayprivacy'), - "away" => $away, - "profile_fields" => $mybb->get_input('profile_fields', MyBB::INPUT_ARRAY) - ); - foreach(array('icq', 'aim', 'yahoo', 'skype', 'google') as $cfield) - { - $csetting = 'allow'.$cfield.'field'; - if($mybb->settings[$csetting] == '') - { - continue; - } - - if(!is_member($mybb->settings[$csetting])) - { - continue; - } - - if($cfield == 'icq') - { - $user[$cfield] = $mybb->get_input($cfield, 1); - } - else - { - $user[$cfield] = $mybb->get_input($cfield); - } - } - - if($mybb->usergroup['canchangewebsite'] == 1) - { - $user['website'] = $mybb->get_input('website'); - } - - if($mybb->usergroup['cancustomtitle'] == 1) - { - if($mybb->get_input('usertitle') != '') - { - $user['usertitle'] = $mybb->get_input('usertitle'); - } - else if(!empty($mybb->input['reverttitle'])) - { - $user['usertitle'] = ''; - } - } - $userhandler->set_data($user); - - if(!$userhandler->validate_user()) - { - $errors = $userhandler->get_friendly_errors(); - - // Set allowed value otherwise select options disappear - if(in_array($lang->userdata_invalid_birthday_privacy, $errors)) - { - $mybb->input['birthdayprivacy'] = 'none'; - } - - $errors = inline_error($errors); - $mybb->input['action'] = "profile"; - } - else - { - $userhandler->update_user(); - - $plugins->run_hooks("usercp_do_profile_end"); - redirect("usercp.php?action=profile", $lang->redirect_profileupdated); - } -} - -if($mybb->input['action'] == "profile") -{ - if($errors) - { - $user = $mybb->input; - $bday = array(); - $bday[0] = $mybb->get_input('bday1', MyBB::INPUT_INT); - $bday[1] = $mybb->get_input('bday2', MyBB::INPUT_INT); - $bday[2] = $mybb->get_input('bday3', MyBB::INPUT_INT); - } - else - { - $user = $mybb->user; - $bday = explode("-", $user['birthday']); - if(!isset($bday[1])) - { - $bday[1] = 0; - } - if(!isset($bday[2])) - { - $bday[2] = ''; - } - } - - $plugins->run_hooks("usercp_profile_start"); - - $bdaydaysel = ''; - for($day = 1; $day <= 31; ++$day) - { - if($bday[0] == $day) - { - $selected = "selected=\"selected\""; - } - else - { - $selected = ''; - } - - eval("\$bdaydaysel .= \"".$templates->get("usercp_profile_day")."\";"); - } - - $bdaymonthsel = array(); - foreach(range(1, 12) as $month) - { - $bdaymonthsel[$month] = ''; - } - $bdaymonthsel[$bday[1]] = 'selected="selected"'; - - $allselected = $noneselected = $ageselected = ''; - if($user['birthdayprivacy'] == 'all' || !$user['birthdayprivacy']) - { - $allselected = " selected=\"selected\""; - } - else if($user['birthdayprivacy'] == 'none') - { - $noneselected = " selected=\"selected\""; - } - else if($user['birthdayprivacy'] == 'age') - { - $ageselected = " selected=\"selected\""; - } - - if(!my_validate_url($user['website'])) - { - $user['website'] = ''; - } - else - { - $user['website'] = htmlspecialchars_uni($user['website']); - } - - if($user['icq'] != "0") - { - $user['icq'] = (int)$user['icq']; - } - - if($user['icq'] == 0) - { - $user['icq'] = ''; - } - - if($errors) - { - $user['skype'] = htmlspecialchars_uni($user['skype']); - $user['google'] = htmlspecialchars_uni($user['google']); - $user['aim'] = htmlspecialchars_uni($user['aim']); - $user['yahoo'] = htmlspecialchars_uni($user['yahoo']); - } - - $contact_fields = array(); - $contactfields = ''; - $cfieldsshow = false; - - foreach(array('icq', 'aim', 'yahoo', 'skype', 'google') as $cfield) - { - $contact_fields[$cfield] = ''; - $csetting = 'allow'.$cfield.'field'; - if($mybb->settings[$csetting] == '') - { - continue; - } - - if(!is_member($mybb->settings[$csetting])) - { - continue; - } - - $cfieldsshow = true; - - $lang_string = 'contact_field_'.$cfield; - $lang_string = $lang->{$lang_string}; - $cfvalue = htmlspecialchars_uni($user[$cfield]); - - eval('$contact_fields[$cfield] = "'.$templates->get('usercp_profile_contact_fields_field').'";'); - } - - if($cfieldsshow) - { - eval('$contactfields = "'.$templates->get('usercp_profile_contact_fields').'";'); - } - - if($mybb->settings['allowaway'] != 0) - { - $awaycheck = array('', ''); - if($errors) - { - if($user['away'] == 1) - { - $awaycheck[1] = "checked=\"checked\""; - } - else - { - $awaycheck[0] = "checked=\"checked\""; - } - $returndate = array(); - $returndate[0] = $mybb->get_input('awayday', MyBB::INPUT_INT); - $returndate[1] = $mybb->get_input('awaymonth', MyBB::INPUT_INT); - $returndate[2] = $mybb->get_input('awayyear', MyBB::INPUT_INT); - $user['awayreason'] = htmlspecialchars_uni($mybb->get_input('awayreason')); - } - else - { - $user['awayreason'] = htmlspecialchars_uni($user['awayreason']); - if($mybb->user['away'] == 1) - { - $awaydate = my_date($mybb->settings['dateformat'], $mybb->user['awaydate']); - $awaycheck[1] = "checked=\"checked\""; - $awaynotice = $lang->sprintf($lang->away_notice_away, $awaydate); - } - else - { - $awaynotice = $lang->away_notice; - $awaycheck[0] = "checked=\"checked\""; - } - $returndate = explode("-", $mybb->user['returndate']); - if(!isset($returndate[1])) - { - $returndate[1] = 0; - } - if(!isset($returndate[2])) - { - $returndate[2] = ''; - } - } - - $returndatesel = ''; - for($day = 1; $day <= 31; ++$day) - { - if($returndate[0] == $day) - { - $selected = "selected=\"selected\""; - } - else - { - $selected = ''; - } - - eval("\$returndatesel .= \"".$templates->get("usercp_profile_day")."\";"); - } - - $returndatemonthsel = array(); - foreach(range(1, 12) as $month) - { - $returndatemonthsel[$month] = ''; - } - $returndatemonthsel[$returndate[1]] = "selected"; - - eval("\$awaysection = \"".$templates->get("usercp_profile_away")."\";"); - } - - // Custom profile fields baby! - $altbg = "trow1"; - $requiredfields = $customfields = ''; - $mybb->input['profile_fields'] = $mybb->get_input('profile_fields', MyBB::INPUT_ARRAY); - - $pfcache = $cache->read('profilefields'); - - if(is_array($pfcache)) - { - foreach($pfcache as $profilefield) - { - if(!is_member($profilefield['editableby']) || ($profilefield['postnum'] && $profilefield['postnum'] > $mybb->user['postnum'])) - { - continue; - } - - $profilefield['type'] = htmlspecialchars_uni($profilefield['type']); - $profilefield['name'] = htmlspecialchars_uni($profilefield['name']); - $profilefield['description'] = htmlspecialchars_uni($profilefield['description']); - $thing = explode("\n", $profilefield['type'], "2"); - $type = $thing[0]; - if(isset($thing[1])) - { - $options = $thing[1]; - } - else - { - $options = array(); - } - $field = "fid{$profilefield['fid']}"; - $select = ''; - if($errors) - { - if(!isset($mybb->input['profile_fields'][$field])) - { - $mybb->input['profile_fields'][$field] = ''; - } - $userfield = $mybb->input['profile_fields'][$field]; - } - else - { - $userfield = $user[$field]; - } - if($type == "multiselect") - { - if($errors) - { - $useropts = $userfield; - } - else - { - $useropts = explode("\n", $userfield); - } - if(is_array($useropts)) - { - foreach($useropts as $key => $val) - { - $val = htmlspecialchars_uni($val); - $seloptions[$val] = $val; - } - } - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $val = trim($val); - $val = str_replace("\n", "\\n", $val); - - $sel = ""; - if(isset($seloptions[$val]) && $val == $seloptions[$val]) - { - $sel = " selected=\"selected\""; - } - - eval("\$select .= \"".$templates->get("usercp_profile_profilefields_select_option")."\";"); - } - if(!$profilefield['length']) - { - $profilefield['length'] = 3; - } - - eval("\$code = \"".$templates->get("usercp_profile_profilefields_multiselect")."\";"); - } - } - elseif($type == "select") - { - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $val = trim($val); - $val = str_replace("\n", "\\n", $val); - $sel = ""; - if($val == htmlspecialchars_uni($userfield)) - { - $sel = " selected=\"selected\""; - } - - eval("\$select .= \"".$templates->get("usercp_profile_profilefields_select_option")."\";"); - } - if(!$profilefield['length']) - { - $profilefield['length'] = 1; - } - - eval("\$code = \"".$templates->get("usercp_profile_profilefields_select")."\";"); - } - } - elseif($type == "radio") - { - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $checked = ""; - if($val == $userfield) - { - $checked = " checked=\"checked\""; - } - - eval("\$code .= \"".$templates->get("usercp_profile_profilefields_radio")."\";"); - } - } - } - elseif($type == "checkbox") - { - if($errors) - { - $useropts = $userfield; - } - else - { - $useropts = explode("\n", $userfield); - } - if(is_array($useropts)) - { - foreach($useropts as $key => $val) - { - $seloptions[$val] = $val; - } - } - $expoptions = explode("\n", $options); - if(is_array($expoptions)) - { - foreach($expoptions as $key => $val) - { - $checked = ""; - if(isset($seloptions[$val]) && $val == $seloptions[$val]) - { - $checked = " checked=\"checked\""; - } - - eval("\$code .= \"".$templates->get("usercp_profile_profilefields_checkbox")."\";"); - } - } - } - elseif($type == "textarea") - { - $value = htmlspecialchars_uni($userfield); - eval("\$code = \"".$templates->get("usercp_profile_profilefields_textarea")."\";"); - } - else - { - $value = htmlspecialchars_uni($userfield); - $maxlength = ""; - if($profilefield['maxlength'] > 0) - { - $maxlength = " maxlength=\"{$profilefield['maxlength']}\""; - } - - eval("\$code = \"".$templates->get("usercp_profile_profilefields_text")."\";"); - } - - if($profilefield['required'] == 1) - { - eval("\$requiredfields .= \"".$templates->get("usercp_profile_customfield")."\";"); - } - else - { - eval("\$customfields .= \"".$templates->get("usercp_profile_customfield")."\";"); - } - $altbg = alt_trow(); - $code = ""; - $select = ""; - $val = ""; - $options = ""; - $expoptions = ""; - $useropts = ""; - $seloptions = array(); - } - } - if($customfields) - { - eval("\$customfields = \"".$templates->get("usercp_profile_profilefields")."\";"); - } - - if($mybb->usergroup['cancustomtitle'] == 1) - { - if($mybb->usergroup['usertitle'] == "") - { - $defaulttitle = ''; - $usertitles = $cache->read('usertitles'); - - foreach($usertitles as $title) - { - if($title['posts'] <= $mybb->user['postnum']) - { - $defaulttitle = htmlspecialchars_uni($title['title']); - break; - } - } - } - else - { - $defaulttitle = htmlspecialchars_uni($mybb->usergroup['usertitle']); - } - - $newtitle = ''; - if(trim($user['usertitle']) == '') - { - $lang->current_custom_usertitle = ''; - } - else - { - if($errors) - { - $newtitle = htmlspecialchars_uni($user['usertitle']); - $user['usertitle'] = $mybb->user['usertitle']; - } - } - - $user['usertitle'] = htmlspecialchars_uni($user['usertitle']); - - $currentcustom = $reverttitle = ''; - if(!empty($mybb->user['usertitle'])) - { - eval("\$currentcustom = \"".$templates->get("usercp_profile_customtitle_currentcustom")."\";"); - - if($mybb->user['usertitle'] != $mybb->usergroup['usertitle']) - { - eval("\$reverttitle = \"".$templates->get("usercp_profile_customtitle_reverttitle")."\";"); - } - } - - eval("\$customtitle = \"".$templates->get("usercp_profile_customtitle")."\";"); - } - else - { - $customtitle = ""; - } - - if($mybb->usergroup['canchangewebsite'] == 1) - { - eval("\$website = \"".$templates->get("usercp_profile_website")."\";"); - } - - $plugins->run_hooks("usercp_profile_end"); - - eval("\$editprofile = \"".$templates->get("usercp_profile")."\";"); - output_page($editprofile); -} - -if($mybb->input['action'] == "do_options" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("usercp_do_options_start"); - - // Set up user handler. - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler("update"); - - $user = array( - "uid" => $mybb->user['uid'], - "style" => $mybb->get_input('style', MyBB::INPUT_INT), - "dateformat" => $mybb->get_input('dateformat', MyBB::INPUT_INT), - "timeformat" => $mybb->get_input('timeformat', MyBB::INPUT_INT), - "timezone" => $db->escape_string($mybb->get_input('timezoneoffset')), - "language" => $mybb->get_input('language'), - 'usergroup' => $mybb->user['usergroup'], - 'additionalgroups' => $mybb->user['additionalgroups'] - ); - - $user['options'] = array( - "allownotices" => $mybb->get_input('allownotices', MyBB::INPUT_INT), - "hideemail" => $mybb->get_input('hideemail', MyBB::INPUT_INT), - "subscriptionmethod" => $mybb->get_input('subscriptionmethod', MyBB::INPUT_INT), - "invisible" => $mybb->get_input('invisible', MyBB::INPUT_INT), - "dstcorrection" => $mybb->get_input('dstcorrection', MyBB::INPUT_INT), - "threadmode" => $mybb->get_input('threadmode'), - "showimages" => $mybb->get_input('showimages', MyBB::INPUT_INT), - "showvideos" => $mybb->get_input('showvideos', MyBB::INPUT_INT), - "showsigs" => $mybb->get_input('showsigs', MyBB::INPUT_INT), - "showavatars" => $mybb->get_input('showavatars', MyBB::INPUT_INT), - "showquickreply" => $mybb->get_input('showquickreply', MyBB::INPUT_INT), - "receivepms" => $mybb->get_input('receivepms', MyBB::INPUT_INT), - "pmnotice" => $mybb->get_input('pmnotice', MyBB::INPUT_INT), - "receivefrombuddy" => $mybb->get_input('receivefrombuddy', MyBB::INPUT_INT), - "daysprune" => $mybb->get_input('daysprune', MyBB::INPUT_INT), - "showcodebuttons" => $mybb->get_input('showcodebuttons', MyBB::INPUT_INT), - "sourceeditor" => $mybb->get_input('sourceeditor', MyBB::INPUT_INT), - "pmnotify" => $mybb->get_input('pmnotify', MyBB::INPUT_INT), - "buddyrequestspm" => $mybb->get_input('buddyrequestspm', MyBB::INPUT_INT), - "buddyrequestsauto" => $mybb->get_input('buddyrequestsauto', MyBB::INPUT_INT), - "showredirect" => $mybb->get_input('showredirect', MyBB::INPUT_INT), - "classicpostbit" => $mybb->get_input('classicpostbit', MyBB::INPUT_INT) - ); - - if($mybb->settings['usertppoptions']) - { - $user['options']['tpp'] = $mybb->get_input('tpp', MyBB::INPUT_INT); - } - - if($mybb->settings['userpppoptions']) - { - $user['options']['ppp'] = $mybb->get_input('ppp', MyBB::INPUT_INT); - } - - $userhandler->set_data($user); - - if(!$userhandler->validate_user()) - { - $errors = $userhandler->get_friendly_errors(); - $errors = inline_error($errors); - $mybb->input['action'] = "options"; - } - else - { - $userhandler->update_user(); - - $plugins->run_hooks("usercp_do_options_end"); - - redirect("usercp.php?action=options", $lang->redirect_optionsupdated); - } -} - -if($mybb->input['action'] == "options") -{ - $plugins->run_hooks("usercp_options_start"); - - if($errors != '') - { - $user = $mybb->input; - } - else - { - $user = $mybb->user; - } - - $languages = $lang->get_languages(); - $board_language = $langoptions = ''; - if(count($languages) > 1) - { - foreach($languages as $name => $language) - { - $language = htmlspecialchars_uni($language); - - $sel = ''; - if(isset($user['language']) && $user['language'] == $name) - { - $sel = " selected=\"selected\""; - } - - eval('$langoptions .= "'.$templates->get('usercp_options_language_option').'";'); - } - - eval('$board_language = "'.$templates->get('usercp_options_language').'";'); - } - - // Lets work out which options the user has selected and check the boxes - if(isset($user['allownotices']) && $user['allownotices'] == 1) - { - $allownoticescheck = "checked=\"checked\""; - } - else - { - $allownoticescheck = ""; - } - - if(isset($user['invisible']) && $user['invisible'] == 1) - { - $invisiblecheck = "checked=\"checked\""; - } - else - { - $invisiblecheck = ""; - } - - if(isset($user['hideemail']) && $user['hideemail'] == 1) - { - $hideemailcheck = "checked=\"checked\""; - } - else - { - $hideemailcheck = ""; - } - - $no_auto_subscribe_selected = $instant_email_subscribe_selected = $instant_pm_subscribe_selected = $no_subscribe_selected = ''; - if(isset($user['subscriptionmethod']) && $user['subscriptionmethod'] == 1) - { - $no_subscribe_selected = "selected=\"selected\""; - } - else if(isset($user['subscriptionmethod']) && $user['subscriptionmethod'] == 2) - { - $instant_email_subscribe_selected = "selected=\"selected\""; - } - else if(isset($user['subscriptionmethod']) && $user['subscriptionmethod'] == 3) - { - $instant_pm_subscribe_selected = "selected=\"selected\""; - } - else - { - $no_auto_subscribe_selected = "selected=\"selected\""; - } - - if(isset($user['showimages']) && $user['showimages'] == 1) - { - $showimagescheck = "checked=\"checked\""; - } - else - { - $showimagescheck = ""; - } - - if(isset($user['showvideos']) && $user['showvideos'] == 1) - { - $showvideoscheck = "checked=\"checked\""; - } - else - { - $showvideoscheck = ""; - } - - if(isset($user['showsigs']) && $user['showsigs'] == 1) - { - $showsigscheck = "checked=\"checked\""; - } - else - { - $showsigscheck = ""; - } - - if(isset($user['showavatars']) && $user['showavatars'] == 1) - { - $showavatarscheck = "checked=\"checked\""; - } - else - { - $showavatarscheck = ""; - } - - if(isset($user['showquickreply']) && $user['showquickreply'] == 1) - { - $showquickreplycheck = "checked=\"checked\""; - } - else - { - $showquickreplycheck = ""; - } - - if(isset($user['receivepms']) && $user['receivepms'] == 1) - { - $receivepmscheck = "checked=\"checked\""; - } - else - { - $receivepmscheck = ""; - } - - if(isset($user['receivefrombuddy']) && $user['receivefrombuddy'] == 1) - { - $receivefrombuddycheck = "checked=\"checked\""; - } - else - { - $receivefrombuddycheck = ""; - } - - if(isset($user['pmnotice']) && $user['pmnotice'] >= 1) - { - $pmnoticecheck = " checked=\"checked\""; - } - else - { - $pmnoticecheck = ""; - } - - $dst_auto_selected = $dst_enabled_selected = $dst_disabled_selected = ''; - if(isset($user['dstcorrection']) && $user['dstcorrection'] == 2) - { - $dst_auto_selected = "selected=\"selected\""; - } - else if(isset($user['dstcorrection']) && $user['dstcorrection'] == 1) - { - $dst_enabled_selected = "selected=\"selected\""; - } - else - { - $dst_disabled_selected = "selected=\"selected\""; - } - - if(isset($user['showcodebuttons']) && $user['showcodebuttons'] == 1) - { - $showcodebuttonscheck = "checked=\"checked\""; - } - else - { - $showcodebuttonscheck = ""; - } - - if(isset($user['sourceeditor']) && $user['sourceeditor'] == 1) - { - $sourcemodecheck = "checked=\"checked\""; - } - else - { - $sourcemodecheck = ""; - } - - if(isset($user['showredirect']) && $user['showredirect'] != 0) - { - $showredirectcheck = "checked=\"checked\""; - } - else - { - $showredirectcheck = ""; - } - - if(isset($user['pmnotify']) && $user['pmnotify'] != 0) - { - $pmnotifycheck = "checked=\"checked\""; - } - else - { - $pmnotifycheck = ''; - } - - if(isset($user['buddyrequestspm']) && $user['buddyrequestspm'] != 0) - { - $buddyrequestspmcheck = "checked=\"checked\""; - } - else - { - $buddyrequestspmcheck = ''; - } - - if(isset($user['buddyrequestsauto']) && $user['buddyrequestsauto'] != 0) - { - $buddyrequestsautocheck = "checked=\"checked\""; - } - else - { - $buddyrequestsautocheck = ''; - } - - if(!isset($user['threadmode']) || ($user['threadmode'] != "threaded" && $user['threadmode'] != "linear")) - { - $user['threadmode'] = ''; // Leave blank to show default - } - - if(isset($user['classicpostbit']) && $user['classicpostbit'] != 0) - { - $classicpostbitcheck = "checked=\"checked\""; - } - else - { - $classicpostbitcheck = ''; - } - - $date_format_options = $dateformat = ''; - foreach($date_formats as $key => $format) - { - $selected = ''; - if(isset($user['dateformat']) && $user['dateformat'] == $key) - { - $selected = " selected=\"selected\""; - } - - $dateformat = my_date($format, TIME_NOW, "", 0); - eval("\$date_format_options .= \"".$templates->get("usercp_options_date_format")."\";"); - } - - $time_format_options = $timeformat = ''; - foreach($time_formats as $key => $format) - { - $selected = ''; - if(isset($user['timeformat']) && $user['timeformat'] == $key) - { - $selected = " selected=\"selected\""; - } - - $timeformat = my_date($format, TIME_NOW, "", 0); - eval("\$time_format_options .= \"".$templates->get("usercp_options_time_format")."\";"); - } - - $tzselect = build_timezone_select("timezoneoffset", $mybb->user['timezone'], true); - - $pms_from_buddys = ''; - if($mybb->settings['allowbuddyonly'] == 1) - { - eval("\$pms_from_buddys = \"".$templates->get("usercp_options_pms_from_buddys")."\";"); - } - - $pms = ''; - if($mybb->settings['enablepms'] != 0 && $mybb->usergroup['canusepms'] == 1) - { - eval("\$pms = \"".$templates->get("usercp_options_pms")."\";"); - } - - $quick_reply = ''; - if($mybb->settings['quickreply'] == 1) - { - eval("\$quick_reply = \"".$templates->get("usercp_options_quick_reply")."\";"); - } - - $threadview = array('linear' => '', 'threaded' => ''); - if(isset($user['threadmode']) && is_scalar($user['threadmode'])) - { - $threadview[$user['threadmode']] = 'selected="selected"'; - } - $daysprunesel = array(1 => '', 5 => '', 10 => '', 20 => '', 50 => '', 75 => '', 100 => '', 365 => '', 9999 => ''); - if(isset($user['daysprune']) && is_numeric($user['daysprune'])) - { - $daysprunesel[$user['daysprune']] = 'selected="selected"'; - } - if(!isset($user['style'])) - { - $user['style'] = ''; - } - - $board_style = $stylelist = ''; - $stylelist = build_theme_select("style", $user['style']); - - if(!empty($stylelist)) - { - eval('$board_style = "'.$templates->get('usercp_options_style').'";'); - } - - $tppselect = $pppselect = ''; - if($mybb->settings['usertppoptions']) - { - $explodedtpp = explode(",", $mybb->settings['usertppoptions']); - $tppoptions = $tpp_option = ''; - if(is_array($explodedtpp)) - { - foreach($explodedtpp as $key => $val) - { - $val = trim($val); - $selected = ""; - if(isset($user['tpp']) && $user['tpp'] == $val) - { - $selected = " selected=\"selected\""; - } - - $tpp_option = $lang->sprintf($lang->tpp_option, $val); - eval("\$tppoptions .= \"".$templates->get("usercp_options_tppselect_option")."\";"); - } - } - eval("\$tppselect = \"".$templates->get("usercp_options_tppselect")."\";"); - } - - if($mybb->settings['userpppoptions']) - { - $explodedppp = explode(",", $mybb->settings['userpppoptions']); - $pppoptions = $ppp_option = ''; - if(is_array($explodedppp)) - { - foreach($explodedppp as $key => $val) - { - $val = trim($val); - $selected = ""; - if(isset($user['ppp']) && $user['ppp'] == $val) - { - $selected = " selected=\"selected\""; - } - - $ppp_option = $lang->sprintf($lang->ppp_option, $val); - eval("\$pppoptions .= \"".$templates->get("usercp_options_pppselect_option")."\";"); - } - } - eval("\$pppselect = \"".$templates->get("usercp_options_pppselect")."\";"); - } - - $plugins->run_hooks("usercp_options_end"); - - eval("\$editprofile = \"".$templates->get("usercp_options")."\";"); - output_page($editprofile); -} - -if($mybb->input['action'] == "do_email" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $errors = array(); - - $plugins->run_hooks("usercp_do_email_start"); - if(validate_password_from_uid($mybb->user['uid'], $mybb->get_input('password')) == false) - { - $errors[] = $lang->error_invalidpassword; - } - else - { - // Set up user handler. - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler("update"); - - $user = array( - "uid" => $mybb->user['uid'], - "email" => $mybb->get_input('email'), - "email2" => $mybb->get_input('email2') - ); - - $userhandler->set_data($user); - - if(!$userhandler->validate_user()) - { - $errors = $userhandler->get_friendly_errors(); - } - else - { - if($mybb->user['usergroup'] != "5" && $mybb->usergroup['cancp'] != 1 && $mybb->settings['regtype'] != "verify") - { - $uid = $mybb->user['uid']; - $username = $mybb->user['username']; - - // Emails require verification - $activationcode = random_str(); - $db->delete_query("awaitingactivation", "uid='".$mybb->user['uid']."'"); - - $newactivation = array( - "uid" => $mybb->user['uid'], - "dateline" => TIME_NOW, - "code" => $activationcode, - "type" => "e", - "misc" => $db->escape_string($mybb->get_input('email')) - ); - - $db->insert_query("awaitingactivation", $newactivation); - - $mail_message = $lang->sprintf($lang->email_changeemail, $mybb->user['username'], $mybb->settings['bbname'], $mybb->user['email'], $mybb->get_input('email'), $mybb->settings['bburl'], $activationcode, $mybb->user['username'], $mybb->user['uid']); - - $lang->emailsubject_changeemail = $lang->sprintf($lang->emailsubject_changeemail, $mybb->settings['bbname']); - my_mail($mybb->get_input('email'), $lang->emailsubject_changeemail, $mail_message); - - $plugins->run_hooks("usercp_do_email_verify"); - error($lang->redirect_changeemail_activation); - } - else - { - $userhandler->update_user(); - // Email requires no activation - $mail_message = $lang->sprintf($lang->email_changeemail_noactivation, $mybb->user['username'], $mybb->settings['bbname'], $mybb->user['email'], $mybb->get_input('email'), $mybb->settings['bburl']); - my_mail($mybb->get_input('email'), $lang->sprintf($lang->emailsubject_changeemail, $mybb->settings['bbname']), $mail_message); - $plugins->run_hooks("usercp_do_email_changed"); - redirect("usercp.php?action=email", $lang->redirect_emailupdated); - } - } - } - if(count($errors) > 0) - { - $mybb->input['action'] = "email"; - $errors = inline_error($errors); - } -} - -if($mybb->input['action'] == "email") -{ - // Coming back to this page after one or more errors were experienced, show fields the user previously entered (with the exception of the password) - if($errors) - { - $email = htmlspecialchars_uni($mybb->get_input('email')); - $email2 = htmlspecialchars_uni($mybb->get_input('email2')); - } - else - { - $email = $email2 = ''; - } - - $plugins->run_hooks("usercp_email"); - - eval("\$changemail = \"".$templates->get("usercp_email")."\";"); - output_page($changemail); -} - -if($mybb->input['action'] == "do_password" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $errors = array(); - - $plugins->run_hooks("usercp_do_password_start"); - if(validate_password_from_uid($mybb->user['uid'], $mybb->get_input('oldpassword')) == false) - { - $errors[] = $lang->error_invalidpassword; - } - else - { - // Set up user handler. - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler("update"); - - $user = array( - "uid" => $mybb->user['uid'], - "password" => $mybb->get_input('password'), - "password2" => $mybb->get_input('password2') - ); - - $userhandler->set_data($user); - - if(!$userhandler->validate_user()) - { - $errors = $userhandler->get_friendly_errors(); - } - else - { - $userhandler->update_user(); - my_setcookie("mybbuser", $mybb->user['uid']."_".$userhandler->data['loginkey'], null, true); - - // Notify the user by email that their password has been changed - $mail_message = $lang->sprintf($lang->email_changepassword, $mybb->user['username'], $mybb->user['email'], $mybb->settings['bbname'], $mybb->settings['bburl']); - $lang->emailsubject_changepassword = $lang->sprintf($lang->emailsubject_changepassword, $mybb->settings['bbname']); - my_mail($mybb->user['email'], $lang->emailsubject_changepassword, $mail_message); - - $plugins->run_hooks("usercp_do_password_end"); - redirect("usercp.php?action=password", $lang->redirect_passwordupdated); - } - } - if(count($errors) > 0) - { - $mybb->input['action'] = "password"; - $errors = inline_error($errors); - } -} - -if($mybb->input['action'] == "password") -{ - $plugins->run_hooks("usercp_password"); - - eval("\$editpassword = \"".$templates->get("usercp_password")."\";"); - output_page($editpassword); -} - -if($mybb->input['action'] == "do_changename" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("usercp_do_changename_start"); - if($mybb->usergroup['canchangename'] != 1) - { - error_no_permission(); - } - - if(validate_password_from_uid($mybb->user['uid'], $mybb->get_input('password')) == false) - { - $errors[] = $lang->error_invalidpassword; - } - else - { - // Set up user handler. - require_once MYBB_ROOT."inc/datahandlers/user.php"; - $userhandler = new UserDataHandler("update"); - - $user = array( - "uid" => $mybb->user['uid'], - "username" => $mybb->get_input('username') - ); - - $userhandler->set_data($user); - - if(!$userhandler->validate_user()) - { - $errors = $userhandler->get_friendly_errors(); - } - else - { - $userhandler->update_user(); - $plugins->run_hooks("usercp_do_changename_end"); - redirect("usercp.php?action=changename", $lang->redirect_namechanged); - - } - } - if(count($errors) > 0) - { - $errors = inline_error($errors); - $mybb->input['action'] = "changename"; - } -} - -if($mybb->input['action'] == "changename") -{ - $plugins->run_hooks("usercp_changename_start"); - if($mybb->usergroup['canchangename'] != 1) - { - error_no_permission(); - } - - $plugins->run_hooks("usercp_changename_end"); - - eval("\$changename = \"".$templates->get("usercp_changename")."\";"); - output_page($changename); -} - -if($mybb->input['action'] == "do_subscriptions") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("usercp_do_subscriptions_start"); - - if(!isset($mybb->input['check']) || !is_array($mybb->input['check'])) - { - error($lang->no_subscriptions_selected); - } - - // Clean input - only accept integers thanks! - $mybb->input['check'] = array_map('intval', $mybb->get_input('check', MyBB::INPUT_ARRAY)); - $tids = implode(",", $mybb->input['check']); - - // Deleting these subscriptions? - if($mybb->get_input('do') == "delete") - { - $db->delete_query("threadsubscriptions", "tid IN ($tids) AND uid='{$mybb->user['uid']}'"); - } - // Changing subscription type - else - { - if($mybb->get_input('do') == "no_notification") - { - $new_notification = 0; - } - else if($mybb->get_input('do') == "email_notification") - { - $new_notification = 1; - } - else if($mybb->get_input('do') == "pm_notification") - { - $new_notification = 2; - } - - // Update - $update_array = array("notification" => $new_notification); - $db->update_query("threadsubscriptions", $update_array, "tid IN ($tids) AND uid='{$mybb->user['uid']}'"); - } - - // Done, redirect - redirect("usercp.php?action=subscriptions", $lang->redirect_subscriptions_updated); -} - -if($mybb->input['action'] == "subscriptions") -{ - $plugins->run_hooks("usercp_subscriptions_start"); - - // Thread visiblity - $visible = "AND t.visible != 0"; - if(is_moderator() == true) - { - $visible = ''; - } - - // Do Multi Pages - $query = $db->query(" - SELECT COUNT(ts.tid) as threads - FROM ".TABLE_PREFIX."threadsubscriptions ts - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid = ts.tid) - WHERE ts.uid = '".$mybb->user['uid']."' AND t.visible >= 0 {$visible} - "); - $threadcount = $db->fetch_field($query, "threads"); - - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - $perpage = $mybb->settings['threadsperpage']; - $page = $mybb->get_input('page', MyBB::INPUT_INT); - if($page > 0) - { - $start = ($page-1) * $perpage; - $pages = $threadcount / $perpage; - $pages = ceil($pages); - if($page > $pages || $page <= 0) - { - $start = 0; - $page = 1; - } - } - else - { - $start = 0; - $page = 1; - } - $end = $start + $perpage; - $lower = $start+1; - $upper = $end; - if($upper > $threadcount) - { - $upper = $threadcount; - } - $multipage = multipage($threadcount, $perpage, $page, "usercp.php?action=subscriptions"); - $fpermissions = forum_permissions(); - $del_subscriptions = $subscriptions = array(); - - // Fetch subscriptions - $query = $db->query(" - SELECT s.*, t.*, t.username AS threadusername, u.username - FROM ".TABLE_PREFIX."threadsubscriptions s - LEFT JOIN ".TABLE_PREFIX."threads t ON (s.tid=t.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid = t.uid) - WHERE s.uid='".$mybb->user['uid']."' and t.visible >= 0 {$visible} - ORDER BY t.lastpost DESC - LIMIT $start, $perpage - "); - while($subscription = $db->fetch_array($query)) - { - $forumpermissions = $fpermissions[$subscription['fid']]; - - if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0 || (isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0 && $subscription['uid'] != $mybb->user['uid'])) - { - // Hmm, you don't have permission to view this thread - unsubscribe! - $del_subscriptions[] = $subscription['sid']; - } - else if($subscription['tid']) - { - $subscriptions[$subscription['tid']] = $subscription; - } - } - - if(!empty($del_subscriptions)) - { - $sids = implode(',', $del_subscriptions); - - if($sids) - { - $db->delete_query("threadsubscriptions", "sid IN ({$sids}) AND uid='{$mybb->user['uid']}'"); - } - - $threadcount = $threadcount - count($del_subscriptions); - - if($threadcount < 0) - { - $threadcount = 0; - } - } - - if(!empty($subscriptions)) - { - $tids = implode(",", array_keys($subscriptions)); - $readforums = array(); - - // Build a forum cache. - $query = $db->query(" - SELECT f.fid, fr.dateline AS lastread - FROM ".TABLE_PREFIX."forums f - LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}') - WHERE f.active != 0 - ORDER BY pid, disporder - "); - - while($forum = $db->fetch_array($query)) - { - $readforums[$forum['fid']] = $forum['lastread']; - } - - // Check participation by the current user in any of these threads - for 'dot' folder icons - if($mybb->settings['dotfolders'] != 0) - { - $query = $db->simple_select("posts", "tid,uid", "uid='{$mybb->user['uid']}' AND tid IN ({$tids})"); - while($post = $db->fetch_array($query)) - { - $subscriptions[$post['tid']]['doticon'] = 1; - } - } - - // Read threads - if($mybb->settings['threadreadcut'] > 0) - { - $query = $db->simple_select("threadsread", "*", "uid='{$mybb->user['uid']}' AND tid IN ({$tids})"); - while($readthread = $db->fetch_array($query)) - { - $subscriptions[$readthread['tid']]['lastread'] = $readthread['dateline']; - } - } - - $icon_cache = $cache->read("posticons"); - $threadprefixes = build_prefixes(); - - $threads = ''; - - // Now we can build our subscription list - foreach($subscriptions as $thread) - { - $bgcolor = alt_trow(); - - $folder = ''; - $prefix = ''; - $thread['threadprefix'] = ''; - - // If this thread has a prefix, insert a space between prefix and subject - if($thread['prefix'] != 0 && !empty($threadprefixes[$thread['prefix']])) - { - $thread['threadprefix'] = $threadprefixes[$thread['prefix']]['displaystyle'].' '; - } - - // Sanitize - $thread['subject'] = $parser->parse_badwords($thread['subject']); - $thread['subject'] = htmlspecialchars_uni($thread['subject']); - - // Build our links - $thread['threadlink'] = get_thread_link($thread['tid']); - $thread['lastpostlink'] = get_thread_link($thread['tid'], 0, "lastpost"); - - // Fetch the thread icon if we have one - if($thread['icon'] > 0 && $icon_cache[$thread['icon']]) - { - $icon = $icon_cache[$thread['icon']]; - $icon['path'] = str_replace("{theme}", $theme['imgdir'], $icon['path']); - $icon['path'] = htmlspecialchars_uni($icon['path']); - $icon['name'] = htmlspecialchars_uni($icon['name']); - eval("\$icon = \"".$templates->get("usercp_subscriptions_thread_icon")."\";"); - } - else - { - $icon = " "; - } - - // Determine the folder - $folder = ''; - $folder_label = ''; - - if(isset($thread['doticon'])) - { - $folder = "dot_"; - $folder_label .= $lang->icon_dot; - } - - $gotounread = ''; - $isnew = 0; - $donenew = 0; - $lastread = 0; - - if($mybb->settings['threadreadcut'] > 0) - { - $forum_read = $readforums[$thread['fid']]; - - $read_cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - if($forum_read == 0 || $forum_read < $read_cutoff) - { - $forum_read = $read_cutoff; - } - } - - $cutoff = 0; - if($mybb->settings['threadreadcut'] > 0 && $thread['lastpost'] > $forum_read) - { - $cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - } - - if($thread['lastpost'] > $cutoff) - { - if($thread['lastread']) - { - $lastread = $thread['lastread']; - } - else - { - $lastread = 1; - } - } - - if(!$lastread) - { - $readcookie = $threadread = my_get_array_cookie("threadread", $thread['tid']); - if($readcookie > $forum_read) - { - $lastread = $readcookie; - } - else - { - $lastread = $forum_read; - } - } - - if($lastread && $lastread < $thread['lastpost']) - { - $folder .= "new"; - $folder_label .= $lang->icon_new; - $new_class = "subject_new"; - $thread['newpostlink'] = get_thread_link($thread['tid'], 0, "newpost"); - eval("\$gotounread = \"".$templates->get("forumdisplay_thread_gotounread")."\";"); - $unreadpost = 1; - } - else - { - $folder_label .= $lang->icon_no_new; - $new_class = "subject_old"; - } - - if($thread['replies'] >= $mybb->settings['hottopic'] || $thread['views'] >= $mybb->settings['hottopicviews']) - { - $folder .= "hot"; - $folder_label .= $lang->icon_hot; - } - - if($thread['closed'] == 1) - { - $folder .= "lock"; - $folder_label .= $lang->icon_lock; - } - - $folder .= "folder"; - - if($thread['visible'] == 0) - { - $bgcolor = "trow_shaded"; - } - - // Build last post info - $lastpostdate = my_date('relative', $thread['lastpost']); - $lastposter = htmlspecialchars_uni($thread['lastposter']); - $lastposteruid = $thread['lastposteruid']; - - // Don't link to guest's profiles (they have no profile). - if($lastposteruid == 0) - { - $lastposterlink = $lastposter; - } - else - { - $lastposterlink = build_profile_link($lastposter, $lastposteruid); - } - - $thread['replies'] = my_number_format($thread['replies']); - $thread['views'] = my_number_format($thread['views']); - - // What kind of notification type do we have here? - switch($thread['notification']) - { - case "2": // PM - $notification_type = $lang->pm_notification; - break; - case "1": // Email - $notification_type = $lang->email_notification; - break; - default: // No notification - $notification_type = $lang->no_notification; - } - - eval("\$threads .= \"".$templates->get("usercp_subscriptions_thread")."\";"); - } - - // Provide remove options - eval("\$remove_options = \"".$templates->get("usercp_subscriptions_remove")."\";"); - } - else - { - $remove_options = ''; - eval("\$threads = \"".$templates->get("usercp_subscriptions_none")."\";"); - } - - $plugins->run_hooks("usercp_subscriptions_end"); - - eval("\$subscriptions = \"".$templates->get("usercp_subscriptions")."\";"); - output_page($subscriptions); -} - -if($mybb->input['action'] == "forumsubscriptions") -{ - $plugins->run_hooks("usercp_forumsubscriptions_start"); - - // Build a forum cache. - $query = $db->query(" - SELECT f.fid, fr.dateline AS lastread - FROM ".TABLE_PREFIX."forums f - LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}') - WHERE f.active != 0 - ORDER BY pid, disporder - "); - $readforums = array(); - while($forum = $db->fetch_array($query)) - { - $readforums[$forum['fid']] = $forum['lastread']; - } - - $fpermissions = forum_permissions(); - require_once MYBB_ROOT."inc/functions_forumlist.php"; - - $query = $db->query(" - SELECT fs.*, f.*, t.subject AS lastpostsubject, fr.dateline AS lastread - FROM ".TABLE_PREFIX."forumsubscriptions fs - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid = fs.fid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid = f.lastposttid) - LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}') - WHERE f.type='f' AND fs.uid='".$mybb->user['uid']."' - ORDER BY f.name ASC - "); - - $forums = ''; - while($forum = $db->fetch_array($query)) - { - $forum_url = get_forum_link($forum['fid']); - $forumpermissions = $fpermissions[$forum['fid']]; - - if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0) - { - continue; - } - - $lightbulb = get_forum_lightbulb(array('open' => $forum['open'], 'lastread' => $forum['lastread']), array('lastpost' => $forum['lastpost'])); - $folder = $lightbulb['folder']; - - if(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0) - { - $posts = '-'; - $threads = '-'; - } - else - { - $posts = my_number_format($forum['posts']); - $threads = my_number_format($forum['threads']); - } - - if($forum['lastpost'] == 0 || $forum['lastposter'] == "") - { - eval("\$lastpost = \"".$templates->get("forumbit_depth2_forum_lastpost_never")."\";"); - } - // Hide last post - elseif(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0 && $forum['lastposteruid'] != $mybb->user['uid']) - { - eval("\$lastpost = \"".$templates->get("forumbit_depth2_forum_lastpost_hidden")."\";"); - } - else - { - $forum['lastpostsubject'] = $parser->parse_badwords($forum['lastpostsubject']); - $lastpost_date = my_date('relative', $forum['lastpost']); - $lastposttid = $forum['lastposttid']; - $lastposter = htmlspecialchars_uni($forum['lastposter']); - $lastpost_profilelink = build_profile_link($lastposter, $forum['lastposteruid']); - $full_lastpost_subject = $lastpost_subject = htmlspecialchars_uni($forum['lastpostsubject']); - if(my_strlen($lastpost_subject) > 25) - { - $lastpost_subject = my_substr($lastpost_subject, 0, 25) . "..."; - } - $lastpost_link = get_thread_link($forum['lastposttid'], 0, "lastpost"); - eval("\$lastpost = \"".$templates->get("forumbit_depth2_forum_lastpost")."\";"); - } - - if($mybb->settings['showdescriptions'] == 0) - { - $forum['description'] = ""; - } - - eval("\$forums .= \"".$templates->get("usercp_forumsubscriptions_forum")."\";"); - } - - if(!$forums) - { - eval("\$forums = \"".$templates->get("usercp_forumsubscriptions_none")."\";"); - } - - $plugins->run_hooks("usercp_forumsubscriptions_end"); - - eval("\$forumsubscriptions = \"".$templates->get("usercp_forumsubscriptions")."\";"); - output_page($forumsubscriptions); -} - -if($mybb->input['action'] == "do_editsig" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("usercp_do_editsig_start"); - - // User currently has a suspended signature - if($mybb->user['suspendsignature'] == 1 && $mybb->user['suspendsigtime'] > TIME_NOW) - { - error_no_permission(); - } - - if($mybb->get_input('updateposts') == "enable") - { - $update_signature = array( - "includesig" => 1 - ); - $db->update_query("posts", $update_signature, "uid='".$mybb->user['uid']."'"); - } - elseif($mybb->get_input('updateposts') == "disable") - { - $update_signature = array( - "includesig" => 0 - ); - $db->update_query("posts", $update_signature, "uid='".$mybb->user['uid']."'"); - } - $new_signature = array( - "signature" => $db->escape_string($mybb->get_input('signature')) - ); - $plugins->run_hooks("usercp_do_editsig_process"); - $db->update_query("users", $new_signature, "uid='".$mybb->user['uid']."'"); - $plugins->run_hooks("usercp_do_editsig_end"); - redirect("usercp.php?action=editsig", $lang->redirect_sigupdated); -} - -if($mybb->input['action'] == "editsig") -{ - $plugins->run_hooks("usercp_editsig_start"); - if(!empty($mybb->input['preview']) && empty($error)) - { - $sig = $mybb->get_input('signature'); - $template = "usercp_editsig_preview"; - } - elseif(empty($error)) - { - $sig = $mybb->user['signature']; - $template = "usercp_editsig_current"; - } - else - { - $sig = $mybb->get_input('signature'); - $template = false; - } - - if(!isset($error)) - { - $error = ''; - } - - if($mybb->user['suspendsignature'] && ($mybb->user['suspendsigtime'] == 0 || $mybb->user['suspendsigtime'] > 0 && $mybb->user['suspendsigtime'] > TIME_NOW)) - { - // User currently has no signature and they're suspended - error($lang->sig_suspended); - } - - if($mybb->usergroup['canusesig'] != 1) - { - // Usergroup has no permission to use this facility - error_no_permission(); - } - else if($mybb->usergroup['canusesig'] == 1 && $mybb->usergroup['canusesigxposts'] > 0 && $mybb->user['postnum'] < $mybb->usergroup['canusesigxposts']) - { - // Usergroup can use this facility, but only after x posts - error($lang->sprintf($lang->sig_suspended_posts, $mybb->usergroup['canusesigxposts'])); - } - - $signature = ''; - if($sig && $template) - { - $sig_parser = array( - "allow_html" => $mybb->settings['sightml'], - "allow_mycode" => $mybb->settings['sigmycode'], - "allow_smilies" => $mybb->settings['sigsmilies'], - "allow_imgcode" => $mybb->settings['sigimgcode'], - "me_username" => $mybb->user['username'], - "filter_badwords" => 1 - ); - - if($mybb->user['showimages'] != 1) - { - $sig_parser['allow_imgcode'] = 0; - } - - $sigpreview = $parser->parse_message($sig, $sig_parser); - eval("\$signature = \"".$templates->get($template)."\";"); - } - - // User has a current signature, so let's display it (but show an error message) - if($mybb->user['suspendsignature'] && $mybb->user['suspendsigtime'] > TIME_NOW) - { - $plugins->run_hooks("usercp_editsig_end"); - - // User either doesn't have permission, or has their signature suspended - eval("\$editsig = \"".$templates->get("usercp_editsig_suspended")."\";"); - } - else - { - // User is allowed to edit their signature - if($mybb->settings['sigsmilies'] == 1) - { - $sigsmilies = $lang->on; - $smilieinserter = build_clickable_smilies(); - } - else - { - $sigsmilies = $lang->off; - } - if($mybb->settings['sigmycode'] == 1) - { - $sigmycode = $lang->on; - } - else - { - $sigmycode = $lang->off; - } - if($mybb->settings['sightml'] == 1) - { - $sightml = $lang->on; - } - else - { - $sightml = $lang->off; - } - if($mybb->settings['sigimgcode'] == 1) - { - $sigimgcode = $lang->on; - } - else - { - $sigimgcode = $lang->off; - } - $sig = htmlspecialchars_uni($sig); - $lang->edit_sig_note2 = $lang->sprintf($lang->edit_sig_note2, $sigsmilies, $sigmycode, $sigimgcode, $sightml, $mybb->settings['siglength']); - - if($mybb->settings['bbcodeinserter'] != 0 || $mybb->user['showcodebuttons'] != 0) - { - $codebuttons = build_mycode_inserter("signature"); - } - - $plugins->run_hooks("usercp_editsig_end"); - - eval("\$editsig = \"".$templates->get("usercp_editsig")."\";"); - } - - output_page($editsig); -} - -if($mybb->input['action'] == "do_avatar" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("usercp_do_avatar_start"); - require_once MYBB_ROOT."inc/functions_upload.php"; - - $avatar_error = ""; - - if(!empty($mybb->input['remove'])) // remove avatar - { - $updated_avatar = array( - "avatar" => "", - "avatardimensions" => "", - "avatartype" => "" - ); - $db->update_query("users", $updated_avatar, "uid='".$mybb->user['uid']."'"); - remove_avatars($mybb->user['uid']); - } - elseif($_FILES['avatarupload']['name']) // upload avatar - { - if($mybb->usergroup['canuploadavatars'] == 0) - { - error_no_permission(); - } - $avatar = upload_avatar(); - if($avatar['error']) - { - $avatar_error = $avatar['error']; - } - else - { - if($avatar['width'] > 0 && $avatar['height'] > 0) - { - $avatar_dimensions = $avatar['width']."|".$avatar['height']; - } - $updated_avatar = array( - "avatar" => $avatar['avatar'].'?dateline='.TIME_NOW, - "avatardimensions" => $avatar_dimensions, - "avatartype" => "upload" - ); - $db->update_query("users", $updated_avatar, "uid='".$mybb->user['uid']."'"); - } - } - elseif($mybb->settings['allowremoteavatars']) // remote avatar - { - $mybb->input['avatarurl'] = trim($mybb->get_input('avatarurl')); - if(validate_email_format($mybb->input['avatarurl']) != false) - { - // Gravatar - $mybb->input['avatarurl'] = my_strtolower($mybb->input['avatarurl']); - - // If user image does not exist, or is a higher rating, use the mystery man - $email = md5($mybb->input['avatarurl']); - - $s = ''; - if(!$mybb->settings['maxavatardims']) - { - $mybb->settings['maxavatardims'] = '100x100'; // Hard limit of 100 if there are no limits - } - - // Because Gravatars are square, hijack the width - list($maxwidth, $maxheight) = explode("x", my_strtolower($mybb->settings['maxavatardims'])); - $maxheight = (int)$maxwidth; - - // Rating? - $types = array('g', 'pg', 'r', 'x'); - $rating = $mybb->settings['useravatarrating']; - - if(!in_array($rating, $types)) - { - $rating = 'g'; - } - - $s = "?s={$maxheight}&r={$rating}&d=mm"; - - $updated_avatar = array( - "avatar" => "https://www.gravatar.com/avatar/{$email}{$s}", - "avatardimensions" => "{$maxheight}|{$maxheight}", - "avatartype" => "gravatar" - ); - - $db->update_query("users", $updated_avatar, "uid = '{$mybb->user['uid']}'"); - } - else - { - $mybb->input['avatarurl'] = preg_replace("#script:#i", "", $mybb->get_input('avatarurl')); - $ext = get_extension($mybb->input['avatarurl']); - - // Copy the avatar to the local server (work around remote URL access disabled for getimagesize) - $file = fetch_remote_file($mybb->input['avatarurl']); - if(!$file) - { - $avatar_error = $lang->error_invalidavatarurl; - } - else - { - $tmp_name = $mybb->settings['avataruploadpath']."/remote_".md5(random_str()); - $fp = @fopen($tmp_name, "wb"); - if(!$fp) - { - $avatar_error = $lang->error_invalidavatarurl; - } - else - { - fwrite($fp, $file); - fclose($fp); - list($width, $height, $type) = @getimagesize($tmp_name); - @unlink($tmp_name); - if(!$type) - { - $avatar_error = $lang->error_invalidavatarurl; - } - } - } - - if(empty($avatar_error)) - { - if($width && $height && $mybb->settings['maxavatardims'] != "") - { - list($maxwidth, $maxheight) = explode("x", my_strtolower($mybb->settings['maxavatardims'])); - if(($maxwidth && $width > $maxwidth) || ($maxheight && $height > $maxheight)) - { - $lang->error_avatartoobig = $lang->sprintf($lang->error_avatartoobig, $maxwidth, $maxheight); - $avatar_error = $lang->error_avatartoobig; - } - } - } - - if(empty($avatar_error)) - { - if($width > 0 && $height > 0) - { - $avatar_dimensions = (int)$width."|".(int)$height; - } - $updated_avatar = array( - "avatar" => $db->escape_string($mybb->input['avatarurl'].'?dateline='.TIME_NOW), - "avatardimensions" => $avatar_dimensions, - "avatartype" => "remote" - ); - $db->update_query("users", $updated_avatar, "uid='".$mybb->user['uid']."'"); - remove_avatars($mybb->user['uid']); - } - } - } - else // remote avatar, but remote avatars are not allowed - { - $avatar_error = $lang->error_remote_avatar_not_allowed; - } - - if(empty($avatar_error)) - { - $plugins->run_hooks("usercp_do_avatar_end"); - redirect("usercp.php?action=avatar", $lang->redirect_avatarupdated); - } - else - { - $mybb->input['action'] = "avatar"; - $avatar_error = inline_error($avatar_error); - } -} - -if($mybb->input['action'] == "avatar") -{ - $plugins->run_hooks("usercp_avatar_start"); - - $avatarmsg = $avatarurl = ''; - - if($mybb->user['avatartype'] == "upload" || stristr($mybb->user['avatar'], $mybb->settings['avataruploadpath'])) - { - $avatarmsg = "
    ".$lang->already_uploaded_avatar.""; - } - elseif($mybb->user['avatartype'] == "remote" || my_validate_url($mybb->user['avatar'])) - { - $avatarmsg = "
    ".$lang->using_remote_avatar.""; - $avatarurl = htmlspecialchars_uni($mybb->user['avatar']); - } - - $useravatar = format_avatar($mybb->user['avatar'], $mybb->user['avatardimensions'], '100x100'); - eval("\$currentavatar = \"".$templates->get("usercp_avatar_current")."\";"); - - if($mybb->settings['maxavatardims'] != "") - { - list($maxwidth, $maxheight) = explode("x", my_strtolower($mybb->settings['maxavatardims'])); - $lang->avatar_note .= "
    ".$lang->sprintf($lang->avatar_note_dimensions, $maxwidth, $maxheight); - } - - if($mybb->settings['avatarsize']) - { - $maxsize = get_friendly_size($mybb->settings['avatarsize']*1024); - $lang->avatar_note .= "
    ".$lang->sprintf($lang->avatar_note_size, $maxsize); - } - - $plugins->run_hooks("usercp_avatar_intermediate"); - - $auto_resize = ''; - if($mybb->settings['avatarresizing'] == "auto") - { - eval("\$auto_resize = \"".$templates->get("usercp_avatar_auto_resize_auto")."\";"); - } - else if($mybb->settings['avatarresizing'] == "user") - { - eval("\$auto_resize = \"".$templates->get("usercp_avatar_auto_resize_user")."\";"); - } - - $avatarupload = ''; - if($mybb->usergroup['canuploadavatars'] == 1) - { - eval("\$avatarupload = \"".$templates->get("usercp_avatar_upload")."\";"); - } - - $avatar_remote = ''; - if($mybb->settings['allowremoteavatars'] == 1) - { - eval("\$avatar_remote = \"".$templates->get("usercp_avatar_remote")."\";"); - } - - $removeavatar = ''; - if(!empty($mybb->user['avatar'])) - { - eval("\$removeavatar = \"".$templates->get("usercp_avatar_remove")."\";"); - } - - $plugins->run_hooks("usercp_avatar_end"); - - if(!isset($avatar_error)) - { - $avatar_error = ''; - } - - eval("\$avatar = \"".$templates->get("usercp_avatar")."\";"); - output_page($avatar); -} - -if($mybb->input['action'] == "acceptrequest") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - // Validate request - $query = $db->simple_select('buddyrequests', '*', 'id='.$mybb->get_input('id', MyBB::INPUT_INT).' AND touid='.(int)$mybb->user['uid']); - $request = $db->fetch_array($query); - if(empty($request)) - { - error($lang->invalid_request); - } - - $plugins->run_hooks("usercp_acceptrequest_start"); - - $user = get_user($request['uid']); - if(!empty($user)) - { - // We want to add us to this user's buddy list - if($user['buddylist'] != '') - { - $user['buddylist'] = explode(',', $user['buddylist']); - } - else - { - $user['buddylist'] = array(); - } - - $user['buddylist'][] = (int)$mybb->user['uid']; - - // Now we have the new list, so throw it all back together - $new_list = implode(",", $user['buddylist']); - - // And clean it up a little to ensure there is no possibility of bad values - $new_list = preg_replace("#,{2,}#", ",", $new_list); - $new_list = preg_replace("#[^0-9,]#", "", $new_list); - - if(my_substr($new_list, 0, 1) == ",") - { - $new_list = my_substr($new_list, 1); - } - if(my_substr($new_list, -1) == ",") - { - $new_list = my_substr($new_list, 0, my_strlen($new_list)-2); - } - - $user['buddylist'] = $db->escape_string($new_list); - - $db->update_query("users", array('buddylist' => $user['buddylist']), "uid='".(int)$user['uid']."'"); - - - // We want to add the user to our buddy list - if($mybb->user['buddylist'] != '') - { - $mybb->user['buddylist'] = explode(',', $mybb->user['buddylist']); - } - else - { - $mybb->user['buddylist'] = array(); - } - - $mybb->user['buddylist'][] = (int)$request['uid']; - - // Now we have the new list, so throw it all back together - $new_list = implode(",", $mybb->user['buddylist']); - - // And clean it up a little to ensure there is no possibility of bad values - $new_list = preg_replace("#,{2,}#", ",", $new_list); - $new_list = preg_replace("#[^0-9,]#", "", $new_list); - - if(my_substr($new_list, 0, 1) == ",") - { - $new_list = my_substr($new_list, 1); - } - if(my_substr($new_list, -1) == ",") - { - $new_list = my_substr($new_list, 0, my_strlen($new_list)-2); - } - - $mybb->user['buddylist'] = $db->escape_string($new_list); - - $db->update_query("users", array('buddylist' => $mybb->user['buddylist']), "uid='".(int)$mybb->user['uid']."'"); - - $pm = array( - 'subject' => 'buddyrequest_accepted_request', - 'message' => 'buddyrequest_accepted_request_message', - 'touid' => $user['uid'], - 'language' => $user['language'], - 'language_file' => 'usercp' - ); - - send_pm($pm, $mybb->user['uid'], true); - - $db->delete_query('buddyrequests', 'id='.(int)$request['id']); - } - else - { - error($lang->user_doesnt_exist); - } - - $plugins->run_hooks("usercp_acceptrequest_end"); - - redirect("usercp.php?action=editlists", $lang->buddyrequest_accepted); -} - -elseif($mybb->input['action'] == "declinerequest") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - // Validate request - $query = $db->simple_select('buddyrequests', '*', 'id='.$mybb->get_input('id', MyBB::INPUT_INT).' AND touid='.(int)$mybb->user['uid']); - $request = $db->fetch_array($query); - if(empty($request)) - { - error($lang->invalid_request); - } - - $plugins->run_hooks("usercp_declinerequest_start"); - - $user = get_user($request['uid']); - if(!empty($user)) - { - $db->delete_query('buddyrequests', 'id='.(int)$request['id']); - } - else - { - error($lang->user_doesnt_exist); - } - - $plugins->run_hooks("usercp_declinerequest_end"); - - redirect("usercp.php?action=editlists", $lang->buddyrequest_declined); -} - -elseif($mybb->input['action'] == "cancelrequest") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - // Validate request - $query = $db->simple_select('buddyrequests', '*', 'id='.$mybb->get_input('id', MyBB::INPUT_INT).' AND uid='.(int)$mybb->user['uid']); - $request = $db->fetch_array($query); - if(empty($request)) - { - error($lang->invalid_request); - } - - $plugins->run_hooks("usercp_cancelrequest_start"); - - $db->delete_query('buddyrequests', 'id='.(int)$request['id']); - - $plugins->run_hooks("usercp_cancelrequest_end"); - - redirect("usercp.php?action=editlists", $lang->buddyrequest_cancelled); -} - -if($mybb->input['action'] == "do_editlists") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("usercp_do_editlists_start"); - - $existing_users = array(); - $selected_list = array(); - if($mybb->get_input('manage') == "ignored") - { - if($mybb->user['ignorelist']) - { - $existing_users = explode(",", $mybb->user['ignorelist']); - } - - if($mybb->user['buddylist']) - { - // Create a list of buddies... - $selected_list = explode(",", $mybb->user['buddylist']); - } - } - else - { - if($mybb->user['buddylist']) - { - $existing_users = explode(",", $mybb->user['buddylist']); - } - - if($mybb->user['ignorelist']) - { - // Create a list of ignored users - $selected_list = explode(",", $mybb->user['ignorelist']); - } - } - - $error_message = ""; - $message = ""; - - // Adding one or more users to this list - if($mybb->get_input('add_username')) - { - // Split up any usernames we have - $found_users = 0; - $adding_self = false; - $users = explode(",", $mybb->get_input('add_username')); - $users = array_map("trim", $users); - $users = array_unique($users); - foreach($users as $key => $username) - { - if(empty($username)) - { - unset($users[$key]); - continue; - } - - if(my_strtoupper($mybb->user['username']) == my_strtoupper($username)) - { - $adding_self = true; - unset($users[$key]); - continue; - } - $users[$key] = $db->escape_string($username); - } - - // Get the requests we have sent that are still pending - $query = $db->simple_select('buddyrequests', 'touid', 'uid='.(int)$mybb->user['uid']); - $requests = array(); - while($req = $db->fetch_array($query)) - { - $requests[$req['touid']] = true; - } - - // Get the requests we have received that are still pending - $query = $db->simple_select('buddyrequests', 'uid', 'touid='.(int)$mybb->user['uid']); - $requests_rec = array(); - while($req = $db->fetch_array($query)) - { - $requests_rec[$req['uid']] = true; - } - - $sent = false; - - // Fetch out new users - if(count($users) > 0) - { - switch($db->type) - { - case 'mysql': - case 'mysqli': - $field = 'username'; - break; - default: - $field = 'LOWER(username)'; - break; - } - $query = $db->simple_select("users", "uid,buddyrequestsauto,buddyrequestspm,language", "{$field} IN ('".my_strtolower(implode("','", $users))."')"); - while($user = $db->fetch_array($query)) - { - ++$found_users; - - // Make sure we're not adding a duplicate - if(in_array($user['uid'], $existing_users) || in_array($user['uid'], $selected_list)) - { - if($mybb->get_input('manage') == "ignored") - { - $error_message = "ignore"; - } - else - { - $error_message = "buddy"; - } - - // On another list? - $string = "users_already_on_".$error_message."_list"; - if(in_array($user['uid'], $selected_list)) - { - $string .= "_alt"; - } - - $error_message = $lang->$string; - array_pop($users); // To maintain a proper count when we call count($users) - continue; - } - - if(isset($requests[$user['uid']])) - { - if($mybb->get_input('manage') != "ignored") - { - $error_message = $lang->users_already_sent_request; - } - elseif($mybb->get_input('manage') == "ignored") - { - $error_message = $lang->users_already_sent_request_alt; - } - - array_pop($users); // To maintain a proper count when we call count($users) - continue; - } - - if(isset($requests_rec[$user['uid']])) - { - if($mybb->get_input('manage') != "ignored") - { - $error_message = $lang->users_already_rec_request; - } - elseif($mybb->get_input('manage') == "ignored") - { - $error_message = $lang->users_already_rec_request_alt; - } - - array_pop($users); // To maintain a proper count when we call count($users) - continue; - } - - // Do we have auto approval set to On? - if($user['buddyrequestsauto'] == 1 && $mybb->get_input('manage') != "ignored") - { - $existing_users[] = $user['uid']; - - $pm = array( - 'subject' => 'buddyrequest_new_buddy', - 'message' => 'buddyrequest_new_buddy_message', - 'touid' => $user['uid'], - 'receivepms' => (int)$user['buddyrequestspm'], - 'language' => $user['language'], - 'language_file' => 'usercp' - ); - - send_pm($pm); - } - elseif($user['buddyrequestsauto'] != 1 && $mybb->get_input('manage') != "ignored") - { - // Send request - $id = $db->insert_query('buddyrequests', array('uid' => (int)$mybb->user['uid'], 'touid' => (int)$user['uid'], 'date' => TIME_NOW)); - - $pm = array( - 'subject' => 'buddyrequest_received', - 'message' => 'buddyrequest_received_message', - 'touid' => $user['uid'], - 'receivepms' => (int)$user['buddyrequestspm'], - 'language' => $user['language'], - 'language_file' => 'usercp' - ); - - send_pm($pm); - - $sent = true; - } - elseif($mybb->get_input('manage') == "ignored") - { - $existing_users[] = $user['uid']; - } - } - } - - if($found_users < count($users)) - { - if($error_message) - { - $error_message .= "
    "; - } - - $error_message .= $lang->invalid_user_selected; - } - - if(($adding_self != true || ($adding_self == true && count($users) > 0)) && ($error_message == "" || count($users) > 1)) - { - if($mybb->get_input('manage') == "ignored") - { - $message = $lang->users_added_to_ignore_list; - } - else - { - $message = $lang->users_added_to_buddy_list; - } - } - - if($adding_self == true) - { - if($mybb->get_input('manage') == "ignored") - { - $error_message = $lang->cant_add_self_to_ignore_list; - } - else - { - $error_message = $lang->cant_add_self_to_buddy_list; - } - } - - if(count($existing_users) == 0) - { - $message = ""; - - if($sent === true) - { - $message = $lang->buddyrequests_sent_success; - } - } - } - - // Removing a user from this list - else if($mybb->get_input('delete', MyBB::INPUT_INT)) - { - // Check if user exists on the list - $key = array_search($mybb->get_input('delete', MyBB::INPUT_INT), $existing_users); - if($key !== false) - { - unset($existing_users[$key]); - $user = get_user($mybb->get_input('delete', MyBB::INPUT_INT)); - if(!empty($user)) - { - // We want to remove us from this user's buddy list - if($user['buddylist'] != '') - { - $user['buddylist'] = explode(',', $user['buddylist']); - } - else - { - $user['buddylist'] = array(); - } - - $key = array_search($mybb->get_input('delete', MyBB::INPUT_INT), $user['buddylist']); - unset($user['buddylist'][$key]); - - // Now we have the new list, so throw it all back together - $new_list = implode(",", $user['buddylist']); - - // And clean it up a little to ensure there is no possibility of bad values - $new_list = preg_replace("#,{2,}#", ",", $new_list); - $new_list = preg_replace("#[^0-9,]#", "", $new_list); - - if(my_substr($new_list, 0, 1) == ",") - { - $new_list = my_substr($new_list, 1); - } - if(my_substr($new_list, -1) == ",") - { - $new_list = my_substr($new_list, 0, my_strlen($new_list)-2); - } - - $user['buddylist'] = $db->escape_string($new_list); - - $db->update_query("users", array('buddylist' => $user['buddylist']), "uid='".(int)$user['uid']."'"); - } - - if($mybb->get_input('manage') == "ignored") - { - $message = $lang->removed_from_ignore_list; - } - else - { - $message = $lang->removed_from_buddy_list; - } - $user['username'] = htmlspecialchars_uni($user['username']); - $message = $lang->sprintf($message, $user['username']); - } - } - - // Now we have the new list, so throw it all back together - $new_list = implode(",", $existing_users); - - // And clean it up a little to ensure there is no possibility of bad values - $new_list = preg_replace("#,{2,}#", ",", $new_list); - $new_list = preg_replace("#[^0-9,]#", "", $new_list); - - if(my_substr($new_list, 0, 1) == ",") - { - $new_list = my_substr($new_list, 1); - } - if(my_substr($new_list, -1) == ",") - { - $new_list = my_substr($new_list, 0, my_strlen($new_list)-2); - } - - // And update - $user = array(); - if($mybb->get_input('manage') == "ignored") - { - $user['ignorelist'] = $db->escape_string($new_list); - $mybb->user['ignorelist'] = $user['ignorelist']; - } - else - { - $user['buddylist'] = $db->escape_string($new_list); - $mybb->user['buddylist'] = $user['buddylist']; - } - - $db->update_query("users", $user, "uid='".$mybb->user['uid']."'"); - - $plugins->run_hooks("usercp_do_editlists_end"); - - // Ajax based request, throw new list to browser - if(!empty($mybb->input['ajax'])) - { - if($mybb->get_input('manage') == "ignored") - { - $list = "ignore"; - } - else - { - $list = "buddy"; - } - - $message_js = ''; - if($message) - { - $message_js = "$.jGrowl('{$message}', {theme:'jgrowl_success'});"; - } - - if($error_message) - { - $message_js .= " $.jGrowl('{$error_message}', {theme:'jgrowl_error'});"; - } - - if($mybb->get_input('delete', MyBB::INPUT_INT)) - { - header("Content-type: text/javascript"); - echo "$(\"#".$mybb->get_input('manage')."_".$mybb->get_input('delete', MyBB::INPUT_INT)."\").remove();\n"; - if($new_list == "") - { - echo "\$(\"#".$mybb->get_input('manage')."_count\").html(\"0\");\n"; - if($mybb->get_input('manage') == "ignored") - { - echo "\$(\"#ignore_list\").html(\"
  • {$lang->ignore_list_empty}
  • \");\n"; - } - else - { - echo "\$(\"#buddy_list\").html(\"
  • {$lang->buddy_list_empty}
  • \");\n"; - } - } - else - { - echo "\$(\"#".$mybb->get_input('manage')."_count\").html(\"".count(explode(",", $new_list))."\");\n"; - } - echo $message_js; - exit; - } - $mybb->input['action'] = "editlists"; - } - else - { - if($error_message) - { - $message .= "
    ".$error_message; - } - redirect("usercp.php?action=editlists#".$mybb->get_input('manage'), $message); - } -} - -if($mybb->input['action'] == "editlists") -{ - $plugins->run_hooks("usercp_editlists_start"); - - $timecut = TIME_NOW - $mybb->settings['wolcutoff']; - - // Fetch out buddies - $buddy_count = 0; - $buddy_list = ''; - if($mybb->user['buddylist']) - { - $type = "buddy"; - $query = $db->simple_select("users", "*", "uid IN ({$mybb->user['buddylist']})", array("order_by" => "username")); - while($user = $db->fetch_array($query)) - { - $user['username'] = htmlspecialchars_uni($user['username']); - $profile_link = build_profile_link(format_name($user['username'], $user['usergroup'], $user['displaygroup']), $user['uid']); - if($user['lastactive'] > $timecut && ($user['invisible'] == 0 || $mybb->usergroup['canviewwolinvis'] == 1) && $user['lastvisit'] != $user['lastactive']) - { - $status = "online"; - } - else - { - $status = "offline"; - } - eval("\$buddy_list .= \"".$templates->get("usercp_editlists_user")."\";"); - ++$buddy_count; - } - } - - $lang->current_buddies = $lang->sprintf($lang->current_buddies, $buddy_count); - if(!$buddy_list) - { - eval("\$buddy_list = \"".$templates->get("usercp_editlists_no_buddies")."\";"); - } - - // Fetch out ignore list users - $ignore_count = 0; - $ignore_list = ''; - if($mybb->user['ignorelist']) - { - $type = "ignored"; - $query = $db->simple_select("users", "*", "uid IN ({$mybb->user['ignorelist']})", array("order_by" => "username")); - while($user = $db->fetch_array($query)) - { - $user['username'] = htmlspecialchars_uni($user['username']); - $profile_link = build_profile_link(format_name($user['username'], $user['usergroup'], $user['displaygroup']), $user['uid']); - if($user['lastactive'] > $timecut && ($user['invisible'] == 0 || $mybb->usergroup['canviewwolinvis'] == 1) && $user['lastvisit'] != $user['lastactive']) - { - $status = "online"; - } - else - { - $status = "offline"; - } - eval("\$ignore_list .= \"".$templates->get("usercp_editlists_user")."\";"); - ++$ignore_count; - } - } - - $lang->current_ignored_users = $lang->sprintf($lang->current_ignored_users, $ignore_count); - if(!$ignore_list) - { - eval("\$ignore_list = \"".$templates->get("usercp_editlists_no_ignored")."\";"); - } - - // If an AJAX request from buddy management, echo out whatever the new list is. - if($mybb->request_method == "post" && $mybb->input['ajax'] == 1) - { - if($mybb->input['manage'] == "ignored") - { - echo $ignore_list; - echo ""; - } - else - { - if(isset($sent) && $sent === true) - { - $sent_rows = ''; - $query = $db->query(" - SELECT r.*, u.username - FROM ".TABLE_PREFIX."buddyrequests r - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=r.touid) - WHERE r.uid=".(int)$mybb->user['uid']); - - while($request = $db->fetch_array($query)) - { - $bgcolor = alt_trow(); - $request['username'] = build_profile_link(htmlspecialchars_uni($request['username']), (int)$request['touid']); - $request['date'] = my_date($mybb->settings['dateformat'], $request['date'])." ".my_date($mybb->settings['timeformat'], $request['date']); - eval("\$sent_rows .= \"".$templates->get("usercp_editlists_sent_request", 1, 0)."\";"); - } - - if($sent_rows == '') - { - eval("\$sent_rows = \"".$templates->get("usercp_editlists_no_requests", 1, 0)."\";"); - } - - eval("\$sent_requests = \"".$templates->get("usercp_editlists_sent_requests", 1, 0)."\";"); - - echo $sentrequests; - echo $sent_requests.""; - } - else - { - echo $buddy_list; - echo ""; - } - } - exit; - } - - $received_rows = ''; - $query = $db->query(" - SELECT r.*, u.username - FROM ".TABLE_PREFIX."buddyrequests r - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=r.uid) - WHERE r.touid=".(int)$mybb->user['uid']); - - while($request = $db->fetch_array($query)) - { - $bgcolor = alt_trow(); - $request['username'] = build_profile_link(htmlspecialchars_uni($request['username']), (int)$request['uid']); - $request['date'] = my_date($mybb->settings['dateformat'], $request['date'])." ".my_date($mybb->settings['timeformat'], $request['date']); - eval("\$received_rows .= \"".$templates->get("usercp_editlists_received_request")."\";"); - } - - if($received_rows == '') - { - eval("\$received_rows = \"".$templates->get("usercp_editlists_no_requests")."\";"); - } - - eval("\$received_requests = \"".$templates->get("usercp_editlists_received_requests")."\";"); - - $sent_rows = ''; - $query = $db->query(" - SELECT r.*, u.username - FROM ".TABLE_PREFIX."buddyrequests r - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=r.touid) - WHERE r.uid=".(int)$mybb->user['uid']); - - while($request = $db->fetch_array($query)) - { - $bgcolor = alt_trow(); - $request['username'] = build_profile_link(htmlspecialchars_uni($request['username']), (int)$request['touid']); - $request['date'] = my_date($mybb->settings['dateformat'], $request['date'])." ".my_date($mybb->settings['timeformat'], $request['date']); - eval("\$sent_rows .= \"".$templates->get("usercp_editlists_sent_request")."\";"); - } - - if($sent_rows == '') - { - eval("\$sent_rows = \"".$templates->get("usercp_editlists_no_requests")."\";"); - } - - eval("\$sent_requests = \"".$templates->get("usercp_editlists_sent_requests")."\";"); - - $plugins->run_hooks("usercp_editlists_end"); - - eval("\$listpage = \"".$templates->get("usercp_editlists")."\";"); - output_page($listpage); -} - -if($mybb->input['action'] == "drafts") -{ - $plugins->run_hooks("usercp_drafts_start"); - - $query = $db->simple_select("posts", "COUNT(pid) AS draftcount", "visible='-2' AND uid='{$mybb->user['uid']}'"); - $draftcount = $db->fetch_field($query, 'draftcount'); - - $drafts = $disable_delete_drafts = ''; - $lang->drafts_count = $lang->sprintf($lang->drafts_count, my_number_format($draftcount)); - - // Show a listing of all of the current 'draft' posts or threads the user has. - if($draftcount) - { - $query = $db->query(" - SELECT p.subject, p.pid, t.tid, t.subject AS threadsubject, t.fid, f.name AS forumname, p.dateline, t.visible AS threadvisible, p.visible AS postvisible - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=t.fid) - WHERE p.uid = '{$mybb->user['uid']}' AND p.visible = '-2' - ORDER BY p.dateline DESC - "); - - while($draft = $db->fetch_array($query)) - { - $detail = ''; - $trow = alt_trow(); - if($draft['threadvisible'] == 1) // We're looking at a draft post - { - $draft['threadlink'] = get_thread_link($draft['tid']); - $draft['threadsubject'] = htmlspecialchars_uni($draft['threadsubject']); - eval("\$detail = \"".$templates->get("usercp_drafts_draft_thread")."\";"); - $editurl = "newreply.php?action=editdraft&pid={$draft['pid']}"; - $id = $draft['pid']; - $type = "post"; - } - elseif($draft['threadvisible'] == -2) // We're looking at a draft thread - { - $draft['forumlink'] = get_forum_link($draft['fid']); - $draft['forumname'] = htmlspecialchars_uni($draft['forumname']); - eval("\$detail = \"".$templates->get("usercp_drafts_draft_forum")."\";"); - $editurl = "newthread.php?action=editdraft&tid={$draft['tid']}"; - $id = $draft['tid']; - $type = "thread"; - } - - $draft['subject'] = htmlspecialchars_uni($draft['subject']); - $savedate = my_date('relative', $draft['dateline']); - eval("\$drafts .= \"".$templates->get("usercp_drafts_draft")."\";"); - } - } - else - { - $disable_delete_drafts = 'disabled="disabled"'; - eval("\$drafts = \"".$templates->get("usercp_drafts_none")."\";"); - } - - $plugins->run_hooks("usercp_drafts_end"); - - eval("\$draftlist = \"".$templates->get("usercp_drafts")."\";"); - output_page($draftlist); -} - -if($mybb->input['action'] == "do_drafts" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("usercp_do_drafts_start"); - $mybb->input['deletedraft'] = $mybb->get_input('deletedraft', MyBB::INPUT_ARRAY); - if(empty($mybb->input['deletedraft'])) - { - error($lang->no_drafts_selected); - } - $pidin = array(); - $tidin = array(); - foreach($mybb->input['deletedraft'] as $id => $val) - { - if($val == "post") - { - $pidin[] = "'".(int)$id."'"; - } - elseif($val == "thread") - { - $tidin[] = "'".(int)$id."'"; - } - } - if($tidin) - { - $tidin = implode(",", $tidin); - $db->delete_query("threads", "tid IN ($tidin) AND visible='-2' AND uid='".$mybb->user['uid']."'"); - $tidinp = "OR tid IN ($tidin)"; - } - if($pidin || $tidinp) - { - $pidinq = $tidin = ''; - if($pidin) - { - $pidin = implode(",", $pidin); - $pidinq = "pid IN ($pidin)"; - } - else - { - $pidinq = "1=0"; - } - $db->delete_query("posts", "($pidinq $tidinp) AND visible='-2' AND uid='".$mybb->user['uid']."'"); - } - $plugins->run_hooks("usercp_do_drafts_end"); - redirect("usercp.php?action=drafts", $lang->selected_drafts_deleted); -} - -if($mybb->input['action'] == "usergroups") -{ - $plugins->run_hooks("usercp_usergroups_start"); - $ingroups = ",".$mybb->user['usergroup'].",".$mybb->user['additionalgroups'].",".$mybb->user['displaygroup'].","; - - $usergroups = $mybb->cache->read('usergroups'); - - // Changing our display group - if($mybb->get_input('displaygroup', MyBB::INPUT_INT)) - { - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if(my_strpos($ingroups, ",".$mybb->input['displaygroup'].",") === false) - { - error($lang->not_member_of_group); - } - - $dispgroup = $usergroups[$mybb->get_input('displaygroup', MyBB::INPUT_INT)]; - if($dispgroup['candisplaygroup'] != 1) - { - error($lang->cannot_set_displaygroup); - } - $db->update_query("users", array('displaygroup' => $mybb->get_input('displaygroup', MyBB::INPUT_INT)), "uid='".$mybb->user['uid']."'"); - $cache->update_moderators(); - $plugins->run_hooks("usercp_usergroups_change_displaygroup"); - redirect("usercp.php?action=usergroups", $lang->display_group_changed); - exit; - } - - // Leaving a group - if($mybb->get_input('leavegroup', MyBB::INPUT_INT)) - { - // Verify incoming POST request - verify_post_check($mybb->input['my_post_key']); - - if(my_strpos($ingroups, ",".$mybb->get_input('leavegroup', MyBB::INPUT_INT).",") === false) - { - error($lang->not_member_of_group); - } - if($mybb->user['usergroup'] == $mybb->get_input('leavegroup', MyBB::INPUT_INT)) - { - error($lang->cannot_leave_primary_group); - } - - $usergroup = $usergroups[$mybb->get_input('leavegroup', MyBB::INPUT_INT)]; - if($usergroup['type'] != 4 && $usergroup['type'] != 3 && $usergroup['type'] != 5) - { - error($lang->cannot_leave_group); - } - leave_usergroup($mybb->user['uid'], $mybb->get_input('leavegroup', MyBB::INPUT_INT)); - $plugins->run_hooks("usercp_usergroups_leave_group"); - redirect("usercp.php?action=usergroups", $lang->left_group); - exit; - } - - $groupleaders = array(); - - // List of usergroup leaders - $query = $db->query(" - SELECT g.*, u.username, u.displaygroup, u.usergroup, u.email, u.language - FROM ".TABLE_PREFIX."groupleaders g - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=g.uid) - ORDER BY u.username ASC - "); - while($leader = $db->fetch_array($query)) - { - $groupleaders[$leader['gid']][$leader['uid']] = $leader; - } - - // Joining a group - if($mybb->get_input('joingroup', MyBB::INPUT_INT)) - { - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $usergroup = $usergroups[$mybb->get_input('joingroup', MyBB::INPUT_INT)]; - - if($usergroup['type'] == 5) - { - error($lang->cannot_join_invite_group); - } - - if(($usergroup['type'] != 4 && $usergroup['type'] != 3) || !$usergroup['gid']) - { - error($lang->cannot_join_group); - } - - if(my_strpos($ingroups, ",".$mybb->get_input('joingroup', MyBB::INPUT_INT).",") !== false) - { - error($lang->already_member_of_group); - } - - $query = $db->simple_select("joinrequests", "*", "uid='".$mybb->user['uid']."' AND gid='".$mybb->get_input('joingroup', MyBB::INPUT_INT)."'"); - $joinrequest = $db->fetch_array($query); - if($joinrequest['rid']) - { - error($lang->already_sent_join_request); - } - if($mybb->get_input('do') == "joingroup" && $usergroup['type'] == 4) - { - $now = TIME_NOW; - $joinrequest = array( - "uid" => $mybb->user['uid'], - "gid" => $mybb->get_input('joingroup', MyBB::INPUT_INT), - "reason" => $db->escape_string($mybb->get_input('reason')), - "dateline" => TIME_NOW - ); - - $db->insert_query("joinrequests", $joinrequest); - - if(array_key_exists($usergroup['gid'], $groupleaders)) - { - foreach($groupleaders[$usergroup['gid']] as $leader) - { - // Load language - $lang->set_language($leader['language']); - $lang->load("messages"); - - $subject = $lang->sprintf($lang->emailsubject_newjoinrequest, $mybb->settings['bbname']); - $message = $lang->sprintf($lang->email_groupleader_joinrequest, $leader['username'], $mybb->user['username'], $usergroup['title'], $mybb->settings['bbname'], $mybb->get_input('reason'), $mybb->settings['bburl'], $leader['gid']); - my_mail($leader['email'], $subject, $message); - } - } - - // Load language - $lang->set_language($mybb->user['language']); - $lang->load("messages"); - - $plugins->run_hooks("usercp_usergroups_join_group_request"); - redirect("usercp.php?action=usergroups", $lang->group_join_requestsent); - exit; - } - elseif($usergroup['type'] == 4) - { - $joingroup = $mybb->get_input('joingroup', MyBB::INPUT_INT); - eval("\$joinpage = \"".$templates->get("usercp_usergroups_joingroup")."\";"); - output_page($joinpage); - exit; - } - else - { - join_usergroup($mybb->user['uid'], $mybb->get_input('joingroup', MyBB::INPUT_INT)); - $plugins->run_hooks("usercp_usergroups_join_group"); - redirect("usercp.php?action=usergroups", $lang->joined_group); - } - } - - // Accepting invitation - if($mybb->get_input('acceptinvite', MyBB::INPUT_INT)) - { - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $usergroup = $usergroups[$mybb->get_input('acceptinvite', MyBB::INPUT_INT)]; - - if(my_strpos($ingroups, ",".$mybb->get_input('acceptinvite', MyBB::INPUT_INT).",") !== false) - { - error($lang->already_accepted_invite); - } - - $query = $db->simple_select("joinrequests", "*", "uid='".$mybb->user['uid']."' AND gid='".$mybb->get_input('acceptinvite', MyBB::INPUT_INT)."' AND invite='1'"); - $joinrequest = $db->fetch_array($query); - if($joinrequest['rid']) - { - join_usergroup($mybb->user['uid'], $mybb->get_input('acceptinvite', MyBB::INPUT_INT)); - $db->delete_query("joinrequests", "uid='{$mybb->user['uid']}' AND gid='".$mybb->get_input('acceptinvite', MyBB::INPUT_INT)."'"); - $plugins->run_hooks("usercp_usergroups_accept_invite"); - redirect("usercp.php?action=usergroups", $lang->joined_group); - } - else - { - error($lang->no_pending_invitation); - } - } - // Show listing of various group related things - - // List of groups this user is a leader of - $groupsledlist = ''; - - switch($db->type) - { - case "pgsql": - case "sqlite": - $query = $db->query(" - SELECT g.title, g.gid, g.type, COUNT(DISTINCT u.uid) AS users, COUNT(DISTINCT j.rid) AS joinrequests, l.canmanagerequests, l.canmanagemembers, l.caninvitemembers - FROM ".TABLE_PREFIX."groupleaders l - LEFT JOIN ".TABLE_PREFIX."usergroups g ON(g.gid=l.gid) - LEFT JOIN ".TABLE_PREFIX."users u ON(((','|| u.additionalgroups|| ',' LIKE '%,'|| g.gid|| ',%') OR u.usergroup = g.gid)) - LEFT JOIN ".TABLE_PREFIX."joinrequests j ON(j.gid=g.gid AND j.uid != 0) - WHERE l.uid='".$mybb->user['uid']."' - GROUP BY g.gid, g.title, g.type, l.canmanagerequests, l.canmanagemembers, l.caninvitemembers - "); - break; - default: - $query = $db->query(" - SELECT g.title, g.gid, g.type, COUNT(DISTINCT u.uid) AS users, COUNT(DISTINCT j.rid) AS joinrequests, l.canmanagerequests, l.canmanagemembers, l.caninvitemembers - FROM ".TABLE_PREFIX."groupleaders l - LEFT JOIN ".TABLE_PREFIX."usergroups g ON(g.gid=l.gid) - LEFT JOIN ".TABLE_PREFIX."users u ON(((CONCAT(',', u.additionalgroups, ',') LIKE CONCAT('%,', g.gid, ',%')) OR u.usergroup = g.gid)) - LEFT JOIN ".TABLE_PREFIX."joinrequests j ON(j.gid=g.gid AND j.uid != 0) - WHERE l.uid='".$mybb->user['uid']."' - GROUP BY g.gid, g.title, g.type, l.canmanagerequests, l.canmanagemembers, l.caninvitemembers - "); - } - - while($usergroup = $db->fetch_array($query)) - { - $memberlistlink = $moderaterequestslink = ''; - eval("\$memberlistlink = \"".$templates->get("usercp_usergroups_leader_usergroup_memberlist")."\";"); - $usergroup['title'] = htmlspecialchars_uni($usergroup['title']); - if($usergroup['type'] != 4) - { - $usergroup['joinrequests'] = '--'; - } - if($usergroup['joinrequests'] > 0 && $usergroup['canmanagerequests'] == 1) - { - eval("\$moderaterequestslink = \"".$templates->get("usercp_usergroups_leader_usergroup_moderaterequests")."\";"); - } - $groupleader[$usergroup['gid']] = 1; - $trow = alt_trow(); - eval("\$groupsledlist .= \"".$templates->get("usercp_usergroups_leader_usergroup")."\";"); - } - $leadinggroups = ''; - if($groupsledlist) - { - eval("\$leadinggroups = \"".$templates->get("usercp_usergroups_leader")."\";"); - } - - // Fetch the list of groups the member is in - // Do the primary group first - $usergroup = $usergroups[$mybb->user['usergroup']]; - $usergroup['title'] = htmlspecialchars_uni($usergroup['title']); - $usergroup['usertitle'] = htmlspecialchars_uni($usergroup['usertitle']); - $usergroup['description'] = htmlspecialchars_uni($usergroup['description']); - eval("\$leavelink = \"".$templates->get("usercp_usergroups_memberof_usergroup_leaveprimary")."\";"); - $trow = alt_trow(); - if($usergroup['candisplaygroup'] == 1 && $usergroup['gid'] == $mybb->user['displaygroup']) - { - eval("\$displaycode = \"".$templates->get("usercp_usergroups_memberof_usergroup_display")."\";"); - } - elseif($usergroup['candisplaygroup'] == 1) - { - eval("\$displaycode = \"".$templates->get("usercp_usergroups_memberof_usergroup_setdisplay")."\";"); - } - else - { - $displaycode = ''; - } - - eval("\$memberoflist = \"".$templates->get("usercp_usergroups_memberof_usergroup")."\";"); - $showmemberof = false; - if($mybb->user['additionalgroups']) - { - $query = $db->simple_select("usergroups", "*", "gid IN (".$mybb->user['additionalgroups'].") AND gid !='".$mybb->user['usergroup']."'", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $showmemberof = true; - - if(isset($groupleader[$usergroup['gid']])) - { - eval("\$leavelink = \"".$templates->get("usercp_usergroups_memberof_usergroup_leaveleader")."\";"); - } - elseif($usergroup['type'] != 4 && $usergroup['type'] != 3 && $usergroup['type'] != 5) - { - eval("\$leavelink = \"".$templates->get("usercp_usergroups_memberof_usergroup_leaveother")."\";"); - } - else - { - eval("\$leavelink = \"".$templates->get("usercp_usergroups_memberof_usergroup_leave")."\";"); - } - - $description = ''; - $usergroup['title'] = htmlspecialchars_uni($usergroup['title']); - $usergroup['usertitle'] = htmlspecialchars_uni($usergroup['usertitle']); - if($usergroup['description']) - { - $usergroup['description'] = htmlspecialchars_uni($usergroup['description']); - eval("\$description = \"".$templates->get("usercp_usergroups_memberof_usergroup_description")."\";"); - } - $trow = alt_trow(); - if($usergroup['candisplaygroup'] == 1 && $usergroup['gid'] == $mybb->user['displaygroup']) - { - eval("\$displaycode = \"".$templates->get("usercp_usergroups_memberof_usergroup_display")."\";"); - } - elseif($usergroup['candisplaygroup'] == 1) - { - eval("\$displaycode = \"".$templates->get("usercp_usergroups_memberof_usergroup_setdisplay")."\";"); - } - else - { - $displaycode = ''; - } - eval("\$memberoflist .= \"".$templates->get("usercp_usergroups_memberof_usergroup")."\";"); - } - } - eval("\$membergroups = \"".$templates->get("usercp_usergroups_memberof")."\";"); - - // List of groups this user has applied for but has not been accepted in to - $query = $db->simple_select("joinrequests", "*", "uid='".$mybb->user['uid']."'"); - while($request = $db->fetch_array($query)) - { - $appliedjoin[$request['gid']] = $request['dateline']; - } - - // Fetch list of groups the member can join - $existinggroups = $mybb->user['usergroup']; - if($mybb->user['additionalgroups']) - { - $existinggroups .= ",".$mybb->user['additionalgroups']; - } - - $joinablegroups = $joinablegrouplist = ''; - $query = $db->simple_select("usergroups", "*", "(type='3' OR type='4' OR type='5') AND gid NOT IN ($existinggroups)", array('order_by' => 'title')); - while($usergroup = $db->fetch_array($query)) - { - $trow = alt_trow(); - - $description = ''; - $usergroup['title'] = htmlspecialchars_uni($usergroup['title']); - if($usergroup['description']) - { - $usergroup['description'] = htmlspecialchars_uni($usergroup['description']); - eval("\$description = \"".$templates->get("usercp_usergroups_joinable_usergroup_description")."\";"); - } - - // Moderating join requests? - if($usergroup['type'] == 4) - { - $conditions = $lang->usergroup_joins_moderated; - } - elseif($usergroup['type'] == 5) - { - $conditions = $lang->usergroup_joins_invite; - } - else - { - $conditions = $lang->usergroup_joins_anyone; - } - - if(isset($appliedjoin[$usergroup['gid']]) && $usergroup['type'] != 5) - { - $applydate = my_date('relative', $appliedjoin[$usergroup['gid']]); - $joinlink = $lang->sprintf($lang->join_group_applied, $applydate); - } - elseif(isset($appliedjoin[$usergroup['gid']]) && $usergroup['type'] == 5) - { - $joinlink = $lang->sprintf($lang->pending_invitation, $usergroup['gid'], $mybb->post_code); - } - elseif($usergroup['type'] == 5) - { - $joinlink = "--"; - } - else - { - eval("\$joinlink = \"".$templates->get("usercp_usergroups_joinable_usergroup_join")."\";"); - } - - $usergroupleaders = ''; - if(!empty($groupleaders[$usergroup['gid']])) - { - $comma = ''; - $usergroupleaders = ''; - foreach($groupleaders[$usergroup['gid']] as $leader) - { - $leader['username'] = format_name(htmlspecialchars_uni($leader['username']), $leader['usergroup'], $leader['displaygroup']); - $usergroupleaders .= $comma.build_profile_link($leader['username'], $leader['uid']); - $comma = $lang->comma; - } - $usergroupleaders = $lang->usergroup_leaders." ".$usergroupleaders; - } - - if(my_strpos($usergroupleaders, $mybb->user['username']) === false) - { - // User is already a leader of the group, so don't show as a "Join Group" - eval("\$joinablegrouplist .= \"".$templates->get("usercp_usergroups_joinable_usergroup")."\";"); - } - } - if($joinablegrouplist) - { - eval("\$joinablegroups = \"".$templates->get("usercp_usergroups_joinable")."\";"); - } - - $plugins->run_hooks("usercp_usergroups_end"); - - eval("\$groupmemberships = \"".$templates->get("usercp_usergroups")."\";"); - output_page($groupmemberships); -} - -if($mybb->input['action'] == "attachments") -{ - $plugins->run_hooks("usercp_attachments_start"); - require_once MYBB_ROOT."inc/functions_upload.php"; - - if($mybb->settings['enableattachments'] == 0) - { - error($lang->attachments_disabled); - } - - $attachments = ''; - - // Pagination - if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1) - { - $mybb->settings['threadsperpage'] = 20; - } - - $perpage = $mybb->settings['threadsperpage']; - $page = $mybb->get_input('page', MyBB::INPUT_INT); - - if($page > 0) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $end = $start + $perpage; - $lower = $start+1; - - $query = $db->query(" - SELECT a.*, p.subject, p.dateline, t.tid, t.subject AS threadsubject - FROM ".TABLE_PREFIX."attachments a - LEFT JOIN ".TABLE_PREFIX."posts p ON (a.pid=p.pid) - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - WHERE a.uid='".$mybb->user['uid']."' - ORDER BY p.dateline DESC LIMIT {$start}, {$perpage} - "); - - $bandwidth = $totaldownloads = 0; - while($attachment = $db->fetch_array($query)) - { - if($attachment['dateline'] && $attachment['tid']) - { - $attachment['subject'] = htmlspecialchars_uni($parser->parse_badwords($attachment['subject'])); - $attachment['postlink'] = get_post_link($attachment['pid'], $attachment['tid']); - $attachment['threadlink'] = get_thread_link($attachment['tid']); - $attachment['threadsubject'] = htmlspecialchars_uni($parser->parse_badwords($attachment['threadsubject'])); - - $size = get_friendly_size($attachment['filesize']); - $icon = get_attachment_icon(get_extension($attachment['filename'])); - $attachment['filename'] = htmlspecialchars_uni($attachment['filename']); - - $sizedownloads = $lang->sprintf($lang->attachment_size_downloads, $size, $attachment['downloads']); - $attachdate = my_date('relative', $attachment['dateline']); - $altbg = alt_trow(); - - eval("\$attachments .= \"".$templates->get("usercp_attachments_attachment")."\";"); - - // Add to bandwidth total - $bandwidth += ($attachment['filesize'] * $attachment['downloads']); - $totaldownloads += $attachment['downloads']; - } - else - { - // This little thing delets attachments without a thread/post - remove_attachment($attachment['pid'], $attachment['posthash'], $attachment['aid']); - } - } - - $query = $db->simple_select("attachments", "SUM(filesize) AS ausage, COUNT(aid) AS acount", "uid='".$mybb->user['uid']."'"); - $usage = $db->fetch_array($query); - $totalusage = $usage['ausage']; - $totalattachments = $usage['acount']; - $friendlyusage = get_friendly_size($totalusage); - if($mybb->usergroup['attachquota']) - { - $percent = round(($totalusage/($mybb->usergroup['attachquota']*1024))*100)."%"; - $attachquota = get_friendly_size($mybb->usergroup['attachquota']*1024); - $usagenote = $lang->sprintf($lang->attachments_usage_quota, $friendlyusage, $attachquota, $percent, $totalattachments); - } - else - { - $percent = $lang->unlimited; - $attachquota = $lang->unlimited; - $usagenote = $lang->sprintf($lang->attachments_usage, $friendlyusage, $totalattachments); - } - - $multipage = multipage($totalattachments, $perpage, $page, "usercp.php?action=attachments"); - $bandwidth = get_friendly_size($bandwidth); - - if(!$attachments) - { - eval("\$attachments = \"".$templates->get("usercp_attachments_none")."\";"); - $usagenote = ''; - } - - $plugins->run_hooks("usercp_attachments_end"); - - eval("\$manageattachments = \"".$templates->get("usercp_attachments")."\";"); - output_page($manageattachments); -} - -if($mybb->input['action'] == "do_attachments" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - $plugins->run_hooks("usercp_do_attachments_start"); - require_once MYBB_ROOT."inc/functions_upload.php"; - if(!isset($mybb->input['attachments']) || !is_array($mybb->input['attachments'])) - { - error($lang->no_attachments_selected); - } - $aids = implode(',', array_map('intval', $mybb->input['attachments'])); - $query = $db->simple_select("attachments", "*", "aid IN ($aids) AND uid='".$mybb->user['uid']."'"); - while($attachment = $db->fetch_array($query)) - { - remove_attachment($attachment['pid'], '', $attachment['aid']); - } - $plugins->run_hooks("usercp_do_attachments_end"); - redirect("usercp.php?action=attachments", $lang->attachments_deleted); -} - -if($mybb->input['action'] == "do_notepad" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - // Cap at 60,000 chars; text will allow up to 65535? - if(my_strlen($mybb->get_input('notepad')) > 60000) - { - $mybb->input['notepad'] = my_substr($mybb->get_input('notepad'), 0, 60000); - } - - $plugins->run_hooks("usercp_do_notepad_start"); - $db->update_query("users", array('notepad' => $db->escape_string($mybb->get_input('notepad'))), "uid='".$mybb->user['uid']."'"); - $plugins->run_hooks("usercp_do_notepad_end"); - redirect("usercp.php", $lang->redirect_notepadupdated); -} - -if(!$mybb->input['action']) -{ - // Get posts per day - $daysreg = (TIME_NOW - $mybb->user['regdate']) / (24*3600); - - if($daysreg < 1) - { - $daysreg = 1; - } - - $perday = $mybb->user['postnum'] / $daysreg; - $perday = round($perday, 2); - if($perday > $mybb->user['postnum']) - { - $perday = $mybb->user['postnum']; - } - - $stats = $cache->read("stats"); - $posts = $stats['numposts']; - if($posts == 0) - { - $percent = "0"; - } - else - { - $percent = $mybb->user['postnum']*100/$posts; - $percent = round($percent, 2); - } - - $colspan = 2; - $lang->posts_day = $lang->sprintf($lang->posts_day, my_number_format($perday), $percent); - $regdate = my_date('relative', $mybb->user['regdate']); - - $useravatar = format_avatar($mybb->user['avatar'], $mybb->user['avatardimensions'], '100x100'); - $avatar_username = htmlspecialchars_uni($mybb->user['username']); - eval("\$avatar = \"".$templates->get("usercp_currentavatar")."\";"); - - $usergroup = htmlspecialchars_uni($groupscache[$mybb->user['usergroup']]['title']); - if($mybb->user['usergroup'] == 5 && $mybb->settings['regtype'] != "admin") - { - eval("\$usergroup .= \"".$templates->get("usercp_resendactivation")."\";"); - } - // Make reputations row - $reputations = ''; - if($mybb->usergroup['usereputationsystem'] == 1 && $mybb->settings['enablereputation'] == 1) - { - $reputation_link = get_reputation($mybb->user['reputation']); - eval("\$reputation = \"".$templates->get("usercp_reputation")."\";"); - } - - $latest_warnings = ''; - if($mybb->settings['enablewarningsystem'] != 0 && $mybb->settings['canviewownwarning'] != 0) - { - if($mybb->settings['maxwarningpoints'] < 1) - { - $mybb->settings['maxwarningpoints'] = 10; - } - $warning_level = round($mybb->user['warningpoints']/$mybb->settings['maxwarningpoints']*100); - if($warning_level > 100) - { - $warning_level = 100; - } - - if($mybb->user['warningpoints'] > $mybb->settings['maxwarningpoints']) - { - $mybb->user['warningpoints'] = $mybb->settings['maxwarningpoints']; - } - - if($warning_level > 0) - { - require_once MYBB_ROOT.'inc/datahandlers/warnings.php'; - $warningshandler = new WarningsHandler('update'); - - $warningshandler->expire_warnings(); - - $lang->current_warning_level = $lang->sprintf($lang->current_warning_level, $warning_level, $mybb->user['warningpoints'], $mybb->settings['maxwarningpoints']); - $warnings = ''; - // Fetch latest warnings - $query = $db->query(" - SELECT w.*, t.title AS type_title, u.username, p.subject AS post_subject - FROM ".TABLE_PREFIX."warnings w - LEFT JOIN ".TABLE_PREFIX."warningtypes t ON (t.tid=w.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=w.issuedby) - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=w.pid) - WHERE w.uid='{$mybb->user['uid']}' - ORDER BY w.expired ASC, w.dateline DESC - LIMIT 5 - "); - while($warning = $db->fetch_array($query)) - { - $post_link = ""; - if($warning['post_subject']) - { - $warning['post_subject'] = $parser->parse_badwords($warning['post_subject']); - $warning['post_subject'] = htmlspecialchars_uni($warning['post_subject']); - $warning['postlink'] = get_post_link($warning['pid']); - eval("\$post_link .= \"".$templates->get("usercp_warnings_warning_post")."\";"); - } - $warning['username'] = htmlspecialchars_uni($warning['username']); - $issuedby = build_profile_link($warning['username'], $warning['issuedby']); - $date_issued = my_date('relative', $warning['dateline']); - if($warning['type_title']) - { - $warning_type = $warning['type_title']; - } - else - { - $warning_type = $warning['title']; - } - $warning_type = htmlspecialchars_uni($warning_type); - if($warning['points'] > 0) - { - $warning['points'] = "+{$warning['points']}"; - } - $points = $lang->sprintf($lang->warning_points, $warning['points']); - - // Figure out expiration time - if($warning['daterevoked']) - { - $expires = $lang->warning_revoked; - } - elseif($warning['expired']) - { - $expires = $lang->already_expired; - } - elseif($warning['expires'] == 0) - { - $expires = $lang->never; - } - else - { - $expires = my_date('relative', $warning['expires']); - } - - $alt_bg = alt_trow(); - eval("\$warnings .= \"".$templates->get("usercp_warnings_warning")."\";"); - } - if($warnings) - { - eval("\$latest_warnings = \"".$templates->get("usercp_warnings")."\";"); - } - } - } - - // Format username - $username = format_name(htmlspecialchars_uni($mybb->user['username']), $mybb->user['usergroup'], $mybb->user['displaygroup']); - $username = build_profile_link($username, $mybb->user['uid']); - - // Format post numbers - $mybb->user['posts'] = my_number_format($mybb->user['postnum']); - - // Build referral link - if($mybb->settings['usereferrals'] == 1) - { - $referral_link = $lang->sprintf($lang->referral_link, $settings['bburl'], $mybb->user['uid']); - eval("\$referral_info = \"".$templates->get("usercp_referrals")."\";"); - } - - // User Notepad - $plugins->run_hooks("usercp_notepad_start"); - $mybb->user['notepad'] = htmlspecialchars_uni($mybb->user['notepad']); - eval("\$user_notepad = \"".$templates->get("usercp_notepad")."\";"); - $plugins->run_hooks("usercp_notepad_end"); - - // Thread Subscriptions with New Posts - $latest_subscribed = ''; - $query = $db->simple_select("threadsubscriptions", "sid", "uid = '".$mybb->user['uid']."'", array("limit" => 1)); - if($db->num_rows($query)) - { - $visible = "AND t.visible != 0"; - if(is_moderator() == true) - { - $visible = ''; - } - - $query = $db->query(" - SELECT s.*, t.*, t.username AS threadusername, u.username - FROM ".TABLE_PREFIX."threadsubscriptions s - LEFT JOIN ".TABLE_PREFIX."threads t ON (s.tid=t.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid = t.uid) - WHERE s.uid='".$mybb->user['uid']."' {$visible} - ORDER BY t.lastpost DESC - LIMIT 0, 10 - "); - - $fpermissions = forum_permissions(); - while($subscription = $db->fetch_array($query)) - { - $forumpermissions = $fpermissions[$subscription['fid']]; - if($forumpermissions['canview'] != 0 && $forumpermissions['canviewthreads'] != 0 && ($forumpermissions['canonlyviewownthreads'] == 0 || $subscription['uid'] == $mybb->user['uid'])) - { - $subscriptions[$subscription['tid']] = $subscription; - } - } - - if(is_array($subscriptions)) - { - $tids = implode(",", array_keys($subscriptions)); - - // Checking read - if($mybb->settings['threadreadcut'] > 0) - { - $query = $db->simple_select("threadsread", "*", "uid='{$mybb->user['uid']}' AND tid IN ({$tids})"); - while($readthread = $db->fetch_array($query)) - { - if($readthread['dateline'] >= $subscriptions[$readthread['tid']]['lastpost']) - { - unset($subscriptions[$readthread['tid']]); // If it's already been read, then don't display the thread - } - else - { - $subscriptions[$readthread['tid']]['lastread'] = $readthread['dateline']; - } - } - } - - if($subscriptions) - { - if($mybb->settings['dotfolders'] != 0) - { - $query = $db->simple_select("posts", "tid,uid", "uid='{$mybb->user['uid']}' AND tid IN ({$tids})"); - while($post = $db->fetch_array($query)) - { - $subscriptions[$post['tid']]['doticon'] = 1; - } - } - - $icon_cache = $cache->read("posticons"); - $threadprefixes = build_prefixes(); - - foreach($subscriptions as $thread) - { - $folder = ''; - $folder_label = ''; - $gotounread = ''; - - if($thread['tid']) - { - $bgcolor = alt_trow(); - $thread['subject'] = $parser->parse_badwords($thread['subject']); - $thread['subject'] = htmlspecialchars_uni($thread['subject']); - $thread['threadlink'] = get_thread_link($thread['tid']); - $thread['lastpostlink'] = get_thread_link($thread['tid'], 0, "lastpost"); - - // If this thread has a prefix... - if($thread['prefix'] != 0 && !empty($threadprefixes[$thread['prefix']])) - { - $thread['displayprefix'] = $threadprefixes[$thread['prefix']]['displaystyle'].' '; - } - else - { - $thread['displayprefix'] = ''; - } - - // Icons - if($thread['icon'] > 0 && isset($icon_cache[$thread['icon']])) - { - $icon = $icon_cache[$thread['icon']]; - $icon['path'] = str_replace("{theme}", $theme['imgdir'], $icon['path']); - $icon['path'] = htmlspecialchars_uni($icon['path']); - $icon['name'] = htmlspecialchars_uni($icon['name']); - eval("\$icon = \"".$templates->get("usercp_subscriptions_thread_icon")."\";"); - } - else - { - $icon = " "; - } - - if($thread['doticon']) - { - $folder = "dot_"; - $folder_label .= $lang->icon_dot; - } - - // Check to see which icon we display - if($thread['lastread'] && $thread['lastread'] < $thread['lastpost']) - { - $folder .= "new"; - $folder_label .= $lang->icon_new; - $new_class = "subject_new"; - $thread['newpostlink'] = get_thread_link($thread['tid'], 0, "newpost"); - eval("\$gotounread = \"".$templates->get("forumdisplay_thread_gotounread")."\";"); - } - else - { - $folder_label .= $lang->icon_no_new; - $new_class = "subject_old"; - } - - $folder .= "folder"; - - if($thread['visible'] == 0) - { - $bgcolor = "trow_shaded"; - } - - $lastpostdate = my_date('relative', $thread['lastpost']); - $lastposter = htmlspecialchars_uni($thread['lastposter']); - $lastposteruid = $thread['lastposteruid']; - - if($lastposteruid == 0) - { - $lastposterlink = $lastposter; - } - else - { - $lastposterlink = build_profile_link($lastposter, $lastposteruid); - } - - $thread['replies'] = my_number_format($thread['replies']); - $thread['views'] = my_number_format($thread['views']); - $thread['username'] = htmlspecialchars_uni($thread['username']); - $thread['author'] = build_profile_link($thread['username'], $thread['uid']); - - eval("\$latest_subscribed_threads .= \"".$templates->get("usercp_latest_subscribed_threads")."\";"); - } - } - eval("\$latest_subscribed = \"".$templates->get("usercp_latest_subscribed")."\";"); - } - } - } - - // User's Latest Threads - - // Get unviewable forums - $f_perm_sql = ''; - $unviewable_forums = get_unviewable_forums(); - $inactiveforums = get_inactive_forums(); - if($unviewable_forums) - { - $f_perm_sql = " AND t.fid NOT IN ($unviewable_forums)"; - } - if($inactiveforums) - { - $f_perm_sql .= " AND t.fid NOT IN ($inactiveforums)"; - } - - $visible = " AND t.visible != 0"; - if(is_moderator() == true) - { - $visible = ''; - } - - $query = $db->query(" - SELECT t.*, t.username AS threadusername, u.username - FROM ".TABLE_PREFIX."threads t - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid = t.uid) - WHERE t.uid='".$mybb->user['uid']."' AND t.firstpost != 0 AND t.visible >= 0 {$visible}{$f_perm_sql} - ORDER BY t.lastpost DESC - LIMIT 0, 5 - "); - - // Figure out whether we can view these threads... - $threadcache = array(); - $fpermissions = forum_permissions(); - while($thread = $db->fetch_array($query)) - { - // Moderated, and not moderator? - if($thread['visible'] == 0 && is_moderator($thread['fid'], "canviewunapprove") === false) - { - continue; - } - - $forumpermissions = $fpermissions[$thread['fid']]; - if($forumpermissions['canview'] != 0 || $forumpermissions['canviewthreads'] != 0) - { - $threadcache[$thread['tid']] = $thread; - } - } - - $latest_threads = ''; - if(!empty($threadcache)) - { - $tids = implode(",", array_keys($threadcache)); - $readforums = array(); - - // Read Forums - $query = $db->query(" - SELECT f.fid, fr.dateline AS lastread - FROM ".TABLE_PREFIX."forums f - LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}') - WHERE f.active != 0 - ORDER BY pid, disporder - "); - - while($forum = $db->fetch_array($query)) - { - $readforums[$forum['fid']] = $forum['lastread']; - } - - // Threads being read? - if($mybb->settings['threadreadcut'] > 0) - { - $query = $db->simple_select("threadsread", "*", "uid='{$mybb->user['uid']}' AND tid IN ({$tids})"); - while($readthread = $db->fetch_array($query)) - { - $threadcache[$readthread['tid']]['lastread'] = $readthread['dateline']; - } - } - - // Icon Stuff - if($mybb->settings['dotfolders'] != 0) - { - $query = $db->simple_select("posts", "tid,uid", "uid='{$mybb->user['uid']}' AND tid IN ({$tids})"); - while($post = $db->fetch_array($query)) - { - $threadcache[$post['tid']]['doticon'] = 1; - } - } - - $icon_cache = $cache->read("posticons"); - $threadprefixes = build_prefixes(); - - // Run the threads... - $latest_threads_threads = ''; - foreach($threadcache as $thread) - { - if($thread['tid']) - { - $bgcolor = alt_trow(); - $folder = ''; - $folder_label = ''; - $prefix = ''; - $gotounread = ''; - $isnew = 0; - $donenew = 0; - $lastread = 0; - - // If this thread has a prefix... - if($thread['prefix'] != 0) - { - if(!empty($threadprefixes[$thread['prefix']])) - { - $thread['displayprefix'] = $threadprefixes[$thread['prefix']]['displaystyle'].' '; - } - } - else - { - $thread['displayprefix'] = ''; - } - - $thread['subject'] = $parser->parse_badwords($thread['subject']); - $thread['subject'] = htmlspecialchars_uni($thread['subject']); - $thread['threadlink'] = get_thread_link($thread['tid']); - $thread['lastpostlink'] = get_thread_link($thread['tid'], 0, "lastpost"); - - if($thread['icon'] > 0 && $icon_cache[$thread['icon']]) - { - $icon = $icon_cache[$thread['icon']]; - $icon['path'] = str_replace("{theme}", $theme['imgdir'], $icon['path']); - $icon['path'] = htmlspecialchars_uni($icon['path']); - $icon['name'] = htmlspecialchars_uni($icon['name']); - eval("\$icon = \"".$templates->get("usercp_subscriptions_thread_icon")."\";"); - } - else - { - $icon = " "; - } - - if($mybb->settings['threadreadcut'] > 0) - { - $forum_read = $readforums[$thread['fid']]; - - $read_cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - if($forum_read == 0 || $forum_read < $read_cutoff) - { - $forum_read = $read_cutoff; - } - } - - if($mybb->settings['threadreadcut'] > 0 && $thread['lastpost'] > $forum_read) - { - $cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; - } - - $cutoff = 0; - if($thread['lastpost'] > $cutoff) - { - if($thread['lastread']) - { - $lastread = $thread['lastread']; - } - } - - if(!$lastread) - { - $readcookie = $threadread = my_get_array_cookie("threadread", $thread['tid']); - if($readcookie > $forum_read) - { - $lastread = $readcookie; - } - else - { - $lastread = $forum_read; - } - } - - // Folder Icons - if($thread['doticon']) - { - $folder = "dot_"; - $folder_label .= $lang->icon_dot; - } - - if($thread['lastpost'] > $lastread && $lastread) - { - $folder .= "new"; - $folder_label .= $lang->icon_new; - $new_class = "subject_new"; - $thread['newpostlink'] = get_thread_link($thread['tid'], 0, "newpost"); - eval("\$gotounread = \"".$templates->get("forumdisplay_thread_gotounread")."\";"); - $unreadpost = 1; - } - else - { - $folder_label .= $lang->icon_no_new; - $new_class = "subject_old"; - } - - if($thread['replies'] >= $mybb->settings['hottopic'] || $thread['views'] >= $mybb->settings['hottopicviews']) - { - $folder .= "hot"; - $folder_label .= $lang->icon_hot; - } - - // Is our thread visible? - if($thread['visible'] == 0) - { - $bgcolor = 'trow_shaded'; - } - - if($thread['closed'] == 1) - { - $folder .= "lock"; - $folder_label .= $lang->icon_lock; - } - - $folder .= "folder"; - - $lastpostdate = my_date('relative', $thread['lastpost']); - $lastposter = htmlspecialchars_uni($thread['lastposter']); - $lastposteruid = $thread['lastposteruid']; - - if($lastposteruid == 0) - { - $lastposterlink = $lastposter; - } - else - { - $lastposterlink = build_profile_link($lastposter, $lastposteruid); - } - - $thread['replies'] = my_number_format($thread['replies']); - $thread['views'] = my_number_format($thread['views']); - $thread['username'] = htmlspecialchars_uni($thread['username']); - $thread['author'] = build_profile_link($thread['username'], $thread['uid']); - - eval("\$latest_threads_threads .= \"".$templates->get("usercp_latest_threads_threads")."\";"); - } - } - - eval("\$latest_threads = \"".$templates->get("usercp_latest_threads")."\";"); - } - - $plugins->run_hooks("usercp_end"); - - eval("\$usercp = \"".$templates->get("usercp")."\";"); - output_page($usercp); -} diff --git a/html/forums/usercp2.php b/html/forums/usercp2.php deleted file mode 100644 index ff5ff44..0000000 --- a/html/forums/usercp2.php +++ /dev/null @@ -1,251 +0,0 @@ -user['uid'] == 0) -{ - error_no_permission(); -} - -// Verify incoming POST request -verify_post_check($mybb->get_input('my_post_key')); - -$lang->load("usercp"); - -usercp_menu(); - -$server_http_referer = htmlentities($_SERVER['HTTP_REFERER']); - -$plugins->run_hooks("usercp2_start"); - -if($mybb->get_input('action') == "do_addsubscription" && $mybb->get_input('type') != "forum") -{ - $thread = get_thread($mybb->get_input('tid')); - if(!$thread) - { - error($lang->error_invalidthread); - } - - // Is the currently logged in user a moderator of this forum? - $ismod = is_moderator($thread['fid']); - - // Make sure we are looking at a real thread here. - if(($thread['visible'] != 1 && $ismod == false) || ($thread['visible'] > 1 && $ismod == true)) - { - error($lang->error_invalidthread); - } - - $forumpermissions = forum_permissions($thread['fid']); - if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0 || (isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0 && $thread['uid'] != $mybb->user['uid'])) - { - error_no_permission(); - } - - $plugins->run_hooks("usercp2_do_addsubscription"); - - add_subscribed_thread($thread['tid'], $mybb->get_input('notification', MyBB::INPUT_INT)); - - if($mybb->get_input('referrer')) - { - $url = htmlspecialchars_uni($mybb->get_input('referrer')); - } - else - { - $url = get_thread_link($thread['tid']); - } - redirect($url, $lang->redirect_subscriptionadded); -} -elseif($mybb->get_input('action') == "addsubscription") -{ - if($mybb->get_input('type') == "forum") - { - $forum = get_forum($mybb->get_input('fid', MyBB::INPUT_INT)); - if(!$forum) - { - error($lang->error_invalidforum); - } - $forumpermissions = forum_permissions($forum['fid']); - if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0) - { - error_no_permission(); - } - - $plugins->run_hooks("usercp2_addsubscription_forum"); - - add_subscribed_forum($forum['fid']); - if($server_http_referer) - { - $url = $server_http_referer; - } - else - { - $url = "index.php"; - } - redirect($url, $lang->redirect_forumsubscriptionadded); - } - else - { - $thread = get_thread($mybb->get_input('tid', MyBB::INPUT_INT)); - if(!$thread) - { - error($lang->error_invalidthread); - } - - // Is the currently logged in user a moderator of this forum? - $ismod = is_moderator($thread['fid']); - - // Make sure we are looking at a real thread here. - if(($thread['visible'] != 1 && $ismod == false) || ($thread['visible'] > 1 && $ismod == true)) - { - error($lang->error_invalidthread); - } - - add_breadcrumb($lang->nav_subthreads, "usercp.php?action=subscriptions"); - add_breadcrumb($lang->nav_addsubscription); - - $forumpermissions = forum_permissions($thread['fid']); - if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0 || (isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] != 0 && $thread['uid'] != $mybb->user['uid'])) - { - error_no_permission(); - } - $referrer = ''; - if($server_http_referer) - { - $referrer = $server_http_referer; - } - - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - $thread['subject'] = $parser->parse_badwords($thread['subject']); - $thread['subject'] = htmlspecialchars_uni($thread['subject']); - $lang->subscribe_to_thread = $lang->sprintf($lang->subscribe_to_thread, $thread['subject']); - - $notification_none_checked = $notification_email_checked = $notification_pm_checked = ''; - if($mybb->user['subscriptionmethod'] == 1 || $mybb->user['subscriptionmethod'] == 0) - { - $notification_none_checked = "checked=\"checked\""; - } - else if($mybb->user['subscriptionmethod'] == 2) - { - $notification_email_checked = "checked=\"checked\""; - } - else if($mybb->user['subscriptionmethod'] == 3) - { - $notification_pm_checked = "checked=\"checked\""; - } - - $plugins->run_hooks("usercp2_addsubscription_thread"); - - eval("\$add_subscription = \"".$templates->get("usercp_addsubscription_thread")."\";"); - output_page($add_subscription); - exit; - } -} -elseif($mybb->get_input('action') == "removesubscription") -{ - if($mybb->get_input('type') == "forum") - { - $forum = get_forum($mybb->get_input('fid', MyBB::INPUT_INT)); - if(!$forum) - { - error($lang->error_invalidforum); - } - - $plugins->run_hooks("usercp2_removesubscription_forum"); - - remove_subscribed_forum($forum['fid']); - if($server_http_referer) - { - $url = $server_http_referer; - } - else - { - $url = "usercp.php?action=forumsubscriptions"; - } - redirect($url, $lang->redirect_forumsubscriptionremoved); - } - else - { - $thread = get_thread($mybb->get_input('tid', MyBB::INPUT_INT)); - if(!$thread) - { - error($lang->error_invalidthread); - } - - // Is the currently logged in user a moderator of this forum? - $ismod = is_moderator($thread['fid']); - - // Make sure we are looking at a real thread here. - if(($thread['visible'] != 1 && $ismod == false) || ($thread['visible'] > 1 && $ismod == true)) - { - error($lang->error_invalidthread); - } - - $plugins->run_hooks("usercp2_removesubscription_thread"); - - remove_subscribed_thread($thread['tid']); - if($server_http_referer) - { - $url = $server_http_referer; - } - else - { - $url = "usercp.php?action=subscriptions"; - } - redirect($url, $lang->redirect_subscriptionremoved); - } -} -elseif($mybb->get_input('action') == "removesubscriptions") -{ - if($mybb->get_input('type') == "forum") - { - $plugins->run_hooks("usercp2_removesubscriptions_forum"); - - $db->delete_query("forumsubscriptions", "uid='".$mybb->user['uid']."'"); - if($server_http_referer) - { - $url = $server_http_referer; - } - else - { - $url = "usercp.php?action=forumsubscriptions"; - } - redirect($url, $lang->redirect_forumsubscriptionsremoved); - } - else - { - $plugins->run_hooks("usercp2_removesubscriptions_thread"); - - $db->delete_query("threadsubscriptions", "uid='".$mybb->user['uid']."'"); - if($server_http_referer) - { - $url = $server_http_referer; - } - else - { - $url = "usercp.php?action=subscriptions"; - } - redirect($url, $lang->redirect_subscriptionsremoved); - } -} -else -{ - error($lang->error_invalidaction); -} - diff --git a/html/forums/warnings.php b/html/forums/warnings.php deleted file mode 100644 index ce57f66..0000000 --- a/html/forums/warnings.php +++ /dev/null @@ -1,872 +0,0 @@ -load("warnings"); - -if($mybb->settings['enablewarningsystem'] == 0) -{ - error($lang->error_warning_system_disabled); -} - -// Expire old warnings -require_once MYBB_ROOT.'inc/datahandlers/warnings.php'; -$warningshandler = new WarningsHandler('update'); - -$warningshandler->expire_warnings(); - -$mybb->input['action'] = $mybb->get_input('action'); - -$plugins->run_hooks("warnings_start"); - -// Actually warn a user -if($mybb->input['action'] == "do_warn" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->usergroup['canwarnusers'] != 1) - { - error_no_permission(); - } - - $user = get_user($mybb->get_input('uid', MyBB::INPUT_INT)); - - if(!$user['uid']) - { - error($lang->error_invalid_user); - } - - $group_permissions = user_permissions($user['uid']); - - if($group_permissions['canreceivewarnings'] != 1) - { - error($lang->error_cant_warn_group); - } - - if(!modcp_can_manage_user($user['uid'])) - { - error($lang->error_cant_warn_user); - } - - $plugins->run_hooks("warnings_do_warn_start"); - - $warning = array( - 'uid' => $mybb->get_input('uid', MyBB::INPUT_INT), - 'notes' => $mybb->get_input('notes'), - 'type' => $mybb->get_input('type'), - 'custom_reason' => $mybb->get_input('custom_reason'), - 'custom_points' => $mybb->get_input('custom_points', MyBB::INPUT_INT), - 'expires' => $mybb->get_input('expires', MyBB::INPUT_INT), - 'expires_period' => $mybb->get_input('expires_period') - ); - - // Is this warning being given for a post? - if($mybb->get_input('pid', MyBB::INPUT_INT)) - { - $warning['pid'] = $mybb->get_input('pid', MyBB::INPUT_INT); - - $post = get_post($warning['pid']); - - $forum_permissions = forum_permissions($post['fid']); - - if($forum_permissions['canview'] != 1) - { - error_no_permission(); - } - } - - $warningshandler->set_data($warning); - - if($warningshandler->validate_warning()) - { - $warninginfo = $warningshandler->insert_warning(); - - // Are we notifying the user? - if($mybb->get_input('send_pm', MyBB::INPUT_INT) == 1 && $group_permissions['canusepms'] != 0 && $mybb->settings['enablepms'] != 0) - { - - $pm = array( - 'subject' => $mybb->get_input('pm_subject'), - 'message' => $mybb->get_input('pm_message'), - 'touid' => $user['uid'] - ); - - $sender_uid = $mybb->user['uid']; - if($mybb->settings['allowanonwarningpms'] == 1 && $mybb->get_input('pm_anonymous', MyBB::INPUT_INT)) - { - $sender_uid = -1; - } - - // Some kind of friendly error notification - if(!send_pm($pm, $sender_uid, true)) - { - $warningshandler->friendly_action .= $lang->redirect_warned_pmerror; - } - } - - $plugins->run_hooks("warnings_do_warn_end"); - - $lang->redirect_warned = $lang->sprintf($lang->redirect_warned, htmlspecialchars_uni($user['username']), $warningshandler->new_warning_level, $warningshandler->friendly_action); - - if(!empty($post['pid'])) - { - redirect(get_post_link($post['pid']), $lang->redirect_warned); - } - else - { - redirect(get_profile_link($user['uid']), $lang->redirect_warned); - } - } - else - { - $warn_errors = $warningshandler->get_friendly_errors(); - $warn_errors = inline_error($warn_errors); - $mybb->input['action'] = 'warn'; - } -} - -// Warn a user -if($mybb->input['action'] == "warn") -{ - if($mybb->usergroup['canwarnusers'] != 1) - { - error_no_permission(); - } - - // Check we haven't exceeded the maximum number of warnings per day - if($mybb->usergroup['maxwarningsday'] != 0) - { - $timecut = TIME_NOW-60*60*24; - $query = $db->simple_select("warnings", "COUNT(wid) AS given_today", "issuedby='{$mybb->user['uid']}' AND dateline>'$timecut'"); - $given_today = $db->fetch_field($query, "given_today"); - if($given_today >= $mybb->usergroup['maxwarningsday']) - { - error($lang->sprintf($lang->warnings_reached_max_warnings_day, $mybb->usergroup['maxwarningsday'])); - } - } - - $user = get_user($mybb->get_input('uid', MyBB::INPUT_INT)); - if(!$user) - { - error($lang->error_invalid_user); - } - - if($user['uid'] == $mybb->user['uid']) - { - error($lang->warnings_error_cannot_warn_self); - } - - if($user['warningpoints'] >= $mybb->settings['maxwarningpoints']) - { - error($lang->warnings_error_user_reached_max_warning); - } - - $group_permissions = user_permissions($user['uid']); - - if($group_permissions['canreceivewarnings'] != 1) - { - error($lang->error_cant_warn_group); - } - - if(!modcp_can_manage_user($user['uid'])) - { - error($lang->error_cant_warn_user); - } - - $post = $existing_warnings = ''; - - // Giving a warning for a specific post - if($mybb->get_input('pid', MyBB::INPUT_INT)) - { - $post = get_post($mybb->get_input('pid', MyBB::INPUT_INT)); - - if($post) - { - $thread = get_thread($post['tid']); - } - - if(!$post || !$thread) - { - error($lang->warnings_error_invalid_post); - } - - $forum_permissions = forum_permissions($thread['fid']); - if($forum_permissions['canview'] != 1) - { - error_no_permission(); - } - - $post['subject'] = $parser->parse_badwords($post['subject']); - $post['subject'] = htmlspecialchars_uni($post['subject']); - $post_link = get_post_link($post['pid']); - eval("\$post = \"".$templates->get("warnings_warn_post")."\";"); - - // Fetch any existing warnings issued for this post - $query = $db->query(" - SELECT w.*, t.title AS type_title, u.username - FROM ".TABLE_PREFIX."warnings w - LEFT JOIN ".TABLE_PREFIX."warningtypes t ON (t.tid=w.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=w.issuedby) - WHERE w.pid='".$mybb->get_input('pid', MyBB::INPUT_INT)."' - ORDER BY w.expired ASC, w.dateline DESC - "); - $first = true; - $warnings = ''; - while($warning = $db->fetch_array($query)) - { - if($warning['expired'] != $last_expired || $first) - { - if($warning['expired'] == 0) - { - eval("\$warnings .= \"".$templates->get("warnings_active_header")."\";"); - } - else - { - eval("\$warnings .= \"".$templates->get("warnings_expired_header")."\";"); - } - } - $last_expired = $warning['expired']; - $first = false; - - $post_link = ""; - $warning['username'] = htmlspecialchars_uni($warning['username']); - $issuedby = build_profile_link($warning['username'], $warning['issuedby']); - $date_issued = my_date('relative', $warning['dateline']); - if($warning['type_title']) - { - $warning_type = $warning['type_title']; - } - else - { - $warning_type = $warning['title']; - } - $warning_type = htmlspecialchars_uni($warning_type); - if($warning['points'] > 0) - { - $warning['points'] = "+{$warning['points']}"; - } - $points = $lang->sprintf($lang->warning_points, $warning['points']); - if($warning['expired'] != 1) - { - if($warning['expires'] == 0) - { - $expires = $lang->never; - } - else - { - $expires = my_date($mybb->settings['dateformat'], $warning['expires']) . ", " . my_date($mybb->settings['timeformat'], $warning['expires']); - } - } - else - { - if($warning['daterevoked']) - { - $expires = $lang->warning_revoked; - } - else if($warning['expires']) - { - $expires = $lang->already_expired; - } - } - $alt_bg = alt_trow(); - $plugins->run_hooks("warnings_warning"); - eval("\$warnings .= \"".$templates->get("warnings_warning")."\";"); - } - if($warnings) - { - eval("\$existing_warnings = \"".$templates->get("warnings_warn_existing")."\";"); - } - } - - $plugins->run_hooks("warnings_warn_start"); - - $type_checked = array('custom' => ''); - $expires_period = array('hours' => '', 'days' => '', 'weeks' => '', 'months' => '', 'never' => ''); - $send_pm_checked = ''; - - // Coming here from failed do_warn? - $user['username'] = htmlspecialchars_uni($user['username']); - if(!empty($warn_errors)) - { - $notes = htmlspecialchars_uni($mybb->get_input('notes')); - if($mybb->get_input('type', MyBB::INPUT_INT)) - { - $type_checked[$mybb->get_input('type', MyBB::INPUT_INT)] = "checked=\"checked\""; - } - $pm_subject = htmlspecialchars_uni($mybb->get_input('pm_subject')); - $message = htmlspecialchars_uni($mybb->get_input('pm_message')); - if(!empty($mybb->input['send_pm'])) - { - $send_pm_checked = "checked=\"checked\""; - } - $custom_reason = htmlspecialchars_uni($mybb->get_input('custom_reason')); - $custom_points = $mybb->get_input('custom_points', MyBB::INPUT_INT); - $expires = $mybb->get_input('expires', MyBB::INPUT_INT); - if($mybb->get_input('expires_period', MyBB::INPUT_INT)) - { - $expires_period[$mybb->get_input('expires_period', MyBB::INPUT_INT)] = "selected=\"selected\""; - } - } - else - { - $notes = $custom_reason = $custom_points = $expires = ''; - $expires = 1; - $custom_points = 2; - $pm_subject = $lang->warning_pm_subject; - $message = $lang->sprintf($lang->warning_pm_message, $user['username'], $mybb->settings['bbname']); - $warn_errors = ''; - } - - $lang->nav_profile = $lang->sprintf($lang->nav_profile, $user['username']); - add_breadcrumb($lang->nav_profile, get_profile_link($user['uid'])); - add_breadcrumb($lang->nav_add_warning); - - $user_link = build_profile_link($user['username'], $user['uid']); - - if($mybb->settings['maxwarningpoints'] < 1) - { - $mybb->settings['maxwarningpoints'] = 10; - } - - if(!is_array($groupscache)) - { - $groupscache = $cache->read("usergroups"); - } - - $current_level = round($user['warningpoints']/$mybb->settings['maxwarningpoints']*100); - - // Fetch warning levels - $levels = array(); - $query = $db->simple_select("warninglevels", "*"); - while($level = $db->fetch_array($query)) - { - $level['action'] = my_unserialize($level['action']); - switch($level['action']['type']) - { - case 1: - if($level['action']['length'] > 0) - { - $ban_length = fetch_friendly_expiration($level['action']['length']); - $lang_str = "expiration_".$ban_length['period']; - $period = $lang->sprintf($lang->result_period, $ban_length['time'], $lang->$lang_str); - } - else - { - $period = $lang->result_period_perm; - } - $group_name = $groupscache[$level['action']['usergroup']]['title']; - $level['friendly_action'] = $lang->sprintf($lang->result_banned, $group_name, $period); - break; - case 2: - if($level['action']['length'] > 0) - { - $period = fetch_friendly_expiration($level['action']['length']); - $lang_str = "expiration_".$period['period']; - $period = $lang->sprintf($lang->result_period, $period['time'], $lang->$lang_str); - } - else - { - $period = $lang->result_period_perm; - } - $level['friendly_action'] = $lang->sprintf($lang->result_suspended, $period); - break; - case 3: - if($level['action']['length'] > 0) - { - $period = fetch_friendly_expiration($level['action']['length']); - $lang_str = "expiration_".$period['period']; - $period = $lang->sprintf($lang->result_period, $period['time'], $lang->$lang_str); - } - else - { - $period = $lang->result_period_perm; - } - $level['friendly_action'] = $lang->sprintf($lang->result_moderated, $period); - break; - } - $levels[$level['percentage']] = $level; - } - krsort($levels); - - $types = ''; - - // Fetch all current warning types - $query = $db->simple_select("warningtypes", "*", "", array("order_by" => "title")); - while($type = $db->fetch_array($query)) - { - if(!isset($type_checked[$type['tid']])) - { - $type_checked[$type['tid']] = ''; - } - $checked = $type_checked[$type['tid']]; - $type['title'] = htmlspecialchars_uni($type['title']); - $new_warning_level = round(($user['warningpoints']+$type['points'])/$mybb->settings['maxwarningpoints']*100); - if($new_warning_level > 100) - { - $new_warning_level = 100; - } - if($type['points'] > 0) - { - $type['points'] = "+{$type['points']}"; - } - $points = $lang->sprintf($lang->warning_points, $type['points']); - - if(is_array($levels)) - { - foreach($levels as $level) - { - if($new_warning_level >= $level['percentage']) - { - $new_level = $level; - break; - } - } - } - $level_diff = $new_warning_level-$current_level; - $result = ''; - if(!empty($new_level['friendly_action'])) - { - eval("\$result = \"".$templates->get("warnings_warn_type_result")."\";"); - } - eval("\$types .= \"".$templates->get("warnings_warn_type")."\";"); - unset($new_level); - unset($result); - } - - $custom_warning = ''; - - if($mybb->settings['allowcustomwarnings'] != 0) - { - if(empty($types) && empty($warn_errors) || $mybb->get_input('type') == 'custom') - { - $type_checked['custom'] = "checked=\"checked\""; - } - - eval("\$custom_warning = \"".$templates->get("warnings_warn_custom")."\";"); - } - - $pm_notify = ''; - - if($group_permissions['canusepms'] != 0 && $mybb->user['receivepms'] != 0 && $mybb->settings['enablepms'] != 0) - { - $smilieinserter = $codebuttons = ""; - - if($mybb->settings['bbcodeinserter'] != 0 && $mybb->settings['pmsallowmycode'] != 0 && $mybb->user['showcodebuttons'] != 0) - { - $codebuttons = build_mycode_inserter("message", $mybb->settings['pmsallowsmilies']); - if($mybb->settings['pmsallowsmilies'] != 0) - { - $smilieinserter = build_clickable_smilies(); - } - } - - $anonymous_pm = ''; - if($mybb->settings['allowanonwarningpms'] == 1) - { - $checked = ''; - if($mybb->get_input('pm_anonymous', MyBB::INPUT_INT)) - { - $checked = ' checked="checked"'; - } - - eval('$anonymous_pm = "'.$templates->get('warnings_warn_pm_anonymous').'";'); - } - - eval("\$pm_notify = \"".$templates->get("warnings_warn_pm")."\";"); - } - - $plugins->run_hooks("warnings_warn_end"); - - eval("\$warn = \"".$templates->get("warnings_warn")."\";"); - output_page($warn); - exit; -} - -// Revoke a warning -if($mybb->input['action'] == "do_revoke" && $mybb->request_method == "post") -{ - // Verify incoming POST request - verify_post_check($mybb->get_input('my_post_key')); - - if($mybb->usergroup['canwarnusers'] != 1) - { - error_no_permission(); - } - - $warning = $warningshandler->get($mybb->input['wid']); - - if(!$warning) - { - error($lang->error_invalid_warning); - } - else if($warning['daterevoked']) - { - error($lang->warning_already_revoked); - } - - $user = get_user($warning['uid']); - - $group_permissions = user_permissions($user['uid']); - if($group_permissions['canreceivewarnings'] != 1) - { - error($lang->error_cant_warn_group); - } - - $plugins->run_hooks("warnings_do_revoke_start"); - - if(!trim($mybb->get_input('reason'))) - { - $warn_errors[] = $lang->no_revoke_reason; - $warn_errors = inline_error($warn_errors); - $mybb->input['action'] = "view"; - } - else - { - $warning_data = array( - 'wid' => $warning['wid'], - 'reason' => $mybb->get_input('reason'), - 'expired' => $warning['expired'], - 'uid' => $warning['uid'], - 'points' => $warning['points'] - ); - - $warningshandler->set_data($warning_data); - - $warningshandler->update_warning(); - - redirect("warnings.php?action=view&wid={$warning['wid']}", $lang->redirect_warning_revoked); - } -} - -// Detailed view of a warning -if($mybb->input['action'] == "view") -{ - if($mybb->usergroup['canwarnusers'] != 1) - { - error_no_permission(); - } - - $query = $db->query(" - SELECT w.*, t.title AS type_title, u.username, p.subject AS post_subject - FROM ".TABLE_PREFIX."warnings w - LEFT JOIN ".TABLE_PREFIX."warningtypes t ON (t.tid=w.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=w.issuedby) - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=w.pid) - WHERE w.wid='".$mybb->get_input('wid', MyBB::INPUT_INT)."' - "); - $warning = $db->fetch_array($query); - - if(!$warning) - { - error($lang->error_invalid_warning); - } - - $user = get_user((int)$warning['uid']); - if(!$user) - { - $user['username'] = $lang->guest; - } - $user['username'] = htmlspecialchars_uni($user['username']); - - $group_permissions = user_permissions($user['uid']); - if($group_permissions['canreceivewarnings'] != 1) - { - error($lang->error_cant_warn_group); - } - - $plugins->run_hooks("warnings_view_start"); - - $lang->nav_profile = $lang->sprintf($lang->nav_profile, $user['username']); - if($user['uid']) - { - add_breadcrumb($lang->nav_profile, get_profile_link($user['uid'])); - add_breadcrumb($lang->nav_warning_log, "warnings.php?uid={$user['uid']}"); - } - else - { - add_breadcrumb($lang->nav_profile); - add_breadcrumb($lang->nav_warning_log); - } - add_breadcrumb($lang->nav_view_warning); - - $user_link = build_profile_link($user['username'], $user['uid']); - - $post_link = ""; - if($warning['post_subject']) - { - $warning['post_subject'] = $parser->parse_badwords($warning['post_subject']); - $warning['post_subject'] = htmlspecialchars_uni($warning['post_subject']); - $post_link = get_post_link($warning['pid'])."#pid{$warning['pid']}"; - eval("\$warning_info = \"".$templates->get("warnings_view_post")."\";"); - } - else - { - eval("\$warning_info = \"".$templates->get("warnings_view_user")."\";"); - } - - $warning['username'] = htmlspecialchars_uni($warning['username']); - $issuedby = build_profile_link($warning['username'], $warning['issuedby']); - $notes = nl2br(htmlspecialchars_uni($warning['notes'])); - - $date_issued = my_date('relative', $warning['dateline']); - if($warning['type_title']) - { - $warning_type = $warning['type_title']; - } - else - { - $warning_type = $warning['title']; - } - $warning_type = htmlspecialchars_uni($warning_type); - if($warning['points'] > 0) - { - $warning['points'] = "+{$warning['points']}"; - } - - $revoked_date = ''; - - $points = $lang->sprintf($lang->warning_points, $warning['points']); - if($warning['expired'] != 1) - { - if($warning['expires'] == 0) - { - $expires = $lang->never; - } - else - { - $expires = my_date($mybb->settings['dateformat'], $warning['expires']) . ", " . my_date($mybb->settings['timeformat'], $warning['expires']); - } - $status = $lang->warning_active; - } - else - { - if($warning['daterevoked']) - { - $expires = $status = $lang->warning_revoked; - } - else if($warning['expires']) - { - $revoked_date = '('.my_date($mybb->settings['dateformat'], $warning['expires']).', '.my_date($mybb->settings['timeformat'], $warning['expires']).')'; - $expires = $status = $lang->already_expired; - } - } - - if(!$warning['daterevoked']) - { - if(!isset($warn_errors)) - { - $warn_errors = ''; - } - eval("\$revoke = \"".$templates->get("warnings_view_revoke")."\";"); - } - else - { - $date_revoked = my_date('relative', $warning['daterevoked']); - $revoked_user = get_user($warning['revokedby']); - if(!$revoked_user['username']) - { - $revoked_user['username'] = $lang->guest; - } - $revoked_user['username'] = htmlspecialchars_uni($revoked_user['username']); - $revoked_by = build_profile_link($revoked_user['username'], $revoked_user['uid']); - $revoke_reason = nl2br(htmlspecialchars_uni($warning['revokereason'])); - eval("\$revoke = \"".$templates->get("warnings_view_revoked")."\";"); - } - - $plugins->run_hooks("warnings_view_end"); - - eval("\$warning = \"".$templates->get("warnings_view")."\";"); - output_page($warning); -} - -// Showing list of warnings for a particular user -if(!$mybb->input['action']) -{ - if($mybb->usergroup['canwarnusers'] != 1) - { - error_no_permission(); - } - - $user = get_user($mybb->get_input('uid', MyBB::INPUT_INT)); - if(!$user['uid']) - { - error($lang->error_invalid_user); - } - - $group_permissions = user_permissions($user['uid']); - if($group_permissions['canreceivewarnings'] != 1) - { - error($lang->error_cant_warn_group); - } - - $user['username'] = htmlspecialchars_uni($user['username']); - $lang->nav_profile = $lang->sprintf($lang->nav_profile, $user['username']); - add_breadcrumb($lang->nav_profile, get_profile_link($user['uid'])); - add_breadcrumb($lang->nav_warning_log); - - if(!$mybb->settings['postsperpage'] || (int)$mybb->settings['postsperpage'] < 1) - { - $mybb->settings['postsperpage'] = 20; - } - - // Figure out if we need to display multiple pages. - $perpage = $mybb->settings['postsperpage']; - $page = $mybb->get_input('page', MyBB::INPUT_INT); - - $query = $db->simple_select("warnings", "COUNT(wid) AS warning_count", "uid='{$user['uid']}'"); - $warning_count = $db->fetch_field($query, "warning_count"); - - $pages = ceil($warning_count/$perpage); - - if($page > $pages || $page <= 0) - { - $page = 1; - } - if($page) - { - $start = ($page-1) * $perpage; - } - else - { - $start = 0; - $page = 1; - } - - $multipage = multipage($warning_count, $perpage, $page, "warnings.php?uid={$user['uid']}"); - - if($mybb->settings['maxwarningpoints'] < 1) - { - $mybb->settings['maxwarningpoints'] = 10; - } - - $warning_level = round($user['warningpoints']/$mybb->settings['maxwarningpoints']*100); - if($warning_level > 100) - { - $warning_level = 100; - } - - if($user['warningpoints'] > $mybb->settings['maxwarningpoints']) - { - $user['warningpoints'] = $mybb->settings['maxwarningpoints']; - } - - if($warning_level > 0) - { - $lang->current_warning_level = $lang->sprintf($lang->current_warning_level, $warning_level, $user['warningpoints'], $mybb->settings['maxwarningpoints']); - } - else - { - $lang->current_warning_level = ""; - } - - // Fetch the actual warnings - $query = $db->query(" - SELECT w.*, t.title AS type_title, u.username, p.subject AS post_subject - FROM ".TABLE_PREFIX."warnings w - LEFT JOIN ".TABLE_PREFIX."warningtypes t ON (t.tid=w.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=w.issuedby) - LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid=w.pid) - WHERE w.uid='{$user['uid']}' - ORDER BY w.expired ASC, w.dateline DESC - LIMIT {$start}, {$perpage} - "); - $warnings = ''; - while($warning = $db->fetch_array($query)) - { - if(!isset($last_expired) || $warning['expired'] != $last_expired) - { - if($warning['expired'] == 0) - { - eval("\$warnings .= \"".$templates->get("warnings_active_header")."\";"); - } - else - { - eval("\$warnings .= \"".$templates->get("warnings_expired_header")."\";"); - } - } - $last_expired = $warning['expired']; - - $post_link = ''; - if($warning['post_subject']) - { - $warning['post_subject'] = $parser->parse_badwords($warning['post_subject']); - $warning['post_subject'] = htmlspecialchars_uni($warning['post_subject']); - $warning['post_link'] = get_post_link($warning['pid']); - eval("\$post_link = \"".$templates->get("warnings_postlink")."\";"); - } - - $warning['username'] = htmlspecialchars_uni($warning['username']); - $issuedby = build_profile_link($warning['username'], $warning['issuedby']); - $date_issued = my_date('relative', $warning['dateline']); - if($warning['type_title']) - { - $warning_type = $warning['type_title']; - } - else - { - $warning_type = $warning['title']; - } - $warning_type = htmlspecialchars_uni($warning_type); - if($warning['points'] > 0) - { - $warning['points'] = "+{$warning['points']}"; - } - $points = $lang->sprintf($lang->warning_points, $warning['points']); - if($warning['expired'] != 1) - { - if($warning['expires'] == 0) - { - $expires = $lang->never; - } - else - { - $expires = my_date($mybb->settings['dateformat'], $warning['expires']) . ", " . my_date($mybb->settings['timeformat'], $warning['expires']); - } - } - else - { - if($warning['daterevoked']) - { - $expires = $lang->warning_revoked; - } - else if($warning['expires']) - { - $expires = $lang->already_expired; - } - } - $alt_bg = alt_trow(); - $plugins->run_hooks("warnings_warning"); - eval("\$warnings .= \"".$templates->get("warnings_warning")."\";"); - } - - if(!$warnings) - { - eval("\$warnings = \"".$templates->get("warnings_no_warnings")."\";"); - } - - $plugins->run_hooks("warnings_end"); - - eval("\$warnings = \"".$templates->get("warnings")."\";"); - output_page($warnings); -} - diff --git a/html/forums/xmlhttp.php b/html/forums/xmlhttp.php deleted file mode 100644 index d21d26a..0000000 --- a/html/forums/xmlhttp.php +++ /dev/null @@ -1,1087 +0,0 @@ -read("usergroups"); - -if(!is_array($groupscache)) -{ - $cache->update_usergroups(); - $groupscache = $cache->read("usergroups"); -} - -// Send no cache headers -header("Expires: Sat, 1 Jan 2000 01:00:00 GMT"); -header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); -header("Cache-Control: no-cache, must-revalidate"); -header("Pragma: no-cache"); - -// Create the session -require_once MYBB_ROOT."inc/class_session.php"; -$session = new session; -$session->init(); - -// Load the language we'll be using -if(!isset($mybb->settings['bblanguage'])) -{ - $mybb->settings['bblanguage'] = "english"; -} -if(isset($mybb->user['language']) && $lang->language_exists($mybb->user['language'])) -{ - $mybb->settings['bblanguage'] = $mybb->user['language']; -} -$lang->set_language($mybb->settings['bblanguage']); - -if(function_exists('mb_internal_encoding') && !empty($lang->settings['charset'])) -{ - @mb_internal_encoding($lang->settings['charset']); -} - -// Load the theme -// 1. Check cookies -if(!$mybb->user['uid'] && !empty($mybb->cookies['mybbtheme'])) -{ - $mybb->user['style'] = (int)$mybb->cookies['mybbtheme']; -} - -// 2. Load style -if(isset($mybb->user['style']) && (int)$mybb->user['style'] != 0) -{ - $loadstyle = "tid='".(int)$mybb->user['style']."'"; -} -else -{ - $loadstyle = "def='1'"; -} - -// Load basic theme information that we could be needing. -if($loadstyle != "def='1'") -{ - $query = $db->simple_select('themes', 'name, tid, properties, allowedgroups', $loadstyle, array('limit' => 1)); - $theme = $db->fetch_array($query); - - if(isset($theme['tid']) && !is_member($theme['allowedgroups']) && $theme['allowedgroups'] != 'all') - { - if(isset($mybb->cookies['mybbtheme'])) - { - my_unsetcookie('mybbtheme'); - } - - $loadstyle = "def='1'"; - } -} - -if($loadstyle == "def='1'") -{ - if(!$cache->read('default_theme')) - { - $cache->update_default_theme(); - } - - $theme = $cache->read('default_theme'); -} - -// No theme was found - we attempt to load the master or any other theme -if(!isset($theme['tid']) || isset($theme['tid']) && !$theme['tid']) -{ - // Missing theme was from a user, run a query to set any users using the theme to the default - $db->update_query('users', array('style' => 0), "style = '{$mybb->user['style']}'"); - - // Attempt to load the master or any other theme if the master is not available - $query = $db->simple_select('themes', 'name, tid, properties, stylesheets', '', array('order_by' => 'tid', 'limit' => 1)); - $theme = $db->fetch_array($query); -} -$theme = @array_merge($theme, my_unserialize($theme['properties'])); - -// Set the appropriate image language directory for this theme. -// Are we linking to a remote theme server? -if(my_validate_url($theme['imgdir'])) -{ - // If a language directory for the current language exists within the theme - we use it - if(!empty($mybb->user['language'])) - { - $theme['imglangdir'] = $theme['imgdir'].'/'.$mybb->user['language']; - } - else - { - // Check if a custom language directory exists for this theme - if(!empty($mybb->settings['bblanguage'])) - { - $theme['imglangdir'] = $theme['imgdir'].'/'.$mybb->settings['bblanguage']; - } - // Otherwise, the image language directory is the same as the language directory for the theme - else - { - $theme['imglangdir'] = $theme['imgdir']; - } - } -} -else -{ - $img_directory = $theme['imgdir']; - - if($mybb->settings['usecdn'] && !empty($mybb->settings['cdnpath'])) - { - $img_directory = rtrim($mybb->settings['cdnpath'], '/') . '/' . ltrim($theme['imgdir'], '/'); - } - - if(!@is_dir($img_directory)) - { - $theme['imgdir'] = 'images'; - } - - // If a language directory for the current language exists within the theme - we use it - if(!empty($mybb->user['language']) && is_dir($img_directory.'/'.$mybb->user['language'])) - { - $theme['imglangdir'] = $theme['imgdir'].'/'.$mybb->user['language']; - } - else - { - // Check if a custom language directory exists for this theme - if(is_dir($img_directory.'/'.$mybb->settings['bblanguage'])) - { - $theme['imglangdir'] = $theme['imgdir'].'/'.$mybb->settings['bblanguage']; - } - // Otherwise, the image language directory is the same as the language directory for the theme - else - { - $theme['imglangdir'] = $theme['imgdir']; - } - } - - $theme['imgdir'] = $mybb->get_asset_url($theme['imgdir']); - $theme['imglangdir'] = $mybb->get_asset_url($theme['imglangdir']); -} - -$templatelist = "postbit_editedby,xmlhttp_buddyselect_online,xmlhttp_buddyselect_offline,xmlhttp_buddyselect"; -$templates->cache($db->escape_string($templatelist)); - -if($lang->settings['charset']) -{ - $charset = $lang->settings['charset']; -} -// If not, revert to UTF-8 -else -{ - $charset = "UTF-8"; -} - -$lang->load("global"); -$lang->load("xmlhttp"); - -$closed_bypass = array("refresh_captcha", "validate_captcha"); - -$mybb->input['action'] = $mybb->get_input('action'); - -$plugins->run_hooks("xmlhttp"); - -// If the board is closed, the user is not an administrator and they're not trying to login, show the board closed message -if($mybb->settings['boardclosed'] == 1 && $mybb->usergroup['canviewboardclosed'] != 1 && !in_array($mybb->input['action'], $closed_bypass)) -{ - // Show error - if(!$mybb->settings['boardclosed_reason']) - { - $mybb->settings['boardclosed_reason'] = $lang->boardclosed_reason; - } - - $lang->error_boardclosed .= "
    {$mybb->settings['boardclosed_reason']}"; - - xmlhttp_error($lang->error_boardclosed); -} - -// Fetch a list of usernames beginning with a certain string (used for auto completion) -if($mybb->input['action'] == "get_users") -{ - $mybb->input['query'] = ltrim($mybb->get_input('query')); - - // If the string is less than 2 characters, quit. - if(my_strlen($mybb->input['query']) < 2) - { - exit; - } - - if($mybb->get_input('getone', MyBB::INPUT_INT) == 1) - { - $limit = 1; - } - else - { - $limit = 15; - } - - // Send our headers. - header("Content-type: application/json; charset={$charset}"); - - // Query for any matching users. - $query_options = array( - "order_by" => "username", - "order_dir" => "asc", - "limit_start" => 0, - "limit" => $limit - ); - - $plugins->run_hooks("xmlhttp_get_users_start"); - - $query = $db->simple_select("users", "uid, username", "username LIKE '".$db->escape_string_like($mybb->input['query'])."%'", $query_options); - if($limit == 1) - { - $user = $db->fetch_array($query); - $data = array('id' => $user['username'], 'text' => $user['username']); - } - else - { - $data = array(); - while($user = $db->fetch_array($query)) - { - $data[] = array('id' => $user['username'], 'text' => $user['username']); - } - } - - $plugins->run_hooks("xmlhttp_get_users_end"); - - echo json_encode($data); - exit; -} -// This action provides editing of thread/post subjects from within their respective list pages. -else if($mybb->input['action'] == "edit_subject" && $mybb->request_method == "post") -{ - // Verify POST request - if(!verify_post_check($mybb->get_input('my_post_key'), true)) - { - xmlhttp_error($lang->invalid_post_code); - } - - // We're editing a thread subject. - if($mybb->get_input('tid', MyBB::INPUT_INT)) - { - // Fetch the thread. - $thread = get_thread($mybb->get_input('tid', MyBB::INPUT_INT)); - if(!$thread) - { - xmlhttp_error($lang->thread_doesnt_exist); - } - - // Fetch some of the information from the first post of this thread. - $query_options = array( - "order_by" => "dateline", - "order_dir" => "asc", - ); - $query = $db->simple_select("posts", "pid,uid,dateline", "tid='".$thread['tid']."'", $query_options); - $post = $db->fetch_array($query); - } - else - { - exit; - } - - // Fetch the specific forum this thread/post is in. - $forum = get_forum($thread['fid']); - - // Missing thread, invalid forum? Error. - if(!$forum || $forum['type'] != "f") - { - xmlhttp_error($lang->thread_doesnt_exist); - } - - // Fetch forum permissions. - $forumpermissions = forum_permissions($forum['fid']); - - $plugins->run_hooks("xmlhttp_edit_subject_start"); - - // If this user is not a moderator with "caneditposts" permissions. - if(!is_moderator($forum['fid'], "caneditposts")) - { - // Thread is closed - no editing allowed. - if($thread['closed'] == 1) - { - xmlhttp_error($lang->thread_closed_edit_subjects); - } - // Forum is not open, user doesn't have permission to edit, or author doesn't match this user - don't allow editing. - else if($forum['open'] == 0 || $forumpermissions['caneditposts'] == 0 || $mybb->user['uid'] != $post['uid'] || $mybb->user['uid'] == 0) - { - xmlhttp_error($lang->no_permission_edit_subject); - } - // If we're past the edit time limit - don't allow editing. - else if($mybb->usergroup['edittimelimit'] != 0 && $post['dateline'] < (TIME_NOW-($mybb->usergroup['edittimelimit']*60))) - { - $lang->edit_time_limit = $lang->sprintf($lang->edit_time_limit, $mybb->usergroup['edittimelimit']); - xmlhttp_error($lang->edit_time_limit); - } - $ismod = false; - } - else - { - $ismod = true; - } - $subject = $mybb->get_input('value'); - if(my_strtolower($charset) != "utf-8") - { - if(function_exists("iconv")) - { - $subject = iconv($charset, "UTF-8//IGNORE", $subject); - } - else if(function_exists("mb_convert_encoding")) - { - $subject = @mb_convert_encoding($subject, $charset, "UTF-8"); - } - else if(my_strtolower($charset) == "iso-8859-1") - { - $subject = utf8_decode($subject); - } - } - - // Only edit subject if subject has actually been changed - if($thread['subject'] != $subject) - { - // Set up posthandler. - require_once MYBB_ROOT."inc/datahandlers/post.php"; - $posthandler = new PostDataHandler("update"); - $posthandler->action = "post"; - - // Set the post data that came from the input to the $post array. - $updatepost = array( - "pid" => $post['pid'], - "tid" => $thread['tid'], - "prefix" => $thread['prefix'], - "subject" => $subject, - "edit_uid" => $mybb->user['uid'] - ); - $posthandler->set_data($updatepost); - - // Now let the post handler do all the hard work. - if(!$posthandler->validate_post()) - { - $post_errors = $posthandler->get_friendly_errors(); - xmlhttp_error($post_errors); - } - // No errors were found, we can call the update method. - else - { - $posthandler->update_post(); - if($ismod == true) - { - $modlogdata = array( - "tid" => $thread['tid'], - "fid" => $forum['fid'] - ); - log_moderator_action($modlogdata, $lang->edited_post); - } - } - } - - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - - // Send our headers. - header("Content-type: application/json; charset={$charset}"); - - $plugins->run_hooks("xmlhttp_edit_subject_end"); - - $mybb->input['value'] = $parser->parse_badwords($mybb->get_input('value')); - - // Spit the subject back to the browser. - $subject = substr($mybb->input['value'], 0, 120); // 120 is the varchar length for the subject column - echo json_encode(array("subject" => ''.htmlspecialchars_uni($subject).'')); - - // Close the connection. - exit; -} -else if($mybb->input['action'] == "edit_post") -{ - // Fetch the post from the database. - $post = get_post($mybb->get_input('pid', MyBB::INPUT_INT)); - - // No result, die. - if(!$post) - { - xmlhttp_error($lang->post_doesnt_exist); - } - - // Fetch the thread associated with this post. - $thread = get_thread($post['tid']); - - // Fetch the specific forum this thread/post is in. - $forum = get_forum($thread['fid']); - - // Missing thread, invalid forum? Error. - if(!$thread || !$forum || $forum['type'] != "f") - { - xmlhttp_error($lang->thread_doesnt_exist); - } - - // Check if this forum is password protected and we have a valid password - if(check_forum_password($forum['fid'], 0, true)) - { - xmlhttp_error($lang->wrong_forum_password); - } - - // Fetch forum permissions. - $forumpermissions = forum_permissions($forum['fid']); - - $plugins->run_hooks("xmlhttp_edit_post_start"); - - // If this user is not a moderator with "caneditposts" permissions. - if(!is_moderator($forum['fid'], "caneditposts")) - { - // Thread is closed - no editing allowed. - if($thread['closed'] == 1) - { - xmlhttp_error($lang->thread_closed_edit_message); - } - // Forum is not open, user doesn't have permission to edit, or author doesn't match this user - don't allow editing. - else if($forum['open'] == 0 || $forumpermissions['caneditposts'] == 0 || $mybb->user['uid'] != $post['uid'] || $mybb->user['uid'] == 0 || $mybb->user['suspendposting'] == 1) - { - xmlhttp_error($lang->no_permission_edit_post); - } - // If we're past the edit time limit - don't allow editing. - else if($mybb->usergroup['edittimelimit'] != 0 && $post['dateline'] < (TIME_NOW-($mybb->usergroup['edittimelimit']*60))) - { - $lang->edit_time_limit = $lang->sprintf($lang->edit_time_limit, $mybb->usergroup['edittimelimit']); - xmlhttp_error($lang->edit_time_limit); - } - // User can't edit unapproved post - if($post['visible'] == 0) - { - xmlhttp_error($lang->post_moderation); - } - } - - $plugins->run_hooks("xmlhttp_edit_post_end"); - - if($mybb->get_input('do') == "get_post") - { - // Send our headers. - header("Content-type: application/json; charset={$charset}"); - - // Send the contents of the post. - echo json_encode($post['message']); - exit; - } - else if($mybb->get_input('do') == "update_post") - { - // Verify POST request - if(!verify_post_check($mybb->get_input('my_post_key'), true)) - { - xmlhttp_error($lang->invalid_post_code); - } - - $message = $mybb->get_input('value'); - $editreason = $mybb->get_input('editreason'); - if(my_strtolower($charset) != "utf-8") - { - if(function_exists("iconv")) - { - $message = iconv($charset, "UTF-8//IGNORE", $message); - $editreason = iconv($charset, "UTF-8//IGNORE", $editreason); - } - else if(function_exists("mb_convert_encoding")) - { - $message = @mb_convert_encoding($message, $charset, "UTF-8"); - $editreason = @mb_convert_encoding($editreason, $charset, "UTF-8"); - } - else if(my_strtolower($charset) == "iso-8859-1") - { - $message = utf8_decode($message); - $editreason = utf8_decode($editreason); - } - } - - // Set up posthandler. - require_once MYBB_ROOT."inc/datahandlers/post.php"; - $posthandler = new PostDataHandler("update"); - $posthandler->action = "post"; - - // Set the post data that came from the input to the $post array. - $updatepost = array( - "pid" => $post['pid'], - "message" => $message, - "editreason" => $editreason, - "edit_uid" => $mybb->user['uid'] - ); - - // If this is the first post set the prefix. If a forum requires a prefix the quick edit would throw an error otherwise - if($post['pid'] == $thread['firstpost']) - { - $updatepost['prefix'] = $thread['prefix']; - } - - $posthandler->set_data($updatepost); - - // Now let the post handler do all the hard work. - if(!$posthandler->validate_post()) - { - $post_errors = $posthandler->get_friendly_errors(); - xmlhttp_error($post_errors); - } - // No errors were found, we can call the update method. - else - { - $postinfo = $posthandler->update_post(); - $visible = $postinfo['visible']; - if($visible == 0 && !is_moderator($post['fid'], "canviewunapprove")) - { - // Is it the first post? - if($thread['firstpost'] == $post['pid']) - { - echo json_encode(array("moderation_thread" => $lang->thread_moderation, 'url' => $mybb->settings['bburl'].'/'.get_forum_link($thread['fid']), "message" => $post['message'])); - exit; - } - else - { - echo json_encode(array("moderation_post" => $lang->post_moderation, 'url' => $mybb->settings['bburl'].'/'.get_thread_link($thread['tid']), "message" => $post['message'])); - exit; - } - } - } - - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - - $parser_options = array( - "allow_html" => $forum['allowhtml'], - "allow_mycode" => $forum['allowmycode'], - "allow_smilies" => $forum['allowsmilies'], - "allow_imgcode" => $forum['allowimgcode'], - "allow_videocode" => $forum['allowvideocode'], - "me_username" => $post['username'], - "filter_badwords" => 1 - ); - - $post['username'] = htmlspecialchars_uni($post['username']); - - if($post['smilieoff'] == 1) - { - $parser_options['allow_smilies'] = 0; - } - - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestimages'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_imgcode'] = 0; - } - - if($mybb->user['showvideos'] != 1 && $mybb->user['uid'] != 0 || $mybb->settings['guestvideos'] != 1 && $mybb->user['uid'] == 0) - { - $parser_options['allow_videocode'] = 0; - } - - $post['message'] = $parser->parse_message($message, $parser_options); - - // Now lets fetch all of the attachments for these posts. - if($mybb->settings['enableattachments'] != 0) - { - $query = $db->simple_select("attachments", "*", "pid='{$post['pid']}'"); - while($attachment = $db->fetch_array($query)) - { - $attachcache[$attachment['pid']][$attachment['aid']] = $attachment; - } - - require_once MYBB_ROOT."inc/functions_post.php"; - - get_post_attachments($post['pid'], $post); - } - - // Figure out if we need to show an "edited by" message - // Only show if at least one of "showeditedby" or "showeditedbyadmin" is enabled - if($mybb->settings['showeditedby'] != 0 && $mybb->settings['showeditedbyadmin'] != 0) - { - $post['editdate'] = my_date('relative', TIME_NOW); - $post['editnote'] = $lang->sprintf($lang->postbit_edited, $post['editdate']); - $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); - $post['editedprofilelink'] = build_profile_link($mybb->user['username'], $mybb->user['uid']); - $post['editreason'] = trim($editreason); - $editreason = ""; - if($post['editreason'] != "") - { - $post['editreason'] = $parser->parse_badwords($post['editreason']); - $post['editreason'] = htmlspecialchars_uni($post['editreason']); - eval("\$editreason = \"".$templates->get("postbit_editedby_editreason")."\";"); - } - eval("\$editedmsg = \"".$templates->get("postbit_editedby")."\";"); - } - - // Send our headers. - header("Content-type: application/json; charset={$charset}"); - - $editedmsg_response = null; - if($editedmsg) - { - $editedmsg_response = str_replace(array("\r", "\n"), "", $editedmsg); - } - - $plugins->run_hooks("xmlhttp_update_post"); - - echo json_encode(array("message" => $post['message']."\n", "editedmsg" => $editedmsg_response)); - exit; - } -} -// Fetch the list of multiquoted posts which are not in a specific thread -else if($mybb->input['action'] == "get_multiquoted") -{ - // If the cookie does not exist, exit - if(!array_key_exists("multiquote", $mybb->cookies)) - { - exit; - } - // Divide up the cookie using our delimeter - $multiquoted = explode("|", $mybb->cookies['multiquote']); - - $plugins->run_hooks("xmlhttp_get_multiquoted_start"); - - // No values - exit - if(!is_array($multiquoted)) - { - exit; - } - - // Loop through each post ID and sanitize it before querying - foreach($multiquoted as $post) - { - $quoted_posts[$post] = (int)$post; - } - - // Join the post IDs back together - $quoted_posts = implode(",", $quoted_posts); - - // Fetch unviewable forums - $unviewable_forums = get_unviewable_forums(); - $inactiveforums = get_inactive_forums(); - if($unviewable_forums) - { - $unviewable_forums = "AND t.fid NOT IN ({$unviewable_forums})"; - } - if($inactiveforums) - { - $inactiveforums = "AND t.fid NOT IN ({$inactiveforums})"; - } - - // Check group permissions if we can't view threads not started by us - $group_permissions = forum_permissions(); - $onlyusfids = array(); - foreach($group_permissions as $gpfid => $forum_permissions) - { - if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) - { - $onlyusfids[] = $gpfid; - } - } - - $message = ''; - - // Are we loading all quoted posts or only those not in the current thread? - if(empty($mybb->input['load_all'])) - { - $from_tid = "p.tid != '".$mybb->get_input('tid', MyBB::INPUT_INT)."' AND "; - } - else - { - $from_tid = ''; - } - - require_once MYBB_ROOT."inc/class_parser.php"; - $parser = new postParser; - - require_once MYBB_ROOT."inc/functions_posting.php"; - - $plugins->run_hooks("xmlhttp_get_multiquoted_intermediate"); - - // Query for any posts in the list which are not within the specified thread - $query = $db->query(" - SELECT p.subject, p.message, p.pid, p.tid, p.username, p.dateline, t.fid, t.uid AS thread_uid, p.visible, u.username AS userusername - FROM ".TABLE_PREFIX."posts p - LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) - LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) - WHERE {$from_tid}p.pid IN ({$quoted_posts}) {$unviewable_forums} {$inactiveforums} - ORDER BY p.dateline - "); - while($quoted_post = $db->fetch_array($query)) - { - if( - (!is_moderator($quoted_post['fid'], "canviewunapprove") && $quoted_post['visible'] == 0) || - (!is_moderator($quoted_post['fid'], "canviewdeleted") && $quoted_post['visible'] == -1) || - (in_array($quoted_post['fid'], $onlyusfids) && (!$mybb->user['uid'] || $quoted_post['thread_uid'] != $mybb->user['uid'])) - ) - { - continue; - } - - $message .= parse_quoted_message($quoted_post, false); - } - if($mybb->settings['maxquotedepth'] != '0') - { - $message = remove_message_quotes($message); - } - - // Send our headers. - header("Content-type: application/json; charset={$charset}"); - - $plugins->run_hooks("xmlhttp_get_multiquoted_end"); - - echo json_encode(array("message" => $message)); - exit; -} -else if($mybb->input['action'] == "refresh_captcha") -{ - $imagehash = $db->escape_string($mybb->get_input('imagehash')); - $query = $db->simple_select("captcha", "dateline", "imagehash='$imagehash'"); - if($db->num_rows($query) == 0) - { - xmlhttp_error($lang->captcha_not_exists); - } - $db->delete_query("captcha", "imagehash='$imagehash'"); - $randomstr = random_str(5); - $imagehash = md5(random_str(12)); - $regimagearray = array( - "imagehash" => $imagehash, - "imagestring" => $randomstr, - "dateline" => TIME_NOW - ); - - $plugins->run_hooks("xmlhttp_refresh_captcha"); - - $db->insert_query("captcha", $regimagearray); - header("Content-type: application/json; charset={$charset}"); - echo json_encode(array("imagehash" => $imagehash)); - exit; -} -else if($mybb->input['action'] == "validate_captcha") -{ - header("Content-type: application/json; charset={$charset}"); - $imagehash = $db->escape_string($mybb->get_input('imagehash')); - $query = $db->simple_select("captcha", "imagestring", "imagehash='$imagehash'"); - if($db->num_rows($query) == 0) - { - echo json_encode($lang->captcha_valid_not_exists); - exit; - } - $imagestring = $db->fetch_field($query, 'imagestring'); - - $plugins->run_hooks("xmlhttp_validate_captcha"); - - if(my_strtolower($imagestring) == my_strtolower($mybb->get_input('imagestring'))) - { - //echo json_encode(array("success" => $lang->captcha_matches)); - echo json_encode("true"); - exit; - } - else - { - echo json_encode($lang->captcha_does_not_match); - exit; - } -} -else if($mybb->input['action'] == "refresh_question" && $mybb->settings['securityquestion']) -{ - header("Content-type: application/json; charset={$charset}"); - - $sid = $db->escape_string($mybb->get_input('question_id')); - $query = $db->query(" - SELECT q.qid, s.sid - FROM ".TABLE_PREFIX."questionsessions s - LEFT JOIN ".TABLE_PREFIX."questions q ON (q.qid=s.qid) - WHERE q.active='1' AND s.sid='{$sid}' - "); - - if($db->num_rows($query) == 0) - { - xmlhttp_error($lang->answer_valid_not_exists); - } - - $qsession = $db->fetch_array($query); - - // Delete previous question session - $db->delete_query("questionsessions", "sid='$sid'"); - - require_once MYBB_ROOT."inc/functions_user.php"; - - $sid = generate_question($qsession['qid']); - $query = $db->query(" - SELECT q.question, s.sid - FROM ".TABLE_PREFIX."questionsessions s - LEFT JOIN ".TABLE_PREFIX."questions q ON (q.qid=s.qid) - WHERE q.active='1' AND s.sid='{$sid}' AND q.qid!='{$qsession['qid']}' - "); - - $plugins->run_hooks("xmlhttp_refresh_question"); - - if($db->num_rows($query) > 0) - { - $question = $db->fetch_array($query); - - echo json_encode(array("question" => htmlspecialchars_uni($question['question']), 'sid' => htmlspecialchars_uni($question['sid']))); - exit; - } - else - { - xmlhttp_error($lang->answer_valid_not_exists); - } -} -elseif($mybb->input['action'] == "validate_question" && $mybb->settings['securityquestion']) -{ - header("Content-type: application/json; charset={$charset}"); - $sid = $db->escape_string($mybb->get_input('question')); - $answer = $db->escape_string($mybb->get_input('answer')); - - $query = $db->query(" - SELECT q.*, s.sid - FROM ".TABLE_PREFIX."questionsessions s - LEFT JOIN ".TABLE_PREFIX."questions q ON (q.qid=s.qid) - WHERE q.active='1' AND s.sid='{$sid}' - "); - - if($db->num_rows($query) == 0) - { - echo json_encode($lang->answer_valid_not_exists); - exit; - } - else - { - $question = $db->fetch_array($query); - $valid_answers = preg_split("/\r\n|\n|\r/", $question['answer']); - $validated = 0; - - foreach($valid_answers as $answers) - { - if(my_strtolower($answers) == my_strtolower($answer)) - { - $validated = 1; - } - } - - $plugins->run_hooks("xmlhttp_validate_question"); - - if($validated != 1) - { - echo json_encode($lang->answer_does_not_match); - exit; - } - else - { - echo json_encode("true"); - exit; - } - } - - exit; -} -else if($mybb->input['action'] == "complex_password") -{ - $password = trim($mybb->get_input('password')); - $password = str_replace(array(unichr(160), unichr(173), unichr(0xCA), dec_to_utf8(8238), dec_to_utf8(8237), dec_to_utf8(8203)), array(" ", "-", "", "", "", ""), $password); - - header("Content-type: application/json; charset={$charset}"); - - $plugins->run_hooks("xmlhttp_complex_password"); - - if(!preg_match("/^.*(?=.{".$mybb->settings['minpasswordlength'].",})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/", $password)) - { - echo json_encode($lang->complex_password_fails); - } - else - { - // Return nothing but an OK password if passes regex - echo json_encode("true"); - } - - exit; -} -else if($mybb->input['action'] == "username_availability") -{ - if(!verify_post_check($mybb->get_input('my_post_key'), true)) - { - xmlhttp_error($lang->invalid_post_code); - } - - require_once MYBB_ROOT."inc/functions_user.php"; - $username = $mybb->get_input('username'); - - // Fix bad characters - $username = trim_blank_chrs($username); - $username = str_replace(array(unichr(160), unichr(173), unichr(0xCA), dec_to_utf8(8238), dec_to_utf8(8237), dec_to_utf8(8203)), array(" ", "-", "", "", "", ""), $username); - - // Remove multiple spaces from the username - $username = preg_replace("#\s{2,}#", " ", $username); - - header("Content-type: application/json; charset={$charset}"); - - if(empty($username)) - { - echo json_encode($lang->banned_characters_username); - exit; - } - - // Check if the username belongs to the list of banned usernames. - $banned_username = is_banned_username($username, true); - if($banned_username) - { - echo json_encode($lang->banned_username); - exit; - } - - // Check for certain characters in username (<, >, &, and slashes) - if(strpos($username, "<") !== false || strpos($username, ">") !== false || strpos($username, "&") !== false || my_strpos($username, "\\") !== false || strpos($username, ";") !== false || strpos($username, ",") !== false || !validate_utf8_string($username, false, false)) - { - echo json_encode($lang->banned_characters_username); - exit; - } - - // Check if the username is actually already in use - $user = get_user_by_username($username); - - $plugins->run_hooks("xmlhttp_username_availability"); - - if($user['uid']) - { - $lang->username_taken = $lang->sprintf($lang->username_taken, htmlspecialchars_uni($username)); - echo json_encode($lang->username_taken); - exit; - } - else - { - //$lang->username_available = $lang->sprintf($lang->username_available, htmlspecialchars_uni($username)); - echo json_encode("true"); - exit; - } -} -else if($mybb->input['action'] == "username_exists") -{ - if(!verify_post_check($mybb->get_input('my_post_key'), true)) - { - xmlhttp_error($lang->invalid_post_code); - } - - require_once MYBB_ROOT."inc/functions_user.php"; - $username = $mybb->get_input('value'); - - header("Content-type: application/json; charset={$charset}"); - - if(!trim($username)) - { - echo json_encode(array("success" => 1)); - exit; - } - - // Check if the username actually exists - $user = get_user_by_username($username); - - $plugins->run_hooks("xmlhttp_username_exists"); - - if($user['uid']) - { - $lang->valid_username = $lang->sprintf($lang->valid_username, htmlspecialchars_uni($username)); - echo json_encode(array("success" => $lang->valid_username)); - exit; - } - else - { - $lang->invalid_username = $lang->sprintf($lang->invalid_username, htmlspecialchars_uni($username)); - echo json_encode($lang->invalid_username); - exit; - } -} -else if($mybb->input['action'] == "get_buddyselect") -{ - // Send our headers. - header("Content-type: text/plain; charset={$charset}"); - - if($mybb->user['buddylist'] != "") - { - $query_options = array( - "order_by" => "username", - "order_dir" => "asc" - ); - - $plugins->run_hooks("xmlhttp_get_buddyselect_start"); - - $timecut = TIME_NOW - $mybb->settings['wolcutoff']; - $query = $db->simple_select("users", "uid, username, usergroup, displaygroup, lastactive, lastvisit, invisible", "uid IN ({$mybb->user['buddylist']})", $query_options); - $online = array(); - $offline = array(); - while($buddy = $db->fetch_array($query)) - { - $buddy['username'] = htmlspecialchars_uni($buddy['username']); - $buddy_name = format_name($buddy['username'], $buddy['usergroup'], $buddy['displaygroup']); - $profile_link = build_profile_link($buddy_name, $buddy['uid'], '_blank'); - if($buddy['lastactive'] > $timecut && ($buddy['invisible'] == 0 || $mybb->user['usergroup'] == 4) && $buddy['lastvisit'] != $buddy['lastactive']) - { - eval("\$online[] = \"".$templates->get("xmlhttp_buddyselect_online")."\";"); - } - else - { - eval("\$offline[] = \"".$templates->get("xmlhttp_buddyselect_offline")."\";"); - } - } - $online = implode("", $online); - $offline = implode("", $offline); - - $plugins->run_hooks("xmlhttp_get_buddyselect_end"); - - eval("\$buddy_select = \"".$templates->get("xmlhttp_buddyselect")."\";"); - echo $buddy_select; - } - else - { - xmlhttp_error($lang->buddylist_error); - } -} - -/** - * Spits an XML Http based error message back to the browser - * - * @param string $message The message to send back. - */ -function xmlhttp_error($message) -{ - global $charset; - - // Send our headers. - header("Content-type: application/json; charset={$charset}"); - - // Do we have an array of messages? - if(is_array($message)) - { - $response = array(); - foreach($message as $error) - { - $response[] = $error; - } - - // Send the error messages. - echo json_encode(array("errors" => array($response))); - - exit; - } - - // Just a single error? Send it along. - echo json_encode(array("errors" => array($message))); - - exit; -} diff --git a/html/images/darth_vader-lightsaber-star_wars.jpg b/html/images/darth_vader-lightsaber-star_wars.jpg deleted file mode 100644 index 03e0046..0000000 Binary files a/html/images/darth_vader-lightsaber-star_wars.jpg and /dev/null differ diff --git a/html/images/star_wars_1.jpg b/html/images/star_wars_1.jpg deleted file mode 100644 index c186efa..0000000 Binary files a/html/images/star_wars_1.jpg and /dev/null differ diff --git a/html/includes/db_connect.php b/html/includes/db_connect.php deleted file mode 100644 index 0cc9298..0000000 --- a/html/includes/db_connect.php +++ /dev/null @@ -1,11 +0,0 @@ - diff --git a/html/index.orig b/html/index.orig deleted file mode 100644 index 766401d..0000000 --- a/html/index.orig +++ /dev/null @@ -1,368 +0,0 @@ - - - - - - Apache2 Debian Default Page: It works - - - -
    - - -
    - - -
    -
    - It works! -
    -
    -

    - This is the default welcome page used to test the correct - operation of the Apache2 server after installation on Debian systems. - If you can read this page, it means that the Apache HTTP server installed at - this site is working properly. You should replace this file (located at - /var/www/html/index.html) before continuing to operate your HTTP server. -

    - - -

    - If you are a normal user of this web site and don't know what this page is - about, this probably means that the site is currently unavailable due to - maintenance. - If the problem persists, please contact the site's administrator. -

    - -
    -
    -
    - Configuration Overview -
    -
    -

    - Debian's Apache2 default configuration is different from the - upstream default configuration, and split into several files optimized for - interaction with Debian tools. The configuration system is - fully documented in - /usr/share/doc/apache2/README.Debian.gz. Refer to this for the full - documentation. Documentation for the web server itself can be - found by accessing the manual if the apache2-doc - package was installed on this server. - -

    -

    - The configuration layout for an Apache2 web server installation on Debian systems is as follows: -

    -
    -/etc/apache2/
    -|-- apache2.conf
    -|       `--  ports.conf
    -|-- mods-enabled
    -|       |-- *.load
    -|       `-- *.conf
    -|-- conf-enabled
    -|       `-- *.conf
    -|-- sites-enabled
    -|       `-- *.conf
    -          
    -
      -
    • - apache2.conf is the main configuration - file. It puts the pieces together by including all remaining configuration - files when starting up the web server. -
    • - -
    • - ports.conf is always included from the - main configuration file. It is used to determine the listening ports for - incoming connections, and this file can be customized anytime. -
    • - -
    • - Configuration files in the mods-enabled/, - conf-enabled/ and sites-enabled/ directories contain - particular configuration snippets which manage modules, global configuration - fragments, or virtual host configurations, respectively. -
    • - -
    • - They are activated by symlinking available - configuration files from their respective - *-available/ counterparts. These should be managed - by using our helpers - - a2enmod, - a2dismod, - - - a2ensite, - a2dissite, - - and - - a2enconf, - a2disconf - . See their respective man pages for detailed information. -
    • - -
    • - The binary is called apache2. Due to the use of - environment variables, in the default configuration, apache2 needs to be - started/stopped with /etc/init.d/apache2 or apache2ctl. - Calling /usr/bin/apache2 directly will not work with the - default configuration. -
    • -
    -
    - -
    -
    - Document Roots -
    - -
    -

    - By default, Debian does not allow access through the web browser to - any file apart of those located in /var/www, - public_html - directories (when enabled) and /usr/share (for web - applications). If your site is using a web document root - located elsewhere (such as in /srv) you may need to whitelist your - document root directory in /etc/apache2/apache2.conf. -

    -

    - The default Debian document root is /var/www/html. You - can make your own virtual hosts under /var/www. This is different - to previous releases which provides better security out of the box. -

    -
    - -
    -
    - Reporting Problems -
    -
    -

    - Please use the reportbug tool to report bugs in the - Apache2 package with Debian. However, check existing bug reports before reporting a new bug. -

    -

    - Please report bugs specific to modules (such as PHP and others) - to respective packages, not to the web server itself. -

    -
    - - - - -
    -
    -
    -
    - - - diff --git a/html/index.php b/html/index.php deleted file mode 100644 index da84142..0000000 --- a/html/index.php +++ /dev/null @@ -1,175 +0,0 @@ - - - - -SWG Source Server Main Page - - - - - - - - -
    - -
    - - - - -

    WELCOME

    -

    to

    -

    SWG Source Server v1.2

    -

    This is the Login frontend for your NGE server

    -

    Click below to Create a New Account

    -

    Register an Account

    -
    - - -
    -

    -

    -

    -
    - -
    - -
    - -
    -

    Server Status

    -
    - - Login Server: "; - echo $login ? "Online" : "Offline

    "; - echo "

    Game Server: "; - echo $game ? "Online" : "Offline

    "; - ?> - - - -
    -
    '.mysql_error() ); -//connects to Database - $db_select = mysql_select_db( mySQL_database, $db_link ) - or die( 'Error connecting to Database

    '.mysql_error() ); -//selects desired table - $chars= mysql_query("SELECT `online` FROM `characters` where `online`=1"); -//tells how much rows are there (will come helpfull with while loops) - $rows = mysql_num_rows($chars); - echo "

    Online Players:

    ".$rows.""; //prints out the $x number of players online -?> -
    - - - diff --git a/html/music/Star Wars Main Theme.mp3 b/html/music/Star Wars Main Theme.mp3 deleted file mode 100644 index 7202b00..0000000 Binary files a/html/music/Star Wars Main Theme.mp3 and /dev/null differ diff --git a/html/newuserpost.php b/html/newuserpost.php deleted file mode 100644 index b3dad45..0000000 --- a/html/newuserpost.php +++ /dev/null @@ -1,42 +0,0 @@ - - - - - $salt, "encrypted" => $encrypted); - return $hash; - } - $passwordHash = HashPassword($_POST['realpassword']); - $passwordSalt = $passwordHash['salt']; - $passwordEncrypted = $passwordHash['encrypted']; - $query = "insert into user_account - set - username = '".$mysqli->real_escape_string($_POST['useraccountname'])."', - password_hash = '".$mysqli->real_escape_string($passwordEncrypted)."', - password_salt = '".$mysqli->real_escape_string($passwordSalt)."', - accesslevel = '".$mysqli->real_escape_string($_POST['accesslevel'])."'"; - - if( $mysqli->query($query) ) { - echo ''; - } - else { - printf($mysqli->error); - } - $mysqli->close(); -} -?> - diff --git a/html/stylesheet.css b/html/stylesheet.css deleted file mode 100644 index 2382766..0000000 --- a/html/stylesheet.css +++ /dev/null @@ -1,4 +0,0 @@ -body { font-family: arial, "gill-sans" } -body { text-align: center } -h1 { text-transform: uppercase } -h2 { font-family: arial; color: white } diff --git a/html/test.php b/html/test.php deleted file mode 100644 index 147cebc..0000000 --- a/html/test.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/init.sql b/init.sql new file mode 100644 index 0000000..0324a4b --- /dev/null +++ b/init.sql @@ -0,0 +1,50 @@ +CREATE DATABASE swgusers; +USE swgusers; + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `user_account` +-- + +DROP TABLE IF EXISTS `user_account`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user_account` ( + `user_id` int(11) NOT NULL AUTO_INCREMENT, + `accesslevel` varchar(255) NOT NULL, + `username` varchar(255) NOT NULL, + `password_salt` varchar(255) NOT NULL, + `password_hash` varchar(255) NOT NULL, + UNIQUE KEY `user_id` (`user_id`), + UNIQUE KEY `username` (`username`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user_account` +-- + +LOCK TABLES `user_account` WRITE; +/*!40000 ALTER TABLE `user_account` DISABLE KEYS */; + +/*!40000 ALTER TABLE `user_account` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..5ae8d14 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,594 @@ +{ + "name": "swg-site", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "bignumber.js": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.0.4.tgz", + "integrity": "sha512-LDXpJKVzEx2/OqNbG9mXBNvHuiRL4PzHCGfnANHMJ+fv68Ads3exDVJeGDJws+AoNEuca93bU3q+S0woeUaCdg==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + } + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "discord.js": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.3.2.tgz", + "integrity": "sha512-Abw9CTMX3Jb47IeRffqx2VNSnXl/OsTdQzhvbw/JnqCyqc2imAocc7pX2HoRmgKd8CgSqsjBFBneusz/E16e6A==", + "requires": { + "long": "^4.0.0", + "prism-media": "^0.0.2", + "snekfetch": "^3.6.4", + "tweetnacl": "^1.0.0", + "ws": "^4.0.0" + } + }, + "dotenv": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.0.0.tgz", + "integrity": "sha512-FlWbnhgjtwD+uNLUGHbMykMOYQaTivdHEmYwAKFjn6GKe/CqY0fNae93ZHTd20snh9ZLr8mTzIL9m0APQ1pjQg==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.3", + "qs": "6.5.1", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.1", + "http-errors": "~1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "~2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "~1.6.15" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": ">= 1.3.1 < 2" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + } + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "http": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/http/-/http-0.0.0.tgz", + "integrity": "sha1-huYybSnF0Dnen6xYSkVon5KfT3I=" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "~1.33.0" + } + }, + "moment": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mysql": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.15.0.tgz", + "integrity": "sha512-C7tjzWtbN5nzkLIV+E8Crnl9bFyc7d3XJcBAvHKEVkjrYjogz3llo22q6s/hw+UcsE4/844pDob9ac+3dVjQSA==", + "requires": { + "bignumber.js": "4.0.4", + "readable-stream": "2.3.3", + "safe-buffer": "5.1.1", + "sqlstring": "2.3.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + } + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", + "requires": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "prism-media": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.2.tgz", + "integrity": "sha512-L6yc8P5NVG35ivzvfI7bcTYzqFV+K8gTfX9YaJbmIFfMXTs71RMnAupvTQPTCteGsiOy9QcNLkQyWjAafY/hCQ==" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "snekfetch": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.6.4.tgz", + "integrity": "sha512-NjxjITIj04Ffqid5lqr7XdgwM7X61c/Dns073Ly170bPQHLm6jkmelye/eglS++1nfTWktpP6Y2bFXjdPlQqdw==" + }, + "sqlstring": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.0.tgz", + "integrity": "sha1-UluKT9Jtb3GqYegipsr5dtMa0qg=" + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "timediff": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/timediff/-/timediff-1.1.1.tgz", + "integrity": "sha1-ZkN6+bCUAicR596FDssAqfNAfTg=", + "requires": { + "moment": "^2.9.0" + } + }, + "tweetnacl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.0.tgz", + "integrity": "sha1-cT2LgY2kIGh0C/aDhtBHnmb8ins=" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "ws": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz", + "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..0d7232b --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "swg-site", + "version": "1.0.0", + "description": "", + "main": "app.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "", + "url": "" + }, + "author": "", + "license": "ISC", + "homepage": "", + "dependencies": { + "body-parser": "^1.18.3", + "crypto": "^1.0.1", + "discord.js": "^11.3.2", + "dotenv": "^6.0.0", + "express": "^4.16.3", + "http": "0.0.0", + "mysql": "^2.15.0", + "path": "^0.12.7", + "timediff": "^1.1.1" + } +} diff --git a/public/Content/bootstrap-theme.css b/public/Content/bootstrap-theme.css new file mode 100644 index 0000000..31d8882 --- /dev/null +++ b/public/Content/bootstrap-theme.css @@ -0,0 +1,587 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +.btn-default, +.btn-primary, +.btn-success, +.btn-info, +.btn-warning, +.btn-danger { + text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); +} +.btn-default:active, +.btn-primary:active, +.btn-success:active, +.btn-info:active, +.btn-warning:active, +.btn-danger:active, +.btn-default.active, +.btn-primary.active, +.btn-success.active, +.btn-info.active, +.btn-warning.active, +.btn-danger.active { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-default.disabled, +.btn-primary.disabled, +.btn-success.disabled, +.btn-info.disabled, +.btn-warning.disabled, +.btn-danger.disabled, +.btn-default[disabled], +.btn-primary[disabled], +.btn-success[disabled], +.btn-info[disabled], +.btn-warning[disabled], +.btn-danger[disabled], +fieldset[disabled] .btn-default, +fieldset[disabled] .btn-primary, +fieldset[disabled] .btn-success, +fieldset[disabled] .btn-info, +fieldset[disabled] .btn-warning, +fieldset[disabled] .btn-danger { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default .badge, +.btn-primary .badge, +.btn-success .badge, +.btn-info .badge, +.btn-warning .badge, +.btn-danger .badge { + text-shadow: none; +} +.btn:active, +.btn.active { + background-image: none; +} +.btn-default { + text-shadow: 0 1px 0 #fff; + background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); + background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); + background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #dbdbdb; + border-color: #ccc; +} +.btn-default:hover, +.btn-default:focus { + background-color: #e0e0e0; + background-position: 0 -15px; +} +.btn-default:active, +.btn-default.active { + background-color: #e0e0e0; + border-color: #dbdbdb; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #e0e0e0; + background-image: none; +} +.btn-primary { + background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); + background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #245580; +} +.btn-primary:hover, +.btn-primary:focus { + background-color: #265a88; + background-position: 0 -15px; +} +.btn-primary:active, +.btn-primary.active { + background-color: #265a88; + border-color: #245580; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #265a88; + background-image: none; +} +.btn-success { + background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); + background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); + background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #3e8f3e; +} +.btn-success:hover, +.btn-success:focus { + background-color: #419641; + background-position: 0 -15px; +} +.btn-success:active, +.btn-success.active { + background-color: #419641; + border-color: #3e8f3e; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #419641; + background-image: none; +} +.btn-info { + background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); + background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); + background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #28a4c9; +} +.btn-info:hover, +.btn-info:focus { + background-color: #2aabd2; + background-position: 0 -15px; +} +.btn-info:active, +.btn-info.active { + background-color: #2aabd2; + border-color: #28a4c9; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #2aabd2; + background-image: none; +} +.btn-warning { + background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); + background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #e38d13; +} +.btn-warning:hover, +.btn-warning:focus { + background-color: #eb9316; + background-position: 0 -15px; +} +.btn-warning:active, +.btn-warning.active { + background-color: #eb9316; + border-color: #e38d13; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #eb9316; + background-image: none; +} +.btn-danger { + background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); + background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); + background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #b92c28; +} +.btn-danger:hover, +.btn-danger:focus { + background-color: #c12e2a; + background-position: 0 -15px; +} +.btn-danger:active, +.btn-danger.active { + background-color: #c12e2a; + border-color: #b92c28; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #c12e2a; + background-image: none; +} +.thumbnail, +.img-thumbnail { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + box-shadow: 0 1px 2px rgba(0, 0, 0, .075); +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + background-color: #e8e8e8; + background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); + background-repeat: repeat-x; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + background-color: #2e6da4; + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); + background-repeat: repeat-x; +} +.navbar-default { + background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); + background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); + background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .active > a { + background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); + background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); + background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); + background-repeat: repeat-x; + -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); + box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); +} +.navbar-brand, +.navbar-nav > li > a { + text-shadow: 0 1px 0 rgba(255, 255, 255, .25); +} +.navbar-inverse { + background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); + background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); + background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-radius: 4px; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .active > a { + background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); + background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); + background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); + background-repeat: repeat-x; + -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); + box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); +} +.navbar-inverse .navbar-brand, +.navbar-inverse .navbar-nav > li > a { + text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); +} +.navbar-static-top, +.navbar-fixed-top, +.navbar-fixed-bottom { + border-radius: 0; +} +@media (max-width: 767px) { + .navbar .navbar-nav .open .dropdown-menu > .active > a, + .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); + background-repeat: repeat-x; + } +} +.alert { + text-shadow: 0 1px 0 rgba(255, 255, 255, .2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); +} +.alert-success { + background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); + background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); + background-repeat: repeat-x; + border-color: #b2dba1; +} +.alert-info { + background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); + background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); + background-repeat: repeat-x; + border-color: #9acfea; +} +.alert-warning { + background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); + background-repeat: repeat-x; + border-color: #f5e79e; +} +.alert-danger { + background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); + background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); + background-repeat: repeat-x; + border-color: #dca7a7; +} +.progress { + background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar { + background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); + background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-success { + background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-info { + background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-warning { + background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-danger { + background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.list-group { + border-radius: 4px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + box-shadow: 0 1px 2px rgba(0, 0, 0, .075); +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + text-shadow: 0 -1px 0 #286090; + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); + background-repeat: repeat-x; + border-color: #2b669a; +} +.list-group-item.active .badge, +.list-group-item.active:hover .badge, +.list-group-item.active:focus .badge { + text-shadow: none; +} +.panel { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); + box-shadow: 0 1px 2px rgba(0, 0, 0, .05); +} +.panel-default > .panel-heading { + background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); + background-repeat: repeat-x; +} +.panel-primary > .panel-heading { + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); + background-repeat: repeat-x; +} +.panel-success > .panel-heading { + background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); + background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); + background-repeat: repeat-x; +} +.panel-info > .panel-heading { + background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); + background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); + background-repeat: repeat-x; +} +.panel-warning > .panel-heading { + background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); + background-repeat: repeat-x; +} +.panel-danger > .panel-heading { + background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); + background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); + background-repeat: repeat-x; +} +.well { + background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); + background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); + background-repeat: repeat-x; + border-color: #dcdcdc; + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); +} +/*# sourceMappingURL=bootstrap-theme.css.map */ diff --git a/public/Content/bootstrap-theme.css.map b/public/Content/bootstrap-theme.css.map new file mode 100644 index 0000000..d876f60 --- /dev/null +++ b/public/Content/bootstrap-theme.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["bootstrap-theme.css","less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAAA;;;;GAIG;ACeH;;;;;;EAME,yCAAA;EC2CA,4FAAA;EACQ,oFAAA;CFvDT;ACgBC;;;;;;;;;;;;ECsCA,yDAAA;EACQ,iDAAA;CFxCT;ACMC;;;;;;;;;;;;;;;;;;ECiCA,yBAAA;EACQ,iBAAA;CFnBT;AC/BD;;;;;;EAuBI,kBAAA;CDgBH;ACyBC;;EAEE,uBAAA;CDvBH;AC4BD;EErEI,sEAAA;EACA,iEAAA;EACA,2FAAA;EAAA,oEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;EAuC2C,0BAAA;EAA2B,mBAAA;CDjBvE;ACpBC;;EAEE,0BAAA;EACA,6BAAA;CDsBH;ACnBC;;EAEE,0BAAA;EACA,sBAAA;CDqBH;ACfG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6BL;ACbD;EEtEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8DD;AC5DC;;EAEE,0BAAA;EACA,6BAAA;CD8DH;AC3DC;;EAEE,0BAAA;EACA,sBAAA;CD6DH;ACvDG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqEL;ACpDD;EEvEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CDsGD;ACpGC;;EAEE,0BAAA;EACA,6BAAA;CDsGH;ACnGC;;EAEE,0BAAA;EACA,sBAAA;CDqGH;AC/FG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6GL;AC3FD;EExEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8ID;AC5IC;;EAEE,0BAAA;EACA,6BAAA;CD8IH;AC3IC;;EAEE,0BAAA;EACA,sBAAA;CD6IH;ACvIG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqJL;AClID;EEzEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CDsLD;ACpLC;;EAEE,0BAAA;EACA,6BAAA;CDsLH;ACnLC;;EAEE,0BAAA;EACA,sBAAA;CDqLH;AC/KG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6LL;ACzKD;EE1EI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8ND;AC5NC;;EAEE,0BAAA;EACA,6BAAA;CD8NH;AC3NC;;EAEE,0BAAA;EACA,sBAAA;CD6NH;ACvNG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqOL;AC1MD;;EClCE,mDAAA;EACQ,2CAAA;CFgPT;ACrMD;;EE3FI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF0FF,0BAAA;CD2MD;ACzMD;;;EEhGI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFgGF,0BAAA;CD+MD;ACtMD;EE7GI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ECnBF,oEAAA;EH+HA,mBAAA;ECjEA,4FAAA;EACQ,oFAAA;CF8QT;ACjND;;EE7GI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ED2CF,yDAAA;EACQ,iDAAA;CFwRT;AC9MD;;EAEE,+CAAA;CDgND;AC5MD;EEhII,sEAAA;EACA,iEAAA;EACA,2FAAA;EAAA,oEAAA;EACA,4BAAA;EACA,uHAAA;ECnBF,oEAAA;EHkJA,mBAAA;CDkND;ACrND;;EEhII,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ED2CF,wDAAA;EACQ,gDAAA;CF+ST;AC/ND;;EAYI,0CAAA;CDuNH;AClND;;;EAGE,iBAAA;CDoND;AC/LD;EAfI;;;IAGE,YAAA;IE7JF,yEAAA;IACA,oEAAA;IACA,8FAAA;IAAA,uEAAA;IACA,4BAAA;IACA,uHAAA;GH+WD;CACF;AC3MD;EACE,8CAAA;EC3HA,2FAAA;EACQ,mFAAA;CFyUT;ACnMD;EEtLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CD+MD;AC1MD;EEvLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CDuND;ACjND;EExLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CD+ND;ACxND;EEzLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CDuOD;ACxND;EEjMI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH4ZH;ACrND;EE3MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHmaH;AC3ND;EE5MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH0aH;ACjOD;EE7MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHibH;ACvOD;EE9MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHwbH;AC7OD;EE/MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH+bH;AChPD;EElLI,8MAAA;EACA,yMAAA;EACA,sMAAA;CHqaH;AC5OD;EACE,mBAAA;EC9KA,mDAAA;EACQ,2CAAA;CF6ZT;AC7OD;;;EAGE,8BAAA;EEnOE,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFiOF,sBAAA;CDmPD;ACxPD;;;EAQI,kBAAA;CDqPH;AC3OD;ECnME,kDAAA;EACQ,0CAAA;CFibT;ACrOD;EE5PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHoeH;AC3OD;EE7PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH2eH;ACjPD;EE9PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHkfH;ACvPD;EE/PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHyfH;AC7PD;EEhQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHggBH;ACnQD;EEjQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHugBH;ACnQD;EExQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFsQF,sBAAA;EC3NA,0FAAA;EACQ,kFAAA;CFqeT","file":"bootstrap-theme.css","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/public/Content/bootstrap-theme.min.css b/public/Content/bootstrap-theme.min.css new file mode 100644 index 0000000..5e39401 --- /dev/null +++ b/public/Content/bootstrap-theme.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} +/*# sourceMappingURL=bootstrap-theme.min.css.map */ \ No newline at end of file diff --git a/public/Content/bootstrap-theme.min.css.map b/public/Content/bootstrap-theme.min.css.map new file mode 100644 index 0000000..94813e9 --- /dev/null +++ b/public/Content/bootstrap-theme.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":";;;;AAmBA,YAAA,aAAA,UAAA,aAAA,aAAA,aAME,YAAA,EAAA,KAAA,EAAA,eC2CA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBDvCR,mBAAA,mBAAA,oBAAA,oBAAA,iBAAA,iBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBCsCA,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBDlCR,qBAAA,sBAAA,sBAAA,uBAAA,mBAAA,oBAAA,sBAAA,uBAAA,sBAAA,uBAAA,sBAAA,uBAAA,+BAAA,gCAAA,6BAAA,gCAAA,gCAAA,gCCiCA,mBAAA,KACQ,WAAA,KDlDV,mBAAA,oBAAA,iBAAA,oBAAA,oBAAA,oBAuBI,YAAA,KAyCF,YAAA,YAEE,iBAAA,KAKJ,aErEI,YAAA,EAAA,IAAA,EAAA,KACA,iBAAA,iDACA,iBAAA,4CAAA,iBAAA,qEAEA,iBAAA,+CCnBF,OAAA,+GH4CA,OAAA,0DACA,kBAAA,SAuC2C,aAAA,QAA2B,aAAA,KArCtE,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAgBN,aEtEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAiBN,aEvEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAkBN,UExEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,gBAAA,gBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,iBAAA,iBAEE,iBAAA,QACA,aAAA,QAMA,mBAAA,0BAAA,yBAAA,0BAAA,yBAAA,yBAAA,oBAAA,2BAAA,0BAAA,2BAAA,0BAAA,0BAAA,6BAAA,oCAAA,mCAAA,oCAAA,mCAAA,mCAME,iBAAA,QACA,iBAAA,KAmBN,aEzEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAoBN,YE1EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,kBAAA,kBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,mBAAA,mBAEE,iBAAA,QACA,aAAA,QAMA,qBAAA,4BAAA,2BAAA,4BAAA,2BAAA,2BAAA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,+BAAA,sCAAA,qCAAA,sCAAA,qCAAA,qCAME,iBAAA,QACA,iBAAA,KA2BN,eAAA,WClCE,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBD2CV,0BAAA,0BE3FI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GF0FF,kBAAA,SAEF,yBAAA,+BAAA,+BEhGI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GFgGF,kBAAA,SASF,gBE7GI,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SH+HA,cAAA,ICjEA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBD6DV,sCAAA,oCE7GI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBD0EV,cAAA,iBAEE,YAAA,EAAA,IAAA,EAAA,sBAIF,gBEhII,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SHkJA,cAAA,IAHF,sCAAA,oCEhII,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBDgFV,8BAAA,iCAYI,YAAA,EAAA,KAAA,EAAA,gBAKJ,qBAAA,kBAAA,mBAGE,cAAA,EAqBF,yBAfI,mDAAA,yDAAA,yDAGE,MAAA,KE7JF,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,UFqKJ,OACE,YAAA,EAAA,IAAA,EAAA,qBC3HA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBDsIV,eEtLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAKF,YEvLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAMF,eExLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAOF,cEzLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAeF,UEjMI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFuMJ,cE3MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFwMJ,sBE5MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyMJ,mBE7MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0MJ,sBE9MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2MJ,qBE/MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF+MJ,sBElLI,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKFyLJ,YACE,cAAA,IC9KA,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBDgLV,wBAAA,8BAAA,8BAGE,YAAA,EAAA,KAAA,EAAA,QEnOE,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFiOF,aAAA,QALF,+BAAA,qCAAA,qCAQI,YAAA,KAUJ,OCnME,mBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,EAAA,IAAA,IAAA,gBD4MV,8BE5PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyPJ,8BE7PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0PJ,8BE9PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2PJ,2BE/PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF4PJ,8BEhQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF6PJ,6BEjQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoQJ,MExQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFsQF,aAAA,QC3NA,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA,qBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/public/Content/bootstrap.css b/public/Content/bootstrap.css new file mode 100644 index 0000000..d919b97 --- /dev/null +++ b/public/Content/bootstrap.css @@ -0,0 +1,7022 @@ +@import url("https://fonts.googleapis.com/css?family=Lato:400,700,400italic"); +/*! + * bootswatch v3.3.7 + * Homepage: http://bootswatch.com + * Copyright 2012-2016 Thomas Park + * Licensed under MIT + * Based on Bootstrap +*/ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + text-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\002a"; +} +.glyphicon-plus:before { + content: "\002b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 15px; + line-height: 1.42857143; + color: #2c3e50; + background-color: #ffffff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #18bc9c; + text-decoration: none; +} +a:hover, +a:focus { + color: #18bc9c; + text-decoration: underline; +} +a:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #ecf0f1; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 21px; + margin-bottom: 21px; + border: 0; + border-top: 1px solid #ecf0f1; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: 400; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #b4bcc2; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 21px; + margin-bottom: 10.5px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10.5px; + margin-bottom: 10.5px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 39px; +} +h2, +.h2 { + font-size: 32px; +} +h3, +.h3 { + font-size: 26px; +} +h4, +.h4 { + font-size: 19px; +} +h5, +.h5 { + font-size: 15px; +} +h6, +.h6 { + font-size: 13px; +} +p { + margin: 0 0 10.5px; +} +.lead { + margin-bottom: 21px; + font-size: 17px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 22.5px; + } +} +small, +.small { + font-size: 86%; +} +mark, +.mark { + background-color: #f39c12; + padding: .2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #b4bcc2; +} +.text-primary { + color: #2c3e50; +} +a.text-primary:hover, +a.text-primary:focus { + color: #1a242f; +} +.text-success { + color: #ffffff; +} +a.text-success:hover, +a.text-success:focus { + color: #e6e6e6; +} +.text-info { + color: #ffffff; +} +a.text-info:hover, +a.text-info:focus { + color: #e6e6e6; +} +.text-warning { + color: #ffffff; +} +a.text-warning:hover, +a.text-warning:focus { + color: #e6e6e6; +} +.text-danger { + color: #ffffff; +} +a.text-danger:hover, +a.text-danger:focus { + color: #e6e6e6; +} +.bg-primary { + color: #fff; + background-color: #2c3e50; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #1a242f; +} +.bg-success { + background-color: #18bc9c; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #128f76; +} +.bg-info { + background-color: #3498db; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #217dbb; +} +.bg-warning { + background-color: #f39c12; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #c87f0a; +} +.bg-danger { + background-color: #e74c3c; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #d62c1a; +} +.page-header { + padding-bottom: 9.5px; + margin: 42px 0 21px; + border-bottom: 1px solid transparent; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10.5px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 21px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #b4bcc2; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10.5px 21px; + margin: 0 0 21px; + font-size: 18.75px; + border-left: 5px solid #ecf0f1; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #b4bcc2; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #ecf0f1; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 21px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 10px; + margin: 0 0 10.5px; + font-size: 14px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #7b8a8b; + background-color: #ecf0f1; + border: 1px solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #b4bcc2; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 21px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ecf0f1; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ecf0f1; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ecf0f1; +} +.table .table { + background-color: #ffffff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ecf0f1; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ecf0f1; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #ecf0f1; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #ecf0f1; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #dde4e6; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #18bc9c; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #15a589; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #3498db; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #258cd1; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #f39c12; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #e08e0b; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #e74c3c; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #e43725; +} +.table-responsive { + overflow-x: auto; + min-height: 0.01%; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15.75px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ecf0f1; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 21px; + font-size: 22.5px; + line-height: inherit; + color: #2c3e50; + border: 0; + border-bottom: 1px solid transparent; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 11px; + font-size: 15px; + line-height: 1.42857143; + color: #2c3e50; +} +.form-control { + display: block; + width: 100%; + height: 45px; + padding: 10px 15px; + font-size: 15px; + line-height: 1.42857143; + color: #2c3e50; + background-color: #ffffff; + background-image: none; + border: 1px solid #dce4ec; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #2c3e50; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(44, 62, 80, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(44, 62, 80, 0.6); +} +.form-control::-moz-placeholder { + color: #acb6c0; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #acb6c0; +} +.form-control::-webkit-input-placeholder { + color: #acb6c0; +} +.form-control::-ms-expand { + border: 0; + background-color: transparent; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #ecf0f1; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 45px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 35px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 66px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 21px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 11px; + padding-bottom: 11px; + margin-bottom: 0; + min-height: 36px; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm { + height: 35px; + padding: 6px 9px; + font-size: 13px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 35px; + line-height: 35px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 35px; + padding: 6px 9px; + font-size: 13px; + line-height: 1.5; + border-radius: 3px; +} +.form-group-sm select.form-control { + height: 35px; + line-height: 35px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 35px; + min-height: 34px; + padding: 7px 9px; + font-size: 13px; + line-height: 1.5; +} +.input-lg { + height: 66px; + padding: 18px 27px; + font-size: 19px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 66px; + line-height: 66px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 66px; + padding: 18px 27px; + font-size: 19px; + line-height: 1.3333333; + border-radius: 6px; +} +.form-group-lg select.form-control { + height: 66px; + line-height: 66px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 66px; + min-height: 40px; + padding: 19px 27px; + font-size: 19px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 56.25px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 45px; + height: 45px; + line-height: 45px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 66px; + height: 66px; + line-height: 66px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 35px; + height: 35px; + line-height: 35px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #ffffff; +} +.has-success .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-success .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #18bc9c; +} +.has-success .form-control-feedback { + color: #ffffff; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #ffffff; +} +.has-warning .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-warning .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #f39c12; +} +.has-warning .form-control-feedback { + color: #ffffff; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #ffffff; +} +.has-error .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-error .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #e74c3c; +} +.has-error .form-control-feedback { + color: #ffffff; +} +.has-feedback label ~ .form-control-feedback { + top: 26px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #597ea2; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 11px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 32px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 11px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 19px; + font-size: 19px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 7px; + font-size: 13px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 10px 15px; + font-size: 15px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #ffffff; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #ffffff; + background-color: #95a5a6; + border-color: #95a5a6; +} +.btn-default:focus, +.btn-default.focus { + color: #ffffff; + background-color: #798d8f; + border-color: #566566; +} +.btn-default:hover { + color: #ffffff; + background-color: #798d8f; + border-color: #74898a; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #ffffff; + background-color: #798d8f; + border-color: #74898a; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #ffffff; + background-color: #687b7c; + border-color: #566566; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus { + background-color: #95a5a6; + border-color: #95a5a6; +} +.btn-default .badge { + color: #95a5a6; + background-color: #ffffff; +} +.btn-primary { + color: #ffffff; + background-color: #2c3e50; + border-color: #2c3e50; +} +.btn-primary:focus, +.btn-primary.focus { + color: #ffffff; + background-color: #1a242f; + border-color: #000000; +} +.btn-primary:hover { + color: #ffffff; + background-color: #1a242f; + border-color: #161f29; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #1a242f; + border-color: #161f29; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #ffffff; + background-color: #0d1318; + border-color: #000000; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus { + background-color: #2c3e50; + border-color: #2c3e50; +} +.btn-primary .badge { + color: #2c3e50; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #18bc9c; + border-color: #18bc9c; +} +.btn-success:focus, +.btn-success.focus { + color: #ffffff; + background-color: #128f76; + border-color: #0a4b3e; +} +.btn-success:hover { + color: #ffffff; + background-color: #128f76; + border-color: #11866f; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #128f76; + border-color: #11866f; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #ffffff; + background-color: #0e6f5c; + border-color: #0a4b3e; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus { + background-color: #18bc9c; + border-color: #18bc9c; +} +.btn-success .badge { + color: #18bc9c; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #3498db; + border-color: #3498db; +} +.btn-info:focus, +.btn-info.focus { + color: #ffffff; + background-color: #217dbb; + border-color: #16527a; +} +.btn-info:hover { + color: #ffffff; + background-color: #217dbb; + border-color: #2077b2; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #217dbb; + border-color: #2077b2; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #ffffff; + background-color: #1c699d; + border-color: #16527a; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus { + background-color: #3498db; + border-color: #3498db; +} +.btn-info .badge { + color: #3498db; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f39c12; + border-color: #f39c12; +} +.btn-warning:focus, +.btn-warning.focus { + color: #ffffff; + background-color: #c87f0a; + border-color: #7f5006; +} +.btn-warning:hover { + color: #ffffff; + background-color: #c87f0a; + border-color: #be780a; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #c87f0a; + border-color: #be780a; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #ffffff; + background-color: #a66908; + border-color: #7f5006; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus { + background-color: #f39c12; + border-color: #f39c12; +} +.btn-warning .badge { + color: #f39c12; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #e74c3c; + border-color: #e74c3c; +} +.btn-danger:focus, +.btn-danger.focus { + color: #ffffff; + background-color: #d62c1a; + border-color: #921e12; +} +.btn-danger:hover { + color: #ffffff; + background-color: #d62c1a; + border-color: #cd2a19; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #d62c1a; + border-color: #cd2a19; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #ffffff; + background-color: #b62516; + border-color: #921e12; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus { + background-color: #e74c3c; + border-color: #e74c3c; +} +.btn-danger .badge { + color: #e74c3c; + background-color: #ffffff; +} +.btn-link { + color: #18bc9c; + font-weight: normal; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #18bc9c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #b4bcc2; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 18px 27px; + font-size: 19px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 6px 9px; + font-size: 13px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 13px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + -o-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 15px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + -webkit-background-clip: padding-box; + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9.5px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #7b8a8b; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #ffffff; + background-color: #2c3e50; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #2c3e50; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #b4bcc2; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 13px; + line-height: 1.42857143; + color: #b4bcc2; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-right-radius: 0; + border-top-left-radius: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group .form-control:focus { + z-index: 3; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 66px; + padding: 18px 27px; + font-size: 19px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 66px; + line-height: 66px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 35px; + padding: 6px 9px; + font-size: 13px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 35px; + line-height: 35px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 10px 15px; + font-size: 15px; + font-weight: normal; + line-height: 1; + color: #2c3e50; + text-align: center; + background-color: #ecf0f1; + border: 1px solid #dce4ec; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 6px 9px; + font-size: 13px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 18px 27px; + font-size: 19px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #ecf0f1; +} +.nav > li.disabled > a { + color: #b4bcc2; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #b4bcc2; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #ecf0f1; + border-color: #18bc9c; +} +.nav .nav-divider { + height: 1px; + margin: 9.5px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ecf0f1; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #ecf0f1 #ecf0f1 #ecf0f1; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #2c3e50; + background-color: #ffffff; + border: 1px solid #ecf0f1; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ecf0f1; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ecf0f1; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #2c3e50; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ecf0f1; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ecf0f1; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 60px; + margin-bottom: 21px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 19.5px 15px; + font-size: 19px; + line-height: 21px; + height: 60px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 13px; + margin-bottom: 13px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 9.75px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 21px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 21px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 19.5px; + padding-bottom: 19.5px; + } +} +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 7.5px; + margin-bottom: 7.5px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 7.5px; + margin-bottom: 7.5px; +} +.navbar-btn.btn-sm { + margin-top: 12.5px; + margin-bottom: 12.5px; +} +.navbar-btn.btn-xs { + margin-top: 19px; + margin-bottom: 19px; +} +.navbar-text { + margin-top: 19.5px; + margin-bottom: 19.5px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #2c3e50; + border-color: transparent; +} +.navbar-default .navbar-brand { + color: #ffffff; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #18bc9c; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #ffffff; +} +.navbar-default .navbar-nav > li > a { + color: #ffffff; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #18bc9c; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #1a242f; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #1a242f; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #1a242f; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #ffffff; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: transparent; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: #1a242f; + color: #ffffff; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #ffffff; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #18bc9c; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #1a242f; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #ffffff; +} +.navbar-default .navbar-link:hover { + color: #18bc9c; +} +.navbar-default .btn-link { + color: #ffffff; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #18bc9c; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #cccccc; +} +.navbar-inverse { + background-color: #18bc9c; + border-color: transparent; +} +.navbar-inverse .navbar-brand { + color: #ffffff; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #2c3e50; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #ffffff; +} +.navbar-inverse .navbar-nav > li > a { + color: #ffffff; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #2c3e50; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #15a589; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #128f76; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #128f76; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #149c82; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #15a589; + color: #ffffff; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #ffffff; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #2c3e50; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #15a589; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #ffffff; +} +.navbar-inverse .navbar-link:hover { + color: #2c3e50; +} +.navbar-inverse .btn-link { + color: #ffffff; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #2c3e50; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #cccccc; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 21px; + list-style: none; + background-color: #ecf0f1; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #cccccc; +} +.breadcrumb > .active { + color: #95a5a6; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 21px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 10px 15px; + line-height: 1.42857143; + text-decoration: none; + color: #ffffff; + background-color: #18bc9c; + border: 1px solid transparent; + margin-left: -1px; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #ffffff; + background-color: #0f7864; + border-color: transparent; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 3; + color: #ffffff; + background-color: #0f7864; + border-color: transparent; + cursor: default; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #ecf0f1; + background-color: #3be6c4; + border-color: transparent; + cursor: not-allowed; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 18px 27px; + font-size: 19px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 6px 9px; + font-size: 13px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 21px 0; + list-style: none; + text-align: center; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #18bc9c; + border: 1px solid transparent; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #0f7864; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #ffffff; + background-color: #18bc9c; + cursor: not-allowed; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #95a5a6; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #798d8f; +} +.label-primary { + background-color: #2c3e50; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #1a242f; +} +.label-success { + background-color: #18bc9c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #128f76; +} +.label-info { + background-color: #3498db; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #217dbb; +} +.label-warning { + background-color: #f39c12; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #c87f0a; +} +.label-danger { + background-color: #e74c3c; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #d62c1a; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 13px; + font-weight: bold; + color: #ffffff; + line-height: 1; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: #2c3e50; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #2c3e50; + background-color: #ffffff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #ecf0f1; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 23px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #cfd9db; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px; + padding-left: 15px; + padding-right: 15px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 68px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 21px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #ecf0f1; + border-radius: 4px; + -webkit-transition: border 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-left: auto; + margin-right: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #18bc9c; +} +.thumbnail .caption { + padding: 9px; + color: #2c3e50; +} +.alert { + padding: 15px; + margin-bottom: 21px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + background-color: #18bc9c; + border-color: #18bc9c; + color: #ffffff; +} +.alert-success hr { + border-top-color: #15a589; +} +.alert-success .alert-link { + color: #e6e6e6; +} +.alert-info { + background-color: #3498db; + border-color: #3498db; + color: #ffffff; +} +.alert-info hr { + border-top-color: #258cd1; +} +.alert-info .alert-link { + color: #e6e6e6; +} +.alert-warning { + background-color: #f39c12; + border-color: #f39c12; + color: #ffffff; +} +.alert-warning hr { + border-top-color: #e08e0b; +} +.alert-warning .alert-link { + color: #e6e6e6; +} +.alert-danger { + background-color: #e74c3c; + border-color: #e74c3c; + color: #ffffff; +} +.alert-danger hr { + border-top-color: #e43725; +} +.alert-danger .alert-link { + color: #e6e6e6; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 21px; + margin-bottom: 21px; + background-color: #ecf0f1; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 13px; + line-height: 21px; + color: #ffffff; + text-align: center; + background-color: #2c3e50; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #18bc9c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #3498db; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f39c12; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #e74c3c; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + zoom: 1; + overflow: hidden; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #ecf0f1; +} +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item, +button.list-group-item { + color: #555555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + text-decoration: none; + color: #555555; + background-color: #ecf0f1; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #ecf0f1; + color: #b4bcc2; + cursor: not-allowed; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #b4bcc2; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #2c3e50; + border-color: #2c3e50; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #8aa4be; +} +.list-group-item-success { + color: #ffffff; + background-color: #18bc9c; +} +a.list-group-item-success, +button.list-group-item-success { + color: #ffffff; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #ffffff; + background-color: #15a589; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-info { + color: #ffffff; + background-color: #3498db; +} +a.list-group-item-info, +button.list-group-item-info { + color: #ffffff; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #ffffff; + background-color: #258cd1; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-warning { + color: #ffffff; + background-color: #f39c12; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #ffffff; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #ffffff; + background-color: #e08e0b; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-danger { + color: #ffffff; + background-color: #e74c3c; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #ffffff; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #ffffff; + background-color: #e43725; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 21px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 17px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #ecf0f1; + border-top: 1px solid #ecf0f1; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ecf0f1; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 21px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ecf0f1; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ecf0f1; +} +.panel-default { + border-color: #ecf0f1; +} +.panel-default > .panel-heading { + color: #2c3e50; + background-color: #ecf0f1; + border-color: #ecf0f1; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ecf0f1; +} +.panel-default > .panel-heading .badge { + color: #ecf0f1; + background-color: #2c3e50; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ecf0f1; +} +.panel-primary { + border-color: #2c3e50; +} +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #2c3e50; + border-color: #2c3e50; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #2c3e50; +} +.panel-primary > .panel-heading .badge { + color: #2c3e50; + background-color: #ffffff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #2c3e50; +} +.panel-success { + border-color: #18bc9c; +} +.panel-success > .panel-heading { + color: #ffffff; + background-color: #18bc9c; + border-color: #18bc9c; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #18bc9c; +} +.panel-success > .panel-heading .badge { + color: #18bc9c; + background-color: #ffffff; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #18bc9c; +} +.panel-info { + border-color: #3498db; +} +.panel-info > .panel-heading { + color: #ffffff; + background-color: #3498db; + border-color: #3498db; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #3498db; +} +.panel-info > .panel-heading .badge { + color: #3498db; + background-color: #ffffff; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #3498db; +} +.panel-warning { + border-color: #f39c12; +} +.panel-warning > .panel-heading { + color: #ffffff; + background-color: #f39c12; + border-color: #f39c12; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #f39c12; +} +.panel-warning > .panel-heading .badge { + color: #f39c12; + background-color: #ffffff; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #f39c12; +} +.panel-danger { + border-color: #e74c3c; +} +.panel-danger > .panel-heading { + color: #ffffff; + background-color: #e74c3c; + border-color: #e74c3c; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #e74c3c; +} +.panel-danger > .panel-heading .badge { + color: #e74c3c; + background-color: #ffffff; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #e74c3c; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #ecf0f1; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 22.5px; + font-weight: bold; + line-height: 1; + color: #000000; + text-shadow: none; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + -webkit-background-clip: padding-box; + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 20px; +} +.modal-footer { + padding: 20px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 13px; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + background-color: #000000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 15px; + background-color: #ffffff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 15px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 0; + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); + background-color: rgba(0, 0, 0, 0); +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + outline: 0; + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + margin-top: -10px; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + line-height: 1; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -10px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -10px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -10px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-header:before, +.modal-header:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-header:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +.navbar { + border-width: 0; +} +.navbar-default .badge { + background-color: #fff; + color: #2c3e50; +} +.navbar-inverse .badge { + background-color: #fff; + color: #18bc9c; +} +.navbar-brand { + line-height: 1; +} +.btn { + border-width: 2px; +} +.btn:active { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: none; + box-shadow: none; +} +.text-primary, +.text-primary:hover { + color: #2c3e50; +} +.text-success, +.text-success:hover { + color: #18bc9c; +} +.text-danger, +.text-danger:hover { + color: #e74c3c; +} +.text-warning, +.text-warning:hover { + color: #f39c12; +} +.text-info, +.text-info:hover { + color: #3498db; +} +table a:not(.btn), +.table a:not(.btn) { + text-decoration: underline; +} +table .dropdown-menu a, +.table .dropdown-menu a { + text-decoration: none; +} +table .success, +.table .success, +table .warning, +.table .warning, +table .danger, +.table .danger, +table .info, +.table .info { + color: #fff; +} +table .success > th > a, +.table .success > th > a, +table .warning > th > a, +.table .warning > th > a, +table .danger > th > a, +.table .danger > th > a, +table .info > th > a, +.table .info > th > a, +table .success > td > a, +.table .success > td > a, +table .warning > td > a, +.table .warning > td > a, +table .danger > td > a, +.table .danger > td > a, +table .info > td > a, +.table .info > td > a, +table .success > a, +.table .success > a, +table .warning > a, +.table .warning > a, +table .danger > a, +.table .danger > a, +table .info > a, +.table .info > a { + color: #fff; +} +table > thead > tr > th, +.table > thead > tr > th, +table > tbody > tr > th, +.table > tbody > tr > th, +table > tfoot > tr > th, +.table > tfoot > tr > th, +table > thead > tr > td, +.table > thead > tr > td, +table > tbody > tr > td, +.table > tbody > tr > td, +table > tfoot > tr > td, +.table > tfoot > tr > td { + border: none; +} +table-bordered > thead > tr > th, +.table-bordered > thead > tr > th, +table-bordered > tbody > tr > th, +.table-bordered > tbody > tr > th, +table-bordered > tfoot > tr > th, +.table-bordered > tfoot > tr > th, +table-bordered > thead > tr > td, +.table-bordered > thead > tr > td, +table-bordered > tbody > tr > td, +.table-bordered > tbody > tr > td, +table-bordered > tfoot > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ecf0f1; +} +.form-control, +input { + border-width: 2px; + -webkit-box-shadow: none; + box-shadow: none; +} +.form-control:focus, +input:focus { + -webkit-box-shadow: none; + box-shadow: none; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label, +.has-warning .form-control-feedback { + color: #f39c12; +} +.has-warning .form-control, +.has-warning .form-control:focus { + border: 2px solid #f39c12; +} +.has-warning .input-group-addon { + border-color: #f39c12; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label, +.has-error .form-control-feedback { + color: #e74c3c; +} +.has-error .form-control, +.has-error .form-control:focus { + border: 2px solid #e74c3c; +} +.has-error .input-group-addon { + border-color: #e74c3c; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label, +.has-success .form-control-feedback { + color: #18bc9c; +} +.has-success .form-control, +.has-success .form-control:focus { + border: 2px solid #18bc9c; +} +.has-success .input-group-addon { + border-color: #18bc9c; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + border-color: transparent; +} +.pager a, +.pager a:hover { + color: #fff; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + background-color: #3be6c4; +} +.close { + color: #fff; + text-decoration: none; + opacity: 0.4; +} +.close:hover, +.close:focus { + color: #fff; + opacity: 1; +} +.alert .alert-link { + color: #fff; + text-decoration: underline; +} +.progress { + height: 10px; + -webkit-box-shadow: none; + box-shadow: none; +} +.progress .progress-bar { + font-size: 10px; + line-height: 10px; +} +.well { + -webkit-box-shadow: none; + box-shadow: none; +} +a.list-group-item.active, +a.list-group-item.active:hover, +a.list-group-item.active:focus { + border-color: #ecf0f1; +} +a.list-group-item-success.active { + background-color: #18bc9c; +} +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + background-color: #15a589; +} +a.list-group-item-warning.active { + background-color: #f39c12; +} +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + background-color: #e08e0b; +} +a.list-group-item-danger.active { + background-color: #e74c3c; +} +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + background-color: #e43725; +} +.panel-default .close { + color: #2c3e50; +} +.modal .close { + color: #2c3e50; +} +.popover { + color: #2c3e50; +} diff --git a/public/Content/bootstrap.css.map b/public/Content/bootstrap.css.map new file mode 100644 index 0000000..f010c82 --- /dev/null +++ b/public/Content/bootstrap.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,4EAA4E;ACG5E;EACE,wBAAA;EACA,2BAAA;EACA,+BAAA;CDDD;ACQD;EACE,UAAA;CDND;ACmBD;;;;;;;;;;;;;EAaE,eAAA;CDjBD;ACyBD;;;;EAIE,sBAAA;EACA,yBAAA;CDvBD;AC+BD;EACE,cAAA;EACA,UAAA;CD7BD;ACqCD;;EAEE,cAAA;CDnCD;AC6CD;EACE,8BAAA;CD3CD;ACmDD;;EAEE,WAAA;CDjDD;AC2DD;EACE,0BAAA;CDzDD;ACgED;;EAEE,kBAAA;CD9DD;ACqED;EACE,mBAAA;CDnED;AC2ED;EACE,eAAA;EACA,iBAAA;CDzED;ACgFD;EACE,iBAAA;EACA,YAAA;CD9ED;ACqFD;EACE,eAAA;CDnFD;AC0FD;;EAEE,eAAA;EACA,eAAA;EACA,mBAAA;EACA,yBAAA;CDxFD;AC2FD;EACE,YAAA;CDzFD;AC4FD;EACE,gBAAA;CD1FD;ACoGD;EACE,UAAA;CDlGD;ACyGD;EACE,iBAAA;CDvGD;ACiHD;EACE,iBAAA;CD/GD;ACsHD;EACE,gCAAA;KAAA,6BAAA;UAAA,wBAAA;EACA,UAAA;CDpHD;AC2HD;EACE,eAAA;CDzHD;ACgID;;;;EAIE,kCAAA;EACA,eAAA;CD9HD;ACgJD;;;;;EAKE,eAAA;EACA,cAAA;EACA,UAAA;CD9ID;ACqJD;EACE,kBAAA;CDnJD;AC6JD;;EAEE,qBAAA;CD3JD;ACsKD;;;;EAIE,2BAAA;EACA,gBAAA;CDpKD;AC2KD;;EAEE,gBAAA;CDzKD;ACgLD;;EAEE,UAAA;EACA,WAAA;CD9KD;ACsLD;EACE,oBAAA;CDpLD;AC+LD;;EAEE,+BAAA;KAAA,4BAAA;UAAA,uBAAA;EACA,WAAA;CD7LD;ACsMD;;EAEE,aAAA;CDpMD;AC4MD;EACE,8BAAA;EACA,gCAAA;KAAA,6BAAA;UAAA,wBAAA;CD1MD;ACmND;;EAEE,yBAAA;CDjND;ACwND;EACE,0BAAA;EACA,cAAA;EACA,+BAAA;CDtND;AC8ND;EACE,UAAA;EACA,WAAA;CD5ND;ACmOD;EACE,eAAA;CDjOD;ACyOD;EACE,kBAAA;CDvOD;ACiPD;EACE,0BAAA;EACA,kBAAA;CD/OD;ACkPD;;EAEE,WAAA;CDhPD;AACD,qFAAqF;AElFrF;EA7FI;;;IAGI,mCAAA;IACA,uBAAA;IACA,oCAAA;YAAA,4BAAA;IACA,6BAAA;GFkLL;EE/KC;;IAEI,2BAAA;GFiLL;EE9KC;IACI,6BAAA;GFgLL;EE7KC;IACI,8BAAA;GF+KL;EE1KC;;IAEI,YAAA;GF4KL;EEzKC;;IAEI,uBAAA;IACA,yBAAA;GF2KL;EExKC;IACI,4BAAA;GF0KL;EEvKC;;IAEI,yBAAA;GFyKL;EEtKC;IACI,2BAAA;GFwKL;EErKC;;;IAGI,WAAA;IACA,UAAA;GFuKL;EEpKC;;IAEI,wBAAA;GFsKL;EEhKC;IACI,cAAA;GFkKL;EEhKC;;IAGQ,kCAAA;GFiKT;EE9JC;IACI,uBAAA;GFgKL;EE7JC;IACI,qCAAA;GF+JL;EEhKC;;IAKQ,kCAAA;GF+JT;EE5JC;;IAGQ,kCAAA;GF6JT;CACF;AGnPD;EACE,oCAAA;EACA,sDAAA;EACA,gYAAA;CHqPD;AG7OD;EACE,mBAAA;EACA,SAAA;EACA,sBAAA;EACA,oCAAA;EACA,mBAAA;EACA,oBAAA;EACA,eAAA;EACA,oCAAA;EACA,mCAAA;CH+OD;AG3OmC;EAAW,iBAAA;CH8O9C;AG7OmC;EAAW,iBAAA;CHgP9C;AG9OmC;;EAAW,iBAAA;CHkP9C;AGjPmC;EAAW,iBAAA;CHoP9C;AGnPmC;EAAW,iBAAA;CHsP9C;AGrPmC;EAAW,iBAAA;CHwP9C;AGvPmC;EAAW,iBAAA;CH0P9C;AGzPmC;EAAW,iBAAA;CH4P9C;AG3PmC;EAAW,iBAAA;CH8P9C;AG7PmC;EAAW,iBAAA;CHgQ9C;AG/PmC;EAAW,iBAAA;CHkQ9C;AGjQmC;EAAW,iBAAA;CHoQ9C;AGnQmC;EAAW,iBAAA;CHsQ9C;AGrQmC;EAAW,iBAAA;CHwQ9C;AGvQmC;EAAW,iBAAA;CH0Q9C;AGzQmC;EAAW,iBAAA;CH4Q9C;AG3QmC;EAAW,iBAAA;CH8Q9C;AG7QmC;EAAW,iBAAA;CHgR9C;AG/QmC;EAAW,iBAAA;CHkR9C;AGjRmC;EAAW,iBAAA;CHoR9C;AGnRmC;EAAW,iBAAA;CHsR9C;AGrRmC;EAAW,iBAAA;CHwR9C;AGvRmC;EAAW,iBAAA;CH0R9C;AGzRmC;EAAW,iBAAA;CH4R9C;AG3RmC;EAAW,iBAAA;CH8R9C;AG7RmC;EAAW,iBAAA;CHgS9C;AG/RmC;EAAW,iBAAA;CHkS9C;AGjSmC;EAAW,iBAAA;CHoS9C;AGnSmC;EAAW,iBAAA;CHsS9C;AGrSmC;EAAW,iBAAA;CHwS9C;AGvSmC;EAAW,iBAAA;CH0S9C;AGzSmC;EAAW,iBAAA;CH4S9C;AG3SmC;EAAW,iBAAA;CH8S9C;AG7SmC;EAAW,iBAAA;CHgT9C;AG/SmC;EAAW,iBAAA;CHkT9C;AGjTmC;EAAW,iBAAA;CHoT9C;AGnTmC;EAAW,iBAAA;CHsT9C;AGrTmC;EAAW,iBAAA;CHwT9C;AGvTmC;EAAW,iBAAA;CH0T9C;AGzTmC;EAAW,iBAAA;CH4T9C;AG3TmC;EAAW,iBAAA;CH8T9C;AG7TmC;EAAW,iBAAA;CHgU9C;AG/TmC;EAAW,iBAAA;CHkU9C;AGjUmC;EAAW,iBAAA;CHoU9C;AGnUmC;EAAW,iBAAA;CHsU9C;AGrUmC;EAAW,iBAAA;CHwU9C;AGvUmC;EAAW,iBAAA;CH0U9C;AGzUmC;EAAW,iBAAA;CH4U9C;AG3UmC;EAAW,iBAAA;CH8U9C;AG7UmC;EAAW,iBAAA;CHgV9C;AG/UmC;EAAW,iBAAA;CHkV9C;AGjVmC;EAAW,iBAAA;CHoV9C;AGnVmC;EAAW,iBAAA;CHsV9C;AGrVmC;EAAW,iBAAA;CHwV9C;AGvVmC;EAAW,iBAAA;CH0V9C;AGzVmC;EAAW,iBAAA;CH4V9C;AG3VmC;EAAW,iBAAA;CH8V9C;AG7VmC;EAAW,iBAAA;CHgW9C;AG/VmC;EAAW,iBAAA;CHkW9C;AGjWmC;EAAW,iBAAA;CHoW9C;AGnWmC;EAAW,iBAAA;CHsW9C;AGrWmC;EAAW,iBAAA;CHwW9C;AGvWmC;EAAW,iBAAA;CH0W9C;AGzWmC;EAAW,iBAAA;CH4W9C;AG3WmC;EAAW,iBAAA;CH8W9C;AG7WmC;EAAW,iBAAA;CHgX9C;AG/WmC;EAAW,iBAAA;CHkX9C;AGjXmC;EAAW,iBAAA;CHoX9C;AGnXmC;EAAW,iBAAA;CHsX9C;AGrXmC;EAAW,iBAAA;CHwX9C;AGvXmC;EAAW,iBAAA;CH0X9C;AGzXmC;EAAW,iBAAA;CH4X9C;AG3XmC;EAAW,iBAAA;CH8X9C;AG7XmC;EAAW,iBAAA;CHgY9C;AG/XmC;EAAW,iBAAA;CHkY9C;AGjYmC;EAAW,iBAAA;CHoY9C;AGnYmC;EAAW,iBAAA;CHsY9C;AGrYmC;EAAW,iBAAA;CHwY9C;AGvYmC;EAAW,iBAAA;CH0Y9C;AGzYmC;EAAW,iBAAA;CH4Y9C;AG3YmC;EAAW,iBAAA;CH8Y9C;AG7YmC;EAAW,iBAAA;CHgZ9C;AG/YmC;EAAW,iBAAA;CHkZ9C;AGjZmC;EAAW,iBAAA;CHoZ9C;AGnZmC;EAAW,iBAAA;CHsZ9C;AGrZmC;EAAW,iBAAA;CHwZ9C;AGvZmC;EAAW,iBAAA;CH0Z9C;AGzZmC;EAAW,iBAAA;CH4Z9C;AG3ZmC;EAAW,iBAAA;CH8Z9C;AG7ZmC;EAAW,iBAAA;CHga9C;AG/ZmC;EAAW,iBAAA;CHka9C;AGjamC;EAAW,iBAAA;CHoa9C;AGnamC;EAAW,iBAAA;CHsa9C;AGramC;EAAW,iBAAA;CHwa9C;AGvamC;EAAW,iBAAA;CH0a9C;AGzamC;EAAW,iBAAA;CH4a9C;AG3amC;EAAW,iBAAA;CH8a9C;AG7amC;EAAW,iBAAA;CHgb9C;AG/amC;EAAW,iBAAA;CHkb9C;AGjbmC;EAAW,iBAAA;CHob9C;AGnbmC;EAAW,iBAAA;CHsb9C;AGrbmC;EAAW,iBAAA;CHwb9C;AGvbmC;EAAW,iBAAA;CH0b9C;AGzbmC;EAAW,iBAAA;CH4b9C;AG3bmC;EAAW,iBAAA;CH8b9C;AG7bmC;EAAW,iBAAA;CHgc9C;AG/bmC;EAAW,iBAAA;CHkc9C;AGjcmC;EAAW,iBAAA;CHoc9C;AGncmC;EAAW,iBAAA;CHsc9C;AGrcmC;EAAW,iBAAA;CHwc9C;AGvcmC;EAAW,iBAAA;CH0c9C;AGzcmC;EAAW,iBAAA;CH4c9C;AG3cmC;EAAW,iBAAA;CH8c9C;AG7cmC;EAAW,iBAAA;CHgd9C;AG/cmC;EAAW,iBAAA;CHkd9C;AGjdmC;EAAW,iBAAA;CHod9C;AGndmC;EAAW,iBAAA;CHsd9C;AGrdmC;EAAW,iBAAA;CHwd9C;AGvdmC;EAAW,iBAAA;CH0d9C;AGzdmC;EAAW,iBAAA;CH4d9C;AG3dmC;EAAW,iBAAA;CH8d9C;AG7dmC;EAAW,iBAAA;CHge9C;AG/dmC;EAAW,iBAAA;CHke9C;AGjemC;EAAW,iBAAA;CHoe9C;AGnemC;EAAW,iBAAA;CHse9C;AGremC;EAAW,iBAAA;CHwe9C;AGvemC;EAAW,iBAAA;CH0e9C;AGzemC;EAAW,iBAAA;CH4e9C;AG3emC;EAAW,iBAAA;CH8e9C;AG7emC;EAAW,iBAAA;CHgf9C;AG/emC;EAAW,iBAAA;CHkf9C;AGjfmC;EAAW,iBAAA;CHof9C;AGnfmC;EAAW,iBAAA;CHsf9C;AGrfmC;EAAW,iBAAA;CHwf9C;AGvfmC;EAAW,iBAAA;CH0f9C;AGzfmC;EAAW,iBAAA;CH4f9C;AG3fmC;EAAW,iBAAA;CH8f9C;AG7fmC;EAAW,iBAAA;CHggB9C;AG/fmC;EAAW,iBAAA;CHkgB9C;AGjgBmC;EAAW,iBAAA;CHogB9C;AGngBmC;EAAW,iBAAA;CHsgB9C;AGrgBmC;EAAW,iBAAA;CHwgB9C;AGvgBmC;EAAW,iBAAA;CH0gB9C;AGzgBmC;EAAW,iBAAA;CH4gB9C;AG3gBmC;EAAW,iBAAA;CH8gB9C;AG7gBmC;EAAW,iBAAA;CHghB9C;AG/gBmC;EAAW,iBAAA;CHkhB9C;AGjhBmC;EAAW,iBAAA;CHohB9C;AGnhBmC;EAAW,iBAAA;CHshB9C;AGrhBmC;EAAW,iBAAA;CHwhB9C;AGvhBmC;EAAW,iBAAA;CH0hB9C;AGzhBmC;EAAW,iBAAA;CH4hB9C;AG3hBmC;EAAW,iBAAA;CH8hB9C;AG7hBmC;EAAW,iBAAA;CHgiB9C;AG/hBmC;EAAW,iBAAA;CHkiB9C;AGjiBmC;EAAW,iBAAA;CHoiB9C;AGniBmC;EAAW,iBAAA;CHsiB9C;AGriBmC;EAAW,iBAAA;CHwiB9C;AGviBmC;EAAW,iBAAA;CH0iB9C;AGziBmC;EAAW,iBAAA;CH4iB9C;AG3iBmC;EAAW,iBAAA;CH8iB9C;AG7iBmC;EAAW,iBAAA;CHgjB9C;AG/iBmC;EAAW,iBAAA;CHkjB9C;AGjjBmC;EAAW,iBAAA;CHojB9C;AGnjBmC;EAAW,iBAAA;CHsjB9C;AGrjBmC;EAAW,iBAAA;CHwjB9C;AGvjBmC;EAAW,iBAAA;CH0jB9C;AGzjBmC;EAAW,iBAAA;CH4jB9C;AG3jBmC;EAAW,iBAAA;CH8jB9C;AG7jBmC;EAAW,iBAAA;CHgkB9C;AG/jBmC;EAAW,iBAAA;CHkkB9C;AGjkBmC;EAAW,iBAAA;CHokB9C;AGnkBmC;EAAW,iBAAA;CHskB9C;AGrkBmC;EAAW,iBAAA;CHwkB9C;AGvkBmC;EAAW,iBAAA;CH0kB9C;AGzkBmC;EAAW,iBAAA;CH4kB9C;AG3kBmC;EAAW,iBAAA;CH8kB9C;AG7kBmC;EAAW,iBAAA;CHglB9C;AG/kBmC;EAAW,iBAAA;CHklB9C;AGjlBmC;EAAW,iBAAA;CHolB9C;AGnlBmC;EAAW,iBAAA;CHslB9C;AGrlBmC;EAAW,iBAAA;CHwlB9C;AGvlBmC;EAAW,iBAAA;CH0lB9C;AGzlBmC;EAAW,iBAAA;CH4lB9C;AG3lBmC;EAAW,iBAAA;CH8lB9C;AG7lBmC;EAAW,iBAAA;CHgmB9C;AG/lBmC;EAAW,iBAAA;CHkmB9C;AGjmBmC;EAAW,iBAAA;CHomB9C;AGnmBmC;EAAW,iBAAA;CHsmB9C;AGrmBmC;EAAW,iBAAA;CHwmB9C;AGvmBmC;EAAW,iBAAA;CH0mB9C;AGzmBmC;EAAW,iBAAA;CH4mB9C;AG3mBmC;EAAW,iBAAA;CH8mB9C;AG7mBmC;EAAW,iBAAA;CHgnB9C;AG/mBmC;EAAW,iBAAA;CHknB9C;AGjnBmC;EAAW,iBAAA;CHonB9C;AGnnBmC;EAAW,iBAAA;CHsnB9C;AGrnBmC;EAAW,iBAAA;CHwnB9C;AGvnBmC;EAAW,iBAAA;CH0nB9C;AGznBmC;EAAW,iBAAA;CH4nB9C;AG3nBmC;EAAW,iBAAA;CH8nB9C;AG7nBmC;EAAW,iBAAA;CHgoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AGvoBmC;EAAW,iBAAA;CH0oB9C;AGzoBmC;EAAW,iBAAA;CH4oB9C;AG3oBmC;EAAW,iBAAA;CH8oB9C;AG7oBmC;EAAW,iBAAA;CHgpB9C;AG/oBmC;EAAW,iBAAA;CHkpB9C;AGjpBmC;EAAW,iBAAA;CHopB9C;AGnpBmC;EAAW,iBAAA;CHspB9C;AGrpBmC;EAAW,iBAAA;CHwpB9C;AGvpBmC;EAAW,iBAAA;CH0pB9C;AGzpBmC;EAAW,iBAAA;CH4pB9C;AG3pBmC;EAAW,iBAAA;CH8pB9C;AG7pBmC;EAAW,iBAAA;CHgqB9C;AG/pBmC;EAAW,iBAAA;CHkqB9C;AGjqBmC;EAAW,iBAAA;CHoqB9C;AGnqBmC;EAAW,iBAAA;CHsqB9C;AGrqBmC;EAAW,iBAAA;CHwqB9C;AGvqBmC;EAAW,iBAAA;CH0qB9C;AGzqBmC;EAAW,iBAAA;CH4qB9C;AG3qBmC;EAAW,iBAAA;CH8qB9C;AG7qBmC;EAAW,iBAAA;CHgrB9C;AG/qBmC;EAAW,iBAAA;CHkrB9C;AGjrBmC;EAAW,iBAAA;CHorB9C;AGnrBmC;EAAW,iBAAA;CHsrB9C;AGrrBmC;EAAW,iBAAA;CHwrB9C;AGvrBmC;EAAW,iBAAA;CH0rB9C;AGzrBmC;EAAW,iBAAA;CH4rB9C;AG3rBmC;EAAW,iBAAA;CH8rB9C;AG7rBmC;EAAW,iBAAA;CHgsB9C;AG/rBmC;EAAW,iBAAA;CHksB9C;AGjsBmC;EAAW,iBAAA;CHosB9C;AGnsBmC;EAAW,iBAAA;CHssB9C;AGrsBmC;EAAW,iBAAA;CHwsB9C;AGvsBmC;EAAW,iBAAA;CH0sB9C;AGzsBmC;EAAW,iBAAA;CH4sB9C;AG3sBmC;EAAW,iBAAA;CH8sB9C;AG7sBmC;EAAW,iBAAA;CHgtB9C;AG/sBmC;EAAW,iBAAA;CHktB9C;AGjtBmC;EAAW,iBAAA;CHotB9C;AGntBmC;EAAW,iBAAA;CHstB9C;AGrtBmC;EAAW,iBAAA;CHwtB9C;AGvtBmC;EAAW,iBAAA;CH0tB9C;AGztBmC;EAAW,iBAAA;CH4tB9C;AG3tBmC;EAAW,iBAAA;CH8tB9C;AG7tBmC;EAAW,iBAAA;CHguB9C;AG/tBmC;EAAW,iBAAA;CHkuB9C;AGjuBmC;EAAW,iBAAA;CHouB9C;AGnuBmC;EAAW,iBAAA;CHsuB9C;AGruBmC;EAAW,iBAAA;CHwuB9C;AGvuBmC;EAAW,iBAAA;CH0uB9C;AGzuBmC;EAAW,iBAAA;CH4uB9C;AG3uBmC;EAAW,iBAAA;CH8uB9C;AG7uBmC;EAAW,iBAAA;CHgvB9C;AIthCD;ECgEE,+BAAA;EACG,4BAAA;EACK,uBAAA;CLy9BT;AIxhCD;;EC6DE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL+9BT;AIthCD;EACE,gBAAA;EACA,8CAAA;CJwhCD;AIrhCD;EACE,4DAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,uBAAA;CJuhCD;AInhCD;;;;EAIE,qBAAA;EACA,mBAAA;EACA,qBAAA;CJqhCD;AI/gCD;EACE,eAAA;EACA,sBAAA;CJihCD;AI/gCC;;EAEE,eAAA;EACA,2BAAA;CJihCH;AI9gCC;EEnDA,2CAAA;EACA,qBAAA;CNokCD;AIvgCD;EACE,UAAA;CJygCD;AIngCD;EACE,uBAAA;CJqgCD;AIjgCD;;;;;EGvEE,eAAA;EACA,gBAAA;EACA,aAAA;CP+kCD;AIrgCD;EACE,mBAAA;CJugCD;AIjgCD;EACE,aAAA;EACA,wBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;EC6FA,yCAAA;EACK,oCAAA;EACG,iCAAA;EEvLR,sBAAA;EACA,gBAAA;EACA,aAAA;CP+lCD;AIjgCD;EACE,mBAAA;CJmgCD;AI7/BD;EACE,iBAAA;EACA,oBAAA;EACA,UAAA;EACA,8BAAA;CJ+/BD;AIv/BD;EACE,mBAAA;EACA,WAAA;EACA,YAAA;EACA,aAAA;EACA,WAAA;EACA,iBAAA;EACA,uBAAA;EACA,UAAA;CJy/BD;AIj/BC;;EAEE,iBAAA;EACA,YAAA;EACA,aAAA;EACA,UAAA;EACA,kBAAA;EACA,WAAA;CJm/BH;AIx+BD;EACE,gBAAA;CJ0+BD;AQjoCD;;;;;;;;;;;;EAEE,qBAAA;EACA,iBAAA;EACA,iBAAA;EACA,eAAA;CR6oCD;AQlpCD;;;;;;;;;;;;;;;;;;;;;;;;EASI,oBAAA;EACA,eAAA;EACA,eAAA;CRmqCH;AQ/pCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRoqCD;AQxqCD;;;;;;;;;;;;EAQI,eAAA;CR8qCH;AQ3qCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRgrCD;AQprCD;;;;;;;;;;;;EAQI,eAAA;CR0rCH;AQtrCD;;EAAU,gBAAA;CR0rCT;AQzrCD;;EAAU,gBAAA;CR6rCT;AQ5rCD;;EAAU,gBAAA;CRgsCT;AQ/rCD;;EAAU,gBAAA;CRmsCT;AQlsCD;;EAAU,gBAAA;CRssCT;AQrsCD;;EAAU,gBAAA;CRysCT;AQnsCD;EACE,iBAAA;CRqsCD;AQlsCD;EACE,oBAAA;EACA,gBAAA;EACA,iBAAA;EACA,iBAAA;CRosCD;AQ/rCD;EAwOA;IA1OI,gBAAA;GRqsCD;CACF;AQ7rCD;;EAEE,eAAA;CR+rCD;AQ5rCD;;EAEE,0BAAA;EACA,cAAA;CR8rCD;AQ1rCD;EAAuB,iBAAA;CR6rCtB;AQ5rCD;EAAuB,kBAAA;CR+rCtB;AQ9rCD;EAAuB,mBAAA;CRisCtB;AQhsCD;EAAuB,oBAAA;CRmsCtB;AQlsCD;EAAuB,oBAAA;CRqsCtB;AQlsCD;EAAuB,0BAAA;CRqsCtB;AQpsCD;EAAuB,0BAAA;CRusCtB;AQtsCD;EAAuB,2BAAA;CRysCtB;AQtsCD;EACE,eAAA;CRwsCD;AQtsCD;ECrGE,eAAA;CT8yCD;AS7yCC;;EAEE,eAAA;CT+yCH;AQ1sCD;ECxGE,eAAA;CTqzCD;ASpzCC;;EAEE,eAAA;CTszCH;AQ9sCD;EC3GE,eAAA;CT4zCD;AS3zCC;;EAEE,eAAA;CT6zCH;AQltCD;EC9GE,eAAA;CTm0CD;ASl0CC;;EAEE,eAAA;CTo0CH;AQttCD;ECjHE,eAAA;CT00CD;ASz0CC;;EAEE,eAAA;CT20CH;AQttCD;EAGE,YAAA;EE3HA,0BAAA;CVk1CD;AUj1CC;;EAEE,0BAAA;CVm1CH;AQxtCD;EE9HE,0BAAA;CVy1CD;AUx1CC;;EAEE,0BAAA;CV01CH;AQ5tCD;EEjIE,0BAAA;CVg2CD;AU/1CC;;EAEE,0BAAA;CVi2CH;AQhuCD;EEpIE,0BAAA;CVu2CD;AUt2CC;;EAEE,0BAAA;CVw2CH;AQpuCD;EEvIE,0BAAA;CV82CD;AU72CC;;EAEE,0BAAA;CV+2CH;AQnuCD;EACE,oBAAA;EACA,oBAAA;EACA,iCAAA;CRquCD;AQ7tCD;;EAEE,cAAA;EACA,oBAAA;CR+tCD;AQluCD;;;;EAMI,iBAAA;CRkuCH;AQ3tCD;EACE,gBAAA;EACA,iBAAA;CR6tCD;AQztCD;EALE,gBAAA;EACA,iBAAA;EAMA,kBAAA;CR4tCD;AQ9tCD;EAKI,sBAAA;EACA,kBAAA;EACA,mBAAA;CR4tCH;AQvtCD;EACE,cAAA;EACA,oBAAA;CRytCD;AQvtCD;;EAEE,wBAAA;CRytCD;AQvtCD;EACE,kBAAA;CRytCD;AQvtCD;EACE,eAAA;CRytCD;AQhsCD;EA6EA;IAvFM,YAAA;IACA,aAAA;IACA,YAAA;IACA,kBAAA;IGtNJ,iBAAA;IACA,wBAAA;IACA,oBAAA;GXq6CC;EQ7nCH;IAhFM,mBAAA;GRgtCH;CACF;AQvsCD;;EAGE,aAAA;EACA,kCAAA;CRwsCD;AQtsCD;EACE,eAAA;EA9IqB,0BAAA;CRu1CtB;AQpsCD;EACE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,+BAAA;CRssCD;AQjsCG;;;EACE,iBAAA;CRqsCL;AQ/sCD;;;EAmBI,eAAA;EACA,eAAA;EACA,wBAAA;EACA,eAAA;CRisCH;AQ/rCG;;;EACE,uBAAA;CRmsCL;AQ3rCD;;EAEE,oBAAA;EACA,gBAAA;EACA,gCAAA;EACA,eAAA;EACA,kBAAA;CR6rCD;AQvrCG;;;;;;EAAW,YAAA;CR+rCd;AQ9rCG;;;;;;EACE,uBAAA;CRqsCL;AQ/rCD;EACE,oBAAA;EACA,mBAAA;EACA,wBAAA;CRisCD;AYv+CD;;;;EAIE,+DAAA;CZy+CD;AYr+CD;EACE,iBAAA;EACA,eAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;CZu+CD;AYn+CD;EACE,iBAAA;EACA,eAAA;EACA,YAAA;EACA,uBAAA;EACA,mBAAA;EACA,uDAAA;UAAA,+CAAA;CZq+CD;AY3+CD;EASI,WAAA;EACA,gBAAA;EACA,kBAAA;EACA,yBAAA;UAAA,iBAAA;CZq+CH;AYh+CD;EACE,eAAA;EACA,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,sBAAA;EACA,sBAAA;EACA,eAAA;EACA,0BAAA;EACA,uBAAA;EACA,mBAAA;CZk+CD;AY7+CD;EAeI,WAAA;EACA,mBAAA;EACA,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,iBAAA;CZi+CH;AY59CD;EACE,kBAAA;EACA,mBAAA;CZ89CD;AaxhDD;ECHE,mBAAA;EACA,kBAAA;EACA,mBAAA;EACA,oBAAA;Cd8hDD;AaxhDC;EAqEF;IAvEI,aAAA;Gb8hDD;CACF;Aa1hDC;EAkEF;IApEI,aAAA;GbgiDD;CACF;Aa5hDD;EA+DA;IAjEI,cAAA;GbkiDD;CACF;AazhDD;ECvBE,mBAAA;EACA,kBAAA;EACA,mBAAA;EACA,oBAAA;CdmjDD;AathDD;ECvBE,mBAAA;EACA,oBAAA;CdgjDD;AehjDG;EACE,mBAAA;EAEA,gBAAA;EAEA,mBAAA;EACA,oBAAA;CfgjDL;AehiDG;EACE,YAAA;CfkiDL;Ae3hDC;EACE,YAAA;Cf6hDH;Ae9hDC;EACE,oBAAA;CfgiDH;AejiDC;EACE,oBAAA;CfmiDH;AepiDC;EACE,WAAA;CfsiDH;AeviDC;EACE,oBAAA;CfyiDH;Ae1iDC;EACE,oBAAA;Cf4iDH;Ae7iDC;EACE,WAAA;Cf+iDH;AehjDC;EACE,oBAAA;CfkjDH;AenjDC;EACE,oBAAA;CfqjDH;AetjDC;EACE,WAAA;CfwjDH;AezjDC;EACE,oBAAA;Cf2jDH;Ae5jDC;EACE,mBAAA;Cf8jDH;AehjDC;EACE,YAAA;CfkjDH;AenjDC;EACE,oBAAA;CfqjDH;AetjDC;EACE,oBAAA;CfwjDH;AezjDC;EACE,WAAA;Cf2jDH;Ae5jDC;EACE,oBAAA;Cf8jDH;Ae/jDC;EACE,oBAAA;CfikDH;AelkDC;EACE,WAAA;CfokDH;AerkDC;EACE,oBAAA;CfukDH;AexkDC;EACE,oBAAA;Cf0kDH;Ae3kDC;EACE,WAAA;Cf6kDH;Ae9kDC;EACE,oBAAA;CfglDH;AejlDC;EACE,mBAAA;CfmlDH;Ae/kDC;EACE,YAAA;CfilDH;AejmDC;EACE,WAAA;CfmmDH;AepmDC;EACE,mBAAA;CfsmDH;AevmDC;EACE,mBAAA;CfymDH;Ae1mDC;EACE,UAAA;Cf4mDH;Ae7mDC;EACE,mBAAA;Cf+mDH;AehnDC;EACE,mBAAA;CfknDH;AennDC;EACE,UAAA;CfqnDH;AetnDC;EACE,mBAAA;CfwnDH;AeznDC;EACE,mBAAA;Cf2nDH;Ae5nDC;EACE,UAAA;Cf8nDH;Ae/nDC;EACE,mBAAA;CfioDH;AeloDC;EACE,kBAAA;CfooDH;AehoDC;EACE,WAAA;CfkoDH;AepnDC;EACE,kBAAA;CfsnDH;AevnDC;EACE,0BAAA;CfynDH;Ae1nDC;EACE,0BAAA;Cf4nDH;Ae7nDC;EACE,iBAAA;Cf+nDH;AehoDC;EACE,0BAAA;CfkoDH;AenoDC;EACE,0BAAA;CfqoDH;AetoDC;EACE,iBAAA;CfwoDH;AezoDC;EACE,0BAAA;Cf2oDH;Ae5oDC;EACE,0BAAA;Cf8oDH;Ae/oDC;EACE,iBAAA;CfipDH;AelpDC;EACE,0BAAA;CfopDH;AerpDC;EACE,yBAAA;CfupDH;AexpDC;EACE,gBAAA;Cf0pDH;Aa1pDD;EElCI;IACE,YAAA;Gf+rDH;EexrDD;IACE,YAAA;Gf0rDD;Ee3rDD;IACE,oBAAA;Gf6rDD;Ee9rDD;IACE,oBAAA;GfgsDD;EejsDD;IACE,WAAA;GfmsDD;EepsDD;IACE,oBAAA;GfssDD;EevsDD;IACE,oBAAA;GfysDD;Ee1sDD;IACE,WAAA;Gf4sDD;Ee7sDD;IACE,oBAAA;Gf+sDD;EehtDD;IACE,oBAAA;GfktDD;EentDD;IACE,WAAA;GfqtDD;EettDD;IACE,oBAAA;GfwtDD;EeztDD;IACE,mBAAA;Gf2tDD;Ee7sDD;IACE,YAAA;Gf+sDD;EehtDD;IACE,oBAAA;GfktDD;EentDD;IACE,oBAAA;GfqtDD;EettDD;IACE,WAAA;GfwtDD;EeztDD;IACE,oBAAA;Gf2tDD;Ee5tDD;IACE,oBAAA;Gf8tDD;Ee/tDD;IACE,WAAA;GfiuDD;EeluDD;IACE,oBAAA;GfouDD;EeruDD;IACE,oBAAA;GfuuDD;EexuDD;IACE,WAAA;Gf0uDD;Ee3uDD;IACE,oBAAA;Gf6uDD;Ee9uDD;IACE,mBAAA;GfgvDD;Ee5uDD;IACE,YAAA;Gf8uDD;Ee9vDD;IACE,WAAA;GfgwDD;EejwDD;IACE,mBAAA;GfmwDD;EepwDD;IACE,mBAAA;GfswDD;EevwDD;IACE,UAAA;GfywDD;Ee1wDD;IACE,mBAAA;Gf4wDD;Ee7wDD;IACE,mBAAA;Gf+wDD;EehxDD;IACE,UAAA;GfkxDD;EenxDD;IACE,mBAAA;GfqxDD;EetxDD;IACE,mBAAA;GfwxDD;EezxDD;IACE,UAAA;Gf2xDD;Ee5xDD;IACE,mBAAA;Gf8xDD;Ee/xDD;IACE,kBAAA;GfiyDD;Ee7xDD;IACE,WAAA;Gf+xDD;EejxDD;IACE,kBAAA;GfmxDD;EepxDD;IACE,0BAAA;GfsxDD;EevxDD;IACE,0BAAA;GfyxDD;Ee1xDD;IACE,iBAAA;Gf4xDD;Ee7xDD;IACE,0BAAA;Gf+xDD;EehyDD;IACE,0BAAA;GfkyDD;EenyDD;IACE,iBAAA;GfqyDD;EetyDD;IACE,0BAAA;GfwyDD;EezyDD;IACE,0BAAA;Gf2yDD;Ee5yDD;IACE,iBAAA;Gf8yDD;Ee/yDD;IACE,0BAAA;GfizDD;EelzDD;IACE,yBAAA;GfozDD;EerzDD;IACE,gBAAA;GfuzDD;CACF;Aa/yDD;EE3CI;IACE,YAAA;Gf61DH;Eet1DD;IACE,YAAA;Gfw1DD;Eez1DD;IACE,oBAAA;Gf21DD;Ee51DD;IACE,oBAAA;Gf81DD;Ee/1DD;IACE,WAAA;Gfi2DD;Eel2DD;IACE,oBAAA;Gfo2DD;Eer2DD;IACE,oBAAA;Gfu2DD;Eex2DD;IACE,WAAA;Gf02DD;Ee32DD;IACE,oBAAA;Gf62DD;Ee92DD;IACE,oBAAA;Gfg3DD;Eej3DD;IACE,WAAA;Gfm3DD;Eep3DD;IACE,oBAAA;Gfs3DD;Eev3DD;IACE,mBAAA;Gfy3DD;Ee32DD;IACE,YAAA;Gf62DD;Ee92DD;IACE,oBAAA;Gfg3DD;Eej3DD;IACE,oBAAA;Gfm3DD;Eep3DD;IACE,WAAA;Gfs3DD;Eev3DD;IACE,oBAAA;Gfy3DD;Ee13DD;IACE,oBAAA;Gf43DD;Ee73DD;IACE,WAAA;Gf+3DD;Eeh4DD;IACE,oBAAA;Gfk4DD;Een4DD;IACE,oBAAA;Gfq4DD;Eet4DD;IACE,WAAA;Gfw4DD;Eez4DD;IACE,oBAAA;Gf24DD;Ee54DD;IACE,mBAAA;Gf84DD;Ee14DD;IACE,YAAA;Gf44DD;Ee55DD;IACE,WAAA;Gf85DD;Ee/5DD;IACE,mBAAA;Gfi6DD;Eel6DD;IACE,mBAAA;Gfo6DD;Eer6DD;IACE,UAAA;Gfu6DD;Eex6DD;IACE,mBAAA;Gf06DD;Ee36DD;IACE,mBAAA;Gf66DD;Ee96DD;IACE,UAAA;Gfg7DD;Eej7DD;IACE,mBAAA;Gfm7DD;Eep7DD;IACE,mBAAA;Gfs7DD;Eev7DD;IACE,UAAA;Gfy7DD;Ee17DD;IACE,mBAAA;Gf47DD;Ee77DD;IACE,kBAAA;Gf+7DD;Ee37DD;IACE,WAAA;Gf67DD;Ee/6DD;IACE,kBAAA;Gfi7DD;Eel7DD;IACE,0BAAA;Gfo7DD;Eer7DD;IACE,0BAAA;Gfu7DD;Eex7DD;IACE,iBAAA;Gf07DD;Ee37DD;IACE,0BAAA;Gf67DD;Ee97DD;IACE,0BAAA;Gfg8DD;Eej8DD;IACE,iBAAA;Gfm8DD;Eep8DD;IACE,0BAAA;Gfs8DD;Eev8DD;IACE,0BAAA;Gfy8DD;Ee18DD;IACE,iBAAA;Gf48DD;Ee78DD;IACE,0BAAA;Gf+8DD;Eeh9DD;IACE,yBAAA;Gfk9DD;Een9DD;IACE,gBAAA;Gfq9DD;CACF;Aa18DD;EE9CI;IACE,YAAA;Gf2/DH;Eep/DD;IACE,YAAA;Gfs/DD;Eev/DD;IACE,oBAAA;Gfy/DD;Ee1/DD;IACE,oBAAA;Gf4/DD;Ee7/DD;IACE,WAAA;Gf+/DD;EehgED;IACE,oBAAA;GfkgED;EengED;IACE,oBAAA;GfqgED;EetgED;IACE,WAAA;GfwgED;EezgED;IACE,oBAAA;Gf2gED;Ee5gED;IACE,oBAAA;Gf8gED;Ee/gED;IACE,WAAA;GfihED;EelhED;IACE,oBAAA;GfohED;EerhED;IACE,mBAAA;GfuhED;EezgED;IACE,YAAA;Gf2gED;Ee5gED;IACE,oBAAA;Gf8gED;Ee/gED;IACE,oBAAA;GfihED;EelhED;IACE,WAAA;GfohED;EerhED;IACE,oBAAA;GfuhED;EexhED;IACE,oBAAA;Gf0hED;Ee3hED;IACE,WAAA;Gf6hED;Ee9hED;IACE,oBAAA;GfgiED;EejiED;IACE,oBAAA;GfmiED;EepiED;IACE,WAAA;GfsiED;EeviED;IACE,oBAAA;GfyiED;Ee1iED;IACE,mBAAA;Gf4iED;EexiED;IACE,YAAA;Gf0iED;Ee1jED;IACE,WAAA;Gf4jED;Ee7jED;IACE,mBAAA;Gf+jED;EehkED;IACE,mBAAA;GfkkED;EenkED;IACE,UAAA;GfqkED;EetkED;IACE,mBAAA;GfwkED;EezkED;IACE,mBAAA;Gf2kED;Ee5kED;IACE,UAAA;Gf8kED;Ee/kED;IACE,mBAAA;GfilED;EellED;IACE,mBAAA;GfolED;EerlED;IACE,UAAA;GfulED;EexlED;IACE,mBAAA;Gf0lED;Ee3lED;IACE,kBAAA;Gf6lED;EezlED;IACE,WAAA;Gf2lED;Ee7kED;IACE,kBAAA;Gf+kED;EehlED;IACE,0BAAA;GfklED;EenlED;IACE,0BAAA;GfqlED;EetlED;IACE,iBAAA;GfwlED;EezlED;IACE,0BAAA;Gf2lED;Ee5lED;IACE,0BAAA;Gf8lED;Ee/lED;IACE,iBAAA;GfimED;EelmED;IACE,0BAAA;GfomED;EermED;IACE,0BAAA;GfumED;EexmED;IACE,iBAAA;Gf0mED;Ee3mED;IACE,0BAAA;Gf6mED;Ee9mED;IACE,yBAAA;GfgnED;EejnED;IACE,gBAAA;GfmnED;CACF;AgBvrED;EACE,8BAAA;ChByrED;AgBvrED;EACE,iBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;ChByrED;AgBvrED;EACE,iBAAA;ChByrED;AgBnrED;EACE,YAAA;EACA,gBAAA;EACA,oBAAA;ChBqrED;AgBxrED;;;;;;EAWQ,aAAA;EACA,wBAAA;EACA,oBAAA;EACA,2BAAA;ChBqrEP;AgBnsED;EAoBI,uBAAA;EACA,8BAAA;ChBkrEH;AgBvsED;;;;;;EA8BQ,cAAA;ChBirEP;AgB/sED;EAoCI,2BAAA;ChB8qEH;AgBltED;EAyCI,uBAAA;ChB4qEH;AgBrqED;;;;;;EAOQ,aAAA;ChBsqEP;AgB3pED;EACE,uBAAA;ChB6pED;AgB9pED;;;;;;EAQQ,uBAAA;ChB8pEP;AgBtqED;;EAeM,yBAAA;ChB2pEL;AgBjpED;EAEI,0BAAA;ChBkpEH;AgBzoED;EAEI,0BAAA;ChB0oEH;AgBjoED;EACE,iBAAA;EACA,YAAA;EACA,sBAAA;ChBmoED;AgB9nEG;;EACE,iBAAA;EACA,YAAA;EACA,oBAAA;ChBioEL;AiB7wEC;;;;;;;;;;;;EAOI,0BAAA;CjBoxEL;AiB9wEC;;;;;EAMI,0BAAA;CjB+wEL;AiBlyEC;;;;;;;;;;;;EAOI,0BAAA;CjByyEL;AiBnyEC;;;;;EAMI,0BAAA;CjBoyEL;AiBvzEC;;;;;;;;;;;;EAOI,0BAAA;CjB8zEL;AiBxzEC;;;;;EAMI,0BAAA;CjByzEL;AiB50EC;;;;;;;;;;;;EAOI,0BAAA;CjBm1EL;AiB70EC;;;;;EAMI,0BAAA;CjB80EL;AiBj2EC;;;;;;;;;;;;EAOI,0BAAA;CjBw2EL;AiBl2EC;;;;;EAMI,0BAAA;CjBm2EL;AgBjtED;EACE,iBAAA;EACA,kBAAA;ChBmtED;AgBtpED;EACA;IA3DI,YAAA;IACA,oBAAA;IACA,mBAAA;IACA,6CAAA;IACA,uBAAA;GhBotED;EgB7pEH;IAnDM,iBAAA;GhBmtEH;EgBhqEH;;;;;;IA1CY,oBAAA;GhBktET;EgBxqEH;IAlCM,UAAA;GhB6sEH;EgB3qEH;;;;;;IAzBY,eAAA;GhB4sET;EgBnrEH;;;;;;IArBY,gBAAA;GhBgtET;EgB3rEH;;;;IARY,iBAAA;GhBysET;CACF;AkBn6ED;EACE,WAAA;EACA,UAAA;EACA,UAAA;EAIA,aAAA;ClBk6ED;AkB/5ED;EACE,eAAA;EACA,YAAA;EACA,WAAA;EACA,oBAAA;EACA,gBAAA;EACA,qBAAA;EACA,eAAA;EACA,UAAA;EACA,iCAAA;ClBi6ED;AkB95ED;EACE,sBAAA;EACA,gBAAA;EACA,mBAAA;EACA,kBAAA;ClBg6ED;AkBr5ED;Eb4BE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL43ET;AkBr5ED;;EAEE,gBAAA;EACA,mBAAA;EACA,oBAAA;ClBu5ED;AkBp5ED;EACE,eAAA;ClBs5ED;AkBl5ED;EACE,eAAA;EACA,YAAA;ClBo5ED;AkBh5ED;;EAEE,aAAA;ClBk5ED;AkB94ED;;;EZrEE,2CAAA;EACA,qBAAA;CNw9ED;AkB74ED;EACE,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;ClB+4ED;AkBr3ED;EACE,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,uBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;EbxDA,yDAAA;EACQ,iDAAA;EAyHR,uFAAA;EACK,0EAAA;EACG,uEAAA;CLwzET;AmBh8EC;EACE,sBAAA;EACA,WAAA;EdUF,uFAAA;EACQ,+EAAA;CLy7ET;AKx5EC;EACE,YAAA;EACA,WAAA;CL05EH;AKx5EC;EAA0B,YAAA;CL25E3B;AK15EC;EAAgC,YAAA;CL65EjC;AkBj4EC;EACE,UAAA;EACA,8BAAA;ClBm4EH;AkB33EC;;;EAGE,0BAAA;EACA,WAAA;ClB63EH;AkB13EC;;EAEE,oBAAA;ClB43EH;AkBx3EC;EACE,aAAA;ClB03EH;AkB92ED;EACE,yBAAA;ClBg3ED;AkBx0ED;EAtBI;;;;IACE,kBAAA;GlBo2EH;EkBj2EC;;;;;;;;IAEE,kBAAA;GlBy2EH;EkBt2EC;;;;;;;;IAEE,kBAAA;GlB82EH;CACF;AkBp2ED;EACE,oBAAA;ClBs2ED;AkB91ED;;EAEE,mBAAA;EACA,eAAA;EACA,iBAAA;EACA,oBAAA;ClBg2ED;AkBr2ED;;EAQI,iBAAA;EACA,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,gBAAA;ClBi2EH;AkB91ED;;;;EAIE,mBAAA;EACA,mBAAA;EACA,mBAAA;ClBg2ED;AkB71ED;;EAEE,iBAAA;ClB+1ED;AkB31ED;;EAEE,mBAAA;EACA,sBAAA;EACA,mBAAA;EACA,iBAAA;EACA,uBAAA;EACA,oBAAA;EACA,gBAAA;ClB61ED;AkB31ED;;EAEE,cAAA;EACA,kBAAA;ClB61ED;AkBp1EC;;;;;;EAGE,oBAAA;ClBy1EH;AkBn1EC;;;;EAEE,oBAAA;ClBu1EH;AkBj1EC;;;;EAGI,oBAAA;ClBo1EL;AkBz0ED;EAEE,iBAAA;EACA,oBAAA;EAEA,iBAAA;EACA,iBAAA;ClBy0ED;AkBv0EC;;EAEE,gBAAA;EACA,iBAAA;ClBy0EH;AkB5zED;ECnQE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnBkkFD;AmBhkFC;EACE,aAAA;EACA,kBAAA;CnBkkFH;AmB/jFC;;EAEE,aAAA;CnBikFH;AkBx0ED;EAEI,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;ClBy0EH;AkB/0ED;EASI,aAAA;EACA,kBAAA;ClBy0EH;AkBn1ED;;EAcI,aAAA;ClBy0EH;AkBv1ED;EAiBI,aAAA;EACA,iBAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;ClBy0EH;AkBr0ED;EC/RE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnBumFD;AmBrmFC;EACE,aAAA;EACA,kBAAA;CnBumFH;AmBpmFC;;EAEE,aAAA;CnBsmFH;AkBj1ED;EAEI,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;ClBk1EH;AkBx1ED;EASI,aAAA;EACA,kBAAA;ClBk1EH;AkB51ED;;EAcI,aAAA;ClBk1EH;AkBh2ED;EAiBI,aAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;ClBk1EH;AkBz0ED;EAEE,mBAAA;ClB00ED;AkB50ED;EAMI,sBAAA;ClBy0EH;AkBr0ED;EACE,mBAAA;EACA,OAAA;EACA,SAAA;EACA,WAAA;EACA,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,mBAAA;EACA,qBAAA;ClBu0ED;AkBr0ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClBu0ED;AkBr0ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClBu0ED;AkBn0ED;;;;;;;;;;EC1ZI,eAAA;CnByuFH;AkB/0ED;ECtZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CL0rFT;AmBxuFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL+rFT;AkBz1ED;EC5YI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBwuFH;AkB91ED;ECtYI,eAAA;CnBuuFH;AkB91ED;;;;;;;;;;EC7ZI,eAAA;CnBuwFH;AkB12ED;ECzZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLwtFT;AmBtwFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL6tFT;AkBp3ED;EC/YI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBswFH;AkBz3ED;ECzYI,eAAA;CnBqwFH;AkBz3ED;;;;;;;;;;EChaI,eAAA;CnBqyFH;AkBr4ED;EC5ZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLsvFT;AmBpyFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL2vFT;AkB/4ED;EClZI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBoyFH;AkBp5ED;EC5YI,eAAA;CnBmyFH;AkBh5EC;EACE,UAAA;ClBk5EH;AkBh5EC;EACE,OAAA;ClBk5EH;AkBx4ED;EACE,eAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;ClB04ED;AkBvzED;EAwEA;IAtIM,sBAAA;IACA,iBAAA;IACA,uBAAA;GlBy3EH;EkBrvEH;IA/HM,sBAAA;IACA,YAAA;IACA,uBAAA;GlBu3EH;EkB1vEH;IAxHM,sBAAA;GlBq3EH;EkB7vEH;IApHM,sBAAA;IACA,uBAAA;GlBo3EH;EkBjwEH;;;IA9GQ,YAAA;GlBo3EL;EkBtwEH;IAxGM,YAAA;GlBi3EH;EkBzwEH;IApGM,iBAAA;IACA,uBAAA;GlBg3EH;EkB7wEH;;IA5FM,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlB62EH;EkBpxEH;;IAtFQ,gBAAA;GlB82EL;EkBxxEH;;IAjFM,mBAAA;IACA,eAAA;GlB62EH;EkB7xEH;IA3EM,OAAA;GlB22EH;CACF;AkBj2ED;;;;EASI,cAAA;EACA,iBAAA;EACA,iBAAA;ClB81EH;AkBz2ED;;EAiBI,iBAAA;ClB41EH;AkB72ED;EJthBE,mBAAA;EACA,oBAAA;Cds4FD;AkB10EC;EAyBF;IAnCM,kBAAA;IACA,iBAAA;IACA,iBAAA;GlBw1EH;CACF;AkBx3ED;EAwCI,YAAA;ClBm1EH;AkBr0EC;EAUF;IAdQ,kBAAA;IACA,gBAAA;GlB60EL;CACF;AkBn0EC;EAEF;IANQ,iBAAA;IACA,gBAAA;GlB20EL;CACF;AoBp6FD;EACE,sBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;EACA,uBAAA;EACA,+BAAA;MAAA,2BAAA;EACA,gBAAA;EACA,uBAAA;EACA,8BAAA;EACA,oBAAA;EC0CA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,mBAAA;EhB+JA,0BAAA;EACG,uBAAA;EACC,sBAAA;EACI,kBAAA;CL+tFT;AoBv6FG;;;;;;EdnBF,2CAAA;EACA,qBAAA;CNk8FD;AoB16FC;;;EAGE,YAAA;EACA,sBAAA;CpB46FH;AoBz6FC;;EAEE,WAAA;EACA,uBAAA;Ef2BF,yDAAA;EACQ,iDAAA;CLi5FT;AoBz6FC;;;EAGE,oBAAA;EE7CF,cAAA;EAGA,0BAAA;EjB8DA,yBAAA;EACQ,iBAAA;CL05FT;AoBz6FG;;EAEE,qBAAA;CpB26FL;AoBl6FD;EC3DE,YAAA;EACA,uBAAA;EACA,mBAAA;CrBg+FD;AqB99FC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBg+FP;AqB99FC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBg+FP;AqB99FC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBg+FP;AqB99FG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBs+FT;AqBn+FC;;;EAGE,uBAAA;CrBq+FH;AqBh+FG;;;;;;;;;EAGE,uBAAA;EACI,mBAAA;CrBw+FT;AoBv9FD;ECZI,YAAA;EACA,uBAAA;CrBs+FH;AoBx9FD;EC9DE,YAAA;EACA,0BAAA;EACA,sBAAA;CrByhGD;AqBvhGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrByhGP;AqBvhGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrByhGP;AqBvhGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrByhGP;AqBvhGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB+hGT;AqB5hGC;;;EAGE,uBAAA;CrB8hGH;AqBzhGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrBiiGT;AoB7gGD;ECfI,eAAA;EACA,uBAAA;CrB+hGH;AoB7gGD;EClEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBklGD;AqBhlGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBklGP;AqBhlGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBklGP;AqBhlGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBklGP;AqBhlGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBwlGT;AqBrlGC;;;EAGE,uBAAA;CrBulGH;AqBllGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrB0lGT;AoBlkGD;ECnBI,eAAA;EACA,uBAAA;CrBwlGH;AoBlkGD;ECtEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB2oGD;AqBzoGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB2oGP;AqBzoGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB2oGP;AqBzoGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB2oGP;AqBzoGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBipGT;AqB9oGC;;;EAGE,uBAAA;CrBgpGH;AqB3oGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrBmpGT;AoBvnGD;ECvBI,eAAA;EACA,uBAAA;CrBipGH;AoBvnGD;EC1EE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBosGD;AqBlsGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBosGP;AqBlsGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBosGP;AqBlsGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBosGP;AqBlsGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB0sGT;AqBvsGC;;;EAGE,uBAAA;CrBysGH;AqBpsGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrB4sGT;AoB5qGD;EC3BI,eAAA;EACA,uBAAA;CrB0sGH;AoB5qGD;EC9EE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB6vGD;AqB3vGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB6vGP;AqB3vGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB6vGP;AqB3vGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB6vGP;AqB3vGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBmwGT;AqBhwGC;;;EAGE,uBAAA;CrBkwGH;AqB7vGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrBqwGT;AoBjuGD;EC/BI,eAAA;EACA,uBAAA;CrBmwGH;AoB5tGD;EACE,eAAA;EACA,oBAAA;EACA,iBAAA;CpB8tGD;AoB5tGC;;;;;EAKE,8BAAA;EfnCF,yBAAA;EACQ,iBAAA;CLkwGT;AoB7tGC;;;;EAIE,0BAAA;CpB+tGH;AoB7tGC;;EAEE,eAAA;EACA,2BAAA;EACA,8BAAA;CpB+tGH;AoB3tGG;;;;EAEE,eAAA;EACA,sBAAA;CpB+tGL;AoBttGD;;ECxEE,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CrBkyGD;AoBztGD;;EC5EE,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrByyGD;AoB5tGD;;EChFE,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrBgzGD;AoB3tGD;EACE,eAAA;EACA,YAAA;CpB6tGD;AoBztGD;EACE,gBAAA;CpB2tGD;AoBptGC;;;EACE,YAAA;CpBwtGH;AuBl3GD;EACE,WAAA;ElBoLA,yCAAA;EACK,oCAAA;EACG,iCAAA;CLisGT;AuBr3GC;EACE,WAAA;CvBu3GH;AuBn3GD;EACE,cAAA;CvBq3GD;AuBn3GC;EAAY,eAAA;CvBs3Gb;AuBr3GC;EAAY,mBAAA;CvBw3Gb;AuBv3GC;EAAY,yBAAA;CvB03Gb;AuBv3GD;EACE,mBAAA;EACA,UAAA;EACA,iBAAA;ElBuKA,gDAAA;EACQ,2CAAA;KAAA,wCAAA;EAOR,mCAAA;EACQ,8BAAA;KAAA,2BAAA;EAGR,yCAAA;EACQ,oCAAA;KAAA,iCAAA;CL2sGT;AwBr5GD;EACE,sBAAA;EACA,SAAA;EACA,UAAA;EACA,iBAAA;EACA,uBAAA;EACA,uBAAA;EACA,yBAAA;EACA,oCAAA;EACA,mCAAA;CxBu5GD;AwBn5GD;;EAEE,mBAAA;CxBq5GD;AwBj5GD;EACE,WAAA;CxBm5GD;AwB/4GD;EACE,mBAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,YAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,uBAAA;EACA,uBAAA;EACA,sCAAA;EACA,mBAAA;EnBsBA,oDAAA;EACQ,4CAAA;EmBrBR,qCAAA;UAAA,6BAAA;CxBk5GD;AwB74GC;EACE,SAAA;EACA,WAAA;CxB+4GH;AwBx6GD;ECzBE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzBo8GD;AwB96GD;EAmCI,eAAA;EACA,kBAAA;EACA,YAAA;EACA,oBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxB84GH;AwBx4GC;;EAEE,sBAAA;EACA,eAAA;EACA,0BAAA;CxB04GH;AwBp4GC;;;EAGE,YAAA;EACA,sBAAA;EACA,WAAA;EACA,0BAAA;CxBs4GH;AwB73GC;;;EAGE,eAAA;CxB+3GH;AwB33GC;;EAEE,sBAAA;EACA,8BAAA;EACA,uBAAA;EE3GF,oEAAA;EF6GE,oBAAA;CxB63GH;AwBx3GD;EAGI,eAAA;CxBw3GH;AwB33GD;EAQI,WAAA;CxBs3GH;AwB92GD;EACE,WAAA;EACA,SAAA;CxBg3GD;AwBx2GD;EACE,QAAA;EACA,YAAA;CxB02GD;AwBt2GD;EACE,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxBw2GD;AwBp2GD;EACE,gBAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;EACA,OAAA;EACA,aAAA;CxBs2GD;AwBl2GD;EACE,SAAA;EACA,WAAA;CxBo2GD;AwB51GD;;EAII,cAAA;EACA,0BAAA;EACA,4BAAA;EACA,YAAA;CxB41GH;AwBn2GD;;EAWI,UAAA;EACA,aAAA;EACA,mBAAA;CxB41GH;AwBv0GD;EAXE;IApEA,WAAA;IACA,SAAA;GxB05GC;EwBv1GD;IA1DA,QAAA;IACA,YAAA;GxBo5GC;CACF;A2BpiHD;;EAEE,mBAAA;EACA,sBAAA;EACA,uBAAA;C3BsiHD;A2B1iHD;;EAMI,mBAAA;EACA,YAAA;C3BwiHH;A2BtiHG;;;;;;;;EAIE,WAAA;C3B4iHL;A2BtiHD;;;;EAKI,kBAAA;C3BuiHH;A2BliHD;EACE,kBAAA;C3BoiHD;A2BriHD;;;EAOI,YAAA;C3BmiHH;A2B1iHD;;;EAYI,iBAAA;C3BmiHH;A2B/hHD;EACE,iBAAA;C3BiiHD;A2B7hHD;EACE,eAAA;C3B+hHD;A2B9hHC;EClDA,8BAAA;EACG,2BAAA;C5BmlHJ;A2B7hHD;;EC/CE,6BAAA;EACG,0BAAA;C5BglHJ;A2B5hHD;EACE,YAAA;C3B8hHD;A2B5hHD;EACE,iBAAA;C3B8hHD;A2B5hHD;;ECnEE,8BAAA;EACG,2BAAA;C5BmmHJ;A2B3hHD;ECjEE,6BAAA;EACG,0BAAA;C5B+lHJ;A2B1hHD;;EAEE,WAAA;C3B4hHD;A2B3gHD;EACE,kBAAA;EACA,mBAAA;C3B6gHD;A2B3gHD;EACE,mBAAA;EACA,oBAAA;C3B6gHD;A2BxgHD;EtB/CE,yDAAA;EACQ,iDAAA;CL0jHT;A2BxgHC;EtBnDA,yBAAA;EACQ,iBAAA;CL8jHT;A2BrgHD;EACE,eAAA;C3BugHD;A2BpgHD;EACE,wBAAA;EACA,uBAAA;C3BsgHD;A2BngHD;EACE,wBAAA;C3BqgHD;A2B9/GD;;;EAII,eAAA;EACA,YAAA;EACA,YAAA;EACA,gBAAA;C3B+/GH;A2BtgHD;EAcM,YAAA;C3B2/GL;A2BzgHD;;;;EAsBI,iBAAA;EACA,eAAA;C3By/GH;A2Bp/GC;EACE,iBAAA;C3Bs/GH;A2Bp/GC;EC3KA,6BAAA;EACC,4BAAA;EAOD,8BAAA;EACC,6BAAA;C5B4pHF;A2Bt/GC;EC/KA,2BAAA;EACC,0BAAA;EAOD,gCAAA;EACC,+BAAA;C5BkqHF;A2Bv/GD;EACE,iBAAA;C3By/GD;A2Bv/GD;;EC/KE,8BAAA;EACC,6BAAA;C5B0qHF;A2Bt/GD;EC7LE,2BAAA;EACC,0BAAA;C5BsrHF;A2Bl/GD;EACE,eAAA;EACA,YAAA;EACA,oBAAA;EACA,0BAAA;C3Bo/GD;A2Bx/GD;;EAOI,YAAA;EACA,oBAAA;EACA,UAAA;C3Bq/GH;A2B9/GD;EAYI,YAAA;C3Bq/GH;A2BjgHD;EAgBI,WAAA;C3Bo/GH;A2Bn+GD;;;;EAKM,mBAAA;EACA,uBAAA;EACA,qBAAA;C3Bo+GL;A6B9sHD;EACE,mBAAA;EACA,eAAA;EACA,0BAAA;C7BgtHD;A6B7sHC;EACE,YAAA;EACA,gBAAA;EACA,iBAAA;C7B+sHH;A6BxtHD;EAeI,mBAAA;EACA,WAAA;EAKA,YAAA;EAEA,YAAA;EACA,iBAAA;C7BusHH;A6BrsHG;EACE,WAAA;C7BusHL;A6B7rHD;;;EV0BE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnBwqHD;AmBtqHC;;;EACE,aAAA;EACA,kBAAA;CnB0qHH;AmBvqHC;;;;;;EAEE,aAAA;CnB6qHH;A6B/sHD;;;EVqBE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnB+rHD;AmB7rHC;;;EACE,aAAA;EACA,kBAAA;CnBisHH;AmB9rHC;;;;;;EAEE,aAAA;CnBosHH;A6B7tHD;;;EAGE,oBAAA;C7B+tHD;A6B7tHC;;;EACE,iBAAA;C7BiuHH;A6B7tHD;;EAEE,UAAA;EACA,oBAAA;EACA,uBAAA;C7B+tHD;A6B1tHD;EACE,kBAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;EACA,eAAA;EACA,mBAAA;EACA,0BAAA;EACA,uBAAA;EACA,mBAAA;C7B4tHD;A6BztHC;EACE,kBAAA;EACA,gBAAA;EACA,mBAAA;C7B2tHH;A6BztHC;EACE,mBAAA;EACA,gBAAA;EACA,mBAAA;C7B2tHH;A6B/uHD;;EA0BI,cAAA;C7BytHH;A6BptHD;;;;;;;EDpGE,8BAAA;EACG,2BAAA;C5Bi0HJ;A6BrtHD;EACE,gBAAA;C7ButHD;A6BrtHD;;;;;;;EDxGE,6BAAA;EACG,0BAAA;C5Bs0HJ;A6BttHD;EACE,eAAA;C7BwtHD;A6BntHD;EACE,mBAAA;EAGA,aAAA;EACA,oBAAA;C7BmtHD;A6BxtHD;EAUI,mBAAA;C7BitHH;A6B3tHD;EAYM,kBAAA;C7BktHL;A6B/sHG;;;EAGE,WAAA;C7BitHL;A6B5sHC;;EAGI,mBAAA;C7B6sHL;A6B1sHC;;EAGI,WAAA;EACA,kBAAA;C7B2sHL;A8B12HD;EACE,iBAAA;EACA,gBAAA;EACA,iBAAA;C9B42HD;A8B/2HD;EAOI,mBAAA;EACA,eAAA;C9B22HH;A8Bn3HD;EAWM,mBAAA;EACA,eAAA;EACA,mBAAA;C9B22HL;A8B12HK;;EAEE,sBAAA;EACA,0BAAA;C9B42HP;A8Bv2HG;EACE,eAAA;C9By2HL;A8Bv2HK;;EAEE,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,oBAAA;C9By2HP;A8Bl2HG;;;EAGE,0BAAA;EACA,sBAAA;C9Bo2HL;A8B74HD;ELHE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzBm5HD;A8Bn5HD;EA0DI,gBAAA;C9B41HH;A8Bn1HD;EACE,8BAAA;C9Bq1HD;A8Bt1HD;EAGI,YAAA;EAEA,oBAAA;C9Bq1HH;A8B11HD;EASM,kBAAA;EACA,wBAAA;EACA,8BAAA;EACA,2BAAA;C9Bo1HL;A8Bn1HK;EACE,mCAAA;C9Bq1HP;A8B/0HK;;;EAGE,eAAA;EACA,uBAAA;EACA,uBAAA;EACA,iCAAA;EACA,gBAAA;C9Bi1HP;A8B50HC;EAqDA,YAAA;EA8BA,iBAAA;C9B6vHD;A8Bh1HC;EAwDE,YAAA;C9B2xHH;A8Bn1HC;EA0DI,mBAAA;EACA,mBAAA;C9B4xHL;A8Bv1HC;EAgEE,UAAA;EACA,WAAA;C9B0xHH;A8B9wHD;EA0DA;IAjEM,oBAAA;IACA,UAAA;G9ByxHH;E8BztHH;IA9DQ,iBAAA;G9B0xHL;CACF;A8Bp2HC;EAuFE,gBAAA;EACA,mBAAA;C9BgxHH;A8Bx2HC;;;EA8FE,uBAAA;C9B+wHH;A8BjwHD;EA2BA;IApCM,8BAAA;IACA,2BAAA;G9B8wHH;E8B3uHH;;;IA9BM,0BAAA;G9B8wHH;CACF;A8B/2HD;EAEI,YAAA;C9Bg3HH;A8Bl3HD;EAMM,mBAAA;C9B+2HL;A8Br3HD;EASM,iBAAA;C9B+2HL;A8B12HK;;;EAGE,YAAA;EACA,0BAAA;C9B42HP;A8Bp2HD;EAEI,YAAA;C9Bq2HH;A8Bv2HD;EAIM,gBAAA;EACA,eAAA;C9Bs2HL;A8B11HD;EACE,YAAA;C9B41HD;A8B71HD;EAII,YAAA;C9B41HH;A8Bh2HD;EAMM,mBAAA;EACA,mBAAA;C9B61HL;A8Bp2HD;EAYI,UAAA;EACA,WAAA;C9B21HH;A8B/0HD;EA0DA;IAjEM,oBAAA;IACA,UAAA;G9B01HH;E8B1xHH;IA9DQ,iBAAA;G9B21HL;CACF;A8Bn1HD;EACE,iBAAA;C9Bq1HD;A8Bt1HD;EAKI,gBAAA;EACA,mBAAA;C9Bo1HH;A8B11HD;;;EAYI,uBAAA;C9Bm1HH;A8Br0HD;EA2BA;IApCM,8BAAA;IACA,2BAAA;G9Bk1HH;E8B/yHH;;;IA9BM,0BAAA;G9Bk1HH;CACF;A8Bz0HD;EAEI,cAAA;C9B00HH;A8B50HD;EAKI,eAAA;C9B00HH;A8Bj0HD;EAEE,iBAAA;EF3OA,2BAAA;EACC,0BAAA;C5B8iIF;A+BxiID;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,8BAAA;C/B0iID;A+BliID;EA8nBA;IAhoBI,mBAAA;G/BwiID;CACF;A+BzhID;EAgnBA;IAlnBI,YAAA;G/B+hID;CACF;A+BjhID;EACE,oBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,2DAAA;UAAA,mDAAA;EAEA,kCAAA;C/BkhID;A+BhhIC;EACE,iBAAA;C/BkhIH;A+Bt/HD;EA6jBA;IArlBI,YAAA;IACA,cAAA;IACA,yBAAA;YAAA,iBAAA;G/BkhID;E+BhhIC;IACE,0BAAA;IACA,wBAAA;IACA,kBAAA;IACA,6BAAA;G/BkhIH;E+B/gIC;IACE,oBAAA;G/BihIH;E+B5gIC;;;IAGE,gBAAA;IACA,iBAAA;G/B8gIH;CACF;A+B1gID;;EAGI,kBAAA;C/B2gIH;A+BtgIC;EAmjBF;;IArjBM,kBAAA;G/B6gIH;CACF;A+BpgID;;;;EAII,oBAAA;EACA,mBAAA;C/BsgIH;A+BhgIC;EAgiBF;;;;IAniBM,gBAAA;IACA,eAAA;G/B0gIH;CACF;A+B9/HD;EACE,cAAA;EACA,sBAAA;C/BggID;A+B3/HD;EA8gBA;IAhhBI,iBAAA;G/BigID;CACF;A+B7/HD;;EAEE,gBAAA;EACA,SAAA;EACA,QAAA;EACA,cAAA;C/B+/HD;A+Bz/HD;EAggBA;;IAlgBI,iBAAA;G/BggID;CACF;A+B9/HD;EACE,OAAA;EACA,sBAAA;C/BggID;A+B9/HD;EACE,UAAA;EACA,iBAAA;EACA,sBAAA;C/BggID;A+B1/HD;EACE,YAAA;EACA,mBAAA;EACA,gBAAA;EACA,kBAAA;EACA,aAAA;C/B4/HD;A+B1/HC;;EAEE,sBAAA;C/B4/HH;A+BrgID;EAaI,eAAA;C/B2/HH;A+Bl/HD;EALI;;IAEE,mBAAA;G/B0/HH;CACF;A+Bh/HD;EACE,mBAAA;EACA,aAAA;EACA,mBAAA;EACA,kBAAA;EC9LA,gBAAA;EACA,mBAAA;ED+LA,8BAAA;EACA,uBAAA;EACA,8BAAA;EACA,mBAAA;C/Bm/HD;A+B/+HC;EACE,WAAA;C/Bi/HH;A+B//HD;EAmBI,eAAA;EACA,YAAA;EACA,YAAA;EACA,mBAAA;C/B++HH;A+BrgID;EAyBI,gBAAA;C/B++HH;A+Bz+HD;EAqbA;IAvbI,cAAA;G/B++HD;CACF;A+Bt+HD;EACE,oBAAA;C/Bw+HD;A+Bz+HD;EAII,kBAAA;EACA,qBAAA;EACA,kBAAA;C/Bw+HH;A+B58HC;EA2YF;IAjaM,iBAAA;IACA,YAAA;IACA,YAAA;IACA,cAAA;IACA,8BAAA;IACA,UAAA;IACA,yBAAA;YAAA,iBAAA;G/Bs+HH;E+B3kHH;;IAxZQ,2BAAA;G/Bu+HL;E+B/kHH;IArZQ,kBAAA;G/Bu+HL;E+Bt+HK;;IAEE,uBAAA;G/Bw+HP;CACF;A+Bt9HD;EA+XA;IA1YI,YAAA;IACA,UAAA;G/Bq+HD;E+B5lHH;IAtYM,YAAA;G/Bq+HH;E+B/lHH;IApYQ,kBAAA;IACA,qBAAA;G/Bs+HL;CACF;A+B39HD;EACE,mBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,qCAAA;E1B9NA,6FAAA;EACQ,qFAAA;E2B/DR,gBAAA;EACA,mBAAA;ChC4vID;AkBtuHD;EAwEA;IAtIM,sBAAA;IACA,iBAAA;IACA,uBAAA;GlBwyHH;EkBpqHH;IA/HM,sBAAA;IACA,YAAA;IACA,uBAAA;GlBsyHH;EkBzqHH;IAxHM,sBAAA;GlBoyHH;EkB5qHH;IApHM,sBAAA;IACA,uBAAA;GlBmyHH;EkBhrHH;;;IA9GQ,YAAA;GlBmyHL;EkBrrHH;IAxGM,YAAA;GlBgyHH;EkBxrHH;IApGM,iBAAA;IACA,uBAAA;GlB+xHH;EkB5rHH;;IA5FM,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlB4xHH;EkBnsHH;;IAtFQ,gBAAA;GlB6xHL;EkBvsHH;;IAjFM,mBAAA;IACA,eAAA;GlB4xHH;EkB5sHH;IA3EM,OAAA;GlB0xHH;CACF;A+BpgIC;EAmWF;IAzWM,mBAAA;G/B8gIH;E+B5gIG;IACE,iBAAA;G/B8gIL;CACF;A+B7/HD;EAoVA;IA5VI,YAAA;IACA,UAAA;IACA,eAAA;IACA,gBAAA;IACA,eAAA;IACA,kBAAA;I1BzPF,yBAAA;IACQ,iBAAA;GLmwIP;CACF;A+BngID;EACE,cAAA;EHpUA,2BAAA;EACC,0BAAA;C5B00IF;A+BngID;EACE,iBAAA;EHzUA,6BAAA;EACC,4BAAA;EAOD,8BAAA;EACC,6BAAA;C5By0IF;A+B//HD;EChVE,gBAAA;EACA,mBAAA;ChCk1ID;A+BhgIC;ECnVA,iBAAA;EACA,oBAAA;ChCs1ID;A+BjgIC;ECtVA,iBAAA;EACA,oBAAA;ChC01ID;A+B3/HD;EChWE,iBAAA;EACA,oBAAA;ChC81ID;A+Bv/HD;EAsSA;IA1SI,YAAA;IACA,kBAAA;IACA,mBAAA;G/B+/HD;CACF;A+Bl+HD;EAhBE;IExWA,uBAAA;GjC81IC;E+Br/HD;IE5WA,wBAAA;IF8WE,oBAAA;G/Bu/HD;E+Bz/HD;IAKI,gBAAA;G/Bu/HH;CACF;A+B9+HD;EACE,0BAAA;EACA,sBAAA;C/Bg/HD;A+Bl/HD;EAKI,YAAA;C/Bg/HH;A+B/+HG;;EAEE,eAAA;EACA,8BAAA;C/Bi/HL;A+B1/HD;EAcI,YAAA;C/B++HH;A+B7/HD;EAmBM,YAAA;C/B6+HL;A+B3+HK;;EAEE,YAAA;EACA,8BAAA;C/B6+HP;A+Bz+HK;;;EAGE,YAAA;EACA,0BAAA;C/B2+HP;A+Bv+HK;;;EAGE,YAAA;EACA,8BAAA;C/By+HP;A+BjhID;EA8CI,mBAAA;C/Bs+HH;A+Br+HG;;EAEE,uBAAA;C/Bu+HL;A+BxhID;EAoDM,uBAAA;C/Bu+HL;A+B3hID;;EA0DI,sBAAA;C/Bq+HH;A+B99HK;;;EAGE,0BAAA;EACA,YAAA;C/Bg+HP;A+B/7HC;EAoKF;IA7LU,YAAA;G/B49HP;E+B39HO;;IAEE,YAAA;IACA,8BAAA;G/B69HT;E+Bz9HO;;;IAGE,YAAA;IACA,0BAAA;G/B29HT;E+Bv9HO;;;IAGE,YAAA;IACA,8BAAA;G/By9HT;CACF;A+B3jID;EA8GI,YAAA;C/Bg9HH;A+B/8HG;EACE,YAAA;C/Bi9HL;A+BjkID;EAqHI,YAAA;C/B+8HH;A+B98HG;;EAEE,YAAA;C/Bg9HL;A+B58HK;;;;EAEE,YAAA;C/Bg9HP;A+Bx8HD;EACE,uBAAA;EACA,sBAAA;C/B08HD;A+B58HD;EAKI,eAAA;C/B08HH;A+Bz8HG;;EAEE,YAAA;EACA,8BAAA;C/B28HL;A+Bp9HD;EAcI,eAAA;C/By8HH;A+Bv9HD;EAmBM,eAAA;C/Bu8HL;A+Br8HK;;EAEE,YAAA;EACA,8BAAA;C/Bu8HP;A+Bn8HK;;;EAGE,YAAA;EACA,0BAAA;C/Bq8HP;A+Bj8HK;;;EAGE,YAAA;EACA,8BAAA;C/Bm8HP;A+B3+HD;EA+CI,mBAAA;C/B+7HH;A+B97HG;;EAEE,uBAAA;C/Bg8HL;A+Bl/HD;EAqDM,uBAAA;C/Bg8HL;A+Br/HD;;EA2DI,sBAAA;C/B87HH;A+Bx7HK;;;EAGE,0BAAA;EACA,YAAA;C/B07HP;A+Bn5HC;EAwBF;IAvDU,sBAAA;G/Bs7HP;E+B/3HH;IApDU,0BAAA;G/Bs7HP;E+Bl4HH;IAjDU,eAAA;G/Bs7HP;E+Br7HO;;IAEE,YAAA;IACA,8BAAA;G/Bu7HT;E+Bn7HO;;;IAGE,YAAA;IACA,0BAAA;G/Bq7HT;E+Bj7HO;;;IAGE,YAAA;IACA,8BAAA;G/Bm7HT;CACF;A+B3hID;EA+GI,eAAA;C/B+6HH;A+B96HG;EACE,YAAA;C/Bg7HL;A+BjiID;EAsHI,eAAA;C/B86HH;A+B76HG;;EAEE,YAAA;C/B+6HL;A+B36HK;;;;EAEE,YAAA;C/B+6HP;AkCzjJD;EACE,kBAAA;EACA,oBAAA;EACA,iBAAA;EACA,0BAAA;EACA,mBAAA;ClC2jJD;AkChkJD;EAQI,sBAAA;ClC2jJH;AkCnkJD;EAWM,kBAAA;EACA,eAAA;EACA,YAAA;ClC2jJL;AkCxkJD;EAkBI,eAAA;ClCyjJH;AmC7kJD;EACE,sBAAA;EACA,gBAAA;EACA,eAAA;EACA,mBAAA;CnC+kJD;AmCnlJD;EAOI,gBAAA;CnC+kJH;AmCtlJD;;EAUM,mBAAA;EACA,YAAA;EACA,kBAAA;EACA,wBAAA;EACA,sBAAA;EACA,eAAA;EACA,uBAAA;EACA,uBAAA;EACA,kBAAA;CnCglJL;AmC9kJG;;EAGI,eAAA;EPXN,+BAAA;EACG,4BAAA;C5B2lJJ;AmC7kJG;;EPvBF,gCAAA;EACG,6BAAA;C5BwmJJ;AmCxkJG;;;;EAEE,WAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;CnC4kJL;AmCtkJG;;;;;;EAGE,WAAA;EACA,YAAA;EACA,0BAAA;EACA,sBAAA;EACA,gBAAA;CnC2kJL;AmCloJD;;;;;;EAkEM,eAAA;EACA,uBAAA;EACA,mBAAA;EACA,oBAAA;CnCwkJL;AmC/jJD;;EC3EM,mBAAA;EACA,gBAAA;EACA,uBAAA;CpC8oJL;AoC5oJG;;ERKF,+BAAA;EACG,4BAAA;C5B2oJJ;AoC3oJG;;ERTF,gCAAA;EACG,6BAAA;C5BwpJJ;AmC1kJD;;EChFM,kBAAA;EACA,gBAAA;EACA,iBAAA;CpC8pJL;AoC5pJG;;ERKF,+BAAA;EACG,4BAAA;C5B2pJJ;AoC3pJG;;ERTF,gCAAA;EACG,6BAAA;C5BwqJJ;AqC3qJD;EACE,gBAAA;EACA,eAAA;EACA,iBAAA;EACA,mBAAA;CrC6qJD;AqCjrJD;EAOI,gBAAA;CrC6qJH;AqCprJD;;EAUM,sBAAA;EACA,kBAAA;EACA,uBAAA;EACA,uBAAA;EACA,oBAAA;CrC8qJL;AqC5rJD;;EAmBM,sBAAA;EACA,0BAAA;CrC6qJL;AqCjsJD;;EA2BM,aAAA;CrC0qJL;AqCrsJD;;EAkCM,YAAA;CrCuqJL;AqCzsJD;;;;EA2CM,eAAA;EACA,uBAAA;EACA,oBAAA;CrCoqJL;AsCltJD;EACE,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,kBAAA;EACA,eAAA;EACA,YAAA;EACA,mBAAA;EACA,oBAAA;EACA,yBAAA;EACA,qBAAA;CtCotJD;AsChtJG;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;CtCktJL;AsC7sJC;EACE,cAAA;CtC+sJH;AsC3sJC;EACE,mBAAA;EACA,UAAA;CtC6sJH;AsCtsJD;ECtCE,0BAAA;CvC+uJD;AuC5uJG;;EAEE,0BAAA;CvC8uJL;AsCzsJD;EC1CE,0BAAA;CvCsvJD;AuCnvJG;;EAEE,0BAAA;CvCqvJL;AsC5sJD;EC9CE,0BAAA;CvC6vJD;AuC1vJG;;EAEE,0BAAA;CvC4vJL;AsC/sJD;EClDE,0BAAA;CvCowJD;AuCjwJG;;EAEE,0BAAA;CvCmwJL;AsCltJD;ECtDE,0BAAA;CvC2wJD;AuCxwJG;;EAEE,0BAAA;CvC0wJL;AsCrtJD;EC1DE,0BAAA;CvCkxJD;AuC/wJG;;EAEE,0BAAA;CvCixJL;AwCnxJD;EACE,sBAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,YAAA;EACA,eAAA;EACA,uBAAA;EACA,oBAAA;EACA,mBAAA;EACA,0BAAA;EACA,oBAAA;CxCqxJD;AwClxJC;EACE,cAAA;CxCoxJH;AwChxJC;EACE,mBAAA;EACA,UAAA;CxCkxJH;AwC/wJC;;EAEE,OAAA;EACA,iBAAA;CxCixJH;AwC5wJG;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;CxC8wJL;AwCzwJC;;EAEE,eAAA;EACA,uBAAA;CxC2wJH;AwCxwJC;EACE,aAAA;CxC0wJH;AwCvwJC;EACE,kBAAA;CxCywJH;AwCtwJC;EACE,iBAAA;CxCwwJH;AyCl0JD;EACE,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,eAAA;EACA,0BAAA;CzCo0JD;AyCz0JD;;EASI,eAAA;CzCo0JH;AyC70JD;EAaI,oBAAA;EACA,gBAAA;EACA,iBAAA;CzCm0JH;AyCl1JD;EAmBI,0BAAA;CzCk0JH;AyC/zJC;;EAEE,mBAAA;EACA,mBAAA;EACA,oBAAA;CzCi0JH;AyC31JD;EA8BI,gBAAA;CzCg0JH;AyC9yJD;EACA;IAfI,kBAAA;IACA,qBAAA;GzCg0JD;EyC9zJC;;IAEE,mBAAA;IACA,oBAAA;GzCg0JH;EyCvzJH;;IAJM,gBAAA;GzC+zJH;CACF;A0C52JD;EACE,eAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;ErCiLA,4CAAA;EACK,uCAAA;EACG,oCAAA;CL8rJT;A0Cx3JD;;EAaI,kBAAA;EACA,mBAAA;C1C+2JH;A0C32JC;;;EAGE,sBAAA;C1C62JH;A0Cl4JD;EA0BI,aAAA;EACA,eAAA;C1C22JH;A2Cp4JD;EACE,cAAA;EACA,oBAAA;EACA,8BAAA;EACA,mBAAA;C3Cs4JD;A2C14JD;EAQI,cAAA;EAEA,eAAA;C3Co4JH;A2C94JD;EAeI,kBAAA;C3Ck4JH;A2Cj5JD;;EAqBI,iBAAA;C3Cg4JH;A2Cr5JD;EAyBI,gBAAA;C3C+3JH;A2Cv3JD;;EAEE,oBAAA;C3Cy3JD;A2C33JD;;EAMI,mBAAA;EACA,UAAA;EACA,aAAA;EACA,eAAA;C3Cy3JH;A2Cj3JD;ECvDE,0BAAA;EACA,sBAAA;EACA,eAAA;C5C26JD;A2Ct3JD;EClDI,0BAAA;C5C26JH;A2Cz3JD;EC/CI,eAAA;C5C26JH;A2Cx3JD;EC3DE,0BAAA;EACA,sBAAA;EACA,eAAA;C5Cs7JD;A2C73JD;ECtDI,0BAAA;C5Cs7JH;A2Ch4JD;ECnDI,eAAA;C5Cs7JH;A2C/3JD;EC/DE,0BAAA;EACA,sBAAA;EACA,eAAA;C5Ci8JD;A2Cp4JD;EC1DI,0BAAA;C5Ci8JH;A2Cv4JD;ECvDI,eAAA;C5Ci8JH;A2Ct4JD;ECnEE,0BAAA;EACA,sBAAA;EACA,eAAA;C5C48JD;A2C34JD;EC9DI,0BAAA;C5C48JH;A2C94JD;EC3DI,eAAA;C5C48JH;A6C98JD;EACE;IAAQ,4BAAA;G7Ci9JP;E6Ch9JD;IAAQ,yBAAA;G7Cm9JP;CACF;A6Ch9JD;EACE;IAAQ,4BAAA;G7Cm9JP;E6Cl9JD;IAAQ,yBAAA;G7Cq9JP;CACF;A6Cx9JD;EACE;IAAQ,4BAAA;G7Cm9JP;E6Cl9JD;IAAQ,yBAAA;G7Cq9JP;CACF;A6C98JD;EACE,iBAAA;EACA,aAAA;EACA,oBAAA;EACA,0BAAA;EACA,mBAAA;ExCsCA,uDAAA;EACQ,+CAAA;CL26JT;A6C78JD;EACE,YAAA;EACA,UAAA;EACA,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,YAAA;EACA,mBAAA;EACA,0BAAA;ExCyBA,uDAAA;EACQ,+CAAA;EAyHR,oCAAA;EACK,+BAAA;EACG,4BAAA;CL+zJT;A6C18JD;;ECCI,8MAAA;EACA,yMAAA;EACA,sMAAA;EDAF,mCAAA;UAAA,2BAAA;C7C88JD;A6Cv8JD;;ExC5CE,2DAAA;EACK,sDAAA;EACG,mDAAA;CLu/JT;A6Cp8JD;EErEE,0BAAA;C/C4gKD;A+CzgKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C49JH;A6Cx8JD;EEzEE,0BAAA;C/CohKD;A+CjhKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9Co+JH;A6C58JD;EE7EE,0BAAA;C/C4hKD;A+CzhKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C4+JH;A6Ch9JD;EEjFE,0BAAA;C/CoiKD;A+CjiKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9Co/JH;AgD5iKD;EAEE,iBAAA;ChD6iKD;AgD3iKC;EACE,cAAA;ChD6iKH;AgDziKD;;EAEE,QAAA;EACA,iBAAA;ChD2iKD;AgDxiKD;EACE,eAAA;ChD0iKD;AgDviKD;EACE,eAAA;ChDyiKD;AgDtiKC;EACE,gBAAA;ChDwiKH;AgDpiKD;;EAEE,mBAAA;ChDsiKD;AgDniKD;;EAEE,oBAAA;ChDqiKD;AgDliKD;;;EAGE,oBAAA;EACA,oBAAA;ChDoiKD;AgDjiKD;EACE,uBAAA;ChDmiKD;AgDhiKD;EACE,uBAAA;ChDkiKD;AgD9hKD;EACE,cAAA;EACA,mBAAA;ChDgiKD;AgD1hKD;EACE,gBAAA;EACA,iBAAA;ChD4hKD;AiDnlKD;EAEE,oBAAA;EACA,gBAAA;CjDolKD;AiD5kKD;EACE,mBAAA;EACA,eAAA;EACA,mBAAA;EAEA,oBAAA;EACA,uBAAA;EACA,uBAAA;CjD6kKD;AiD1kKC;ErB3BA,6BAAA;EACC,4BAAA;C5BwmKF;AiD3kKC;EACE,iBAAA;ErBvBF,gCAAA;EACC,+BAAA;C5BqmKF;AiDpkKD;;EAEE,YAAA;CjDskKD;AiDxkKD;;EAKI,YAAA;CjDukKH;AiDnkKC;;;;EAEE,sBAAA;EACA,YAAA;EACA,0BAAA;CjDukKH;AiDnkKD;EACE,YAAA;EACA,iBAAA;CjDqkKD;AiDhkKC;;;EAGE,0BAAA;EACA,eAAA;EACA,oBAAA;CjDkkKH;AiDvkKC;;;EASI,eAAA;CjDmkKL;AiD5kKC;;;EAYI,eAAA;CjDqkKL;AiDhkKC;;;EAGE,WAAA;EACA,YAAA;EACA,0BAAA;EACA,sBAAA;CjDkkKH;AiDxkKC;;;;;;;;;EAYI,eAAA;CjDukKL;AiDnlKC;;;EAeI,eAAA;CjDykKL;AkD3qKC;EACE,eAAA;EACA,0BAAA;ClD6qKH;AkD3qKG;;EAEE,eAAA;ClD6qKL;AkD/qKG;;EAKI,eAAA;ClD8qKP;AkD3qKK;;;;EAEE,eAAA;EACA,0BAAA;ClD+qKP;AkD7qKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDkrKP;AkDxsKC;EACE,eAAA;EACA,0BAAA;ClD0sKH;AkDxsKG;;EAEE,eAAA;ClD0sKL;AkD5sKG;;EAKI,eAAA;ClD2sKP;AkDxsKK;;;;EAEE,eAAA;EACA,0BAAA;ClD4sKP;AkD1sKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD+sKP;AkDruKC;EACE,eAAA;EACA,0BAAA;ClDuuKH;AkDruKG;;EAEE,eAAA;ClDuuKL;AkDzuKG;;EAKI,eAAA;ClDwuKP;AkDruKK;;;;EAEE,eAAA;EACA,0BAAA;ClDyuKP;AkDvuKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD4uKP;AkDlwKC;EACE,eAAA;EACA,0BAAA;ClDowKH;AkDlwKG;;EAEE,eAAA;ClDowKL;AkDtwKG;;EAKI,eAAA;ClDqwKP;AkDlwKK;;;;EAEE,eAAA;EACA,0BAAA;ClDswKP;AkDpwKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDywKP;AiDxqKD;EACE,cAAA;EACA,mBAAA;CjD0qKD;AiDxqKD;EACE,iBAAA;EACA,iBAAA;CjD0qKD;AmDpyKD;EACE,oBAAA;EACA,uBAAA;EACA,8BAAA;EACA,mBAAA;E9C0DA,kDAAA;EACQ,0CAAA;CL6uKT;AmDnyKD;EACE,cAAA;CnDqyKD;AmDhyKD;EACE,mBAAA;EACA,qCAAA;EvBpBA,6BAAA;EACC,4BAAA;C5BuzKF;AmDtyKD;EAMI,eAAA;CnDmyKH;AmD9xKD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,eAAA;CnDgyKD;AmDpyKD;;;;;EAWI,eAAA;CnDgyKH;AmD3xKD;EACE,mBAAA;EACA,0BAAA;EACA,2BAAA;EvBxCA,gCAAA;EACC,+BAAA;C5Bs0KF;AmDrxKD;;EAGI,iBAAA;CnDsxKH;AmDzxKD;;EAMM,oBAAA;EACA,iBAAA;CnDuxKL;AmDnxKG;;EAEI,cAAA;EvBvEN,6BAAA;EACC,4BAAA;C5B61KF;AmDjxKG;;EAEI,iBAAA;EvBvEN,gCAAA;EACC,+BAAA;C5B21KF;AmD1yKD;EvB1DE,2BAAA;EACC,0BAAA;C5Bu2KF;AmD7wKD;EAEI,oBAAA;CnD8wKH;AmD3wKD;EACE,oBAAA;CnD6wKD;AmDrwKD;;;EAII,iBAAA;CnDswKH;AmD1wKD;;;EAOM,mBAAA;EACA,oBAAA;CnDwwKL;AmDhxKD;;EvBzGE,6BAAA;EACC,4BAAA;C5B63KF;AmDrxKD;;;;EAmBQ,4BAAA;EACA,6BAAA;CnDwwKP;AmD5xKD;;;;;;;;EAwBU,4BAAA;CnD8wKT;AmDtyKD;;;;;;;;EA4BU,6BAAA;CnDoxKT;AmDhzKD;;EvBjGE,gCAAA;EACC,+BAAA;C5Bq5KF;AmDrzKD;;;;EAyCQ,+BAAA;EACA,gCAAA;CnDkxKP;AmD5zKD;;;;;;;;EA8CU,+BAAA;CnDwxKT;AmDt0KD;;;;;;;;EAkDU,gCAAA;CnD8xKT;AmDh1KD;;;;EA2DI,2BAAA;CnD2xKH;AmDt1KD;;EA+DI,cAAA;CnD2xKH;AmD11KD;;EAmEI,UAAA;CnD2xKH;AmD91KD;;;;;;;;;;;;EA0EU,eAAA;CnDkyKT;AmD52KD;;;;;;;;;;;;EA8EU,gBAAA;CnD4yKT;AmD13KD;;;;;;;;EAuFU,iBAAA;CnD6yKT;AmDp4KD;;;;;;;;EAgGU,iBAAA;CnD8yKT;AmD94KD;EAsGI,UAAA;EACA,iBAAA;CnD2yKH;AmDjyKD;EACE,oBAAA;CnDmyKD;AmDpyKD;EAKI,iBAAA;EACA,mBAAA;CnDkyKH;AmDxyKD;EASM,gBAAA;CnDkyKL;AmD3yKD;EAcI,iBAAA;CnDgyKH;AmD9yKD;;EAkBM,2BAAA;CnDgyKL;AmDlzKD;EAuBI,cAAA;CnD8xKH;AmDrzKD;EAyBM,8BAAA;CnD+xKL;AmDxxKD;EC1PE,mBAAA;CpDqhLD;AoDnhLC;EACE,eAAA;EACA,0BAAA;EACA,mBAAA;CpDqhLH;AoDxhLC;EAMI,uBAAA;CpDqhLL;AoD3hLC;EASI,eAAA;EACA,0BAAA;CpDqhLL;AoDlhLC;EAEI,0BAAA;CpDmhLL;AmDvyKD;EC7PE,sBAAA;CpDuiLD;AoDriLC;EACE,YAAA;EACA,0BAAA;EACA,sBAAA;CpDuiLH;AoD1iLC;EAMI,0BAAA;CpDuiLL;AoD7iLC;EASI,eAAA;EACA,uBAAA;CpDuiLL;AoDpiLC;EAEI,6BAAA;CpDqiLL;AmDtzKD;EChQE,sBAAA;CpDyjLD;AoDvjLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDyjLH;AoD5jLC;EAMI,0BAAA;CpDyjLL;AoD/jLC;EASI,eAAA;EACA,0BAAA;CpDyjLL;AoDtjLC;EAEI,6BAAA;CpDujLL;AmDr0KD;ECnQE,sBAAA;CpD2kLD;AoDzkLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD2kLH;AoD9kLC;EAMI,0BAAA;CpD2kLL;AoDjlLC;EASI,eAAA;EACA,0BAAA;CpD2kLL;AoDxkLC;EAEI,6BAAA;CpDykLL;AmDp1KD;ECtQE,sBAAA;CpD6lLD;AoD3lLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD6lLH;AoDhmLC;EAMI,0BAAA;CpD6lLL;AoDnmLC;EASI,eAAA;EACA,0BAAA;CpD6lLL;AoD1lLC;EAEI,6BAAA;CpD2lLL;AmDn2KD;ECzQE,sBAAA;CpD+mLD;AoD7mLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD+mLH;AoDlnLC;EAMI,0BAAA;CpD+mLL;AoDrnLC;EASI,eAAA;EACA,0BAAA;CpD+mLL;AoD5mLC;EAEI,6BAAA;CpD6mLL;AqD7nLD;EACE,mBAAA;EACA,eAAA;EACA,UAAA;EACA,WAAA;EACA,iBAAA;CrD+nLD;AqDpoLD;;;;;EAYI,mBAAA;EACA,OAAA;EACA,QAAA;EACA,UAAA;EACA,aAAA;EACA,YAAA;EACA,UAAA;CrD+nLH;AqD1nLD;EACE,uBAAA;CrD4nLD;AqDxnLD;EACE,oBAAA;CrD0nLD;AsDrpLD;EACE,iBAAA;EACA,cAAA;EACA,oBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;EjDwDA,wDAAA;EACQ,gDAAA;CLgmLT;AsD/pLD;EASI,mBAAA;EACA,kCAAA;CtDypLH;AsDppLD;EACE,cAAA;EACA,mBAAA;CtDspLD;AsDppLD;EACE,aAAA;EACA,mBAAA;CtDspLD;AuD5qLD;EACE,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,YAAA;EACA,0BAAA;EjCRA,aAAA;EAGA,0BAAA;CtBqrLD;AuD7qLC;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;EjCfF,aAAA;EAGA,0BAAA;CtB6rLD;AuDzqLC;EACE,WAAA;EACA,gBAAA;EACA,wBAAA;EACA,UAAA;EACA,yBAAA;CvD2qLH;AwDhsLD;EACE,iBAAA;CxDksLD;AwD9rLD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,kCAAA;EAIA,WAAA;CxD6rLD;AwD1rLC;EnD+GA,sCAAA;EACI,kCAAA;EACC,iCAAA;EACG,8BAAA;EAkER,oDAAA;EAEK,0CAAA;EACG,oCAAA;CL6gLT;AwDhsLC;EnD2GA,mCAAA;EACI,+BAAA;EACC,8BAAA;EACG,2BAAA;CLwlLT;AwDpsLD;EACE,mBAAA;EACA,iBAAA;CxDssLD;AwDlsLD;EACE,mBAAA;EACA,YAAA;EACA,aAAA;CxDosLD;AwDhsLD;EACE,mBAAA;EACA,uBAAA;EACA,uBAAA;EACA,qCAAA;EACA,mBAAA;EnDaA,iDAAA;EACQ,yCAAA;EmDZR,qCAAA;UAAA,6BAAA;EAEA,WAAA;CxDksLD;AwD9rLD;EACE,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,uBAAA;CxDgsLD;AwD9rLC;ElCrEA,WAAA;EAGA,yBAAA;CtBowLD;AwDjsLC;ElCtEA,aAAA;EAGA,0BAAA;CtBwwLD;AwDhsLD;EACE,cAAA;EACA,iCAAA;CxDksLD;AwD9rLD;EACE,iBAAA;CxDgsLD;AwD5rLD;EACE,UAAA;EACA,wBAAA;CxD8rLD;AwDzrLD;EACE,mBAAA;EACA,cAAA;CxD2rLD;AwDvrLD;EACE,cAAA;EACA,kBAAA;EACA,8BAAA;CxDyrLD;AwD5rLD;EAQI,iBAAA;EACA,iBAAA;CxDurLH;AwDhsLD;EAaI,kBAAA;CxDsrLH;AwDnsLD;EAiBI,eAAA;CxDqrLH;AwDhrLD;EACE,mBAAA;EACA,aAAA;EACA,YAAA;EACA,aAAA;EACA,iBAAA;CxDkrLD;AwDhqLD;EAZE;IACE,aAAA;IACA,kBAAA;GxD+qLD;EwD7qLD;InDvEA,kDAAA;IACQ,0CAAA;GLuvLP;EwD5qLD;IAAY,aAAA;GxD+qLX;CACF;AwD1qLD;EAFE;IAAY,aAAA;GxDgrLX;CACF;AyD/zLD;EACE,mBAAA;EACA,cAAA;EACA,eAAA;ECRA,4DAAA;EAEA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;EDHA,gBAAA;EnCVA,WAAA;EAGA,yBAAA;CtBs1LD;AyD30LC;EnCdA,aAAA;EAGA,0BAAA;CtB01LD;AyD90LC;EAAW,iBAAA;EAAmB,eAAA;CzDk1L/B;AyDj1LC;EAAW,iBAAA;EAAmB,eAAA;CzDq1L/B;AyDp1LC;EAAW,gBAAA;EAAmB,eAAA;CzDw1L/B;AyDv1LC;EAAW,kBAAA;EAAmB,eAAA;CzD21L/B;AyDv1LD;EACE,iBAAA;EACA,iBAAA;EACA,YAAA;EACA,mBAAA;EACA,uBAAA;EACA,mBAAA;CzDy1LD;AyDr1LD;EACE,mBAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;CzDu1LD;AyDn1LC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,uBAAA;CzDq1LH;AyDn1LC;EACE,UAAA;EACA,WAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;CzDq1LH;AyDn1LC;EACE,UAAA;EACA,UAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;CzDq1LH;AyDn1LC;EACE,SAAA;EACA,QAAA;EACA,iBAAA;EACA,4BAAA;EACA,yBAAA;CzDq1LH;AyDn1LC;EACE,SAAA;EACA,SAAA;EACA,iBAAA;EACA,4BAAA;EACA,wBAAA;CzDq1LH;AyDn1LC;EACE,OAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,0BAAA;CzDq1LH;AyDn1LC;EACE,OAAA;EACA,WAAA;EACA,iBAAA;EACA,wBAAA;EACA,0BAAA;CzDq1LH;AyDn1LC;EACE,OAAA;EACA,UAAA;EACA,iBAAA;EACA,wBAAA;EACA,0BAAA;CzDq1LH;A2Dl7LD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EDXA,4DAAA;EAEA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;ECAA,gBAAA;EAEA,uBAAA;EACA,qCAAA;UAAA,6BAAA;EACA,uBAAA;EACA,qCAAA;EACA,mBAAA;EtD8CA,kDAAA;EACQ,0CAAA;CLk5LT;A2D77LC;EAAY,kBAAA;C3Dg8Lb;A2D/7LC;EAAY,kBAAA;C3Dk8Lb;A2Dj8LC;EAAY,iBAAA;C3Do8Lb;A2Dn8LC;EAAY,mBAAA;C3Ds8Lb;A2Dn8LD;EACE,UAAA;EACA,kBAAA;EACA,gBAAA;EACA,0BAAA;EACA,iCAAA;EACA,2BAAA;C3Dq8LD;A2Dl8LD;EACE,kBAAA;C3Do8LD;A2D57LC;;EAEE,mBAAA;EACA,eAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;C3D87LH;A2D37LD;EACE,mBAAA;C3D67LD;A2D37LD;EACE,mBAAA;EACA,YAAA;C3D67LD;A2Dz7LC;EACE,UAAA;EACA,mBAAA;EACA,uBAAA;EACA,0BAAA;EACA,sCAAA;EACA,cAAA;C3D27LH;A2D17LG;EACE,aAAA;EACA,YAAA;EACA,mBAAA;EACA,uBAAA;EACA,uBAAA;C3D47LL;A2Dz7LC;EACE,SAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,4BAAA;EACA,wCAAA;C3D27LH;A2D17LG;EACE,aAAA;EACA,UAAA;EACA,cAAA;EACA,qBAAA;EACA,yBAAA;C3D47LL;A2Dz7LC;EACE,UAAA;EACA,mBAAA;EACA,oBAAA;EACA,6BAAA;EACA,yCAAA;EACA,WAAA;C3D27LH;A2D17LG;EACE,aAAA;EACA,SAAA;EACA,mBAAA;EACA,oBAAA;EACA,0BAAA;C3D47LL;A2Dx7LC;EACE,SAAA;EACA,aAAA;EACA,kBAAA;EACA,sBAAA;EACA,2BAAA;EACA,uCAAA;C3D07LH;A2Dz7LG;EACE,aAAA;EACA,WAAA;EACA,sBAAA;EACA,wBAAA;EACA,cAAA;C3D27LL;A4DpjMD;EACE,mBAAA;C5DsjMD;A4DnjMD;EACE,mBAAA;EACA,iBAAA;EACA,YAAA;C5DqjMD;A4DxjMD;EAMI,cAAA;EACA,mBAAA;EvD6KF,0CAAA;EACK,qCAAA;EACG,kCAAA;CLy4LT;A4D/jMD;;EAcM,eAAA;C5DqjML;A4D3hMC;EA4NF;IvD3DE,uDAAA;IAEK,6CAAA;IACG,uCAAA;IA7JR,oCAAA;IAEQ,4BAAA;IA+GR,4BAAA;IAEQ,oBAAA;GL86LP;E4DzjMG;;IvDmHJ,2CAAA;IACQ,mCAAA;IuDjHF,QAAA;G5D4jML;E4D1jMG;;IvD8GJ,4CAAA;IACQ,oCAAA;IuD5GF,QAAA;G5D6jML;E4D3jMG;;;IvDyGJ,wCAAA;IACQ,gCAAA;IuDtGF,QAAA;G5D8jML;CACF;A4DpmMD;;;EA6CI,eAAA;C5D4jMH;A4DzmMD;EAiDI,QAAA;C5D2jMH;A4D5mMD;;EAsDI,mBAAA;EACA,OAAA;EACA,YAAA;C5D0jMH;A4DlnMD;EA4DI,WAAA;C5DyjMH;A4DrnMD;EA+DI,YAAA;C5DyjMH;A4DxnMD;;EAmEI,QAAA;C5DyjMH;A4D5nMD;EAuEI,YAAA;C5DwjMH;A4D/nMD;EA0EI,WAAA;C5DwjMH;A4DhjMD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EtC9FA,aAAA;EAGA,0BAAA;EsC6FA,gBAAA;EACA,YAAA;EACA,mBAAA;EACA,0CAAA;EACA,mCAAA;C5DmjMD;A4D9iMC;EdnGE,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,4BAAA;EACA,uHAAA;C9CopMH;A4DljMC;EACE,WAAA;EACA,SAAA;EdxGA,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,4BAAA;EACA,uHAAA;C9C6pMH;A4DpjMC;;EAEE,WAAA;EACA,YAAA;EACA,sBAAA;EtCvHF,aAAA;EAGA,0BAAA;CtB4qMD;A4DtlMD;;;;EAuCI,mBAAA;EACA,SAAA;EACA,kBAAA;EACA,WAAA;EACA,sBAAA;C5DqjMH;A4DhmMD;;EA+CI,UAAA;EACA,mBAAA;C5DqjMH;A4DrmMD;;EAoDI,WAAA;EACA,oBAAA;C5DqjMH;A4D1mMD;;EAyDI,YAAA;EACA,aAAA;EACA,eAAA;EACA,mBAAA;C5DqjMH;A4DhjMG;EACE,iBAAA;C5DkjML;A4D9iMG;EACE,iBAAA;C5DgjML;A4DtiMD;EACE,mBAAA;EACA,aAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;C5DwiMD;A4DjjMD;EAYI,sBAAA;EACA,YAAA;EACA,aAAA;EACA,YAAA;EACA,oBAAA;EACA,uBAAA;EACA,oBAAA;EACA,gBAAA;EAWA,0BAAA;EACA,mCAAA;C5D8hMH;A4D7jMD;EAkCI,UAAA;EACA,YAAA;EACA,aAAA;EACA,uBAAA;C5D8hMH;A4DvhMD;EACE,mBAAA;EACA,UAAA;EACA,WAAA;EACA,aAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,YAAA;EACA,mBAAA;EACA,0CAAA;C5DyhMD;A4DxhMC;EACE,kBAAA;C5D0hMH;A4Dj/LD;EAhCE;;;;IAKI,YAAA;IACA,aAAA;IACA,kBAAA;IACA,gBAAA;G5DmhMH;E4D3hMD;;IAYI,mBAAA;G5DmhMH;E4D/hMD;;IAgBI,oBAAA;G5DmhMH;E4D9gMD;IACE,UAAA;IACA,WAAA;IACA,qBAAA;G5DghMD;E4D5gMD;IACE,aAAA;G5D8gMD;CACF;A6D7wMC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,aAAA;EACA,eAAA;C7D6yMH;A6D3yMC;;;;;;;;;;;;;;;;EACE,YAAA;C7D4zMH;AiCp0MD;E6BRE,eAAA;EACA,kBAAA;EACA,mBAAA;C9D+0MD;AiCt0MD;EACE,wBAAA;CjCw0MD;AiCt0MD;EACE,uBAAA;CjCw0MD;AiCh0MD;EACE,yBAAA;CjCk0MD;AiCh0MD;EACE,0BAAA;CjCk0MD;AiCh0MD;EACE,mBAAA;CjCk0MD;AiCh0MD;E8BzBE,YAAA;EACA,mBAAA;EACA,kBAAA;EACA,8BAAA;EACA,UAAA;C/D41MD;AiC9zMD;EACE,yBAAA;CjCg0MD;AiCzzMD;EACE,gBAAA;CjC2zMD;AgE51MD;EACE,oBAAA;ChE81MD;AgEx1MD;;;;ECdE,yBAAA;CjE42MD;AgEv1MD;;;;;;;;;;;;EAYE,yBAAA;ChEy1MD;AgEl1MD;EA6IA;IC7LE,0BAAA;GjEs4MC;EiEr4MD;IAAU,0BAAA;GjEw4MT;EiEv4MD;IAAU,8BAAA;GjE04MT;EiEz4MD;;IACU,+BAAA;GjE44MT;CACF;AgE51MD;EAwIA;IA1II,0BAAA;GhEk2MD;CACF;AgE51MD;EAmIA;IArII,2BAAA;GhEk2MD;CACF;AgE51MD;EA8HA;IAhII,iCAAA;GhEk2MD;CACF;AgE31MD;EAwHA;IC7LE,0BAAA;GjEo6MC;EiEn6MD;IAAU,0BAAA;GjEs6MT;EiEr6MD;IAAU,8BAAA;GjEw6MT;EiEv6MD;;IACU,+BAAA;GjE06MT;CACF;AgEr2MD;EAmHA;IArHI,0BAAA;GhE22MD;CACF;AgEr2MD;EA8GA;IAhHI,2BAAA;GhE22MD;CACF;AgEr2MD;EAyGA;IA3GI,iCAAA;GhE22MD;CACF;AgEp2MD;EAmGA;IC7LE,0BAAA;GjEk8MC;EiEj8MD;IAAU,0BAAA;GjEo8MT;EiEn8MD;IAAU,8BAAA;GjEs8MT;EiEr8MD;;IACU,+BAAA;GjEw8MT;CACF;AgE92MD;EA8FA;IAhGI,0BAAA;GhEo3MD;CACF;AgE92MD;EAyFA;IA3FI,2BAAA;GhEo3MD;CACF;AgE92MD;EAoFA;IAtFI,iCAAA;GhEo3MD;CACF;AgE72MD;EA8EA;IC7LE,0BAAA;GjEg+MC;EiE/9MD;IAAU,0BAAA;GjEk+MT;EiEj+MD;IAAU,8BAAA;GjEo+MT;EiEn+MD;;IACU,+BAAA;GjEs+MT;CACF;AgEv3MD;EAyEA;IA3EI,0BAAA;GhE63MD;CACF;AgEv3MD;EAoEA;IAtEI,2BAAA;GhE63MD;CACF;AgEv3MD;EA+DA;IAjEI,iCAAA;GhE63MD;CACF;AgEt3MD;EAyDA;ICrLE,yBAAA;GjEs/MC;CACF;AgEt3MD;EAoDA;ICrLE,yBAAA;GjE2/MC;CACF;AgEt3MD;EA+CA;ICrLE,yBAAA;GjEggNC;CACF;AgEt3MD;EA0CA;ICrLE,yBAAA;GjEqgNC;CACF;AgEn3MD;ECnJE,yBAAA;CjEygND;AgEh3MD;EA4BA;IC7LE,0BAAA;GjEqhNC;EiEphND;IAAU,0BAAA;GjEuhNT;EiEthND;IAAU,8BAAA;GjEyhNT;EiExhND;;IACU,+BAAA;GjE2hNT;CACF;AgE93MD;EACE,yBAAA;ChEg4MD;AgE33MD;EAqBA;IAvBI,0BAAA;GhEi4MD;CACF;AgE/3MD;EACE,yBAAA;ChEi4MD;AgE53MD;EAcA;IAhBI,2BAAA;GhEk4MD;CACF;AgEh4MD;EACE,yBAAA;ChEk4MD;AgE73MD;EAOA;IATI,iCAAA;GhEm4MD;CACF;AgE53MD;EACA;ICrLE,yBAAA;GjEojNC;CACF","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n border: 0;\n background-color: transparent;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #fff;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #fff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #ccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #fff;\n border: 1px solid #ddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #fff;\n border-color: #ddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #fff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #fff;\n line-height: 1;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n text-decoration: none;\n color: #555;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 12px;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #fff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #fff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #fff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #fff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #fff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // WebKit-specific. Other browsers will keep their default outline style.\n // (Initially tried to also force default via `outline: initial`,\n // but that seems to erroneously remove the outline in Firefox altogether.)\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: floor((@gutter / 2));\n padding-right: ceil((@gutter / 2));\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: ceil((@gutter / -2));\n margin-right: floor((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: ceil((@grid-gutter-width / 2));\n padding-right: floor((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Unstyle the caret on ``\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus,\n &.focus {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n .border-top-radius(@btn-border-radius-base);\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n .border-top-radius(0);\n .border-bottom-radius(@btn-border-radius-base);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n\n &:focus {\n z-index: 3;\n }\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @input-border-radius;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @input-border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @input-border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on
    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Request expectationsBackend definitions
    Syntax.expect(...).respond(...).when(...).respond(...)
    Typical usagestrict unit testsloose (black-box) unit testing
    Fulfills multiple requestsNOYES
    Order of requests mattersYESNO
    Request requiredYESNO
    Response requiredoptional (see below)YES
    + * + * In cases where both backend definitions and request expectations are specified during unit + * testing, the request expectations are evaluated first. + * + * If a request expectation has no response specified, the algorithm will search your backend + * definitions for an appropriate response. + * + * If a request didn't match any expectation or if the expectation doesn't have the response + * defined, the backend definitions are evaluated in sequential order to see if any of them match + * the request. The response from the first matched definition is returned. + * + * + * ## Flushing HTTP requests + * + * The $httpBackend used in production always responds to requests asynchronously. If we preserved + * this behavior in unit testing, we'd have to create async unit tests, which are hard to write, + * to follow and to maintain. But neither can the testing mock respond synchronously; that would + * change the execution of the code under test. For this reason, the mock $httpBackend has a + * `flush()` method, which allows the test to explicitly flush pending requests. This preserves + * the async api of the backend, while allowing the test to execute synchronously. + * + * + * ## Unit testing with mock $httpBackend + * The following code shows how to setup and use the mock backend when unit testing a controller. + * First we create the controller under test: + * + ```js + // The module code + angular + .module('MyApp', []) + .controller('MyController', MyController); + + // The controller code + function MyController($scope, $http) { + var authToken; + + $http.get('/auth.py').then(function(response) { + authToken = response.headers('A-Token'); + $scope.user = response.data; + }); + + $scope.saveMessage = function(message) { + var headers = { 'Authorization': authToken }; + $scope.status = 'Saving...'; + + $http.post('/add-msg.py', message, { headers: headers } ).then(function(response) { + $scope.status = ''; + }).catch(function() { + $scope.status = 'Failed...'; + }); + }; + } + ``` + * + * Now we setup the mock backend and create the test specs: + * + ```js + // testing controller + describe('MyController', function() { + var $httpBackend, $rootScope, createController, authRequestHandler; + + // Set up the module + beforeEach(module('MyApp')); + + beforeEach(inject(function($injector) { + // Set up the mock http service responses + $httpBackend = $injector.get('$httpBackend'); + // backend definition common for all tests + authRequestHandler = $httpBackend.when('GET', '/auth.py') + .respond({userId: 'userX'}, {'A-Token': 'xxx'}); + + // Get hold of a scope (i.e. the root scope) + $rootScope = $injector.get('$rootScope'); + // The $controller service is used to create instances of controllers + var $controller = $injector.get('$controller'); + + createController = function() { + return $controller('MyController', {'$scope' : $rootScope }); + }; + })); + + + afterEach(function() { + $httpBackend.verifyNoOutstandingExpectation(); + $httpBackend.verifyNoOutstandingRequest(); + }); + + + it('should fetch authentication token', function() { + $httpBackend.expectGET('/auth.py'); + var controller = createController(); + $httpBackend.flush(); + }); + + + it('should fail authentication', function() { + + // Notice how you can change the response even after it was set + authRequestHandler.respond(401, ''); + + $httpBackend.expectGET('/auth.py'); + var controller = createController(); + $httpBackend.flush(); + expect($rootScope.status).toBe('Failed...'); + }); + + + it('should send msg to server', function() { + var controller = createController(); + $httpBackend.flush(); + + // now you don’t care about the authentication, but + // the controller will still send the request and + // $httpBackend will respond without you having to + // specify the expectation and response for this request + + $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, ''); + $rootScope.saveMessage('message content'); + expect($rootScope.status).toBe('Saving...'); + $httpBackend.flush(); + expect($rootScope.status).toBe(''); + }); + + + it('should send auth header', function() { + var controller = createController(); + $httpBackend.flush(); + + $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) { + // check if the header was sent, if it wasn't the expectation won't + // match the request and the test will fail + return headers['Authorization'] == 'xxx'; + }).respond(201, ''); + + $rootScope.saveMessage('whatever'); + $httpBackend.flush(); + }); + }); + ``` + * + * ## Dynamic responses + * + * You define a response to a request by chaining a call to `respond()` onto a definition or expectation. + * If you provide a **callback** as the first parameter to `respond(callback)` then you can dynamically generate + * a response based on the properties of the request. + * + * The `callback` function should be of the form `function(method, url, data, headers, params)`. + * + * ### Query parameters + * + * By default, query parameters on request URLs are parsed into the `params` object. So a request URL + * of `/list?q=searchstr&orderby=-name` would set `params` to be `{q: 'searchstr', orderby: '-name'}`. + * + * ### Regex parameter matching + * + * If an expectation or definition uses a **regex** to match the URL, you can provide an array of **keys** via a + * `params` argument. The index of each **key** in the array will match the index of a **group** in the + * **regex**. + * + * The `params` object in the **callback** will now have properties with these keys, which hold the value of the + * corresponding **group** in the **regex**. + * + * This also applies to the `when` and `expect` shortcut methods. + * + * + * ```js + * $httpBackend.expect('GET', /\/user\/(.+)/, undefined, undefined, ['id']) + * .respond(function(method, url, data, headers, params) { + * // for requested url of '/user/1234' params is {id: '1234'} + * }); + * + * $httpBackend.whenPATCH(/\/user\/(.+)\/article\/(.+)/, undefined, undefined, ['user', 'article']) + * .respond(function(method, url, data, headers, params) { + * // for url of '/user/1234/article/567' params is {user: '1234', article: '567'} + * }); + * ``` + * + * ## Matching route requests + * + * For extra convenience, `whenRoute` and `expectRoute` shortcuts are available. These methods offer colon + * delimited matching of the url path, ignoring the query string. This allows declarations + * similar to how application routes are configured with `$routeProvider`. Because these methods convert + * the definition url to regex, declaration order is important. Combined with query parameter parsing, + * the following is possible: + * + ```js + $httpBackend.whenRoute('GET', '/users/:id') + .respond(function(method, url, data, headers, params) { + return [200, MockUserList[Number(params.id)]]; + }); + + $httpBackend.whenRoute('GET', '/users') + .respond(function(method, url, data, headers, params) { + var userList = angular.copy(MockUserList), + defaultSort = 'lastName', + count, pages, isPrevious, isNext; + + // paged api response '/v1/users?page=2' + params.page = Number(params.page) || 1; + + // query for last names '/v1/users?q=Archer' + if (params.q) { + userList = $filter('filter')({lastName: params.q}); + } + + pages = Math.ceil(userList.length / pagingLength); + isPrevious = params.page > 1; + isNext = params.page < pages; + + return [200, { + count: userList.length, + previous: isPrevious, + next: isNext, + // sort field -> '/v1/users?sortBy=firstName' + results: $filter('orderBy')(userList, params.sortBy || defaultSort) + .splice((params.page - 1) * pagingLength, pagingLength) + }]; + }); + ``` + */ +angular.mock.$HttpBackendProvider = function() { + this.$get = ['$rootScope', '$timeout', createHttpBackendMock]; +}; + +/** + * General factory function for $httpBackend mock. + * Returns instance for unit testing (when no arguments specified): + * - passing through is disabled + * - auto flushing is disabled + * + * Returns instance for e2e testing (when `$delegate` and `$browser` specified): + * - passing through (delegating request to real backend) is enabled + * - auto flushing is enabled + * + * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified) + * @param {Object=} $browser Auto-flushing enabled if specified + * @return {Object} Instance of $httpBackend mock + */ +function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { + var definitions = [], + expectations = [], + responses = [], + responsesPush = angular.bind(responses, responses.push), + copy = angular.copy; + + function createResponse(status, data, headers, statusText) { + if (angular.isFunction(status)) return status; + + return function() { + return angular.isNumber(status) + ? [status, data, headers, statusText] + : [200, status, data, headers]; + }; + } + + // TODO(vojta): change params to: method, url, data, headers, callback + function $httpBackend(method, url, data, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers) { + + var xhr = new MockXhr(), + expectation = expectations[0], + wasExpected = false; + + xhr.$$events = eventHandlers; + xhr.upload.$$events = uploadEventHandlers; + + function prettyPrint(data) { + return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp) + ? data + : angular.toJson(data); + } + + function wrapResponse(wrapped) { + if (!$browser && timeout) { + timeout.then ? timeout.then(handleTimeout) : $timeout(handleTimeout, timeout); + } + + return handleResponse; + + function handleResponse() { + var response = wrapped.response(method, url, data, headers, wrapped.params(url)); + xhr.$$respHeaders = response[2]; + callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders(), + copy(response[3] || '')); + } + + function handleTimeout() { + for (var i = 0, ii = responses.length; i < ii; i++) { + if (responses[i] === handleResponse) { + responses.splice(i, 1); + callback(-1, undefined, ''); + break; + } + } + } + } + + if (expectation && expectation.match(method, url)) { + if (!expectation.matchData(data)) { + throw new Error('Expected ' + expectation + ' with different data\n' + + 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data); + } + + if (!expectation.matchHeaders(headers)) { + throw new Error('Expected ' + expectation + ' with different headers\n' + + 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + + prettyPrint(headers)); + } + + expectations.shift(); + + if (expectation.response) { + responses.push(wrapResponse(expectation)); + return; + } + wasExpected = true; + } + + var i = -1, definition; + while ((definition = definitions[++i])) { + if (definition.match(method, url, data, headers || {})) { + if (definition.response) { + // if $browser specified, we do auto flush all requests + ($browser ? $browser.defer : responsesPush)(wrapResponse(definition)); + } else if (definition.passThrough) { + $delegate(method, url, data, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers); + } else throw new Error('No response defined !'); + return; + } + } + throw wasExpected ? + new Error('No response defined !') : + new Error('Unexpected request: ' + method + ' ' + url + '\n' + + (expectation ? 'Expected ' + expectation : 'No more request expected')); + } + + /** + * @ngdoc method + * @name $httpBackend#when + * @description + * Creates a new backend definition. + * + * @param {string} method HTTP method. + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + * + * - respond – + * ```js + * {function([status,] data[, headers, statusText]) + * | function(function(method, url, data, headers, params)} + * ``` + * – The respond method takes a set of static data to be returned or a function that can + * return an array containing response status (number), response data (Array|Object|string), + * response headers (Object), and the text for the status (string). The respond method returns + * the `requestHandler` object for possible overrides. + */ + $httpBackend.when = function(method, url, data, headers, keys) { + var definition = new MockHttpExpectation(method, url, data, headers, keys), + chain = { + respond: function(status, data, headers, statusText) { + definition.passThrough = undefined; + definition.response = createResponse(status, data, headers, statusText); + return chain; + } + }; + + if ($browser) { + chain.passThrough = function() { + definition.response = undefined; + definition.passThrough = true; + return chain; + }; + } + + definitions.push(definition); + return chain; + }; + + /** + * @ngdoc method + * @name $httpBackend#whenGET + * @description + * Creates a new backend definition for GET requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + + /** + * @ngdoc method + * @name $httpBackend#whenHEAD + * @description + * Creates a new backend definition for HEAD requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + + /** + * @ngdoc method + * @name $httpBackend#whenDELETE + * @description + * Creates a new backend definition for DELETE requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + + /** + * @ngdoc method + * @name $httpBackend#whenPOST + * @description + * Creates a new backend definition for POST requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + + /** + * @ngdoc method + * @name $httpBackend#whenPUT + * @description + * Creates a new backend definition for PUT requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + + /** + * @ngdoc method + * @name $httpBackend#whenJSONP + * @description + * Creates a new backend definition for JSONP requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + createShortMethods('when'); + + /** + * @ngdoc method + * @name $httpBackend#whenRoute + * @description + * Creates a new backend definition that compares only with the requested route. + * + * @param {string} method HTTP method. + * @param {string} url HTTP url string that supports colon param matching. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. See #when for more info. + */ + $httpBackend.whenRoute = function(method, url) { + var pathObj = parseRoute(url); + return $httpBackend.when(method, pathObj.regexp, undefined, undefined, pathObj.keys); + }; + + function parseRoute(url) { + var ret = { + regexp: url + }, + keys = ret.keys = []; + + if (!url || !angular.isString(url)) return ret; + + url = url + .replace(/([().])/g, '\\$1') + .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) { + var optional = option === '?' ? option : null; + var star = option === '*' ? option : null; + keys.push({ name: key, optional: !!optional }); + slash = slash || ''; + return '' + + (optional ? '' : slash) + + '(?:' + + (optional ? slash : '') + + (star && '(.+?)' || '([^/]+)') + + (optional || '') + + ')' + + (optional || ''); + }) + .replace(/([\/$\*])/g, '\\$1'); + + ret.regexp = new RegExp('^' + url, 'i'); + return ret; + } + + /** + * @ngdoc method + * @name $httpBackend#expect + * @description + * Creates a new request expectation. + * + * @param {string} method HTTP method. + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current expectation. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + * + * - respond – + * ``` + * { function([status,] data[, headers, statusText]) + * | function(function(method, url, data, headers, params)} + * ``` + * – The respond method takes a set of static data to be returned or a function that can + * return an array containing response status (number), response data (Array|Object|string), + * response headers (Object), and the text for the status (string). The respond method returns + * the `requestHandler` object for possible overrides. + */ + $httpBackend.expect = function(method, url, data, headers, keys) { + var expectation = new MockHttpExpectation(method, url, data, headers, keys), + chain = { + respond: function(status, data, headers, statusText) { + expectation.response = createResponse(status, data, headers, statusText); + return chain; + } + }; + + expectations.push(expectation); + return chain; + }; + + /** + * @ngdoc method + * @name $httpBackend#expectGET + * @description + * Creates a new request expectation for GET requests. For more info see `expect()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {Object=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. See #expect for more info. + */ + + /** + * @ngdoc method + * @name $httpBackend#expectHEAD + * @description + * Creates a new request expectation for HEAD requests. For more info see `expect()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {Object=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + + /** + * @ngdoc method + * @name $httpBackend#expectDELETE + * @description + * Creates a new request expectation for DELETE requests. For more info see `expect()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {Object=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + + /** + * @ngdoc method + * @name $httpBackend#expectPOST + * @description + * Creates a new request expectation for POST requests. For more info see `expect()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + + /** + * @ngdoc method + * @name $httpBackend#expectPUT + * @description + * Creates a new request expectation for PUT requests. For more info see `expect()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + + /** + * @ngdoc method + * @name $httpBackend#expectPATCH + * @description + * Creates a new request expectation for PATCH requests. For more info see `expect()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + + /** + * @ngdoc method + * @name $httpBackend#expectJSONP + * @description + * Creates a new request expectation for JSONP requests. For more info see `expect()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives an url + * and returns true if the url matches the current definition. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. + */ + createShortMethods('expect'); + + /** + * @ngdoc method + * @name $httpBackend#expectRoute + * @description + * Creates a new request expectation that compares only with the requested route. + * + * @param {string} method HTTP method. + * @param {string} url HTTP url string that supports colon param matching. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. You can save this object for later use and invoke `respond` again in + * order to change how a matched request is handled. See #expect for more info. + */ + $httpBackend.expectRoute = function(method, url) { + var pathObj = parseRoute(url); + return $httpBackend.expect(method, pathObj.regexp, undefined, undefined, pathObj.keys); + }; + + + /** + * @ngdoc method + * @name $httpBackend#flush + * @description + * Flushes all pending requests using the trained responses. + * + * @param {number=} count Number of responses to flush (in the order they arrived). If undefined, + * all pending requests will be flushed. If there are no pending requests when the flush method + * is called an exception is thrown (as this typically a sign of programming error). + */ + $httpBackend.flush = function(count, digest) { + if (digest !== false) $rootScope.$digest(); + if (!responses.length) throw new Error('No pending request to flush !'); + + if (angular.isDefined(count) && count !== null) { + while (count--) { + if (!responses.length) throw new Error('No more pending request to flush !'); + responses.shift()(); + } + } else { + while (responses.length) { + responses.shift()(); + } + } + $httpBackend.verifyNoOutstandingExpectation(digest); + }; + + + /** + * @ngdoc method + * @name $httpBackend#verifyNoOutstandingExpectation + * @description + * Verifies that all of the requests defined via the `expect` api were made. If any of the + * requests were not made, verifyNoOutstandingExpectation throws an exception. + * + * Typically, you would call this method following each test case that asserts requests using an + * "afterEach" clause. + * + * ```js + * afterEach($httpBackend.verifyNoOutstandingExpectation); + * ``` + */ + $httpBackend.verifyNoOutstandingExpectation = function(digest) { + if (digest !== false) $rootScope.$digest(); + if (expectations.length) { + throw new Error('Unsatisfied requests: ' + expectations.join(', ')); + } + }; + + + /** + * @ngdoc method + * @name $httpBackend#verifyNoOutstandingRequest + * @description + * Verifies that there are no outstanding requests that need to be flushed. + * + * Typically, you would call this method following each test case that asserts requests using an + * "afterEach" clause. + * + * ```js + * afterEach($httpBackend.verifyNoOutstandingRequest); + * ``` + */ + $httpBackend.verifyNoOutstandingRequest = function() { + if (responses.length) { + throw new Error('Unflushed requests: ' + responses.length); + } + }; + + + /** + * @ngdoc method + * @name $httpBackend#resetExpectations + * @description + * Resets all request expectations, but preserves all backend definitions. Typically, you would + * call resetExpectations during a multiple-phase test when you want to reuse the same instance of + * $httpBackend mock. + */ + $httpBackend.resetExpectations = function() { + expectations.length = 0; + responses.length = 0; + }; + + return $httpBackend; + + + function createShortMethods(prefix) { + angular.forEach(['GET', 'DELETE', 'JSONP', 'HEAD'], function(method) { + $httpBackend[prefix + method] = function(url, headers, keys) { + return $httpBackend[prefix](method, url, undefined, headers, keys); + }; + }); + + angular.forEach(['PUT', 'POST', 'PATCH'], function(method) { + $httpBackend[prefix + method] = function(url, data, headers, keys) { + return $httpBackend[prefix](method, url, data, headers, keys); + }; + }); + } +} + +function MockHttpExpectation(method, url, data, headers, keys) { + + function getUrlParams(u) { + var params = u.slice(u.indexOf('?') + 1).split('&'); + return params.sort(); + } + + function compareUrl(u) { + return (url.slice(0, url.indexOf('?')) == u.slice(0, u.indexOf('?')) && getUrlParams(url).join() == getUrlParams(u).join()); + } + + this.data = data; + this.headers = headers; + + this.match = function(m, u, d, h) { + if (method != m) return false; + if (!this.matchUrl(u)) return false; + if (angular.isDefined(d) && !this.matchData(d)) return false; + if (angular.isDefined(h) && !this.matchHeaders(h)) return false; + return true; + }; + + this.matchUrl = function(u) { + if (!url) return true; + if (angular.isFunction(url.test)) return url.test(u); + if (angular.isFunction(url)) return url(u); + return (url == u || compareUrl(u)); + }; + + this.matchHeaders = function(h) { + if (angular.isUndefined(headers)) return true; + if (angular.isFunction(headers)) return headers(h); + return angular.equals(headers, h); + }; + + this.matchData = function(d) { + if (angular.isUndefined(data)) return true; + if (data && angular.isFunction(data.test)) return data.test(d); + if (data && angular.isFunction(data)) return data(d); + if (data && !angular.isString(data)) { + return angular.equals(angular.fromJson(angular.toJson(data)), angular.fromJson(d)); + } + return data == d; + }; + + this.toString = function() { + return method + ' ' + url; + }; + + this.params = function(u) { + return angular.extend(parseQuery(), pathParams()); + + function pathParams() { + var keyObj = {}; + if (!url || !angular.isFunction(url.test) || !keys || keys.length === 0) return keyObj; + + var m = url.exec(u); + if (!m) return keyObj; + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1]; + var val = m[i]; + if (key && val) { + keyObj[key.name || key] = val; + } + } + + return keyObj; + } + + function parseQuery() { + var obj = {}, key_value, key, + queryStr = u.indexOf('?') > -1 + ? u.substring(u.indexOf('?') + 1) + : ""; + + angular.forEach(queryStr.split('&'), function(keyValue) { + if (keyValue) { + key_value = keyValue.replace(/\+/g,'%20').split('='); + key = tryDecodeURIComponent(key_value[0]); + if (angular.isDefined(key)) { + var val = angular.isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true; + if (!hasOwnProperty.call(obj, key)) { + obj[key] = val; + } else if (angular.isArray(obj[key])) { + obj[key].push(val); + } else { + obj[key] = [obj[key],val]; + } + } + } + }); + return obj; + } + function tryDecodeURIComponent(value) { + try { + return decodeURIComponent(value); + } catch (e) { + // Ignore any invalid uri component + } + } + }; +} + +function createMockXhr() { + return new MockXhr(); +} + +function MockXhr() { + + // hack for testing $http, $httpBackend + MockXhr.$$lastInstance = this; + + this.open = function(method, url, async) { + this.$$method = method; + this.$$url = url; + this.$$async = async; + this.$$reqHeaders = {}; + this.$$respHeaders = {}; + }; + + this.send = function(data) { + this.$$data = data; + }; + + this.setRequestHeader = function(key, value) { + this.$$reqHeaders[key] = value; + }; + + this.getResponseHeader = function(name) { + // the lookup must be case insensitive, + // that's why we try two quick lookups first and full scan last + var header = this.$$respHeaders[name]; + if (header) return header; + + name = angular.lowercase(name); + header = this.$$respHeaders[name]; + if (header) return header; + + header = undefined; + angular.forEach(this.$$respHeaders, function(headerVal, headerName) { + if (!header && angular.lowercase(headerName) == name) header = headerVal; + }); + return header; + }; + + this.getAllResponseHeaders = function() { + var lines = []; + + angular.forEach(this.$$respHeaders, function(value, key) { + lines.push(key + ': ' + value); + }); + return lines.join('\n'); + }; + + this.abort = angular.noop; + + // This section simulates the events on a real XHR object (and the upload object) + // When we are testing $httpBackend (inside the angular project) we make partial use of this + // but store the events directly ourselves on `$$events`, instead of going through the `addEventListener` + this.$$events = {}; + this.addEventListener = function(name, listener) { + if (angular.isUndefined(this.$$events[name])) this.$$events[name] = []; + this.$$events[name].push(listener); + }; + + this.upload = { + $$events: {}, + addEventListener: this.addEventListener + }; +} + + +/** + * @ngdoc service + * @name $timeout + * @description + * + * This service is just a simple decorator for {@link ng.$timeout $timeout} service + * that adds a "flush" and "verifyNoPendingTasks" methods. + */ + +angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $browser) { + + /** + * @ngdoc method + * @name $timeout#flush + * @description + * + * Flushes the queue of pending tasks. + * + * @param {number=} delay maximum timeout amount to flush up until + */ + $delegate.flush = function(delay) { + $browser.defer.flush(delay); + }; + + /** + * @ngdoc method + * @name $timeout#verifyNoPendingTasks + * @description + * + * Verifies that there are no pending tasks that need to be flushed. + */ + $delegate.verifyNoPendingTasks = function() { + if ($browser.deferredFns.length) { + throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' + + formatPendingTasksAsString($browser.deferredFns)); + } + }; + + function formatPendingTasksAsString(tasks) { + var result = []; + angular.forEach(tasks, function(task) { + result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}'); + }); + + return result.join(', '); + } + + return $delegate; +}]; + +angular.mock.$RAFDecorator = ['$delegate', function($delegate) { + var rafFn = function(fn) { + var index = rafFn.queue.length; + rafFn.queue.push(fn); + return function() { + rafFn.queue.splice(index, 1); + }; + }; + + rafFn.queue = []; + rafFn.supported = $delegate.supported; + + rafFn.flush = function() { + if (rafFn.queue.length === 0) { + throw new Error('No rAF callbacks present'); + } + + var length = rafFn.queue.length; + for (var i = 0; i < length; i++) { + rafFn.queue[i](); + } + + rafFn.queue = rafFn.queue.slice(i); + }; + + return rafFn; +}]; + +/** + * + */ +var originalRootElement; +angular.mock.$RootElementProvider = function() { + this.$get = ['$injector', function($injector) { + originalRootElement = angular.element('
    ').data('$injector', $injector); + return originalRootElement; + }]; +}; + +/** + * @ngdoc service + * @name $controller + * @description + * A decorator for {@link ng.$controller} with additional `bindings` parameter, useful when testing + * controllers of directives that use {@link $compile#-bindtocontroller- `bindToController`}. + * + * + * ## Example + * + * ```js + * + * // Directive definition ... + * + * myMod.directive('myDirective', { + * controller: 'MyDirectiveController', + * bindToController: { + * name: '@' + * } + * }); + * + * + * // Controller definition ... + * + * myMod.controller('MyDirectiveController', ['$log', function($log) { + * $log.info(this.name); + * }]); + * + * + * // In a test ... + * + * describe('myDirectiveController', function() { + * it('should write the bound name to the log', inject(function($controller, $log) { + * var ctrl = $controller('MyDirectiveController', { /* no locals */ }, { name: 'Clark Kent' }); + * expect(ctrl.name).toEqual('Clark Kent'); + * expect($log.info.logs).toEqual(['Clark Kent']); + * })); + * }); + * + * ``` + * + * @param {Function|string} constructor If called with a function then it's considered to be the + * controller constructor function. Otherwise it's considered to be a string which is used + * to retrieve the controller constructor using the following steps: + * + * * check if a controller with given name is registered via `$controllerProvider` + * * check if evaluating the string on the current scope returns a constructor + * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global + * `window` object (not recommended) + * + * The string can use the `controller as property` syntax, where the controller instance is published + * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this + * to work correctly. + * + * @param {Object} locals Injection locals for Controller. + * @param {Object=} bindings Properties to add to the controller before invoking the constructor. This is used + * to simulate the `bindToController` feature and simplify certain kinds of tests. + * @return {Object} Instance of given controller. + */ +angular.mock.$ControllerDecorator = ['$delegate', function($delegate) { + return function(expression, locals, later, ident) { + if (later && typeof later === 'object') { + var instantiate = $delegate(expression, locals, true, ident); + angular.extend(instantiate.instance, later); + + var instance = instantiate(); + if (instance !== instantiate.instance) { + angular.extend(instance, later); + } + + return instance; + } + return $delegate(expression, locals, later, ident); + }; +}]; + +/** + * @ngdoc service + * @name $componentController + * @description + * A service that can be used to create instances of component controllers. + *
    + * Be aware that the controller will be instantiated and attached to the scope as specified in + * the component definition object. If you do not provide a `$scope` object in the `locals` param + * then the helper will create a new isolated scope as a child of `$rootScope`. + *
    + * @param {string} componentName the name of the component whose controller we want to instantiate + * @param {Object} locals Injection locals for Controller. + * @param {Object=} bindings Properties to add to the controller before invoking the constructor. This is used + * to simulate the `bindToController` feature and simplify certain kinds of tests. + * @param {string=} ident Override the property name to use when attaching the controller to the scope. + * @return {Object} Instance of requested controller. + */ +angular.mock.$ComponentControllerProvider = ['$compileProvider', function($compileProvider) { + this.$get = ['$controller','$injector', '$rootScope', function($controller, $injector, $rootScope) { + return function $componentController(componentName, locals, bindings, ident) { + // get all directives associated to the component name + var directives = $injector.get(componentName + 'Directive'); + // look for those directives that are components + var candidateDirectives = directives.filter(function(directiveInfo) { + // components have controller, controllerAs and restrict:'E' + return directiveInfo.controller && directiveInfo.controllerAs && directiveInfo.restrict === 'E'; + }); + // check if valid directives found + if (candidateDirectives.length === 0) { + throw new Error('No component found'); + } + if (candidateDirectives.length > 1) { + throw new Error('Too many components found'); + } + // get the info of the component + var directiveInfo = candidateDirectives[0]; + // create a scope if needed + locals = locals || {}; + locals.$scope = locals.$scope || $rootScope.$new(true); + return $controller(directiveInfo.controller, locals, bindings, ident || directiveInfo.controllerAs); + }; + }]; +}]; + + +/** + * @ngdoc module + * @name ngMock + * @packageName angular-mocks + * @description + * + * # ngMock + * + * The `ngMock` module provides support to inject and mock Angular services into unit tests. + * In addition, ngMock also extends various core ng services such that they can be + * inspected and controlled in a synchronous manner within test code. + * + * + *
    + * + * @installation + * + * First, download the file: + * * [Google CDN](https://developers.google.com/speed/libraries/devguide#angularjs) e.g. + * `"//ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-mocks.js"` + * * [NPM](https://www.npmjs.com/) e.g. `npm install angular-mocks@X.Y.Z` + * * [Bower](http://bower.io) e.g. `bower install angular-mocks#X.Y.Z` + * * [code.angularjs.org](https://code.angularjs.org/) (discouraged for production use) e.g. + * `"//code.angularjs.org/X.Y.Z/angular-mocks.js"` + * + * where X.Y.Z is the AngularJS version you are running. + * + * Then, configure your test runner to load `angular-mocks.js` after `angular.js`. + * This example uses
    Karma: + * + * ``` + * config.set({ + * files: [ + * 'build/angular.js', // and other module files you need + * 'build/angular-mocks.js', + * '', + * '' + * ] + * }); + * ``` + * + * Including the `angular-mocks.js` file automatically adds the `ngMock` module, so your tests + * are ready to go! + */ +angular.module('ngMock', ['ng']).provider({ + $browser: angular.mock.$BrowserProvider, + $exceptionHandler: angular.mock.$ExceptionHandlerProvider, + $log: angular.mock.$LogProvider, + $interval: angular.mock.$IntervalProvider, + $httpBackend: angular.mock.$HttpBackendProvider, + $rootElement: angular.mock.$RootElementProvider, + $componentController: angular.mock.$ComponentControllerProvider +}).config(['$provide', function($provide) { + $provide.decorator('$timeout', angular.mock.$TimeoutDecorator); + $provide.decorator('$$rAF', angular.mock.$RAFDecorator); + $provide.decorator('$rootScope', angular.mock.$RootScopeDecorator); + $provide.decorator('$controller', angular.mock.$ControllerDecorator); +}]); + +/** + * @ngdoc module + * @name ngMockE2E + * @module ngMockE2E + * @packageName angular-mocks + * @description + * + * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing. + * Currently there is only one mock present in this module - + * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock. + */ +angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) { + $provide.value('$httpBackend', angular.injector(['ng']).get('$httpBackend')); + $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); +}]); + +/** + * @ngdoc service + * @name $httpBackend + * @module ngMockE2E + * @description + * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of + * applications that use the {@link ng.$http $http service}. + * + *
    + * **Note**: For fake http backend implementation suitable for unit testing please see + * {@link ngMock.$httpBackend unit-testing $httpBackend mock}. + *
    + * + * This implementation can be used to respond with static or dynamic responses via the `when` api + * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the + * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch + * templates from a webserver). + * + * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application + * is being developed with the real backend api replaced with a mock, it is often desirable for + * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch + * templates or static files from the webserver). To configure the backend with this behavior + * use the `passThrough` request handler of `when` instead of `respond`. + * + * Additionally, we don't want to manually have to flush mocked out requests like we do during unit + * testing. For this reason the e2e $httpBackend flushes mocked out requests + * automatically, closely simulating the behavior of the XMLHttpRequest object. + * + * To setup the application to run with this http backend, you have to create a module that depends + * on the `ngMockE2E` and your application modules and defines the fake backend: + * + * ```js + * var myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']); + * myAppDev.run(function($httpBackend) { + * var phones = [{name: 'phone1'}, {name: 'phone2'}]; + * + * // returns the current list of phones + * $httpBackend.whenGET('/phones').respond(phones); + * + * // adds a new phone to the phones array + * $httpBackend.whenPOST('/phones').respond(function(method, url, data) { + * var phone = angular.fromJson(data); + * phones.push(phone); + * return [200, phone, {}]; + * }); + * $httpBackend.whenGET(/^\/templates\//).passThrough(); // Requests for templare are handled by the real server + * //... + * }); + * ``` + * + * Afterwards, bootstrap your app with this new module. + * + * ## Example + * + * + * var myApp = angular.module('myApp', []); + * + * myApp.controller('main', function($http) { + * var ctrl = this; + * + * ctrl.phones = []; + * ctrl.newPhone = { + * name: '' + * }; + * + * ctrl.getPhones = function() { + * $http.get('/phones').then(function(response) { + * ctrl.phones = response.data; + * }); + * }; + * + * ctrl.addPhone = function(phone) { + * $http.post('/phones', phone).then(function() { + * ctrl.newPhone = {name: ''}; + * return ctrl.getPhones(); + * }); + * }; + * + * ctrl.getPhones(); + * }); + * + * + * var myAppDev = angular.module('myAppE2E', ['myApp', 'ngMockE2E']); + * + * myAppDev.run(function($httpBackend) { + * var phones = [{name: 'phone1'}, {name: 'phone2'}]; + * + * // returns the current list of phones + * $httpBackend.whenGET('/phones').respond(phones); + * + * // adds a new phone to the phones array + * $httpBackend.whenPOST('/phones').respond(function(method, url, data) { + * var phone = angular.fromJson(data); + * phones.push(phone); + * return [200, phone, {}]; + * }); + * }); + * + * + *
    + *
    + * + * + *
    + *

    Phones

    + *
      + *
    • {{phone.name}}
    • + *
    + *
    + *
    + *
    + * + * + */ + +/** + * @ngdoc method + * @name $httpBackend#when + * @module ngMockE2E + * @description + * Creates a new backend definition. + * + * @param {string} method HTTP method. + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on + * {@link ngMock.$httpBackend $httpBackend mock}. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. You can save this object for later use and invoke + * `respond` or `passThrough` again in order to change how a matched request is handled. + * + * - respond – + * ``` + * { function([status,] data[, headers, statusText]) + * | function(function(method, url, data, headers, params)} + * ``` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (Array|Object|string), response + * headers (Object), and the text for the status (string). + * - passThrough – `{function()}` – Any request matching a backend definition with + * `passThrough` handler will be passed through to the real backend (an XHR request will be made + * to the server.) + * - Both methods return the `requestHandler` object for possible overrides. + */ + +/** + * @ngdoc method + * @name $httpBackend#whenGET + * @module ngMockE2E + * @description + * Creates a new backend definition for GET requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on + * {@link ngMock.$httpBackend $httpBackend mock}. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. You can save this object for later use and invoke + * `respond` or `passThrough` again in order to change how a matched request is handled. + */ + +/** + * @ngdoc method + * @name $httpBackend#whenHEAD + * @module ngMockE2E + * @description + * Creates a new backend definition for HEAD requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on + * {@link ngMock.$httpBackend $httpBackend mock}. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. You can save this object for later use and invoke + * `respond` or `passThrough` again in order to change how a matched request is handled. + */ + +/** + * @ngdoc method + * @name $httpBackend#whenDELETE + * @module ngMockE2E + * @description + * Creates a new backend definition for DELETE requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on + * {@link ngMock.$httpBackend $httpBackend mock}. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. You can save this object for later use and invoke + * `respond` or `passThrough` again in order to change how a matched request is handled. + */ + +/** + * @ngdoc method + * @name $httpBackend#whenPOST + * @module ngMockE2E + * @description + * Creates a new backend definition for POST requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on + * {@link ngMock.$httpBackend $httpBackend mock}. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. You can save this object for later use and invoke + * `respond` or `passThrough` again in order to change how a matched request is handled. + */ + +/** + * @ngdoc method + * @name $httpBackend#whenPUT + * @module ngMockE2E + * @description + * Creates a new backend definition for PUT requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on + * {@link ngMock.$httpBackend $httpBackend mock}. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. You can save this object for later use and invoke + * `respond` or `passThrough` again in order to change how a matched request is handled. + */ + +/** + * @ngdoc method + * @name $httpBackend#whenPATCH + * @module ngMockE2E + * @description + * Creates a new backend definition for PATCH requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on + * {@link ngMock.$httpBackend $httpBackend mock}. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. You can save this object for later use and invoke + * `respond` or `passThrough` again in order to change how a matched request is handled. + */ + +/** + * @ngdoc method + * @name $httpBackend#whenJSONP + * @module ngMockE2E + * @description + * Creates a new backend definition for JSONP requests. For more info see `when()`. + * + * @param {string|RegExp|function(string)} url HTTP url or function that receives a url + * and returns true if the url matches the current definition. + * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on + * {@link ngMock.$httpBackend $httpBackend mock}. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. You can save this object for later use and invoke + * `respond` or `passThrough` again in order to change how a matched request is handled. + */ +/** + * @ngdoc method + * @name $httpBackend#whenRoute + * @module ngMockE2E + * @description + * Creates a new backend definition that compares only with the requested route. + * + * @param {string} method HTTP method. + * @param {string} url HTTP url string that supports colon param matching. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. You can save this object for later use and invoke + * `respond` or `passThrough` again in order to change how a matched request is handled. + */ +angular.mock.e2e = {}; +angular.mock.e2e.$httpBackendDecorator = + ['$rootScope', '$timeout', '$delegate', '$browser', createHttpBackendMock]; + + +/** + * @ngdoc type + * @name $rootScope.Scope + * @module ngMock + * @description + * {@link ng.$rootScope.Scope Scope} type decorated with helper methods useful for testing. These + * methods are automatically available on any {@link ng.$rootScope.Scope Scope} instance when + * `ngMock` module is loaded. + * + * In addition to all the regular `Scope` methods, the following helper methods are available: + */ +angular.mock.$RootScopeDecorator = ['$delegate', function($delegate) { + + var $rootScopePrototype = Object.getPrototypeOf($delegate); + + $rootScopePrototype.$countChildScopes = countChildScopes; + $rootScopePrototype.$countWatchers = countWatchers; + + return $delegate; + + // ------------------------------------------------------------------------------------------ // + + /** + * @ngdoc method + * @name $rootScope.Scope#$countChildScopes + * @module ngMock + * @description + * Counts all the direct and indirect child scopes of the current scope. + * + * The current scope is excluded from the count. The count includes all isolate child scopes. + * + * @returns {number} Total number of child scopes. + */ + function countChildScopes() { + // jshint validthis: true + var count = 0; // exclude the current scope + var pendingChildHeads = [this.$$childHead]; + var currentScope; + + while (pendingChildHeads.length) { + currentScope = pendingChildHeads.shift(); + + while (currentScope) { + count += 1; + pendingChildHeads.push(currentScope.$$childHead); + currentScope = currentScope.$$nextSibling; + } + } + + return count; + } + + + /** + * @ngdoc method + * @name $rootScope.Scope#$countWatchers + * @module ngMock + * @description + * Counts all the watchers of direct and indirect child scopes of the current scope. + * + * The watchers of the current scope are included in the count and so are all the watchers of + * isolate child scopes. + * + * @returns {number} Total number of watchers. + */ + function countWatchers() { + // jshint validthis: true + var count = this.$$watchers ? this.$$watchers.length : 0; // include the current scope + var pendingChildHeads = [this.$$childHead]; + var currentScope; + + while (pendingChildHeads.length) { + currentScope = pendingChildHeads.shift(); + + while (currentScope) { + count += currentScope.$$watchers ? currentScope.$$watchers.length : 0; + pendingChildHeads.push(currentScope.$$childHead); + currentScope = currentScope.$$nextSibling; + } + } + + return count; + } +}]; + + +!(function(jasmineOrMocha) { + + if (!jasmineOrMocha) { + return; + } + + var currentSpec = null, + injectorState = new InjectorState(), + annotatedFunctions = [], + wasInjectorCreated = function() { + return !!currentSpec; + }; + + angular.mock.$$annotate = angular.injector.$$annotate; + angular.injector.$$annotate = function(fn) { + if (typeof fn === 'function' && !fn.$inject) { + annotatedFunctions.push(fn); + } + return angular.mock.$$annotate.apply(this, arguments); + }; + + /** + * @ngdoc function + * @name angular.mock.module + * @description + * + * *NOTE*: This function is also published on window for easy access.
    + * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha + * + * This function registers a module configuration code. It collects the configuration information + * which will be used when the injector is created by {@link angular.mock.inject inject}. + * + * See {@link angular.mock.inject inject} for usage example + * + * @param {...(string|Function|Object)} fns any number of modules which are represented as string + * aliases or as anonymous module initialization functions. The modules are used to + * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an + * object literal is passed each key-value pair will be registered on the module via + * {@link auto.$provide $provide}.value, the key being the string name (or token) to associate + * with the value on the injector. + */ + var module = window.module = angular.mock.module = function() { + var moduleFns = Array.prototype.slice.call(arguments, 0); + return wasInjectorCreated() ? workFn() : workFn; + ///////////////////// + function workFn() { + if (currentSpec.$injector) { + throw new Error('Injector already created, can not register a module!'); + } else { + var fn, modules = currentSpec.$modules || (currentSpec.$modules = []); + angular.forEach(moduleFns, function(module) { + if (angular.isObject(module) && !angular.isArray(module)) { + fn = ['$provide', function($provide) { + angular.forEach(module, function(value, key) { + $provide.value(key, value); + }); + }]; + } else { + fn = module; + } + if (currentSpec.$providerInjector) { + currentSpec.$providerInjector.invoke(fn); + } else { + modules.push(fn); + } + }); + } + } + }; + + module.$$beforeAllHook = (window.before || window.beforeAll); + module.$$afterAllHook = (window.after || window.afterAll); + + // purely for testing ngMock itself + module.$$currentSpec = function(to) { + if (arguments.length === 0) return to; + currentSpec = to; + }; + + /** + * @ngdoc function + * @name angular.mock.module.sharedInjector + * @description + * + * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha + * + * This function ensures a single injector will be used for all tests in a given describe context. + * This contrasts with the default behaviour where a new injector is created per test case. + * + * Use sharedInjector when you want to take advantage of Jasmine's `beforeAll()`, or mocha's + * `before()` methods. Call `module.sharedInjector()` before you setup any other hooks that + * will create (i.e call `module()`) or use (i.e call `inject()`) the injector. + * + * You cannot call `sharedInjector()` from within a context already using `sharedInjector()`. + * + * ## Example + * + * Typically beforeAll is used to make many assertions about a single operation. This can + * cut down test run-time as the test setup doesn't need to be re-run, and enabling focussed + * tests each with a single assertion. + * + * ```js + * describe("Deep Thought", function() { + * + * module.sharedInjector(); + * + * beforeAll(module("UltimateQuestion")); + * + * beforeAll(inject(function(DeepThought) { + * expect(DeepThought.answer).toBeUndefined(); + * DeepThought.generateAnswer(); + * })); + * + * it("has calculated the answer correctly", inject(function(DeepThought) { + * // Because of sharedInjector, we have access to the instance of the DeepThought service + * // that was provided to the beforeAll() hook. Therefore we can test the generated answer + * expect(DeepThought.answer).toBe(42); + * })); + * + * it("has calculated the answer within the expected time", inject(function(DeepThought) { + * expect(DeepThought.runTimeMillennia).toBeLessThan(8000); + * })); + * + * it("has double checked the answer", inject(function(DeepThought) { + * expect(DeepThought.absolutelySureItIsTheRightAnswer).toBe(true); + * })); + * + * }); + * + * ``` + */ + module.sharedInjector = function() { + if (!(module.$$beforeAllHook && module.$$afterAllHook)) { + throw Error("sharedInjector() cannot be used unless your test runner defines beforeAll/afterAll"); + } + + var initialized = false; + + module.$$beforeAllHook(function() { + if (injectorState.shared) { + injectorState.sharedError = Error("sharedInjector() cannot be called inside a context that has already called sharedInjector()"); + throw injectorState.sharedError; + } + initialized = true; + currentSpec = this; + injectorState.shared = true; + }); + + module.$$afterAllHook(function() { + if (initialized) { + injectorState = new InjectorState(); + module.$$cleanup(); + } else { + injectorState.sharedError = null; + } + }); + }; + + module.$$beforeEach = function() { + if (injectorState.shared && currentSpec && currentSpec != this) { + var state = currentSpec; + currentSpec = this; + angular.forEach(["$injector","$modules","$providerInjector", "$injectorStrict"], function(k) { + currentSpec[k] = state[k]; + state[k] = null; + }); + } else { + currentSpec = this; + originalRootElement = null; + annotatedFunctions = []; + } + }; + + module.$$afterEach = function() { + if (injectorState.cleanupAfterEach()) { + module.$$cleanup(); + } + }; + + module.$$cleanup = function() { + var injector = currentSpec.$injector; + + annotatedFunctions.forEach(function(fn) { + delete fn.$inject; + }); + + angular.forEach(currentSpec.$modules, function(module) { + if (module && module.$$hashKey) { + module.$$hashKey = undefined; + } + }); + + currentSpec.$injector = null; + currentSpec.$modules = null; + currentSpec.$providerInjector = null; + currentSpec = null; + + if (injector) { + // Ensure `$rootElement` is instantiated, before checking `originalRootElement` + var $rootElement = injector.get('$rootElement'); + var rootNode = $rootElement && $rootElement[0]; + var cleanUpNodes = !originalRootElement ? [] : [originalRootElement[0]]; + if (rootNode && (!originalRootElement || rootNode !== originalRootElement[0])) { + cleanUpNodes.push(rootNode); + } + angular.element.cleanData(cleanUpNodes); + + // Ensure `$destroy()` is available, before calling it + // (a mocked `$rootScope` might not implement it (or not even be an object at all)) + var $rootScope = injector.get('$rootScope'); + if ($rootScope && $rootScope.$destroy) $rootScope.$destroy(); + } + + // clean up jquery's fragment cache + angular.forEach(angular.element.fragments, function(val, key) { + delete angular.element.fragments[key]; + }); + + MockXhr.$$lastInstance = null; + + angular.forEach(angular.callbacks, function(val, key) { + delete angular.callbacks[key]; + }); + angular.callbacks.$$counter = 0; + }; + + (window.beforeEach || window.setup)(module.$$beforeEach); + (window.afterEach || window.teardown)(module.$$afterEach); + + /** + * @ngdoc function + * @name angular.mock.inject + * @description + * + * *NOTE*: This function is also published on window for easy access.
    + * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha + * + * The inject function wraps a function into an injectable function. The inject() creates new + * instance of {@link auto.$injector $injector} per test, which is then used for + * resolving references. + * + * + * ## Resolving References (Underscore Wrapping) + * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this + * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable + * that is declared in the scope of the `describe()` block. Since we would, most likely, want + * the variable to have the same name of the reference we have a problem, since the parameter + * to the `inject()` function would hide the outer variable. + * + * To help with this, the injected parameters can, optionally, be enclosed with underscores. + * These are ignored by the injector when the reference name is resolved. + * + * For example, the parameter `_myService_` would be resolved as the reference `myService`. + * Since it is available in the function body as _myService_, we can then assign it to a variable + * defined in an outer scope. + * + * ``` + * // Defined out reference variable outside + * var myService; + * + * // Wrap the parameter in underscores + * beforeEach( inject( function(_myService_){ + * myService = _myService_; + * })); + * + * // Use myService in a series of tests. + * it('makes use of myService', function() { + * myService.doStuff(); + * }); + * + * ``` + * + * See also {@link angular.mock.module angular.mock.module} + * + * ## Example + * Example of what a typical jasmine tests looks like with the inject method. + * ```js + * + * angular.module('myApplicationModule', []) + * .value('mode', 'app') + * .value('version', 'v1.0.1'); + * + * + * describe('MyApp', function() { + * + * // You need to load modules that you want to test, + * // it loads only the "ng" module by default. + * beforeEach(module('myApplicationModule')); + * + * + * // inject() is used to inject arguments of all given functions + * it('should provide a version', inject(function(mode, version) { + * expect(version).toEqual('v1.0.1'); + * expect(mode).toEqual('app'); + * })); + * + * + * // The inject and module method can also be used inside of the it or beforeEach + * it('should override a version and test the new version is injected', function() { + * // module() takes functions or strings (module aliases) + * module(function($provide) { + * $provide.value('version', 'overridden'); // override version here + * }); + * + * inject(function(version) { + * expect(version).toEqual('overridden'); + * }); + * }); + * }); + * + * ``` + * + * @param {...Function} fns any number of functions which will be injected using the injector. + */ + + + + var ErrorAddingDeclarationLocationStack = function(e, errorForStack) { + this.message = e.message; + this.name = e.name; + if (e.line) this.line = e.line; + if (e.sourceId) this.sourceId = e.sourceId; + if (e.stack && errorForStack) + this.stack = e.stack + '\n' + errorForStack.stack; + if (e.stackArray) this.stackArray = e.stackArray; + }; + ErrorAddingDeclarationLocationStack.prototype = Error.prototype; + + window.inject = angular.mock.inject = function() { + var blockFns = Array.prototype.slice.call(arguments, 0); + var errorForStack = new Error('Declaration Location'); + // IE10+ and PhanthomJS do not set stack trace information, until the error is thrown + if (!errorForStack.stack) { + try { + throw errorForStack; + } catch (e) {} + } + return wasInjectorCreated() ? workFn.call(currentSpec) : workFn; + ///////////////////// + function workFn() { + var modules = currentSpec.$modules || []; + var strictDi = !!currentSpec.$injectorStrict; + modules.unshift(['$injector', function($injector) { + currentSpec.$providerInjector = $injector; + }]); + modules.unshift('ngMock'); + modules.unshift('ng'); + var injector = currentSpec.$injector; + if (!injector) { + if (strictDi) { + // If strictDi is enabled, annotate the providerInjector blocks + angular.forEach(modules, function(moduleFn) { + if (typeof moduleFn === "function") { + angular.injector.$$annotate(moduleFn); + } + }); + } + injector = currentSpec.$injector = angular.injector(modules, strictDi); + currentSpec.$injectorStrict = strictDi; + } + for (var i = 0, ii = blockFns.length; i < ii; i++) { + if (currentSpec.$injectorStrict) { + // If the injector is strict / strictDi, and the spec wants to inject using automatic + // annotation, then annotate the function here. + injector.annotate(blockFns[i]); + } + try { + /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */ + injector.invoke(blockFns[i] || angular.noop, this); + /* jshint +W040 */ + } catch (e) { + if (e.stack && errorForStack) { + throw new ErrorAddingDeclarationLocationStack(e, errorForStack); + } + throw e; + } finally { + errorForStack = null; + } + } + } + }; + + + angular.mock.inject.strictDi = function(value) { + value = arguments.length ? !!value : true; + return wasInjectorCreated() ? workFn() : workFn; + + function workFn() { + if (value !== currentSpec.$injectorStrict) { + if (currentSpec.$injector) { + throw new Error('Injector already created, can not modify strict annotations'); + } else { + currentSpec.$injectorStrict = value; + } + } + } + }; + + function InjectorState() { + this.shared = false; + this.sharedError = null; + + this.cleanupAfterEach = function() { + return !this.shared || this.sharedError; + }; + } +})(window.jasmine || window.mocha); + + +})(window, window.angular); diff --git a/public/Scripts/angular-route.js b/public/Scripts/angular-route.js new file mode 100644 index 0000000..6654d83 --- /dev/null +++ b/public/Scripts/angular-route.js @@ -0,0 +1,1069 @@ +/** + * @license AngularJS v1.5.8 + * (c) 2010-2016 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular) {'use strict'; + +/* global shallowCopy: true */ + +/** + * Creates a shallow copy of an object, an array or a primitive. + * + * Assumes that there are no proto properties for objects. + */ +function shallowCopy(src, dst) { + if (isArray(src)) { + dst = dst || []; + + for (var i = 0, ii = src.length; i < ii; i++) { + dst[i] = src[i]; + } + } else if (isObject(src)) { + dst = dst || {}; + + for (var key in src) { + if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) { + dst[key] = src[key]; + } + } + } + + return dst || src; +} + +/* global shallowCopy: false */ + +// There are necessary for `shallowCopy()` (included via `src/shallowCopy.js`). +// They are initialized inside the `$RouteProvider`, to ensure `window.angular` is available. +var isArray; +var isObject; + +/** + * @ngdoc module + * @name ngRoute + * @description + * + * # ngRoute + * + * The `ngRoute` module provides routing and deeplinking services and directives for angular apps. + * + * ## Example + * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. + * + * + *
    + */ + /* global -ngRouteModule */ +var ngRouteModule = angular.module('ngRoute', ['ng']). + provider('$route', $RouteProvider), + $routeMinErr = angular.$$minErr('ngRoute'); + +/** + * @ngdoc provider + * @name $routeProvider + * + * @description + * + * Used for configuring routes. + * + * ## Example + * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. + * + * ## Dependencies + * Requires the {@link ngRoute `ngRoute`} module to be installed. + */ +function $RouteProvider() { + isArray = angular.isArray; + isObject = angular.isObject; + + function inherit(parent, extra) { + return angular.extend(Object.create(parent), extra); + } + + var routes = {}; + + /** + * @ngdoc method + * @name $routeProvider#when + * + * @param {string} path Route path (matched against `$location.path`). If `$location.path` + * contains redundant trailing slash or is missing one, the route will still match and the + * `$location.path` will be updated to add or drop the trailing slash to exactly match the + * route definition. + * + * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up + * to the next slash are matched and stored in `$routeParams` under the given `name` + * when the route matches. + * * `path` can contain named groups starting with a colon and ending with a star: + * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name` + * when the route matches. + * * `path` can contain optional named groups with a question mark: e.g.`:name?`. + * + * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match + * `/color/brown/largecode/code/with/slashes/edit` and extract: + * + * * `color: brown` + * * `largecode: code/with/slashes`. + * + * + * @param {Object} route Mapping information to be assigned to `$route.current` on route + * match. + * + * Object properties: + * + * - `controller` – `{(string|function()=}` – Controller fn that should be associated with + * newly created scope or the name of a {@link angular.Module#controller registered + * controller} if passed as a string. + * - `controllerAs` – `{string=}` – An identifier name for a reference to the controller. + * If present, the controller will be published to scope under the `controllerAs` name. + * - `template` – `{string=|function()=}` – html template as a string or a function that + * returns an html template as a string which should be used by {@link + * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives. + * This property takes precedence over `templateUrl`. + * + * If `template` is a function, it will be called with the following parameters: + * + * - `{Array.}` - route parameters extracted from the current + * `$location.path()` by applying the current route + * + * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html + * template that should be used by {@link ngRoute.directive:ngView ngView}. + * + * If `templateUrl` is a function, it will be called with the following parameters: + * + * - `{Array.}` - route parameters extracted from the current + * `$location.path()` by applying the current route + * + * - `resolve` - `{Object.=}` - An optional map of dependencies which should + * be injected into the controller. If any of these dependencies are promises, the router + * will wait for them all to be resolved or one to be rejected before the controller is + * instantiated. + * If all the promises are resolved successfully, the values of the resolved promises are + * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is + * fired. If any of the promises are rejected the + * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. + * For easier access to the resolved dependencies from the template, the `resolve` map will + * be available on the scope of the route, under `$resolve` (by default) or a custom name + * specified by the `resolveAs` property (see below). This can be particularly useful, when + * working with {@link angular.Module#component components} as route templates.
    + *
    + * **Note:** If your scope already contains a property with this name, it will be hidden + * or overwritten. Make sure, you specify an appropriate name for this property, that + * does not collide with other properties on the scope. + *
    + * The map object is: + * + * - `key` – `{string}`: a name of a dependency to be injected into the controller. + * - `factory` - `{string|function}`: If `string` then it is an alias for a service. + * Otherwise if function, then it is {@link auto.$injector#invoke injected} + * and the return value is treated as the dependency. If the result is a promise, it is + * resolved before its value is injected into the controller. Be aware that + * `ngRoute.$routeParams` will still refer to the previous route within these resolve + * functions. Use `$route.current.params` to access the new route parameters, instead. + * + * - `resolveAs` - `{string=}` - The name under which the `resolve` map will be available on + * the scope of the route. If omitted, defaults to `$resolve`. + * + * - `redirectTo` – `{(string|function())=}` – value to update + * {@link ng.$location $location} path with and trigger route redirection. + * + * If `redirectTo` is a function, it will be called with the following parameters: + * + * - `{Object.}` - route parameters extracted from the current + * `$location.path()` by applying the current route templateUrl. + * - `{string}` - current `$location.path()` + * - `{Object}` - current `$location.search()` + * + * The custom `redirectTo` function is expected to return a string which will be used + * to update `$location.path()` and `$location.search()`. + * + * - `[reloadOnSearch=true]` - `{boolean=}` - reload route when only `$location.search()` + * or `$location.hash()` changes. + * + * If the option is set to `false` and url in the browser changes, then + * `$routeUpdate` event is broadcasted on the root scope. + * + * - `[caseInsensitiveMatch=false]` - `{boolean=}` - match routes without being case sensitive + * + * If the option is set to `true`, then the particular route can be matched without being + * case sensitive + * + * @returns {Object} self + * + * @description + * Adds a new route definition to the `$route` service. + */ + this.when = function(path, route) { + //copy original route object to preserve params inherited from proto chain + var routeCopy = shallowCopy(route); + if (angular.isUndefined(routeCopy.reloadOnSearch)) { + routeCopy.reloadOnSearch = true; + } + if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) { + routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch; + } + routes[path] = angular.extend( + routeCopy, + path && pathRegExp(path, routeCopy) + ); + + // create redirection for trailing slashes + if (path) { + var redirectPath = (path[path.length - 1] == '/') + ? path.substr(0, path.length - 1) + : path + '/'; + + routes[redirectPath] = angular.extend( + {redirectTo: path}, + pathRegExp(redirectPath, routeCopy) + ); + } + + return this; + }; + + /** + * @ngdoc property + * @name $routeProvider#caseInsensitiveMatch + * @description + * + * A boolean property indicating if routes defined + * using this provider should be matched using a case insensitive + * algorithm. Defaults to `false`. + */ + this.caseInsensitiveMatch = false; + + /** + * @param path {string} path + * @param opts {Object} options + * @return {?Object} + * + * @description + * Normalizes the given path, returning a regular expression + * and the original path. + * + * Inspired by pathRexp in visionmedia/express/lib/utils.js. + */ + function pathRegExp(path, opts) { + var insensitive = opts.caseInsensitiveMatch, + ret = { + originalPath: path, + regexp: path + }, + keys = ret.keys = []; + + path = path + .replace(/([().])/g, '\\$1') + .replace(/(\/)?:(\w+)(\*\?|[\?\*])?/g, function(_, slash, key, option) { + var optional = (option === '?' || option === '*?') ? '?' : null; + var star = (option === '*' || option === '*?') ? '*' : null; + keys.push({ name: key, optional: !!optional }); + slash = slash || ''; + return '' + + (optional ? '' : slash) + + '(?:' + + (optional ? slash : '') + + (star && '(.+?)' || '([^/]+)') + + (optional || '') + + ')' + + (optional || ''); + }) + .replace(/([\/$\*])/g, '\\$1'); + + ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : ''); + return ret; + } + + /** + * @ngdoc method + * @name $routeProvider#otherwise + * + * @description + * Sets route definition that will be used on route change when no other route definition + * is matched. + * + * @param {Object|string} params Mapping information to be assigned to `$route.current`. + * If called with a string, the value maps to `redirectTo`. + * @returns {Object} self + */ + this.otherwise = function(params) { + if (typeof params === 'string') { + params = {redirectTo: params}; + } + this.when(null, params); + return this; + }; + + + this.$get = ['$rootScope', + '$location', + '$routeParams', + '$q', + '$injector', + '$templateRequest', + '$sce', + function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) { + + /** + * @ngdoc service + * @name $route + * @requires $location + * @requires $routeParams + * + * @property {Object} current Reference to the current route definition. + * The route definition contains: + * + * - `controller`: The controller constructor as defined in the route definition. + * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for + * controller instantiation. The `locals` contain + * the resolved values of the `resolve` map. Additionally the `locals` also contain: + * + * - `$scope` - The current route scope. + * - `$template` - The current route template HTML. + * + * The `locals` will be assigned to the route scope's `$resolve` property. You can override + * the property name, using `resolveAs` in the route definition. See + * {@link ngRoute.$routeProvider $routeProvider} for more info. + * + * @property {Object} routes Object with all route configuration Objects as its properties. + * + * @description + * `$route` is used for deep-linking URLs to controllers and views (HTML partials). + * It watches `$location.url()` and tries to map the path to an existing route definition. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API. + * + * The `$route` service is typically used in conjunction with the + * {@link ngRoute.directive:ngView `ngView`} directive and the + * {@link ngRoute.$routeParams `$routeParams`} service. + * + * @example + * This example shows how changing the URL hash causes the `$route` to match a route against the + * URL, and the `ngView` pulls in the partial. + * + * + * + *
    + * Choose: + * Moby | + * Moby: Ch1 | + * Gatsby | + * Gatsby: Ch4 | + * Scarlet Letter
    + * + *
    + * + *
    + * + *
    $location.path() = {{$location.path()}}
    + *
    $route.current.templateUrl = {{$route.current.templateUrl}}
    + *
    $route.current.params = {{$route.current.params}}
    + *
    $route.current.scope.name = {{$route.current.scope.name}}
    + *
    $routeParams = {{$routeParams}}
    + *
    + *
    + * + * + * controller: {{name}}
    + * Book Id: {{params.bookId}}
    + *
    + * + * + * controller: {{name}}
    + * Book Id: {{params.bookId}}
    + * Chapter Id: {{params.chapterId}} + *
    + * + * + * angular.module('ngRouteExample', ['ngRoute']) + * + * .controller('MainController', function($scope, $route, $routeParams, $location) { + * $scope.$route = $route; + * $scope.$location = $location; + * $scope.$routeParams = $routeParams; + * }) + * + * .controller('BookController', function($scope, $routeParams) { + * $scope.name = "BookController"; + * $scope.params = $routeParams; + * }) + * + * .controller('ChapterController', function($scope, $routeParams) { + * $scope.name = "ChapterController"; + * $scope.params = $routeParams; + * }) + * + * .config(function($routeProvider, $locationProvider) { + * $routeProvider + * .when('/Book/:bookId', { + * templateUrl: 'book.html', + * controller: 'BookController', + * resolve: { + * // I will cause a 1 second delay + * delay: function($q, $timeout) { + * var delay = $q.defer(); + * $timeout(delay.resolve, 1000); + * return delay.promise; + * } + * } + * }) + * .when('/Book/:bookId/ch/:chapterId', { + * templateUrl: 'chapter.html', + * controller: 'ChapterController' + * }); + * + * // configure html5 to get links working on jsfiddle + * $locationProvider.html5Mode(true); + * }); + * + * + * + * + * it('should load and compile correct template', function() { + * element(by.linkText('Moby: Ch1')).click(); + * var content = element(by.css('[ng-view]')).getText(); + * expect(content).toMatch(/controller\: ChapterController/); + * expect(content).toMatch(/Book Id\: Moby/); + * expect(content).toMatch(/Chapter Id\: 1/); + * + * element(by.partialLinkText('Scarlet')).click(); + * + * content = element(by.css('[ng-view]')).getText(); + * expect(content).toMatch(/controller\: BookController/); + * expect(content).toMatch(/Book Id\: Scarlet/); + * }); + * + *
    + */ + + /** + * @ngdoc event + * @name $route#$routeChangeStart + * @eventType broadcast on root scope + * @description + * Broadcasted before a route change. At this point the route services starts + * resolving all of the dependencies needed for the route change to occur. + * Typically this involves fetching the view template as well as any dependencies + * defined in `resolve` route property. Once all of the dependencies are resolved + * `$routeChangeSuccess` is fired. + * + * The route change (and the `$location` change that triggered it) can be prevented + * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} + * for more details about event object. + * + * @param {Object} angularEvent Synthetic event object. + * @param {Route} next Future route information. + * @param {Route} current Current route information. + */ + + /** + * @ngdoc event + * @name $route#$routeChangeSuccess + * @eventType broadcast on root scope + * @description + * Broadcasted after a route change has happened successfully. + * The `resolve` dependencies are now available in the `current.locals` property. + * + * {@link ngRoute.directive:ngView ngView} listens for the directive + * to instantiate the controller and render the view. + * + * @param {Object} angularEvent Synthetic event object. + * @param {Route} current Current route information. + * @param {Route|Undefined} previous Previous route information, or undefined if current is + * first route entered. + */ + + /** + * @ngdoc event + * @name $route#$routeChangeError + * @eventType broadcast on root scope + * @description + * Broadcasted if any of the resolve promises are rejected. + * + * @param {Object} angularEvent Synthetic event object + * @param {Route} current Current route information. + * @param {Route} previous Previous route information. + * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise. + */ + + /** + * @ngdoc event + * @name $route#$routeUpdate + * @eventType broadcast on root scope + * @description + * The `reloadOnSearch` property has been set to false, and we are reusing the same + * instance of the Controller. + * + * @param {Object} angularEvent Synthetic event object + * @param {Route} current Current/previous route information. + */ + + var forceReload = false, + preparedRoute, + preparedRouteIsUpdateOnly, + $route = { + routes: routes, + + /** + * @ngdoc method + * @name $route#reload + * + * @description + * Causes `$route` service to reload the current route even if + * {@link ng.$location $location} hasn't changed. + * + * As a result of that, {@link ngRoute.directive:ngView ngView} + * creates new scope and reinstantiates the controller. + */ + reload: function() { + forceReload = true; + + var fakeLocationEvent = { + defaultPrevented: false, + preventDefault: function fakePreventDefault() { + this.defaultPrevented = true; + forceReload = false; + } + }; + + $rootScope.$evalAsync(function() { + prepareRoute(fakeLocationEvent); + if (!fakeLocationEvent.defaultPrevented) commitRoute(); + }); + }, + + /** + * @ngdoc method + * @name $route#updateParams + * + * @description + * Causes `$route` service to update the current URL, replacing + * current route parameters with those specified in `newParams`. + * Provided property names that match the route's path segment + * definitions will be interpolated into the location's path, while + * remaining properties will be treated as query params. + * + * @param {!Object} newParams mapping of URL parameter names to values + */ + updateParams: function(newParams) { + if (this.current && this.current.$$route) { + newParams = angular.extend({}, this.current.params, newParams); + $location.path(interpolate(this.current.$$route.originalPath, newParams)); + // interpolate modifies newParams, only query params are left + $location.search(newParams); + } else { + throw $routeMinErr('norout', 'Tried updating route when with no current route'); + } + } + }; + + $rootScope.$on('$locationChangeStart', prepareRoute); + $rootScope.$on('$locationChangeSuccess', commitRoute); + + return $route; + + ///////////////////////////////////////////////////// + + /** + * @param on {string} current url + * @param route {Object} route regexp to match the url against + * @return {?Object} + * + * @description + * Check if the route matches the current url. + * + * Inspired by match in + * visionmedia/express/lib/router/router.js. + */ + function switchRouteMatcher(on, route) { + var keys = route.keys, + params = {}; + + if (!route.regexp) return null; + + var m = route.regexp.exec(on); + if (!m) return null; + + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1]; + + var val = m[i]; + + if (key && val) { + params[key.name] = val; + } + } + return params; + } + + function prepareRoute($locationEvent) { + var lastRoute = $route.current; + + preparedRoute = parseRoute(); + preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route + && angular.equals(preparedRoute.pathParams, lastRoute.pathParams) + && !preparedRoute.reloadOnSearch && !forceReload; + + if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) { + if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) { + if ($locationEvent) { + $locationEvent.preventDefault(); + } + } + } + } + + function commitRoute() { + var lastRoute = $route.current; + var nextRoute = preparedRoute; + + if (preparedRouteIsUpdateOnly) { + lastRoute.params = nextRoute.params; + angular.copy(lastRoute.params, $routeParams); + $rootScope.$broadcast('$routeUpdate', lastRoute); + } else if (nextRoute || lastRoute) { + forceReload = false; + $route.current = nextRoute; + if (nextRoute) { + if (nextRoute.redirectTo) { + if (angular.isString(nextRoute.redirectTo)) { + $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params) + .replace(); + } else { + $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search())) + .replace(); + } + } + } + + $q.when(nextRoute). + then(resolveLocals). + then(function(locals) { + // after route change + if (nextRoute == $route.current) { + if (nextRoute) { + nextRoute.locals = locals; + angular.copy(nextRoute.params, $routeParams); + } + $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute); + } + }, function(error) { + if (nextRoute == $route.current) { + $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error); + } + }); + } + } + + function resolveLocals(route) { + if (route) { + var locals = angular.extend({}, route.resolve); + angular.forEach(locals, function(value, key) { + locals[key] = angular.isString(value) ? + $injector.get(value) : + $injector.invoke(value, null, null, key); + }); + var template = getTemplateFor(route); + if (angular.isDefined(template)) { + locals['$template'] = template; + } + return $q.all(locals); + } + } + + + function getTemplateFor(route) { + var template, templateUrl; + if (angular.isDefined(template = route.template)) { + if (angular.isFunction(template)) { + template = template(route.params); + } + } else if (angular.isDefined(templateUrl = route.templateUrl)) { + if (angular.isFunction(templateUrl)) { + templateUrl = templateUrl(route.params); + } + if (angular.isDefined(templateUrl)) { + route.loadedTemplateUrl = $sce.valueOf(templateUrl); + template = $templateRequest(templateUrl); + } + } + return template; + } + + + /** + * @returns {Object} the current active route, by matching it against the URL + */ + function parseRoute() { + // Match a route + var params, match; + angular.forEach(routes, function(route, path) { + if (!match && (params = switchRouteMatcher($location.path(), route))) { + match = inherit(route, { + params: angular.extend({}, $location.search(), params), + pathParams: params}); + match.$$route = route; + } + }); + // No route matched; fallback to "otherwise" route + return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); + } + + /** + * @returns {string} interpolation of the redirect path with the parameters + */ + function interpolate(string, params) { + var result = []; + angular.forEach((string || '').split(':'), function(segment, i) { + if (i === 0) { + result.push(segment); + } else { + var segmentMatch = segment.match(/(\w+)(?:[?*])?(.*)/); + var key = segmentMatch[1]; + result.push(params[key]); + result.push(segmentMatch[2] || ''); + delete params[key]; + } + }); + return result.join(''); + } + }]; +} + +ngRouteModule.provider('$routeParams', $RouteParamsProvider); + + +/** + * @ngdoc service + * @name $routeParams + * @requires $route + * + * @description + * The `$routeParams` service allows you to retrieve the current set of route parameters. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * The route parameters are a combination of {@link ng.$location `$location`}'s + * {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}. + * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched. + * + * In case of parameter name collision, `path` params take precedence over `search` params. + * + * The service guarantees that the identity of the `$routeParams` object will remain unchanged + * (but its properties will likely change) even when a route change occurs. + * + * Note that the `$routeParams` are only updated *after* a route change completes successfully. + * This means that you cannot rely on `$routeParams` being correct in route resolve functions. + * Instead you can use `$route.current.params` to access the new route's parameters. + * + * @example + * ```js + * // Given: + * // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby + * // Route: /Chapter/:chapterId/Section/:sectionId + * // + * // Then + * $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'} + * ``` + */ +function $RouteParamsProvider() { + this.$get = function() { return {}; }; +} + +ngRouteModule.directive('ngView', ngViewFactory); +ngRouteModule.directive('ngView', ngViewFillContentFactory); + + +/** + * @ngdoc directive + * @name ngView + * @restrict ECA + * + * @description + * # Overview + * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by + * including the rendered template of the current route into the main layout (`index.html`) file. + * Every time the current route changes, the included view changes with it according to the + * configuration of the `$route` service. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * @animations + * | Animation | Occurs | + * |----------------------------------|-------------------------------------| + * | {@link ng.$animate#enter enter} | when the new element is inserted to the DOM | + * | {@link ng.$animate#leave leave} | when the old element is removed from to the DOM | + * + * The enter and leave animation occur concurrently. + * + * @knownIssue If `ngView` is contained in an asynchronously loaded template (e.g. in another + * directive's templateUrl or in a template loaded using `ngInclude`), then you need to + * make sure that `$route` is instantiated in time to capture the initial + * `$locationChangeStart` event and load the appropriate view. One way to achieve this + * is to have it as a dependency in a `.run` block: + * `myModule.run(['$route', function() {}]);` + * + * @scope + * @priority 400 + * @param {string=} onload Expression to evaluate whenever the view updates. + * + * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll + * $anchorScroll} to scroll the viewport after the view is updated. + * + * - If the attribute is not set, disable scrolling. + * - If the attribute is set without value, enable scrolling. + * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated + * as an expression yields a truthy value. + * @example + + +
    + Choose: + Moby | + Moby: Ch1 | + Gatsby | + Gatsby: Ch4 | + Scarlet Letter
    + +
    +
    +
    +
    + +
    $location.path() = {{main.$location.path()}}
    +
    $route.current.templateUrl = {{main.$route.current.templateUrl}}
    +
    $route.current.params = {{main.$route.current.params}}
    +
    $routeParams = {{main.$routeParams}}
    +
    +
    + + +
    + controller: {{book.name}}
    + Book Id: {{book.params.bookId}}
    +
    +
    + + +
    + controller: {{chapter.name}}
    + Book Id: {{chapter.params.bookId}}
    + Chapter Id: {{chapter.params.chapterId}} +
    +
    + + + .view-animate-container { + position:relative; + height:100px!important; + background:white; + border:1px solid black; + height:40px; + overflow:hidden; + } + + .view-animate { + padding:10px; + } + + .view-animate.ng-enter, .view-animate.ng-leave { + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; + + display:block; + width:100%; + border-left:1px solid black; + + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + padding:10px; + } + + .view-animate.ng-enter { + left:100%; + } + .view-animate.ng-enter.ng-enter-active { + left:0; + } + .view-animate.ng-leave.ng-leave-active { + left:-100%; + } + + + + angular.module('ngViewExample', ['ngRoute', 'ngAnimate']) + .config(['$routeProvider', '$locationProvider', + function($routeProvider, $locationProvider) { + $routeProvider + .when('/Book/:bookId', { + templateUrl: 'book.html', + controller: 'BookCtrl', + controllerAs: 'book' + }) + .when('/Book/:bookId/ch/:chapterId', { + templateUrl: 'chapter.html', + controller: 'ChapterCtrl', + controllerAs: 'chapter' + }); + + $locationProvider.html5Mode(true); + }]) + .controller('MainCtrl', ['$route', '$routeParams', '$location', + function($route, $routeParams, $location) { + this.$route = $route; + this.$location = $location; + this.$routeParams = $routeParams; + }]) + .controller('BookCtrl', ['$routeParams', function($routeParams) { + this.name = "BookCtrl"; + this.params = $routeParams; + }]) + .controller('ChapterCtrl', ['$routeParams', function($routeParams) { + this.name = "ChapterCtrl"; + this.params = $routeParams; + }]); + + + + + it('should load and compile correct template', function() { + element(by.linkText('Moby: Ch1')).click(); + var content = element(by.css('[ng-view]')).getText(); + expect(content).toMatch(/controller\: ChapterCtrl/); + expect(content).toMatch(/Book Id\: Moby/); + expect(content).toMatch(/Chapter Id\: 1/); + + element(by.partialLinkText('Scarlet')).click(); + + content = element(by.css('[ng-view]')).getText(); + expect(content).toMatch(/controller\: BookCtrl/); + expect(content).toMatch(/Book Id\: Scarlet/); + }); + +
    + */ + + +/** + * @ngdoc event + * @name ngView#$viewContentLoaded + * @eventType emit on the current ngView scope + * @description + * Emitted every time the ngView content is reloaded. + */ +ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate']; +function ngViewFactory($route, $anchorScroll, $animate) { + return { + restrict: 'ECA', + terminal: true, + priority: 400, + transclude: 'element', + link: function(scope, $element, attr, ctrl, $transclude) { + var currentScope, + currentElement, + previousLeaveAnimation, + autoScrollExp = attr.autoscroll, + onloadExp = attr.onload || ''; + + scope.$on('$routeChangeSuccess', update); + update(); + + function cleanupLastView() { + if (previousLeaveAnimation) { + $animate.cancel(previousLeaveAnimation); + previousLeaveAnimation = null; + } + + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if (currentElement) { + previousLeaveAnimation = $animate.leave(currentElement); + previousLeaveAnimation.then(function() { + previousLeaveAnimation = null; + }); + currentElement = null; + } + } + + function update() { + var locals = $route.current && $route.current.locals, + template = locals && locals.$template; + + if (angular.isDefined(template)) { + var newScope = scope.$new(); + var current = $route.current; + + // Note: This will also link all children of ng-view that were contained in the original + // html. If that content contains controllers, ... they could pollute/change the scope. + // However, using ng-view on an element with additional content does not make sense... + // Note: We can't remove them in the cloneAttchFn of $transclude as that + // function is called before linking the content, which would apply child + // directives to non existing elements. + var clone = $transclude(newScope, function(clone) { + $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() { + if (angular.isDefined(autoScrollExp) + && (!autoScrollExp || scope.$eval(autoScrollExp))) { + $anchorScroll(); + } + }); + cleanupLastView(); + }); + + currentElement = clone; + currentScope = current.scope = newScope; + currentScope.$emit('$viewContentLoaded'); + currentScope.$eval(onloadExp); + } else { + cleanupLastView(); + } + } + } + }; +} + +// This directive is called during the $transclude call of the first `ngView` directive. +// It will replace and compile the content of the element with the loaded template. +// We need this directive so that the element content is already filled when +// the link function of another directive on the same element as ngView +// is called. +ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route']; +function ngViewFillContentFactory($compile, $controller, $route) { + return { + restrict: 'ECA', + priority: -400, + link: function(scope, $element) { + var current = $route.current, + locals = current.locals; + + $element.html(locals.$template); + + var link = $compile($element.contents()); + + if (current.controller) { + locals.$scope = scope; + var controller = $controller(current.controller, locals); + if (current.controllerAs) { + scope[current.controllerAs] = controller; + } + $element.data('$ngControllerController', controller); + $element.children().data('$ngControllerController', controller); + } + scope[current.resolveAs || '$resolve'] = locals; + + link(scope); + } + }; +} + + +})(window, window.angular); diff --git a/public/Scripts/angular-route.min.js b/public/Scripts/angular-route.min.js new file mode 100644 index 0000000..2fa073f --- /dev/null +++ b/public/Scripts/angular-route.min.js @@ -0,0 +1,16 @@ +/* + AngularJS v1.5.8 + (c) 2010-2016 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(E,d){'use strict';function y(t,l,g){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(b,e,a,c,k){function p(){m&&(g.cancel(m),m=null);h&&(h.$destroy(),h=null);n&&(m=g.leave(n),m.then(function(){m=null}),n=null)}function B(){var a=t.current&&t.current.locals;if(d.isDefined(a&&a.$template)){var a=b.$new(),c=t.current;n=k(a,function(a){g.enter(a,null,n||e).then(function(){!d.isDefined(A)||A&&!b.$eval(A)||l()});p()});h=c.scope=a;h.$emit("$viewContentLoaded"); +h.$eval(s)}else p()}var h,n,m,A=a.autoscroll,s=a.onload||"";b.$on("$routeChangeSuccess",B);B()}}}function w(d,l,g){return{restrict:"ECA",priority:-400,link:function(b,e){var a=g.current,c=a.locals;e.html(c.$template);var k=d(e.contents());if(a.controller){c.$scope=b;var p=l(a.controller,c);a.controllerAs&&(b[a.controllerAs]=p);e.data("$ngControllerController",p);e.children().data("$ngControllerController",p)}b[a.resolveAs||"$resolve"]=c;k(b)}}}var x,C,s=d.module("ngRoute",["ng"]).provider("$route", +function(){function t(b,e){return d.extend(Object.create(b),e)}function l(b,d){var a=d.caseInsensitiveMatch,c={originalPath:b,regexp:b},g=c.keys=[];b=b.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)(\*\?|[\?\*])?/g,function(b,a,d,c){b="?"===c||"*?"===c?"?":null;c="*"===c||"*?"===c?"*":null;g.push({name:d,optional:!!b});a=a||"";return""+(b?"":a)+"(?:"+(b?a:"")+(c&&"(.+?)"||"([^/]+)")+(b||"")+")"+(b||"")}).replace(/([\/$\*])/g,"\\$1");c.regexp=new RegExp("^"+b+"$",a?"i":"");return c}x=d.isArray;C= +d.isObject;var g={};this.when=function(b,e){var a;a=void 0;if(x(e)){a=a||[];for(var c=0,k=e.length;c>> 0, from = Number(arguments[2]) || 0; + from = (from < 0) ? Math.ceil(from) : Math.floor(from); + + if (from < 0) from += len; + + for (; from < len; from++) { + if (from in array && array[from] === value) return from; + } + return -1; +} + +/** + * Merges a set of parameters with all parameters inherited between the common parents of the + * current state and a given destination state. + * + * @param {Object} currentParams The value of the current state parameters ($stateParams). + * @param {Object} newParams The set of parameters which will be composited with inherited params. + * @param {Object} $current Internal definition of object representing the current state. + * @param {Object} $to Internal definition of object representing state to transition to. + */ +function inheritParams(currentParams, newParams, $current, $to) { + var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = []; + + for (var i in parents) { + if (!parents[i] || !parents[i].params) continue; + parentParams = objectKeys(parents[i].params); + if (!parentParams.length) continue; + + for (var j in parentParams) { + if (indexOf(inheritList, parentParams[j]) >= 0) continue; + inheritList.push(parentParams[j]); + inherited[parentParams[j]] = currentParams[parentParams[j]]; + } + } + return extend({}, inherited, newParams); +} + +/** + * Performs a non-strict comparison of the subset of two objects, defined by a list of keys. + * + * @param {Object} a The first object. + * @param {Object} b The second object. + * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified, + * it defaults to the list of keys in `a`. + * @return {Boolean} Returns `true` if the keys match, otherwise `false`. + */ +function equalForKeys(a, b, keys) { + if (!keys) { + keys = []; + for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility + } + + for (var i=0; i + * + * + * + * + * + * + * + * + * + * + * + * + */ +angular.module('ui.router', ['ui.router.state']); + +angular.module('ui.router.compat', ['ui.router']); + +/** + * @ngdoc object + * @name ui.router.util.$resolve + * + * @requires $q + * @requires $injector + * + * @description + * Manages resolution of (acyclic) graphs of promises. + */ +$Resolve.$inject = ['$q', '$injector']; +function $Resolve( $q, $injector) { + + var VISIT_IN_PROGRESS = 1, + VISIT_DONE = 2, + NOTHING = {}, + NO_DEPENDENCIES = [], + NO_LOCALS = NOTHING, + NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING }); + + + /** + * @ngdoc function + * @name ui.router.util.$resolve#study + * @methodOf ui.router.util.$resolve + * + * @description + * Studies a set of invocables that are likely to be used multiple times. + *
    +   * $resolve.study(invocables)(locals, parent, self)
    +   * 
    + * is equivalent to + *
    +   * $resolve.resolve(invocables, locals, parent, self)
    +   * 
    + * but the former is more efficient (in fact `resolve` just calls `study` + * internally). + * + * @param {object} invocables Invocable objects + * @return {function} a function to pass in locals, parent and self + */ + this.study = function (invocables) { + if (!isObject(invocables)) throw new Error("'invocables' must be an object"); + var invocableKeys = objectKeys(invocables || {}); + + // Perform a topological sort of invocables to build an ordered plan + var plan = [], cycle = [], visited = {}; + function visit(value, key) { + if (visited[key] === VISIT_DONE) return; + + cycle.push(key); + if (visited[key] === VISIT_IN_PROGRESS) { + cycle.splice(0, indexOf(cycle, key)); + throw new Error("Cyclic dependency: " + cycle.join(" -> ")); + } + visited[key] = VISIT_IN_PROGRESS; + + if (isString(value)) { + plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES); + } else { + var params = $injector.annotate(value); + forEach(params, function (param) { + if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param); + }); + plan.push(key, value, params); + } + + cycle.pop(); + visited[key] = VISIT_DONE; + } + forEach(invocables, visit); + invocables = cycle = visited = null; // plan is all that's required + + function isResolve(value) { + return isObject(value) && value.then && value.$$promises; + } + + return function (locals, parent, self) { + if (isResolve(locals) && self === undefined) { + self = parent; parent = locals; locals = null; + } + if (!locals) locals = NO_LOCALS; + else if (!isObject(locals)) { + throw new Error("'locals' must be an object"); + } + if (!parent) parent = NO_PARENT; + else if (!isResolve(parent)) { + throw new Error("'parent' must be a promise returned by $resolve.resolve()"); + } + + // To complete the overall resolution, we have to wait for the parent + // promise and for the promise for each invokable in our plan. + var resolution = $q.defer(), + result = resolution.promise, + promises = result.$$promises = {}, + values = extend({}, locals), + wait = 1 + plan.length/3, + merged = false; + + function done() { + // Merge parent values we haven't got yet and publish our own $$values + if (!--wait) { + if (!merged) merge(values, parent.$$values); + result.$$values = values; + result.$$promises = result.$$promises || true; // keep for isResolve() + delete result.$$inheritedValues; + resolution.resolve(values); + } + } + + function fail(reason) { + result.$$failure = reason; + resolution.reject(reason); + } + + // Short-circuit if parent has already failed + if (isDefined(parent.$$failure)) { + fail(parent.$$failure); + return result; + } + + if (parent.$$inheritedValues) { + merge(values, omit(parent.$$inheritedValues, invocableKeys)); + } + + // Merge parent values if the parent has already resolved, or merge + // parent promises and wait if the parent resolve is still in progress. + extend(promises, parent.$$promises); + if (parent.$$values) { + merged = merge(values, omit(parent.$$values, invocableKeys)); + result.$$inheritedValues = omit(parent.$$values, invocableKeys); + done(); + } else { + if (parent.$$inheritedValues) { + result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys); + } + parent.then(done, fail); + } + + // Process each invocable in the plan, but ignore any where a local of the same name exists. + for (var i=0, ii=plan.length; i} The template html as a string, or a promise + * for that string. + */ + this.fromUrl = function (url, params) { + if (isFunction(url)) url = url(params); + if (url == null) return null; + else return $http + .get(url, { cache: $templateCache, headers: { Accept: 'text/html' }}) + .then(function(response) { return response.data; }); + }; + + /** + * @ngdoc function + * @name ui.router.util.$templateFactory#fromProvider + * @methodOf ui.router.util.$templateFactory + * + * @description + * Creates a template by invoking an injectable provider function. + * + * @param {Function} provider Function to invoke via `$injector.invoke` + * @param {Object} params Parameters for the template. + * @param {Object} locals Locals to pass to `invoke`. Defaults to + * `{ params: params }`. + * @return {string|Promise.} The template html as a string, or a promise + * for that string. + */ + this.fromProvider = function (provider, params, locals) { + return $injector.invoke(provider, null, locals || { params: params }); + }; +} + +angular.module('ui.router.util').service('$templateFactory', $TemplateFactory); + +var $$UMFP; // reference to $UrlMatcherFactoryProvider + +/** + * @ngdoc object + * @name ui.router.util.type:UrlMatcher + * + * @description + * Matches URLs against patterns and extracts named parameters from the path or the search + * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list + * of search parameters. Multiple search parameter names are separated by '&'. Search parameters + * do not influence whether or not a URL is matched, but their values are passed through into + * the matched parameters returned by {@link ui.router.util.type:UrlMatcher#methods_exec exec}. + * + * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace + * syntax, which optionally allows a regular expression for the parameter to be specified: + * + * * `':'` name - colon placeholder + * * `'*'` name - catch-all placeholder + * * `'{' name '}'` - curly placeholder + * * `'{' name ':' regexp|type '}'` - curly placeholder with regexp or type name. Should the + * regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash. + * + * Parameter names may contain only word characters (latin letters, digits, and underscore) and + * must be unique within the pattern (across both path and search parameters). For colon + * placeholders or curly placeholders without an explicit regexp, a path parameter matches any + * number of characters other than '/'. For catch-all placeholders the path parameter matches + * any number of characters. + * + * Examples: + * + * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for + * trailing slashes, and patterns have to match the entire path, not just a prefix. + * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or + * '/user/bob/details'. The second path segment will be captured as the parameter 'id'. + * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax. + * * `'/user/{id:[^/]*}'` - Same as the previous example. + * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id + * parameter consists of 1 to 8 hex digits. + * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the + * path into the parameter 'path'. + * * `'/files/*path'` - ditto. + * * `'/calendar/{start:date}'` - Matches "/calendar/2014-11-12" (because the pattern defined + * in the built-in `date` Type matches `2014-11-12`) and provides a Date object in $stateParams.start + * + * @param {string} pattern The pattern to compile into a matcher. + * @param {Object} config A configuration object hash: + * @param {Object=} parentMatcher Used to concatenate the pattern/config onto + * an existing UrlMatcher + * + * * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`. + * * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`. + * + * @property {string} prefix A static prefix of this pattern. The matcher guarantees that any + * URL matching this matcher (i.e. any string for which {@link ui.router.util.type:UrlMatcher#methods_exec exec()} returns + * non-null) will start with this prefix. + * + * @property {string} source The pattern that was passed into the constructor + * + * @property {string} sourcePath The path portion of the source property + * + * @property {string} sourceSearch The search portion of the source property + * + * @property {string} regex The constructed regex that will be used to match against the url when + * it is time to determine which url will match. + * + * @returns {Object} New `UrlMatcher` object + */ +function UrlMatcher(pattern, config, parentMatcher) { + config = extend({ params: {} }, isObject(config) ? config : {}); + + // Find all placeholders and create a compiled pattern, using either classic or curly syntax: + // '*' name + // ':' name + // '{' name '}' + // '{' name ':' regexp '}' + // The regular expression is somewhat complicated due to the need to allow curly braces + // inside the regular expression. The placeholder regexp breaks down as follows: + // ([:*])([\w\[\]]+) - classic placeholder ($1 / $2) (search version has - for snake-case) + // \{([\w\[\]]+)(?:\:\s*( ... ))?\} - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case + // (?: ... | ... | ... )+ - the regexp consists of any number of atoms, an atom being either + // [^{}\\]+ - anything other than curly braces or backslash + // \\. - a backslash escape + // \{(?:[^{}\\]+|\\.)*\} - a matched set of curly braces containing other atoms + var placeholder = /([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, + searchPlaceholder = /([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, + compiled = '^', last = 0, m, + segments = this.segments = [], + parentParams = parentMatcher ? parentMatcher.params : {}, + params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet(), + paramNames = []; + + function addParameter(id, type, config, location) { + paramNames.push(id); + if (parentParams[id]) return parentParams[id]; + if (!/^\w+([-.]+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'"); + if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'"); + params[id] = new $$UMFP.Param(id, type, config, location); + return params[id]; + } + + function quoteRegExp(string, pattern, squash, optional) { + var surroundPattern = ['',''], result = string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&"); + if (!pattern) return result; + switch(squash) { + case false: surroundPattern = ['(', ')' + (optional ? "?" : "")]; break; + case true: + result = result.replace(/\/$/, ''); + surroundPattern = ['(?:\/(', ')|\/)?']; + break; + default: surroundPattern = ['(' + squash + "|", ')?']; break; + } + return result + surroundPattern[0] + pattern + surroundPattern[1]; + } + + this.source = pattern; + + // Split into static segments separated by path parameter placeholders. + // The number of segments is always 1 more than the number of parameters. + function matchDetails(m, isSearch) { + var id, regexp, segment, type, cfg, arrayMode; + id = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null + cfg = config.params[id]; + segment = pattern.substring(last, m.index); + regexp = isSearch ? m[4] : m[4] || (m[1] == '*' ? '.*' : null); + + if (regexp) { + type = $$UMFP.type(regexp) || inherit($$UMFP.type("string"), { pattern: new RegExp(regexp, config.caseInsensitive ? 'i' : undefined) }); + } + + return { + id: id, regexp: regexp, segment: segment, type: type, cfg: cfg + }; + } + + var p, param, segment; + while ((m = placeholder.exec(pattern))) { + p = matchDetails(m, false); + if (p.segment.indexOf('?') >= 0) break; // we're into the search part + + param = addParameter(p.id, p.type, p.cfg, "path"); + compiled += quoteRegExp(p.segment, param.type.pattern.source, param.squash, param.isOptional); + segments.push(p.segment); + last = placeholder.lastIndex; + } + segment = pattern.substring(last); + + // Find any search parameter names and remove them from the last segment + var i = segment.indexOf('?'); + + if (i >= 0) { + var search = this.sourceSearch = segment.substring(i); + segment = segment.substring(0, i); + this.sourcePath = pattern.substring(0, last + i); + + if (search.length > 0) { + last = 0; + while ((m = searchPlaceholder.exec(search))) { + p = matchDetails(m, true); + param = addParameter(p.id, p.type, p.cfg, "search"); + last = placeholder.lastIndex; + // check if ?& + } + } + } else { + this.sourcePath = pattern; + this.sourceSearch = ''; + } + + compiled += quoteRegExp(segment) + (config.strict === false ? '\/?' : '') + '$'; + segments.push(segment); + + this.regexp = new RegExp(compiled, config.caseInsensitive ? 'i' : undefined); + this.prefix = segments[0]; + this.$$paramNames = paramNames; +} + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#concat + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Returns a new matcher for a pattern constructed by appending the path part and adding the + * search parameters of the specified pattern to this pattern. The current pattern is not + * modified. This can be understood as creating a pattern for URLs that are relative to (or + * suffixes of) the current pattern. + * + * @example + * The following two matchers are equivalent: + *
    + * new UrlMatcher('/user/{id}?q').concat('/details?date');
    + * new UrlMatcher('/user/{id}/details?q&date');
    + * 
    + * + * @param {string} pattern The pattern to append. + * @param {Object} config An object hash of the configuration for the matcher. + * @returns {UrlMatcher} A matcher for the concatenated pattern. + */ +UrlMatcher.prototype.concat = function (pattern, config) { + // Because order of search parameters is irrelevant, we can add our own search + // parameters to the end of the new pattern. Parse the new pattern by itself + // and then join the bits together, but it's much easier to do this on a string level. + var defaultConfig = { + caseInsensitive: $$UMFP.caseInsensitive(), + strict: $$UMFP.strictMode(), + squash: $$UMFP.defaultSquashPolicy() + }; + return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this); +}; + +UrlMatcher.prototype.toString = function () { + return this.source; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#exec + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Tests the specified path against this matcher, and returns an object containing the captured + * parameter values, or null if the path does not match. The returned object contains the values + * of any search parameters that are mentioned in the pattern, but their value may be null if + * they are not present in `searchParams`. This means that search parameters are always treated + * as optional. + * + * @example + *
    + * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', {
    + *   x: '1', q: 'hello'
    + * });
    + * // returns { id: 'bob', q: 'hello', r: null }
    + * 
    + * + * @param {string} path The URL path to match, e.g. `$location.path()`. + * @param {Object} searchParams URL search parameters, e.g. `$location.search()`. + * @returns {Object} The captured parameter values. + */ +UrlMatcher.prototype.exec = function (path, searchParams) { + var m = this.regexp.exec(path); + if (!m) return null; + searchParams = searchParams || {}; + + var paramNames = this.parameters(), nTotal = paramNames.length, + nPath = this.segments.length - 1, + values = {}, i, j, cfg, paramName; + + if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'"); + + function decodePathArray(string) { + function reverseString(str) { return str.split("").reverse().join(""); } + function unquoteDashes(str) { return str.replace(/\\-/g, "-"); } + + var split = reverseString(string).split(/-(?!\\)/); + var allReversed = map(split, reverseString); + return map(allReversed, unquoteDashes).reverse(); + } + + var param, paramVal; + for (i = 0; i < nPath; i++) { + paramName = paramNames[i]; + param = this.params[paramName]; + paramVal = m[i+1]; + // if the param value matches a pre-replace pair, replace the value before decoding. + for (j = 0; j < param.replace.length; j++) { + if (param.replace[j].from === paramVal) paramVal = param.replace[j].to; + } + if (paramVal && param.array === true) paramVal = decodePathArray(paramVal); + if (isDefined(paramVal)) paramVal = param.type.decode(paramVal); + values[paramName] = param.value(paramVal); + } + for (/**/; i < nTotal; i++) { + paramName = paramNames[i]; + values[paramName] = this.params[paramName].value(searchParams[paramName]); + param = this.params[paramName]; + paramVal = searchParams[paramName]; + for (j = 0; j < param.replace.length; j++) { + if (param.replace[j].from === paramVal) paramVal = param.replace[j].to; + } + if (isDefined(paramVal)) paramVal = param.type.decode(paramVal); + values[paramName] = param.value(paramVal); + } + + return values; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#parameters + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Returns the names of all path and search parameters of this pattern in an unspecified order. + * + * @returns {Array.} An array of parameter names. Must be treated as read-only. If the + * pattern has no parameters, an empty array is returned. + */ +UrlMatcher.prototype.parameters = function (param) { + if (!isDefined(param)) return this.$$paramNames; + return this.params[param] || null; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#validates + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Checks an object hash of parameters to validate their correctness according to the parameter + * types of this `UrlMatcher`. + * + * @param {Object} params The object hash of parameters to validate. + * @returns {boolean} Returns `true` if `params` validates, otherwise `false`. + */ +UrlMatcher.prototype.validates = function (params) { + return this.params.$$validates(params); +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#format + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Creates a URL that matches this pattern by substituting the specified values + * for the path and search parameters. Null values for path parameters are + * treated as empty strings. + * + * @example + *
    + * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
    + * // returns '/user/bob?q=yes'
    + * 
    + * + * @param {Object} values the values to substitute for the parameters in this pattern. + * @returns {string} the formatted URL (path and optionally search part). + */ +UrlMatcher.prototype.format = function (values) { + values = values || {}; + var segments = this.segments, params = this.parameters(), paramset = this.params; + if (!this.validates(values)) return null; + + var i, search = false, nPath = segments.length - 1, nTotal = params.length, result = segments[0]; + + function encodeDashes(str) { // Replace dashes with encoded "\-" + return encodeURIComponent(str).replace(/-/g, function(c) { return '%5C%' + c.charCodeAt(0).toString(16).toUpperCase(); }); + } + + for (i = 0; i < nTotal; i++) { + var isPathParam = i < nPath; + var name = params[i], param = paramset[name], value = param.value(values[name]); + var isDefaultValue = param.isOptional && param.type.equals(param.value(), value); + var squash = isDefaultValue ? param.squash : false; + var encoded = param.type.encode(value); + + if (isPathParam) { + var nextSegment = segments[i + 1]; + var isFinalPathParam = i + 1 === nPath; + + if (squash === false) { + if (encoded != null) { + if (isArray(encoded)) { + result += map(encoded, encodeDashes).join("-"); + } else { + result += encodeURIComponent(encoded); + } + } + result += nextSegment; + } else if (squash === true) { + var capture = result.match(/\/$/) ? /\/?(.*)/ : /(.*)/; + result += nextSegment.match(capture)[1]; + } else if (isString(squash)) { + result += squash + nextSegment; + } + + if (isFinalPathParam && param.squash === true && result.slice(-1) === '/') result = result.slice(0, -1); + } else { + if (encoded == null || (isDefaultValue && squash !== false)) continue; + if (!isArray(encoded)) encoded = [ encoded ]; + if (encoded.length === 0) continue; + encoded = map(encoded, encodeURIComponent).join('&' + name + '='); + result += (search ? '&' : '?') + (name + '=' + encoded); + search = true; + } + } + + return result; +}; + +/** + * @ngdoc object + * @name ui.router.util.type:Type + * + * @description + * Implements an interface to define custom parameter types that can be decoded from and encoded to + * string parameters matched in a URL. Used by {@link ui.router.util.type:UrlMatcher `UrlMatcher`} + * objects when matching or formatting URLs, or comparing or validating parameter values. + * + * See {@link ui.router.util.$urlMatcherFactory#methods_type `$urlMatcherFactory#type()`} for more + * information on registering custom types. + * + * @param {Object} config A configuration object which contains the custom type definition. The object's + * properties will override the default methods and/or pattern in `Type`'s public interface. + * @example + *
    + * {
    + *   decode: function(val) { return parseInt(val, 10); },
    + *   encode: function(val) { return val && val.toString(); },
    + *   equals: function(a, b) { return this.is(a) && a === b; },
    + *   is: function(val) { return angular.isNumber(val) isFinite(val) && val % 1 === 0; },
    + *   pattern: /\d+/
    + * }
    + * 
    + * + * @property {RegExp} pattern The regular expression pattern used to match values of this type when + * coming from a substring of a URL. + * + * @returns {Object} Returns a new `Type` object. + */ +function Type(config) { + extend(this, config); +} + +/** + * @ngdoc function + * @name ui.router.util.type:Type#is + * @methodOf ui.router.util.type:Type + * + * @description + * Detects whether a value is of a particular type. Accepts a native (decoded) value + * and determines whether it matches the current `Type` object. + * + * @param {*} val The value to check. + * @param {string} key Optional. If the type check is happening in the context of a specific + * {@link ui.router.util.type:UrlMatcher `UrlMatcher`} object, this is the name of the + * parameter in which `val` is stored. Can be used for meta-programming of `Type` objects. + * @returns {Boolean} Returns `true` if the value matches the type, otherwise `false`. + */ +Type.prototype.is = function(val, key) { + return true; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:Type#encode + * @methodOf ui.router.util.type:Type + * + * @description + * Encodes a custom/native type value to a string that can be embedded in a URL. Note that the + * return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it + * only needs to be a representation of `val` that has been coerced to a string. + * + * @param {*} val The value to encode. + * @param {string} key The name of the parameter in which `val` is stored. Can be used for + * meta-programming of `Type` objects. + * @returns {string} Returns a string representation of `val` that can be encoded in a URL. + */ +Type.prototype.encode = function(val, key) { + return val; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:Type#decode + * @methodOf ui.router.util.type:Type + * + * @description + * Converts a parameter value (from URL string or transition param) to a custom/native value. + * + * @param {string} val The URL parameter value to decode. + * @param {string} key The name of the parameter in which `val` is stored. Can be used for + * meta-programming of `Type` objects. + * @returns {*} Returns a custom representation of the URL parameter value. + */ +Type.prototype.decode = function(val, key) { + return val; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:Type#equals + * @methodOf ui.router.util.type:Type + * + * @description + * Determines whether two decoded values are equivalent. + * + * @param {*} a A value to compare against. + * @param {*} b A value to compare against. + * @returns {Boolean} Returns `true` if the values are equivalent/equal, otherwise `false`. + */ +Type.prototype.equals = function(a, b) { + return a == b; +}; + +Type.prototype.$subPattern = function() { + var sub = this.pattern.toString(); + return sub.substr(1, sub.length - 2); +}; + +Type.prototype.pattern = /.*/; + +Type.prototype.toString = function() { return "{Type:" + this.name + "}"; }; + +/** Given an encoded string, or a decoded object, returns a decoded object */ +Type.prototype.$normalize = function(val) { + return this.is(val) ? val : this.decode(val); +}; + +/* + * Wraps an existing custom Type as an array of Type, depending on 'mode'. + * e.g.: + * - urlmatcher pattern "/path?{queryParam[]:int}" + * - url: "/path?queryParam=1&queryParam=2 + * - $stateParams.queryParam will be [1, 2] + * if `mode` is "auto", then + * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1 + * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2] + */ +Type.prototype.$asArray = function(mode, isSearch) { + if (!mode) return this; + if (mode === "auto" && !isSearch) throw new Error("'auto' array mode is for query parameters only"); + + function ArrayType(type, mode) { + function bindTo(type, callbackName) { + return function() { + return type[callbackName].apply(type, arguments); + }; + } + + // Wrap non-array value as array + function arrayWrap(val) { return isArray(val) ? val : (isDefined(val) ? [ val ] : []); } + // Unwrap array value for "auto" mode. Return undefined for empty array. + function arrayUnwrap(val) { + switch(val.length) { + case 0: return undefined; + case 1: return mode === "auto" ? val[0] : val; + default: return val; + } + } + function falsey(val) { return !val; } + + // Wraps type (.is/.encode/.decode) functions to operate on each value of an array + function arrayHandler(callback, allTruthyMode) { + return function handleArray(val) { + if (isArray(val) && val.length === 0) return val; + val = arrayWrap(val); + var result = map(val, callback); + if (allTruthyMode === true) + return filter(result, falsey).length === 0; + return arrayUnwrap(result); + }; + } + + // Wraps type (.equals) functions to operate on each value of an array + function arrayEqualsHandler(callback) { + return function handleArray(val1, val2) { + var left = arrayWrap(val1), right = arrayWrap(val2); + if (left.length !== right.length) return false; + for (var i = 0; i < left.length; i++) { + if (!callback(left[i], right[i])) return false; + } + return true; + }; + } + + this.encode = arrayHandler(bindTo(type, 'encode')); + this.decode = arrayHandler(bindTo(type, 'decode')); + this.is = arrayHandler(bindTo(type, 'is'), true); + this.equals = arrayEqualsHandler(bindTo(type, 'equals')); + this.pattern = type.pattern; + this.$normalize = arrayHandler(bindTo(type, '$normalize')); + this.name = type.name; + this.$arrayMode = mode; + } + + return new ArrayType(this, mode); +}; + + + +/** + * @ngdoc object + * @name ui.router.util.$urlMatcherFactory + * + * @description + * Factory for {@link ui.router.util.type:UrlMatcher `UrlMatcher`} instances. The factory + * is also available to providers under the name `$urlMatcherFactoryProvider`. + */ +function $UrlMatcherFactory() { + $$UMFP = this; + + var isCaseInsensitive = false, isStrictMode = true, defaultSquashPolicy = false; + + // Use tildes to pre-encode slashes. + // If the slashes are simply URLEncoded, the browser can choose to pre-decode them, + // and bidirectional encoding/decoding fails. + // Tilde was chosen because it's not a RFC 3986 section 2.2 Reserved Character + function valToString(val) { return val != null ? val.toString().replace(/~/g, "~~").replace(/\//g, "~2F") : val; } + function valFromString(val) { return val != null ? val.toString().replace(/~2F/g, "/").replace(/~~/g, "~") : val; } + + var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = { + "string": { + encode: valToString, + decode: valFromString, + // TODO: in 1.0, make string .is() return false if value is undefined/null by default. + // In 0.2.x, string params are optional by default for backwards compat + is: function(val) { return val == null || !isDefined(val) || typeof val === "string"; }, + pattern: /[^/]*/ + }, + "int": { + encode: valToString, + decode: function(val) { return parseInt(val, 10); }, + is: function(val) { return isDefined(val) && this.decode(val.toString()) === val; }, + pattern: /\d+/ + }, + "bool": { + encode: function(val) { return val ? 1 : 0; }, + decode: function(val) { return parseInt(val, 10) !== 0; }, + is: function(val) { return val === true || val === false; }, + pattern: /0|1/ + }, + "date": { + encode: function (val) { + if (!this.is(val)) + return undefined; + return [ val.getFullYear(), + ('0' + (val.getMonth() + 1)).slice(-2), + ('0' + val.getDate()).slice(-2) + ].join("-"); + }, + decode: function (val) { + if (this.is(val)) return val; + var match = this.capture.exec(val); + return match ? new Date(match[1], match[2] - 1, match[3]) : undefined; + }, + is: function(val) { return val instanceof Date && !isNaN(val.valueOf()); }, + equals: function (a, b) { return this.is(a) && this.is(b) && a.toISOString() === b.toISOString(); }, + pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/, + capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/ + }, + "json": { + encode: angular.toJson, + decode: angular.fromJson, + is: angular.isObject, + equals: angular.equals, + pattern: /[^/]*/ + }, + "any": { // does not encode/decode + encode: angular.identity, + decode: angular.identity, + equals: angular.equals, + pattern: /.*/ + } + }; + + function getDefaultConfig() { + return { + strict: isStrictMode, + caseInsensitive: isCaseInsensitive + }; + } + + function isInjectable(value) { + return (isFunction(value) || (isArray(value) && isFunction(value[value.length - 1]))); + } + + /** + * [Internal] Get the default value of a parameter, which may be an injectable function. + */ + $UrlMatcherFactory.$$getDefaultValue = function(config) { + if (!isInjectable(config.value)) return config.value; + if (!injector) throw new Error("Injectable functions cannot be called at configuration time"); + return injector.invoke(config.value); + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#caseInsensitive + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Defines whether URL matching should be case sensitive (the default behavior), or not. + * + * @param {boolean} value `false` to match URL in a case sensitive manner; otherwise `true`; + * @returns {boolean} the current value of caseInsensitive + */ + this.caseInsensitive = function(value) { + if (isDefined(value)) + isCaseInsensitive = value; + return isCaseInsensitive; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#strictMode + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Defines whether URLs should match trailing slashes, or not (the default behavior). + * + * @param {boolean=} value `false` to match trailing slashes in URLs, otherwise `true`. + * @returns {boolean} the current value of strictMode + */ + this.strictMode = function(value) { + if (isDefined(value)) + isStrictMode = value; + return isStrictMode; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#defaultSquashPolicy + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Sets the default behavior when generating or matching URLs with default parameter values. + * + * @param {string} value A string that defines the default parameter URL squashing behavior. + * `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL + * `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the + * parameter is surrounded by slashes, squash (remove) one slash from the URL + * any other string, e.g. "~": When generating an href with a default parameter value, squash (remove) + * the parameter value from the URL and replace it with this string. + */ + this.defaultSquashPolicy = function(value) { + if (!isDefined(value)) return defaultSquashPolicy; + if (value !== true && value !== false && !isString(value)) + throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string"); + defaultSquashPolicy = value; + return value; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#compile + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Creates a {@link ui.router.util.type:UrlMatcher `UrlMatcher`} for the specified pattern. + * + * @param {string} pattern The URL pattern. + * @param {Object} config The config object hash. + * @returns {UrlMatcher} The UrlMatcher. + */ + this.compile = function (pattern, config) { + return new UrlMatcher(pattern, extend(getDefaultConfig(), config)); + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#isMatcher + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Returns true if the specified object is a `UrlMatcher`, or false otherwise. + * + * @param {Object} object The object to perform the type check against. + * @returns {Boolean} Returns `true` if the object matches the `UrlMatcher` interface, by + * implementing all the same methods. + */ + this.isMatcher = function (o) { + if (!isObject(o)) return false; + var result = true; + + forEach(UrlMatcher.prototype, function(val, name) { + if (isFunction(val)) { + result = result && (isDefined(o[name]) && isFunction(o[name])); + } + }); + return result; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#type + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Registers a custom {@link ui.router.util.type:Type `Type`} object that can be used to + * generate URLs with typed parameters. + * + * @param {string} name The type name. + * @param {Object|Function} definition The type definition. See + * {@link ui.router.util.type:Type `Type`} for information on the values accepted. + * @param {Object|Function} definitionFn (optional) A function that is injected before the app + * runtime starts. The result of this function is merged into the existing `definition`. + * See {@link ui.router.util.type:Type `Type`} for information on the values accepted. + * + * @returns {Object} Returns `$urlMatcherFactoryProvider`. + * + * @example + * This is a simple example of a custom type that encodes and decodes items from an + * array, using the array index as the URL-encoded value: + * + *
    +   * var list = ['John', 'Paul', 'George', 'Ringo'];
    +   *
    +   * $urlMatcherFactoryProvider.type('listItem', {
    +   *   encode: function(item) {
    +   *     // Represent the list item in the URL using its corresponding index
    +   *     return list.indexOf(item);
    +   *   },
    +   *   decode: function(item) {
    +   *     // Look up the list item by index
    +   *     return list[parseInt(item, 10)];
    +   *   },
    +   *   is: function(item) {
    +   *     // Ensure the item is valid by checking to see that it appears
    +   *     // in the list
    +   *     return list.indexOf(item) > -1;
    +   *   }
    +   * });
    +   *
    +   * $stateProvider.state('list', {
    +   *   url: "/list/{item:listItem}",
    +   *   controller: function($scope, $stateParams) {
    +   *     console.log($stateParams.item);
    +   *   }
    +   * });
    +   *
    +   * // ...
    +   *
    +   * // Changes URL to '/list/3', logs "Ringo" to the console
    +   * $state.go('list', { item: "Ringo" });
    +   * 
    + * + * This is a more complex example of a type that relies on dependency injection to + * interact with services, and uses the parameter name from the URL to infer how to + * handle encoding and decoding parameter values: + * + *
    +   * // Defines a custom type that gets a value from a service,
    +   * // where each service gets different types of values from
    +   * // a backend API:
    +   * $urlMatcherFactoryProvider.type('dbObject', {}, function(Users, Posts) {
    +   *
    +   *   // Matches up services to URL parameter names
    +   *   var services = {
    +   *     user: Users,
    +   *     post: Posts
    +   *   };
    +   *
    +   *   return {
    +   *     encode: function(object) {
    +   *       // Represent the object in the URL using its unique ID
    +   *       return object.id;
    +   *     },
    +   *     decode: function(value, key) {
    +   *       // Look up the object by ID, using the parameter
    +   *       // name (key) to call the correct service
    +   *       return services[key].findById(value);
    +   *     },
    +   *     is: function(object, key) {
    +   *       // Check that object is a valid dbObject
    +   *       return angular.isObject(object) && object.id && services[key];
    +   *     }
    +   *     equals: function(a, b) {
    +   *       // Check the equality of decoded objects by comparing
    +   *       // their unique IDs
    +   *       return a.id === b.id;
    +   *     }
    +   *   };
    +   * });
    +   *
    +   * // In a config() block, you can then attach URLs with
    +   * // type-annotated parameters:
    +   * $stateProvider.state('users', {
    +   *   url: "/users",
    +   *   // ...
    +   * }).state('users.item', {
    +   *   url: "/{user:dbObject}",
    +   *   controller: function($scope, $stateParams) {
    +   *     // $stateParams.user will now be an object returned from
    +   *     // the Users service
    +   *   },
    +   *   // ...
    +   * });
    +   * 
    + */ + this.type = function (name, definition, definitionFn) { + if (!isDefined(definition)) return $types[name]; + if ($types.hasOwnProperty(name)) throw new Error("A type named '" + name + "' has already been defined."); + + $types[name] = new Type(extend({ name: name }, definition)); + if (definitionFn) { + typeQueue.push({ name: name, def: definitionFn }); + if (!enqueue) flushTypeQueue(); + } + return this; + }; + + // `flushTypeQueue()` waits until `$urlMatcherFactory` is injected before invoking the queued `definitionFn`s + function flushTypeQueue() { + while(typeQueue.length) { + var type = typeQueue.shift(); + if (type.pattern) throw new Error("You cannot override a type's .pattern at runtime."); + angular.extend($types[type.name], injector.invoke(type.def)); + } + } + + // Register default types. Store them in the prototype of $types. + forEach(defaultTypes, function(type, name) { $types[name] = new Type(extend({name: name}, type)); }); + $types = inherit($types, {}); + + /* No need to document $get, since it returns this */ + this.$get = ['$injector', function ($injector) { + injector = $injector; + enqueue = false; + flushTypeQueue(); + + forEach(defaultTypes, function(type, name) { + if (!$types[name]) $types[name] = new Type(type); + }); + return this; + }]; + + this.Param = function Param(id, type, config, location) { + var self = this; + config = unwrapShorthand(config); + type = getType(config, type, location); + var arrayMode = getArrayMode(); + type = arrayMode ? type.$asArray(arrayMode, location === "search") : type; + if (type.name === "string" && !arrayMode && location === "path" && config.value === undefined) + config.value = ""; // for 0.2.x; in 0.3.0+ do not automatically default to "" + var isOptional = config.value !== undefined; + var squash = getSquashPolicy(config, isOptional); + var replace = getReplace(config, arrayMode, isOptional, squash); + + function unwrapShorthand(config) { + var keys = isObject(config) ? objectKeys(config) : []; + var isShorthand = indexOf(keys, "value") === -1 && indexOf(keys, "type") === -1 && + indexOf(keys, "squash") === -1 && indexOf(keys, "array") === -1; + if (isShorthand) config = { value: config }; + config.$$fn = isInjectable(config.value) ? config.value : function () { return config.value; }; + return config; + } + + function getType(config, urlType, location) { + if (config.type && urlType) throw new Error("Param '"+id+"' has two type configurations."); + if (urlType) return urlType; + if (!config.type) return (location === "config" ? $types.any : $types.string); + + if (angular.isString(config.type)) + return $types[config.type]; + if (config.type instanceof Type) + return config.type; + return new Type(config.type); + } + + // array config: param name (param[]) overrides default settings. explicit config overrides param name. + function getArrayMode() { + var arrayDefaults = { array: (location === "search" ? "auto" : false) }; + var arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {}; + return extend(arrayDefaults, arrayParamNomenclature, config).array; + } + + /** + * returns false, true, or the squash value to indicate the "default parameter url squash policy". + */ + function getSquashPolicy(config, isOptional) { + var squash = config.squash; + if (!isOptional || squash === false) return false; + if (!isDefined(squash) || squash == null) return defaultSquashPolicy; + if (squash === true || isString(squash)) return squash; + throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string"); + } + + function getReplace(config, arrayMode, isOptional, squash) { + var replace, configuredKeys, defaultPolicy = [ + { from: "", to: (isOptional || arrayMode ? undefined : "") }, + { from: null, to: (isOptional || arrayMode ? undefined : "") } + ]; + replace = isArray(config.replace) ? config.replace : []; + if (isString(squash)) + replace.push({ from: squash, to: undefined }); + configuredKeys = map(replace, function(item) { return item.from; } ); + return filter(defaultPolicy, function(item) { return indexOf(configuredKeys, item.from) === -1; }).concat(replace); + } + + /** + * [Internal] Get the default value of a parameter, which may be an injectable function. + */ + function $$getDefaultValue() { + if (!injector) throw new Error("Injectable functions cannot be called at configuration time"); + var defaultValue = injector.invoke(config.$$fn); + if (defaultValue !== null && defaultValue !== undefined && !self.type.is(defaultValue)) + throw new Error("Default value (" + defaultValue + ") for parameter '" + self.id + "' is not an instance of Type (" + self.type.name + ")"); + return defaultValue; + } + + /** + * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the + * default value, which may be the result of an injectable function. + */ + function $value(value) { + function hasReplaceVal(val) { return function(obj) { return obj.from === val; }; } + function $replace(value) { + var replacement = map(filter(self.replace, hasReplaceVal(value)), function(obj) { return obj.to; }); + return replacement.length ? replacement[0] : value; + } + value = $replace(value); + return !isDefined(value) ? $$getDefaultValue() : self.type.$normalize(value); + } + + function toString() { return "{Param:" + id + " " + type + " squash: '" + squash + "' optional: " + isOptional + "}"; } + + extend(this, { + id: id, + type: type, + location: location, + array: arrayMode, + squash: squash, + replace: replace, + isOptional: isOptional, + value: $value, + dynamic: undefined, + config: config, + toString: toString + }); + }; + + function ParamSet(params) { + extend(this, params || {}); + } + + ParamSet.prototype = { + $$new: function() { + return inherit(this, extend(new ParamSet(), { $$parent: this})); + }, + $$keys: function () { + var keys = [], chain = [], parent = this, + ignore = objectKeys(ParamSet.prototype); + while (parent) { chain.push(parent); parent = parent.$$parent; } + chain.reverse(); + forEach(chain, function(paramset) { + forEach(objectKeys(paramset), function(key) { + if (indexOf(keys, key) === -1 && indexOf(ignore, key) === -1) keys.push(key); + }); + }); + return keys; + }, + $$values: function(paramValues) { + var values = {}, self = this; + forEach(self.$$keys(), function(key) { + values[key] = self[key].value(paramValues && paramValues[key]); + }); + return values; + }, + $$equals: function(paramValues1, paramValues2) { + var equal = true, self = this; + forEach(self.$$keys(), function(key) { + var left = paramValues1 && paramValues1[key], right = paramValues2 && paramValues2[key]; + if (!self[key].type.equals(left, right)) equal = false; + }); + return equal; + }, + $$validates: function $$validate(paramValues) { + var keys = this.$$keys(), i, param, rawVal, normalized, encoded; + for (i = 0; i < keys.length; i++) { + param = this[keys[i]]; + rawVal = paramValues[keys[i]]; + if ((rawVal === undefined || rawVal === null) && param.isOptional) + break; // There was no parameter value, but the param is optional + normalized = param.type.$normalize(rawVal); + if (!param.type.is(normalized)) + return false; // The value was not of the correct Type, and could not be decoded to the correct Type + encoded = param.type.encode(normalized); + if (angular.isString(encoded) && !param.type.pattern.exec(encoded)) + return false; // The value was of the correct type, but when encoded, did not match the Type's regexp + } + return true; + }, + $$parent: undefined + }; + + this.ParamSet = ParamSet; +} + +// Register as a provider so it's available to other providers +angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory); +angular.module('ui.router.util').run(['$urlMatcherFactory', function($urlMatcherFactory) { }]); + +/** + * @ngdoc object + * @name ui.router.router.$urlRouterProvider + * + * @requires ui.router.util.$urlMatcherFactoryProvider + * @requires $locationProvider + * + * @description + * `$urlRouterProvider` has the responsibility of watching `$location`. + * When `$location` changes it runs through a list of rules one by one until a + * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify + * a url in a state configuration. All urls are compiled into a UrlMatcher object. + * + * There are several methods on `$urlRouterProvider` that make it useful to use directly + * in your module config. + */ +$UrlRouterProvider.$inject = ['$locationProvider', '$urlMatcherFactoryProvider']; +function $UrlRouterProvider( $locationProvider, $urlMatcherFactory) { + var rules = [], otherwise = null, interceptDeferred = false, listener; + + // Returns a string that is a prefix of all strings matching the RegExp + function regExpPrefix(re) { + var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source); + return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : ''; + } + + // Interpolates matched values into a String.replace()-style pattern + function interpolate(pattern, match) { + return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) { + return match[what === '$' ? 0 : Number(what)]; + }); + } + + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#rule + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Defines rules that are used by `$urlRouterProvider` to find matches for + * specific URLs. + * + * @example + *
    +   * var app = angular.module('app', ['ui.router.router']);
    +   *
    +   * app.config(function ($urlRouterProvider) {
    +   *   // Here's an example of how you might allow case insensitive urls
    +   *   $urlRouterProvider.rule(function ($injector, $location) {
    +   *     var path = $location.path(),
    +   *         normalized = path.toLowerCase();
    +   *
    +   *     if (path !== normalized) {
    +   *       return normalized;
    +   *     }
    +   *   });
    +   * });
    +   * 
    + * + * @param {function} rule Handler function that takes `$injector` and `$location` + * services as arguments. You can use them to return a valid path as a string. + * + * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance + */ + this.rule = function (rule) { + if (!isFunction(rule)) throw new Error("'rule' must be a function"); + rules.push(rule); + return this; + }; + + /** + * @ngdoc object + * @name ui.router.router.$urlRouterProvider#otherwise + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Defines a path that is used when an invalid route is requested. + * + * @example + *
    +   * var app = angular.module('app', ['ui.router.router']);
    +   *
    +   * app.config(function ($urlRouterProvider) {
    +   *   // if the path doesn't match any of the urls you configured
    +   *   // otherwise will take care of routing the user to the
    +   *   // specified url
    +   *   $urlRouterProvider.otherwise('/index');
    +   *
    +   *   // Example of using function rule as param
    +   *   $urlRouterProvider.otherwise(function ($injector, $location) {
    +   *     return '/a/valid/url';
    +   *   });
    +   * });
    +   * 
    + * + * @param {string|function} rule The url path you want to redirect to or a function + * rule that returns the url path. The function version is passed two params: + * `$injector` and `$location` services, and must return a url string. + * + * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance + */ + this.otherwise = function (rule) { + if (isString(rule)) { + var redirect = rule; + rule = function () { return redirect; }; + } + else if (!isFunction(rule)) throw new Error("'rule' must be a function"); + otherwise = rule; + return this; + }; + + + function handleIfMatch($injector, handler, match) { + if (!match) return false; + var result = $injector.invoke(handler, handler, { $match: match }); + return isDefined(result) ? result : true; + } + + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#when + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Registers a handler for a given url matching. + * + * If the handler is a string, it is + * treated as a redirect, and is interpolated according to the syntax of match + * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise). + * + * If the handler is a function, it is injectable. It gets invoked if `$location` + * matches. You have the option of inject the match object as `$match`. + * + * The handler can return + * + * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter` + * will continue trying to find another one that matches. + * - **string** which is treated as a redirect and passed to `$location.url()` + * - **void** or any **truthy** value tells `$urlRouter` that the url was handled. + * + * @example + *
    +   * var app = angular.module('app', ['ui.router.router']);
    +   *
    +   * app.config(function ($urlRouterProvider) {
    +   *   $urlRouterProvider.when($state.url, function ($match, $stateParams) {
    +   *     if ($state.$current.navigable !== state ||
    +   *         !equalForKeys($match, $stateParams) {
    +   *      $state.transitionTo(state, $match, false);
    +   *     }
    +   *   });
    +   * });
    +   * 
    + * + * @param {string|object} what The incoming path that you want to redirect. + * @param {string|function} handler The path you want to redirect your user to. + */ + this.when = function (what, handler) { + var redirect, handlerIsString = isString(handler); + if (isString(what)) what = $urlMatcherFactory.compile(what); + + if (!handlerIsString && !isFunction(handler) && !isArray(handler)) + throw new Error("invalid 'handler' in when()"); + + var strategies = { + matcher: function (what, handler) { + if (handlerIsString) { + redirect = $urlMatcherFactory.compile(handler); + handler = ['$match', function ($match) { return redirect.format($match); }]; + } + return extend(function ($injector, $location) { + return handleIfMatch($injector, handler, what.exec($location.path(), $location.search())); + }, { + prefix: isString(what.prefix) ? what.prefix : '' + }); + }, + regex: function (what, handler) { + if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky"); + + if (handlerIsString) { + redirect = handler; + handler = ['$match', function ($match) { return interpolate(redirect, $match); }]; + } + return extend(function ($injector, $location) { + return handleIfMatch($injector, handler, what.exec($location.path())); + }, { + prefix: regExpPrefix(what) + }); + } + }; + + var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp }; + + for (var n in check) { + if (check[n]) return this.rule(strategies[n](what, handler)); + } + + throw new Error("invalid 'what' in when()"); + }; + + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#deferIntercept + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Disables (or enables) deferring location change interception. + * + * If you wish to customize the behavior of syncing the URL (for example, if you wish to + * defer a transition but maintain the current URL), call this method at configuration time. + * Then, at run time, call `$urlRouter.listen()` after you have configured your own + * `$locationChangeSuccess` event handler. + * + * @example + *
    +   * var app = angular.module('app', ['ui.router.router']);
    +   *
    +   * app.config(function ($urlRouterProvider) {
    +   *
    +   *   // Prevent $urlRouter from automatically intercepting URL changes;
    +   *   // this allows you to configure custom behavior in between
    +   *   // location changes and route synchronization:
    +   *   $urlRouterProvider.deferIntercept();
    +   *
    +   * }).run(function ($rootScope, $urlRouter, UserService) {
    +   *
    +   *   $rootScope.$on('$locationChangeSuccess', function(e) {
    +   *     // UserService is an example service for managing user state
    +   *     if (UserService.isLoggedIn()) return;
    +   *
    +   *     // Prevent $urlRouter's default handler from firing
    +   *     e.preventDefault();
    +   *
    +   *     UserService.handleLogin().then(function() {
    +   *       // Once the user has logged in, sync the current URL
    +   *       // to the router:
    +   *       $urlRouter.sync();
    +   *     });
    +   *   });
    +   *
    +   *   // Configures $urlRouter's listener *after* your custom listener
    +   *   $urlRouter.listen();
    +   * });
    +   * 
    + * + * @param {boolean} defer Indicates whether to defer location change interception. Passing + no parameter is equivalent to `true`. + */ + this.deferIntercept = function (defer) { + if (defer === undefined) defer = true; + interceptDeferred = defer; + }; + + /** + * @ngdoc object + * @name ui.router.router.$urlRouter + * + * @requires $location + * @requires $rootScope + * @requires $injector + * @requires $browser + * + * @description + * + */ + this.$get = $get; + $get.$inject = ['$location', '$rootScope', '$injector', '$browser', '$sniffer']; + function $get( $location, $rootScope, $injector, $browser, $sniffer) { + + var baseHref = $browser.baseHref(), location = $location.url(), lastPushedUrl; + + function appendBasePath(url, isHtml5, absolute) { + if (baseHref === '/') return url; + if (isHtml5) return baseHref.slice(0, -1) + url; + if (absolute) return baseHref.slice(1) + url; + return url; + } + + // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree + function update(evt) { + if (evt && evt.defaultPrevented) return; + var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl; + lastPushedUrl = undefined; + // TODO: Re-implement this in 1.0 for https://github.com/angular-ui/ui-router/issues/1573 + //if (ignoreUpdate) return true; + + function check(rule) { + var handled = rule($injector, $location); + + if (!handled) return false; + if (isString(handled)) $location.replace().url(handled); + return true; + } + var n = rules.length, i; + + for (i = 0; i < n; i++) { + if (check(rules[i])) return; + } + // always check otherwise last to allow dynamic updates to the set of rules + if (otherwise) check(otherwise); + } + + function listen() { + listener = listener || $rootScope.$on('$locationChangeSuccess', update); + return listener; + } + + if (!interceptDeferred) listen(); + + return { + /** + * @ngdoc function + * @name ui.router.router.$urlRouter#sync + * @methodOf ui.router.router.$urlRouter + * + * @description + * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`. + * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event, + * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed + * with the transition by calling `$urlRouter.sync()`. + * + * @example + *
    +       * angular.module('app', ['ui.router'])
    +       *   .run(function($rootScope, $urlRouter) {
    +       *     $rootScope.$on('$locationChangeSuccess', function(evt) {
    +       *       // Halt state change from even starting
    +       *       evt.preventDefault();
    +       *       // Perform custom logic
    +       *       var meetsRequirement = ...
    +       *       // Continue with the update and state transition if logic allows
    +       *       if (meetsRequirement) $urlRouter.sync();
    +       *     });
    +       * });
    +       * 
    + */ + sync: function() { + update(); + }, + + listen: function() { + return listen(); + }, + + update: function(read) { + if (read) { + location = $location.url(); + return; + } + if ($location.url() === location) return; + + $location.url(location); + $location.replace(); + }, + + push: function(urlMatcher, params, options) { + var url = urlMatcher.format(params || {}); + + // Handle the special hash param, if needed + if (url !== null && params && params['#']) { + url += '#' + params['#']; + } + + $location.url(url); + lastPushedUrl = options && options.$$avoidResync ? $location.url() : undefined; + if (options && options.replace) $location.replace(); + }, + + /** + * @ngdoc function + * @name ui.router.router.$urlRouter#href + * @methodOf ui.router.router.$urlRouter + * + * @description + * A URL generation method that returns the compiled URL for a given + * {@link ui.router.util.type:UrlMatcher `UrlMatcher`}, populated with the provided parameters. + * + * @example + *
    +       * $bob = $urlRouter.href(new UrlMatcher("/about/:person"), {
    +       *   person: "bob"
    +       * });
    +       * // $bob == "/about/bob";
    +       * 
    + * + * @param {UrlMatcher} urlMatcher The `UrlMatcher` object which is used as the template of the URL to generate. + * @param {object=} params An object of parameter values to fill the matcher's required parameters. + * @param {object=} options Options object. The options are: + * + * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". + * + * @returns {string} Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher` + */ + href: function(urlMatcher, params, options) { + if (!urlMatcher.validates(params)) return null; + + var isHtml5 = $locationProvider.html5Mode(); + if (angular.isObject(isHtml5)) { + isHtml5 = isHtml5.enabled; + } + + isHtml5 = isHtml5 && $sniffer.history; + + var url = urlMatcher.format(params); + options = options || {}; + + if (!isHtml5 && url !== null) { + url = "#" + $locationProvider.hashPrefix() + url; + } + + // Handle special hash param, if needed + if (url !== null && params && params['#']) { + url += '#' + params['#']; + } + + url = appendBasePath(url, isHtml5, options.absolute); + + if (!options.absolute || !url) { + return url; + } + + var slash = (!isHtml5 && url ? '/' : ''), port = $location.port(); + port = (port === 80 || port === 443 ? '' : ':' + port); + + return [$location.protocol(), '://', $location.host(), port, slash, url].join(''); + } + }; + } +} + +angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider); + +/** + * @ngdoc object + * @name ui.router.state.$stateProvider + * + * @requires ui.router.router.$urlRouterProvider + * @requires ui.router.util.$urlMatcherFactoryProvider + * + * @description + * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely + * on state. + * + * A state corresponds to a "place" in the application in terms of the overall UI and + * navigation. A state describes (via the controller / template / view properties) what + * the UI looks like and does at that place. + * + * States often have things in common, and the primary way of factoring out these + * commonalities in this model is via the state hierarchy, i.e. parent/child states aka + * nested states. + * + * The `$stateProvider` provides interfaces to declare these states for your app. + */ +$StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider']; +function $StateProvider( $urlRouterProvider, $urlMatcherFactory) { + + var root, states = {}, $state, queue = {}, abstractKey = 'abstract'; + + // Builds state properties from definition passed to registerState() + var stateBuilder = { + + // Derive parent state from a hierarchical name only if 'parent' is not explicitly defined. + // state.children = []; + // if (parent) parent.children.push(state); + parent: function(state) { + if (isDefined(state.parent) && state.parent) return findState(state.parent); + // regex matches any valid composite state name + // would match "contact.list" but not "contacts" + var compositeName = /^(.+)\.[^.]+$/.exec(state.name); + return compositeName ? findState(compositeName[1]) : root; + }, + + // inherit 'data' from parent and override by own values (if any) + data: function(state) { + if (state.parent && state.parent.data) { + state.data = state.self.data = inherit(state.parent.data, state.data); + } + return state.data; + }, + + // Build a URLMatcher if necessary, either via a relative or absolute URL + url: function(state) { + var url = state.url, config = { params: state.params || {} }; + + if (isString(url)) { + if (url.charAt(0) == '^') return $urlMatcherFactory.compile(url.substring(1), config); + return (state.parent.navigable || root).url.concat(url, config); + } + + if (!url || $urlMatcherFactory.isMatcher(url)) return url; + throw new Error("Invalid url '" + url + "' in state '" + state + "'"); + }, + + // Keep track of the closest ancestor state that has a URL (i.e. is navigable) + navigable: function(state) { + return state.url ? state : (state.parent ? state.parent.navigable : null); + }, + + // Own parameters for this state. state.url.params is already built at this point. Create and add non-url params + ownParams: function(state) { + var params = state.url && state.url.params || new $$UMFP.ParamSet(); + forEach(state.params || {}, function(config, id) { + if (!params[id]) params[id] = new $$UMFP.Param(id, null, config, "config"); + }); + return params; + }, + + // Derive parameters for this state and ensure they're a super-set of parent's parameters + params: function(state) { + var ownParams = pick(state.ownParams, state.ownParams.$$keys()); + return state.parent && state.parent.params ? extend(state.parent.params.$$new(), ownParams) : new $$UMFP.ParamSet(); + }, + + // If there is no explicit multi-view configuration, make one up so we don't have + // to handle both cases in the view directive later. Note that having an explicit + // 'views' property will mean the default unnamed view properties are ignored. This + // is also a good time to resolve view names to absolute names, so everything is a + // straight lookup at link time. + views: function(state) { + var views = {}; + + forEach(isDefined(state.views) ? state.views : { '': state }, function (view, name) { + if (name.indexOf('@') < 0) name += '@' + state.parent.name; + view.resolveAs = view.resolveAs || state.resolveAs || '$resolve'; + views[name] = view; + }); + return views; + }, + + // Keep a full path from the root down to this state as this is needed for state activation. + path: function(state) { + return state.parent ? state.parent.path.concat(state) : []; // exclude root from path + }, + + // Speed up $state.contains() as it's used a lot + includes: function(state) { + var includes = state.parent ? extend({}, state.parent.includes) : {}; + includes[state.name] = true; + return includes; + }, + + $delegates: {} + }; + + function isRelative(stateName) { + return stateName.indexOf(".") === 0 || stateName.indexOf("^") === 0; + } + + function findState(stateOrName, base) { + if (!stateOrName) return undefined; + + var isStr = isString(stateOrName), + name = isStr ? stateOrName : stateOrName.name, + path = isRelative(name); + + if (path) { + if (!base) throw new Error("No reference point given for path '" + name + "'"); + base = findState(base); + + var rel = name.split("."), i = 0, pathLength = rel.length, current = base; + + for (; i < pathLength; i++) { + if (rel[i] === "" && i === 0) { + current = base; + continue; + } + if (rel[i] === "^") { + if (!current.parent) throw new Error("Path '" + name + "' not valid for state '" + base.name + "'"); + current = current.parent; + continue; + } + break; + } + rel = rel.slice(i).join("."); + name = current.name + (current.name && rel ? "." : "") + rel; + } + var state = states[name]; + + if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) { + return state; + } + return undefined; + } + + function queueState(parentName, state) { + if (!queue[parentName]) { + queue[parentName] = []; + } + queue[parentName].push(state); + } + + function flushQueuedChildren(parentName) { + var queued = queue[parentName] || []; + while(queued.length) { + registerState(queued.shift()); + } + } + + function registerState(state) { + // Wrap a new object around the state so we can store our private details easily. + state = inherit(state, { + self: state, + resolve: state.resolve || {}, + toString: function() { return this.name; } + }); + + var name = state.name; + if (!isString(name) || name.indexOf('@') >= 0) throw new Error("State must have a valid name"); + if (states.hasOwnProperty(name)) throw new Error("State '" + name + "' is already defined"); + + // Get parent name + var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.')) + : (isString(state.parent)) ? state.parent + : (isObject(state.parent) && isString(state.parent.name)) ? state.parent.name + : ''; + + // If parent is not registered yet, add state to queue and register later + if (parentName && !states[parentName]) { + return queueState(parentName, state.self); + } + + for (var key in stateBuilder) { + if (isFunction(stateBuilder[key])) state[key] = stateBuilder[key](state, stateBuilder.$delegates[key]); + } + states[name] = state; + + // Register the state in the global state list and with $urlRouter if necessary. + if (!state[abstractKey] && state.url) { + $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) { + if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) { + $state.transitionTo(state, $match, { inherit: true, location: false }); + } + }]); + } + + // Register any queued children + flushQueuedChildren(name); + + return state; + } + + // Checks text to see if it looks like a glob. + function isGlob (text) { + return text.indexOf('*') > -1; + } + + // Returns true if glob matches current $state name. + function doesStateMatchGlob (glob) { + var globSegments = glob.split('.'), + segments = $state.$current.name.split('.'); + + //match single stars + for (var i = 0, l = globSegments.length; i < l; i++) { + if (globSegments[i] === '*') { + segments[i] = '*'; + } + } + + //match greedy starts + if (globSegments[0] === '**') { + segments = segments.slice(indexOf(segments, globSegments[1])); + segments.unshift('**'); + } + //match greedy ends + if (globSegments[globSegments.length - 1] === '**') { + segments.splice(indexOf(segments, globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE); + segments.push('**'); + } + + if (globSegments.length != segments.length) { + return false; + } + + return segments.join('') === globSegments.join(''); + } + + + // Implicit root state that is always active + root = registerState({ + name: '', + url: '^', + views: null, + 'abstract': true + }); + root.navigable = null; + + + /** + * @ngdoc function + * @name ui.router.state.$stateProvider#decorator + * @methodOf ui.router.state.$stateProvider + * + * @description + * Allows you to extend (carefully) or override (at your own peril) the + * `stateBuilder` object used internally by `$stateProvider`. This can be used + * to add custom functionality to ui-router, for example inferring templateUrl + * based on the state name. + * + * When passing only a name, it returns the current (original or decorated) builder + * function that matches `name`. + * + * The builder functions that can be decorated are listed below. Though not all + * necessarily have a good use case for decoration, that is up to you to decide. + * + * In addition, users can attach custom decorators, which will generate new + * properties within the state's internal definition. There is currently no clear + * use-case for this beyond accessing internal states (i.e. $state.$current), + * however, expect this to become increasingly relevant as we introduce additional + * meta-programming features. + * + * **Warning**: Decorators should not be interdependent because the order of + * execution of the builder functions in non-deterministic. Builder functions + * should only be dependent on the state definition object and super function. + * + * + * Existing builder functions and current return values: + * + * - **parent** `{object}` - returns the parent state object. + * - **data** `{object}` - returns state data, including any inherited data that is not + * overridden by own values (if any). + * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher} + * or `null`. + * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is + * navigable). + * - **params** `{object}` - returns an array of state params that are ensured to + * be a super-set of parent's params. + * - **views** `{object}` - returns a views object where each key is an absolute view + * name (i.e. "viewName@stateName") and each value is the config object + * (template, controller) for the view. Even when you don't use the views object + * explicitly on a state config, one is still created for you internally. + * So by decorating this builder function you have access to decorating template + * and controller properties. + * - **ownParams** `{object}` - returns an array of params that belong to the state, + * not including any params defined by ancestor states. + * - **path** `{string}` - returns the full path from the root down to this state. + * Needed for state activation. + * - **includes** `{object}` - returns an object that includes every state that + * would pass a `$state.includes()` test. + * + * @example + *
    +   * // Override the internal 'views' builder with a function that takes the state
    +   * // definition, and a reference to the internal function being overridden:
    +   * $stateProvider.decorator('views', function (state, parent) {
    +   *   var result = {},
    +   *       views = parent(state);
    +   *
    +   *   angular.forEach(views, function (config, name) {
    +   *     var autoName = (state.name + '.' + name).replace('.', '/');
    +   *     config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
    +   *     result[name] = config;
    +   *   });
    +   *   return result;
    +   * });
    +   *
    +   * $stateProvider.state('home', {
    +   *   views: {
    +   *     'contact.list': { controller: 'ListController' },
    +   *     'contact.item': { controller: 'ItemController' }
    +   *   }
    +   * });
    +   *
    +   * // ...
    +   *
    +   * $state.go('home');
    +   * // Auto-populates list and item views with /partials/home/contact/list.html,
    +   * // and /partials/home/contact/item.html, respectively.
    +   * 
    + * + * @param {string} name The name of the builder function to decorate. + * @param {object} func A function that is responsible for decorating the original + * builder function. The function receives two parameters: + * + * - `{object}` - state - The state config object. + * - `{object}` - super - The original builder function. + * + * @return {object} $stateProvider - $stateProvider instance + */ + this.decorator = decorator; + function decorator(name, func) { + /*jshint validthis: true */ + if (isString(name) && !isDefined(func)) { + return stateBuilder[name]; + } + if (!isFunction(func) || !isString(name)) { + return this; + } + if (stateBuilder[name] && !stateBuilder.$delegates[name]) { + stateBuilder.$delegates[name] = stateBuilder[name]; + } + stateBuilder[name] = func; + return this; + } + + /** + * @ngdoc function + * @name ui.router.state.$stateProvider#state + * @methodOf ui.router.state.$stateProvider + * + * @description + * Registers a state configuration under a given state name. The stateConfig object + * has the following acceptable properties. + * + * @param {string} name A unique state name, e.g. "home", "about", "contacts". + * To create a parent/child state use a dot, e.g. "about.sales", "home.newest". + * @param {object} stateConfig State configuration object. + * @param {string|function=} stateConfig.template + * + * html template as a string or a function that returns + * an html template as a string which should be used by the uiView directives. This property + * takes precedence over templateUrl. + * + * If `template` is a function, it will be called with the following parameters: + * + * - {array.<object>} - state parameters extracted from the current $location.path() by + * applying the current state + * + *
    template:
    +   *   "

    inline template definition

    " + + * "
    "
    + *
    template: function(params) {
    +   *       return "

    generated template

    "; }
    + * + * + * @param {string|function=} stateConfig.templateUrl + * + * + * path or function that returns a path to an html + * template that should be used by uiView. + * + * If `templateUrl` is a function, it will be called with the following parameters: + * + * - {array.<object>} - state parameters extracted from the current $location.path() by + * applying the current state + * + *
    templateUrl: "home.html"
    + *
    templateUrl: function(params) {
    +   *     return myTemplates[params.pageId]; }
    + * + * @param {function=} stateConfig.templateProvider + * + * Provider function that returns HTML content string. + *
     templateProvider:
    +   *       function(MyTemplateService, params) {
    +   *         return MyTemplateService.getTemplate(params.pageId);
    +   *       }
    + * + * @param {string|function=} stateConfig.controller + * + * + * Controller fn that should be associated with newly + * related scope or the name of a registered controller if passed as a string. + * Optionally, the ControllerAs may be declared here. + *
    controller: "MyRegisteredController"
    + *
    controller:
    +   *     "MyRegisteredController as fooCtrl"}
    + *
    controller: function($scope, MyService) {
    +   *     $scope.data = MyService.getData(); }
    + * + * @param {function=} stateConfig.controllerProvider + * + * + * Injectable provider function that returns the actual controller or string. + *
    controllerProvider:
    +   *   function(MyResolveData) {
    +   *     if (MyResolveData.foo)
    +   *       return "FooCtrl"
    +   *     else if (MyResolveData.bar)
    +   *       return "BarCtrl";
    +   *     else return function($scope) {
    +   *       $scope.baz = "Qux";
    +   *     }
    +   *   }
    + * + * @param {string=} stateConfig.controllerAs + * + * + * A controller alias name. If present the controller will be + * published to scope under the controllerAs name. + *
    controllerAs: "myCtrl"
    + * + * @param {string|object=} stateConfig.parent + * + * Optionally specifies the parent state of this state. + * + *
    parent: 'parentState'
    + *
    parent: parentState // JS variable
    + * + * @param {object=} stateConfig.resolve + * + * + * An optional map<string, function> of dependencies which + * should be injected into the controller. If any of these dependencies are promises, + * the router will wait for them all to be resolved before the controller is instantiated. + * If all the promises are resolved successfully, the $stateChangeSuccess event is fired + * and the values of the resolved promises are injected into any controllers that reference them. + * If any of the promises are rejected the $stateChangeError event is fired. + * + * The map object is: + * + * - key - {string}: name of dependency to be injected into controller + * - factory - {string|function}: If string then it is alias for service. Otherwise if function, + * it is injected and return value it treated as dependency. If result is a promise, it is + * resolved before its value is injected into controller. + * + *
    resolve: {
    +   *     myResolve1:
    +   *       function($http, $stateParams) {
    +   *         return $http.get("/api/foos/"+stateParams.fooID);
    +   *       }
    +   *     }
    + * + * @param {string=} stateConfig.url + * + * + * A url fragment with optional parameters. When a state is navigated or + * transitioned to, the `$stateParams` service will be populated with any + * parameters that were passed. + * + * (See {@link ui.router.util.type:UrlMatcher UrlMatcher} `UrlMatcher`} for + * more details on acceptable patterns ) + * + * examples: + *
    url: "/home"
    +   * url: "/users/:userid"
    +   * url: "/books/{bookid:[a-zA-Z_-]}"
    +   * url: "/books/{categoryid:int}"
    +   * url: "/books/{publishername:string}/{categoryid:int}"
    +   * url: "/messages?before&after"
    +   * url: "/messages?{before:date}&{after:date}"
    +   * url: "/messages/:mailboxid?{before:date}&{after:date}"
    +   * 
    + * + * @param {object=} stateConfig.views + * + * an optional map<string, object> which defined multiple views, or targets views + * manually/explicitly. + * + * Examples: + * + * Targets three named `ui-view`s in the parent state's template + *
    views: {
    +   *     header: {
    +   *       controller: "headerCtrl",
    +   *       templateUrl: "header.html"
    +   *     }, body: {
    +   *       controller: "bodyCtrl",
    +   *       templateUrl: "body.html"
    +   *     }, footer: {
    +   *       controller: "footCtrl",
    +   *       templateUrl: "footer.html"
    +   *     }
    +   *   }
    + * + * Targets named `ui-view="header"` from grandparent state 'top''s template, and named `ui-view="body" from parent state's template. + *
    views: {
    +   *     'header@top': {
    +   *       controller: "msgHeaderCtrl",
    +   *       templateUrl: "msgHeader.html"
    +   *     }, 'body': {
    +   *       controller: "messagesCtrl",
    +   *       templateUrl: "messages.html"
    +   *     }
    +   *   }
    + * + * @param {boolean=} [stateConfig.abstract=false] + * + * An abstract state will never be directly activated, + * but can provide inherited properties to its common children states. + *
    abstract: true
    + * + * @param {function=} stateConfig.onEnter + * + * + * Callback function for when a state is entered. Good way + * to trigger an action or dispatch an event, such as opening a dialog. + * If minifying your scripts, make sure to explicitly annotate this function, + * because it won't be automatically annotated by your build tools. + * + *
    onEnter: function(MyService, $stateParams) {
    +   *     MyService.foo($stateParams.myParam);
    +   * }
    + * + * @param {function=} stateConfig.onExit + * + * + * Callback function for when a state is exited. Good way to + * trigger an action or dispatch an event, such as opening a dialog. + * If minifying your scripts, make sure to explicitly annotate this function, + * because it won't be automatically annotated by your build tools. + * + *
    onExit: function(MyService, $stateParams) {
    +   *     MyService.cleanup($stateParams.myParam);
    +   * }
    + * + * @param {boolean=} [stateConfig.reloadOnSearch=true] + * + * + * If `false`, will not retrigger the same state + * just because a search/query parameter has changed (via $location.search() or $location.hash()). + * Useful for when you'd like to modify $location.search() without triggering a reload. + *
    reloadOnSearch: false
    + * + * @param {object=} stateConfig.data + * + * + * Arbitrary data object, useful for custom configuration. The parent state's `data` is + * prototypally inherited. In other words, adding a data property to a state adds it to + * the entire subtree via prototypal inheritance. + * + *
    data: {
    +   *     requiredRole: 'foo'
    +   * } 
    + * + * @param {object=} stateConfig.params + * + * + * A map which optionally configures parameters declared in the `url`, or + * defines additional non-url parameters. For each parameter being + * configured, add a configuration object keyed to the name of the parameter. + * + * Each parameter configuration object may contain the following properties: + * + * - ** value ** - {object|function=}: specifies the default value for this + * parameter. This implicitly sets this parameter as optional. + * + * When UI-Router routes to a state and no value is + * specified for this parameter in the URL or transition, the + * default value will be used instead. If `value` is a function, + * it will be injected and invoked, and the return value used. + * + * *Note*: `undefined` is treated as "no default value" while `null` + * is treated as "the default value is `null`". + * + * *Shorthand*: If you only need to configure the default value of the + * parameter, you may use a shorthand syntax. In the **`params`** + * map, instead mapping the param name to a full parameter configuration + * object, simply set map it to the default parameter value, e.g.: + * + *
    // define a parameter's default value
    +   * params: {
    +   *     param1: { value: "defaultValue" }
    +   * }
    +   * // shorthand default values
    +   * params: {
    +   *     param1: "defaultValue",
    +   *     param2: "param2Default"
    +   * }
    + * + * - ** array ** - {boolean=}: *(default: false)* If true, the param value will be + * treated as an array of values. If you specified a Type, the value will be + * treated as an array of the specified Type. Note: query parameter values + * default to a special `"auto"` mode. + * + * For query parameters in `"auto"` mode, if multiple values for a single parameter + * are present in the URL (e.g.: `/foo?bar=1&bar=2&bar=3`) then the values + * are mapped to an array (e.g.: `{ foo: [ '1', '2', '3' ] }`). However, if + * only one value is present (e.g.: `/foo?bar=1`) then the value is treated as single + * value (e.g.: `{ foo: '1' }`). + * + *
    params: {
    +   *     param1: { array: true }
    +   * }
    + * + * - ** squash ** - {bool|string=}: `squash` configures how a default parameter value is represented in the URL when + * the current parameter value is the same as the default value. If `squash` is not set, it uses the + * configured default squash policy. + * (See {@link ui.router.util.$urlMatcherFactory#methods_defaultSquashPolicy `defaultSquashPolicy()`}) + * + * There are three squash settings: + * + * - false: The parameter's default value is not squashed. It is encoded and included in the URL + * - true: The parameter's default value is omitted from the URL. If the parameter is preceeded and followed + * by slashes in the state's `url` declaration, then one of those slashes are omitted. + * This can allow for cleaner looking URLs. + * - `""`: The parameter's default value is replaced with an arbitrary placeholder of your choice. + * + *
    params: {
    +   *     param1: {
    +   *       value: "defaultId",
    +   *       squash: true
    +   * } }
    +   * // squash "defaultValue" to "~"
    +   * params: {
    +   *     param1: {
    +   *       value: "defaultValue",
    +   *       squash: "~"
    +   * } }
    +   * 
    + * + * + * @example + *
    +   * // Some state name examples
    +   *
    +   * // stateName can be a single top-level name (must be unique).
    +   * $stateProvider.state("home", {});
    +   *
    +   * // Or it can be a nested state name. This state is a child of the
    +   * // above "home" state.
    +   * $stateProvider.state("home.newest", {});
    +   *
    +   * // Nest states as deeply as needed.
    +   * $stateProvider.state("home.newest.abc.xyz.inception", {});
    +   *
    +   * // state() returns $stateProvider, so you can chain state declarations.
    +   * $stateProvider
    +   *   .state("home", {})
    +   *   .state("about", {})
    +   *   .state("contacts", {});
    +   * 
    + * + */ + this.state = state; + function state(name, definition) { + /*jshint validthis: true */ + if (isObject(name)) definition = name; + else definition.name = name; + registerState(definition); + return this; + } + + /** + * @ngdoc object + * @name ui.router.state.$state + * + * @requires $rootScope + * @requires $q + * @requires ui.router.state.$view + * @requires $injector + * @requires ui.router.util.$resolve + * @requires ui.router.state.$stateParams + * @requires ui.router.router.$urlRouter + * + * @property {object} params A param object, e.g. {sectionId: section.id)}, that + * you'd like to test against the current active state. + * @property {object} current A reference to the state's config object. However + * you passed it in. Useful for accessing custom data. + * @property {object} transition Currently pending transition. A promise that'll + * resolve or reject. + * + * @description + * `$state` service is responsible for representing states as well as transitioning + * between them. It also provides interfaces to ask for current state or even states + * you're coming from. + */ + this.$get = $get; + $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter', '$location', '$urlMatcherFactory']; + function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter, $location, $urlMatcherFactory) { + + var TransitionSuperseded = $q.reject(new Error('transition superseded')); + var TransitionPrevented = $q.reject(new Error('transition prevented')); + var TransitionAborted = $q.reject(new Error('transition aborted')); + var TransitionFailed = $q.reject(new Error('transition failed')); + + // Handles the case where a state which is the target of a transition is not found, and the user + // can optionally retry or defer the transition + function handleRedirect(redirect, state, params, options) { + /** + * @ngdoc event + * @name ui.router.state.$state#$stateNotFound + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired when a requested state **cannot be found** using the provided state name during transition. + * The event is broadcast allowing any handlers a single chance to deal with the error (usually by + * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler, + * you can see its three properties in the example. You can use `event.preventDefault()` to abort the + * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value. + * + * @param {Object} event Event object. + * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties. + * @param {State} fromState Current state object. + * @param {Object} fromParams Current state params. + * + * @example + * + *
    +       * // somewhere, assume lazy.state has not been defined
    +       * $state.go("lazy.state", {a:1, b:2}, {inherit:false});
    +       *
    +       * // somewhere else
    +       * $scope.$on('$stateNotFound',
    +       * function(event, unfoundState, fromState, fromParams){
    +       *     console.log(unfoundState.to); // "lazy.state"
    +       *     console.log(unfoundState.toParams); // {a:1, b:2}
    +       *     console.log(unfoundState.options); // {inherit:false} + default options
    +       * })
    +       * 
    + */ + var evt = $rootScope.$broadcast('$stateNotFound', redirect, state, params); + + if (evt.defaultPrevented) { + $urlRouter.update(); + return TransitionAborted; + } + + if (!evt.retry) { + return null; + } + + // Allow the handler to return a promise to defer state lookup retry + if (options.$retry) { + $urlRouter.update(); + return TransitionFailed; + } + var retryTransition = $state.transition = $q.when(evt.retry); + + retryTransition.then(function() { + if (retryTransition !== $state.transition) return TransitionSuperseded; + redirect.options.$retry = true; + return $state.transitionTo(redirect.to, redirect.toParams, redirect.options); + }, function() { + return TransitionAborted; + }); + $urlRouter.update(); + + return retryTransition; + } + + root.locals = { resolve: null, globals: { $stateParams: {} } }; + + $state = { + params: {}, + current: root.self, + $current: root, + transition: null + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#reload + * @methodOf ui.router.state.$state + * + * @description + * A method that force reloads the current state. All resolves are re-resolved, + * controllers reinstantiated, and events re-fired. + * + * @example + *
    +     * var app angular.module('app', ['ui.router']);
    +     *
    +     * app.controller('ctrl', function ($scope, $state) {
    +     *   $scope.reload = function(){
    +     *     $state.reload();
    +     *   }
    +     * });
    +     * 
    + * + * `reload()` is just an alias for: + *
    +     * $state.transitionTo($state.current, $stateParams, { 
    +     *   reload: true, inherit: false, notify: true
    +     * });
    +     * 
    + * + * @param {string=|object=} state - A state name or a state object, which is the root of the resolves to be re-resolved. + * @example + *
    +     * //assuming app application consists of 3 states: 'contacts', 'contacts.detail', 'contacts.detail.item' 
    +     * //and current state is 'contacts.detail.item'
    +     * var app angular.module('app', ['ui.router']);
    +     *
    +     * app.controller('ctrl', function ($scope, $state) {
    +     *   $scope.reload = function(){
    +     *     //will reload 'contact.detail' and 'contact.detail.item' states
    +     *     $state.reload('contact.detail');
    +     *   }
    +     * });
    +     * 
    + * + * `reload()` is just an alias for: + *
    +     * $state.transitionTo($state.current, $stateParams, { 
    +     *   reload: true, inherit: false, notify: true
    +     * });
    +     * 
    + + * @returns {promise} A promise representing the state of the new transition. See + * {@link ui.router.state.$state#methods_go $state.go}. + */ + $state.reload = function reload(state) { + return $state.transitionTo($state.current, $stateParams, { reload: state || true, inherit: false, notify: true}); + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#go + * @methodOf ui.router.state.$state + * + * @description + * Convenience method for transitioning to a new state. `$state.go` calls + * `$state.transitionTo` internally but automatically sets options to + * `{ location: true, inherit: true, relative: $state.$current, notify: true }`. + * This allows you to easily use an absolute or relative to path and specify + * only the parameters you'd like to update (while letting unspecified parameters + * inherit from the currently active ancestor states). + * + * @example + *
    +     * var app = angular.module('app', ['ui.router']);
    +     *
    +     * app.controller('ctrl', function ($scope, $state) {
    +     *   $scope.changeState = function () {
    +     *     $state.go('contact.detail');
    +     *   };
    +     * });
    +     * 
    + * + * + * @param {string} to Absolute state name or relative state path. Some examples: + * + * - `$state.go('contact.detail')` - will go to the `contact.detail` state + * - `$state.go('^')` - will go to a parent state + * - `$state.go('^.sibling')` - will go to a sibling state + * - `$state.go('.child.grandchild')` - will go to grandchild state + * + * @param {object=} params A map of the parameters that will be sent to the state, + * will populate $stateParams. Any parameters that are not specified will be inherited from currently + * defined parameters. Only parameters specified in the state definition can be overridden, new + * parameters will be ignored. This allows, for example, going to a sibling state that shares parameters + * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e. + * transitioning to a sibling will get you the parameters for all parents, transitioning to a child + * will get you all current parameters, etc. + * @param {object=} options Options object. The options are: + * + * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` + * will not. If string, must be `"replace"`, which will update url and also replace last history record. + * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. + * - **`reload`** (v0.2.5) - {boolean=false|string|object}, If `true` will force transition even if no state or params + * have changed. It will reload the resolves and views of the current state and parent states. + * If `reload` is a string (or state object), the state object is fetched (by name, or object reference); and \ + * the transition reloads the resolves and views for that matched state, and all its children states. + * + * @returns {promise} A promise representing the state of the new transition. + * + * Possible success values: + * + * - $state.current + * + *
    Possible rejection values: + * + * - 'transition superseded' - when a newer transition has been started after this one + * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener + * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or + * when a `$stateNotFound` `event.retry` promise errors. + * - 'transition failed' - when a state has been unsuccessfully found after 2 tries. + * - *resolve error* - when an error has occurred with a `resolve` + * + */ + $state.go = function go(to, params, options) { + return $state.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options)); + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#transitionTo + * @methodOf ui.router.state.$state + * + * @description + * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go} + * uses `transitionTo` internally. `$state.go` is recommended in most situations. + * + * @example + *
    +     * var app = angular.module('app', ['ui.router']);
    +     *
    +     * app.controller('ctrl', function ($scope, $state) {
    +     *   $scope.changeState = function () {
    +     *     $state.transitionTo('contact.detail');
    +     *   };
    +     * });
    +     * 
    + * + * @param {string} to State name. + * @param {object=} toParams A map of the parameters that will be sent to the state, + * will populate $stateParams. + * @param {object=} options Options object. The options are: + * + * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` + * will not. If string, must be `"replace"`, which will update url and also replace last history record. + * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. + * - **`reload`** (v0.2.5) - {boolean=false|string=|object=}, If `true` will force transition even if the state or params + * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd + * use this when you want to force a reload when *everything* is the same, including search params. + * if String, then will reload the state with the name given in reload, and any children. + * if Object, then a stateObj is expected, will reload the state found in stateObj, and any children. + * + * @returns {promise} A promise representing the state of the new transition. See + * {@link ui.router.state.$state#methods_go $state.go}. + */ + $state.transitionTo = function transitionTo(to, toParams, options) { + toParams = toParams || {}; + options = extend({ + location: true, inherit: false, relative: null, notify: true, reload: false, $retry: false + }, options || {}); + + var from = $state.$current, fromParams = $state.params, fromPath = from.path; + var evt, toState = findState(to, options.relative); + + // Store the hash param for later (since it will be stripped out by various methods) + var hash = toParams['#']; + + if (!isDefined(toState)) { + var redirect = { to: to, toParams: toParams, options: options }; + var redirectResult = handleRedirect(redirect, from.self, fromParams, options); + + if (redirectResult) { + return redirectResult; + } + + // Always retry once if the $stateNotFound was not prevented + // (handles either redirect changed or state lazy-definition) + to = redirect.to; + toParams = redirect.toParams; + options = redirect.options; + toState = findState(to, options.relative); + + if (!isDefined(toState)) { + if (!options.relative) throw new Error("No such state '" + to + "'"); + throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'"); + } + } + if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'"); + if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState); + if (!toState.params.$$validates(toParams)) return TransitionFailed; + + toParams = toState.params.$$values(toParams); + to = toState; + + var toPath = to.path; + + // Starting from the root of the path, keep all levels that haven't changed + var keep = 0, state = toPath[keep], locals = root.locals, toLocals = []; + + if (!options.reload) { + while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) { + locals = toLocals[keep] = state.locals; + keep++; + state = toPath[keep]; + } + } else if (isString(options.reload) || isObject(options.reload)) { + if (isObject(options.reload) && !options.reload.name) { + throw new Error('Invalid reload state object'); + } + + var reloadState = options.reload === true ? fromPath[0] : findState(options.reload); + if (options.reload && !reloadState) { + throw new Error("No such reload state '" + (isString(options.reload) ? options.reload : options.reload.name) + "'"); + } + + while (state && state === fromPath[keep] && state !== reloadState) { + locals = toLocals[keep] = state.locals; + keep++; + state = toPath[keep]; + } + } + + // If we're going to the same state and all locals are kept, we've got nothing to do. + // But clear 'transition', as we still want to cancel any other pending transitions. + // TODO: We may not want to bump 'transition' if we're called from a location change + // that we've initiated ourselves, because we might accidentally abort a legitimate + // transition initiated from code? + if (shouldSkipReload(to, toParams, from, fromParams, locals, options)) { + if (hash) toParams['#'] = hash; + $state.params = toParams; + copy($state.params, $stateParams); + copy(filterByKeys(to.params.$$keys(), $stateParams), to.locals.globals.$stateParams); + if (options.location && to.navigable && to.navigable.url) { + $urlRouter.push(to.navigable.url, toParams, { + $$avoidResync: true, replace: options.location === 'replace' + }); + $urlRouter.update(true); + } + $state.transition = null; + return $q.when($state.current); + } + + // Filter parameters before we pass them to event handlers etc. + toParams = filterByKeys(to.params.$$keys(), toParams || {}); + + // Re-add the saved hash before we start returning things or broadcasting $stateChangeStart + if (hash) toParams['#'] = hash; + + // Broadcast start event and cancel the transition if requested + if (options.notify) { + /** + * @ngdoc event + * @name ui.router.state.$state#$stateChangeStart + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired when the state transition **begins**. You can use `event.preventDefault()` + * to prevent the transition from happening and then the transition promise will be + * rejected with a `'transition prevented'` value. + * + * @param {Object} event Event object. + * @param {State} toState The state being transitioned to. + * @param {Object} toParams The params supplied to the `toState`. + * @param {State} fromState The current state, pre-transition. + * @param {Object} fromParams The params supplied to the `fromState`. + * + * @example + * + *
    +         * $rootScope.$on('$stateChangeStart',
    +         * function(event, toState, toParams, fromState, fromParams){
    +         *     event.preventDefault();
    +         *     // transitionTo() promise will be rejected with
    +         *     // a 'transition prevented' error
    +         * })
    +         * 
    + */ + if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams, options).defaultPrevented) { + $rootScope.$broadcast('$stateChangeCancel', to.self, toParams, from.self, fromParams); + //Don't update and resync url if there's been a new transition started. see issue #2238, #600 + if ($state.transition == null) $urlRouter.update(); + return TransitionPrevented; + } + } + + // Resolve locals for the remaining states, but don't update any global state just + // yet -- if anything fails to resolve the current state needs to remain untouched. + // We also set up an inheritance chain for the locals here. This allows the view directive + // to quickly look up the correct definition for each view in the current state. Even + // though we create the locals object itself outside resolveState(), it is initially + // empty and gets filled asynchronously. We need to keep track of the promise for the + // (fully resolved) current locals, and pass this down the chain. + var resolved = $q.when(locals); + + for (var l = keep; l < toPath.length; l++, state = toPath[l]) { + locals = toLocals[l] = inherit(locals); + resolved = resolveState(state, toParams, state === to, resolved, locals, options); + } + + // Once everything is resolved, we are ready to perform the actual transition + // and return a promise for the new state. We also keep track of what the + // current promise is, so that we can detect overlapping transitions and + // keep only the outcome of the last transition. + var transition = $state.transition = resolved.then(function () { + var l, entering, exiting; + + if ($state.transition !== transition) return TransitionSuperseded; + + // Exit 'from' states not kept + for (l = fromPath.length - 1; l >= keep; l--) { + exiting = fromPath[l]; + if (exiting.self.onExit) { + $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals); + } + exiting.locals = null; + } + + // Enter 'to' states not kept + for (l = keep; l < toPath.length; l++) { + entering = toPath[l]; + entering.locals = toLocals[l]; + if (entering.self.onEnter) { + $injector.invoke(entering.self.onEnter, entering.self, entering.locals.globals); + } + } + + // Run it again, to catch any transitions in callbacks + if ($state.transition !== transition) return TransitionSuperseded; + + // Update globals in $state + $state.$current = to; + $state.current = to.self; + $state.params = toParams; + copy($state.params, $stateParams); + $state.transition = null; + + if (options.location && to.navigable) { + $urlRouter.push(to.navigable.url, to.navigable.locals.globals.$stateParams, { + $$avoidResync: true, replace: options.location === 'replace' + }); + } + + if (options.notify) { + /** + * @ngdoc event + * @name ui.router.state.$state#$stateChangeSuccess + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired once the state transition is **complete**. + * + * @param {Object} event Event object. + * @param {State} toState The state being transitioned to. + * @param {Object} toParams The params supplied to the `toState`. + * @param {State} fromState The current state, pre-transition. + * @param {Object} fromParams The params supplied to the `fromState`. + */ + $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams); + } + $urlRouter.update(true); + + return $state.current; + }).then(null, function (error) { + if ($state.transition !== transition) return TransitionSuperseded; + + $state.transition = null; + /** + * @ngdoc event + * @name ui.router.state.$state#$stateChangeError + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired when an **error occurs** during transition. It's important to note that if you + * have any errors in your resolve functions (javascript errors, non-existent services, etc) + * they will not throw traditionally. You must listen for this $stateChangeError event to + * catch **ALL** errors. + * + * @param {Object} event Event object. + * @param {State} toState The state being transitioned to. + * @param {Object} toParams The params supplied to the `toState`. + * @param {State} fromState The current state, pre-transition. + * @param {Object} fromParams The params supplied to the `fromState`. + * @param {Error} error The resolve error object. + */ + evt = $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error); + + if (!evt.defaultPrevented) { + $urlRouter.update(); + } + + return $q.reject(error); + }); + + return transition; + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#is + * @methodOf ui.router.state.$state + * + * @description + * Similar to {@link ui.router.state.$state#methods_includes $state.includes}, + * but only checks for the full state name. If params is supplied then it will be + * tested for strict equality against the current active params object, so all params + * must match with none missing and no extras. + * + * @example + *
    +     * $state.$current.name = 'contacts.details.item';
    +     *
    +     * // absolute name
    +     * $state.is('contact.details.item'); // returns true
    +     * $state.is(contactDetailItemStateObject); // returns true
    +     *
    +     * // relative name (. and ^), typically from a template
    +     * // E.g. from the 'contacts.details' template
    +     * 
    Item
    + *
    + * + * @param {string|object} stateOrName The state name (absolute or relative) or state object you'd like to check. + * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like + * to test against the current active state. + * @param {object=} options An options object. The options are: + * + * - **`relative`** - {string|object} - If `stateOrName` is a relative state name and `options.relative` is set, .is will + * test relative to `options.relative` state (or name). + * + * @returns {boolean} Returns true if it is the state. + */ + $state.is = function is(stateOrName, params, options) { + options = extend({ relative: $state.$current }, options || {}); + var state = findState(stateOrName, options.relative); + + if (!isDefined(state)) { return undefined; } + if ($state.$current !== state) { return false; } + return params ? equalForKeys(state.params.$$values(params), $stateParams) : true; + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#includes + * @methodOf ui.router.state.$state + * + * @description + * A method to determine if the current active state is equal to or is the child of the + * state stateName. If any params are passed then they will be tested for a match as well. + * Not all the parameters need to be passed, just the ones you'd like to test for equality. + * + * @example + * Partial and relative names + *
    +     * $state.$current.name = 'contacts.details.item';
    +     *
    +     * // Using partial names
    +     * $state.includes("contacts"); // returns true
    +     * $state.includes("contacts.details"); // returns true
    +     * $state.includes("contacts.details.item"); // returns true
    +     * $state.includes("contacts.list"); // returns false
    +     * $state.includes("about"); // returns false
    +     *
    +     * // Using relative names (. and ^), typically from a template
    +     * // E.g. from the 'contacts.details' template
    +     * 
    Item
    + *
    + * + * Basic globbing patterns + *
    +     * $state.$current.name = 'contacts.details.item.url';
    +     *
    +     * $state.includes("*.details.*.*"); // returns true
    +     * $state.includes("*.details.**"); // returns true
    +     * $state.includes("**.item.**"); // returns true
    +     * $state.includes("*.details.item.url"); // returns true
    +     * $state.includes("*.details.*.url"); // returns true
    +     * $state.includes("*.details.*"); // returns false
    +     * $state.includes("item.**"); // returns false
    +     * 
    + * + * @param {string} stateOrName A partial name, relative name, or glob pattern + * to be searched for within the current state name. + * @param {object=} params A param object, e.g. `{sectionId: section.id}`, + * that you'd like to test against the current active state. + * @param {object=} options An options object. The options are: + * + * - **`relative`** - {string|object=} - If `stateOrName` is a relative state reference and `options.relative` is set, + * .includes will test relative to `options.relative` state (or name). + * + * @returns {boolean} Returns true if it does include the state + */ + $state.includes = function includes(stateOrName, params, options) { + options = extend({ relative: $state.$current }, options || {}); + if (isString(stateOrName) && isGlob(stateOrName)) { + if (!doesStateMatchGlob(stateOrName)) { + return false; + } + stateOrName = $state.$current.name; + } + + var state = findState(stateOrName, options.relative); + if (!isDefined(state)) { return undefined; } + if (!isDefined($state.$current.includes[state.name])) { return false; } + return params ? equalForKeys(state.params.$$values(params), $stateParams, objectKeys(params)) : true; + }; + + + /** + * @ngdoc function + * @name ui.router.state.$state#href + * @methodOf ui.router.state.$state + * + * @description + * A url generation method that returns the compiled url for the given state populated with the given params. + * + * @example + *
    +     * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob");
    +     * 
    + * + * @param {string|object} stateOrName The state name or state object you'd like to generate a url from. + * @param {object=} params An object of parameter values to fill the state's required parameters. + * @param {object=} options Options object. The options are: + * + * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the + * first parameter, then the constructed href url will be built from the first navigable ancestor (aka + * ancestor with a valid url). + * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". + * + * @returns {string} compiled state url + */ + $state.href = function href(stateOrName, params, options) { + options = extend({ + lossy: true, + inherit: true, + absolute: false, + relative: $state.$current + }, options || {}); + + var state = findState(stateOrName, options.relative); + + if (!isDefined(state)) return null; + if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, state); + + var nav = (state && options.lossy) ? state.navigable : state; + + if (!nav || nav.url === undefined || nav.url === null) { + return null; + } + return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys().concat('#'), params || {}), { + absolute: options.absolute + }); + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#get + * @methodOf ui.router.state.$state + * + * @description + * Returns the state configuration object for any specific state or all states. + * + * @param {string|object=} stateOrName (absolute or relative) If provided, will only get the config for + * the requested state. If not provided, returns an array of ALL state configs. + * @param {string|object=} context When stateOrName is a relative state reference, the state will be retrieved relative to context. + * @returns {Object|Array} State configuration object or array of all objects. + */ + $state.get = function (stateOrName, context) { + if (arguments.length === 0) return map(objectKeys(states), function(name) { return states[name].self; }); + var state = findState(stateOrName, context || $state.$current); + return (state && state.self) ? state.self : null; + }; + + function resolveState(state, params, paramsAreFiltered, inherited, dst, options) { + // Make a restricted $stateParams with only the parameters that apply to this state if + // necessary. In addition to being available to the controller and onEnter/onExit callbacks, + // we also need $stateParams to be available for any $injector calls we make during the + // dependency resolution process. + var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params); + var locals = { $stateParams: $stateParams }; + + // Resolve 'global' dependencies for the state, i.e. those not specific to a view. + // We're also including $stateParams in this; that way the parameters are restricted + // to the set that should be visible to the state, and are independent of when we update + // the global $state and $stateParams values. + dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state); + var promises = [dst.resolve.then(function (globals) { + dst.globals = globals; + })]; + if (inherited) promises.push(inherited); + + function resolveViews() { + var viewsPromises = []; + + // Resolve template and dependencies for all views. + forEach(state.views, function (view, name) { + var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {}); + injectables.$template = [ function () { + return $view.load(name, { view: view, locals: dst.globals, params: $stateParams, notify: options.notify }) || ''; + }]; + + viewsPromises.push($resolve.resolve(injectables, dst.globals, dst.resolve, state).then(function (result) { + // References to the controller (only instantiated at link time) + if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) { + var injectLocals = angular.extend({}, injectables, dst.globals); + result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals); + } else { + result.$$controller = view.controller; + } + // Provide access to the state itself for internal use + result.$$state = state; + result.$$controllerAs = view.controllerAs; + result.$$resolveAs = view.resolveAs; + dst[name] = result; + })); + }); + + return $q.all(viewsPromises).then(function(){ + return dst.globals; + }); + } + + // Wait for all the promises and then return the activation object + return $q.all(promises).then(resolveViews).then(function (values) { + return dst; + }); + } + + return $state; + } + + function shouldSkipReload(to, toParams, from, fromParams, locals, options) { + // Return true if there are no differences in non-search (path/object) params, false if there are differences + function nonSearchParamsEqual(fromAndToState, fromParams, toParams) { + // Identify whether all the parameters that differ between `fromParams` and `toParams` were search params. + function notSearchParam(key) { + return fromAndToState.params[key].location != "search"; + } + var nonQueryParamKeys = fromAndToState.params.$$keys().filter(notSearchParam); + var nonQueryParams = pick.apply({}, [fromAndToState.params].concat(nonQueryParamKeys)); + var nonQueryParamSet = new $$UMFP.ParamSet(nonQueryParams); + return nonQueryParamSet.$$equals(fromParams, toParams); + } + + // If reload was not explicitly requested + // and we're transitioning to the same state we're already in + // and the locals didn't change + // or they changed in a way that doesn't merit reloading + // (reloadOnParams:false, or reloadOnSearch.false and only search params changed) + // Then return true. + if (!options.reload && to === from && + (locals === from.locals || (to.self.reloadOnSearch === false && nonSearchParamsEqual(from, fromParams, toParams)))) { + return true; + } + } +} + +angular.module('ui.router.state') + .factory('$stateParams', function () { return {}; }) + .constant("$state.runtime", { autoinject: true }) + .provider('$state', $StateProvider) + // Inject $state to initialize when entering runtime. #2574 + .run(['$injector', function ($injector) { + // Allow tests (stateSpec.js) to turn this off by defining this constant + if ($injector.get("$state.runtime").autoinject) { + $injector.get('$state'); + } + }]); + + +$ViewProvider.$inject = []; +function $ViewProvider() { + + this.$get = $get; + /** + * @ngdoc object + * @name ui.router.state.$view + * + * @requires ui.router.util.$templateFactory + * @requires $rootScope + * + * @description + * + */ + $get.$inject = ['$rootScope', '$templateFactory']; + function $get( $rootScope, $templateFactory) { + return { + // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... }) + /** + * @ngdoc function + * @name ui.router.state.$view#load + * @methodOf ui.router.state.$view + * + * @description + * + * @param {string} name name + * @param {object} options option object. + */ + load: function load(name, options) { + var result, defaults = { + template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {} + }; + options = extend(defaults, options); + + if (options.view) { + result = $templateFactory.fromConfig(options.view, options.params, options.locals); + } + return result; + } + }; + } +} + +angular.module('ui.router.state').provider('$view', $ViewProvider); + +/** + * @ngdoc object + * @name ui.router.state.$uiViewScrollProvider + * + * @description + * Provider that returns the {@link ui.router.state.$uiViewScroll} service function. + */ +function $ViewScrollProvider() { + + var useAnchorScroll = false; + + /** + * @ngdoc function + * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll + * @methodOf ui.router.state.$uiViewScrollProvider + * + * @description + * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for + * scrolling based on the url anchor. + */ + this.useAnchorScroll = function () { + useAnchorScroll = true; + }; + + /** + * @ngdoc object + * @name ui.router.state.$uiViewScroll + * + * @requires $anchorScroll + * @requires $timeout + * + * @description + * When called with a jqLite element, it scrolls the element into view (after a + * `$timeout` so the DOM has time to refresh). + * + * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor, + * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}. + */ + this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) { + if (useAnchorScroll) { + return $anchorScroll; + } + + return function ($element) { + return $timeout(function () { + $element[0].scrollIntoView(); + }, 0, false); + }; + }]; +} + +angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider); + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-view + * + * @requires ui.router.state.$state + * @requires $compile + * @requires $controller + * @requires $injector + * @requires ui.router.state.$uiViewScroll + * @requires $document + * + * @restrict ECA + * + * @description + * The ui-view directive tells $state where to place your templates. + * + * @param {string=} name A view name. The name should be unique amongst the other views in the + * same state. You can have views of the same name that live in different states. + * + * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window + * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll + * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you + * scroll ui-view elements into view when they are populated during a state activation. + * + * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) + * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.* + * + * @param {string=} onload Expression to evaluate whenever the view updates. + * + * @example + * A view can be unnamed or named. + *
    + * 
    + * 
    + * + * + *
    + *
    + * + * You can only have one unnamed view within any template (or root html). If you are only using a + * single view and it is unnamed then you can populate it like so: + *
    + * 
    + * $stateProvider.state("home", { + * template: "

    HELLO!

    " + * }) + *
    + * + * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#methods_state `views`} + * config property, by name, in this case an empty name: + *
    + * $stateProvider.state("home", {
    + *   views: {
    + *     "": {
    + *       template: "

    HELLO!

    " + * } + * } + * }) + *
    + * + * But typically you'll only use the views property if you name your view or have more than one view + * in the same template. There's not really a compelling reason to name a view if its the only one, + * but you could if you wanted, like so: + *
    + * 
    + *
    + *
    + * $stateProvider.state("home", {
    + *   views: {
    + *     "main": {
    + *       template: "

    HELLO!

    " + * } + * } + * }) + *
    + * + * Really though, you'll use views to set up multiple views: + *
    + * 
    + *
    + *
    + *
    + * + *
    + * $stateProvider.state("home", {
    + *   views: {
    + *     "": {
    + *       template: "

    HELLO!

    " + * }, + * "chart": { + * template: "" + * }, + * "data": { + * template: "" + * } + * } + * }) + *
    + * + * Examples for `autoscroll`: + * + *
    + * 
    + * 
    + *
    + * 
    + * 
    + * 
    + * 
    + * 
    + * + * Resolve data: + * + * The resolved data from the state's `resolve` block is placed on the scope as `$resolve` (this + * can be customized using [[ViewDeclaration.resolveAs]]). This can be then accessed from the template. + * + * Note that when `controllerAs` is being used, `$resolve` is set on the controller instance *after* the + * controller is instantiated. The `$onInit()` hook can be used to perform initialization code which + * depends on `$resolve` data. + * + * Example usage of $resolve in a view template + *
    + * $stateProvider.state('home', {
    + *   template: '',
    + *   resolve: {
    + *     user: function(UserService) { return UserService.fetchUser(); }
    + *   }
    + * });
    + * 
    + */ +$ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate', '$q']; +function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate, $q) { + + function getService() { + return ($injector.has) ? function(service) { + return $injector.has(service) ? $injector.get(service) : null; + } : function(service) { + try { + return $injector.get(service); + } catch (e) { + return null; + } + }; + } + + var service = getService(), + $animator = service('$animator'), + $animate = service('$animate'); + + // Returns a set of DOM manipulation functions based on which Angular version + // it should use + function getRenderer(attrs, scope) { + var statics = function() { + return { + enter: function (element, target, cb) { target.after(element); cb(); }, + leave: function (element, cb) { element.remove(); cb(); } + }; + }; + + if ($animate) { + return { + enter: function(element, target, cb) { + if (angular.version.minor > 2) { + $animate.enter(element, null, target).then(cb); + } else { + $animate.enter(element, null, target, cb); + } + }, + leave: function(element, cb) { + if (angular.version.minor > 2) { + $animate.leave(element).then(cb); + } else { + $animate.leave(element, cb); + } + } + }; + } + + if ($animator) { + var animate = $animator && $animator(scope, attrs); + + return { + enter: function(element, target, cb) {animate.enter(element, null, target); cb(); }, + leave: function(element, cb) { animate.leave(element); cb(); } + }; + } + + return statics(); + } + + var directive = { + restrict: 'ECA', + terminal: true, + priority: 400, + transclude: 'element', + compile: function (tElement, tAttrs, $transclude) { + return function (scope, $element, attrs) { + var previousEl, currentEl, currentScope, latestLocals, + onloadExp = attrs.onload || '', + autoScrollExp = attrs.autoscroll, + renderer = getRenderer(attrs, scope), + inherited = $element.inheritedData('$uiView'); + + scope.$on('$stateChangeSuccess', function() { + updateView(false); + }); + + updateView(true); + + function cleanupLastView() { + if (previousEl) { + previousEl.remove(); + previousEl = null; + } + + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + + if (currentEl) { + var $uiViewData = currentEl.data('$uiViewAnim'); + renderer.leave(currentEl, function() { + $uiViewData.$$animLeave.resolve(); + previousEl = null; + }); + + previousEl = currentEl; + currentEl = null; + } + } + + function updateView(firstTime) { + var newScope, + name = getUiViewName(scope, attrs, $element, $interpolate), + previousLocals = name && $state.$current && $state.$current.locals[name]; + + if (!firstTime && previousLocals === latestLocals) return; // nothing to do + newScope = scope.$new(); + latestLocals = $state.$current.locals[name]; + + /** + * @ngdoc event + * @name ui.router.state.directive:ui-view#$viewContentLoading + * @eventOf ui.router.state.directive:ui-view + * @eventType emits on ui-view directive scope + * @description + * + * Fired once the view **begins loading**, *before* the DOM is rendered. + * + * @param {Object} event Event object. + * @param {string} viewName Name of the view. + */ + newScope.$emit('$viewContentLoading', name); + + var clone = $transclude(newScope, function(clone) { + var animEnter = $q.defer(), animLeave = $q.defer(); + var viewAnimData = { + $animEnter: animEnter.promise, + $animLeave: animLeave.promise, + $$animLeave: animLeave + }; + + clone.data('$uiViewAnim', viewAnimData); + renderer.enter(clone, $element, function onUiViewEnter() { + animEnter.resolve(); + if(currentScope) { + currentScope.$emit('$viewContentAnimationEnded'); + } + + if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) { + $uiViewScroll(clone); + } + }); + cleanupLastView(); + }); + + currentEl = clone; + currentScope = newScope; + /** + * @ngdoc event + * @name ui.router.state.directive:ui-view#$viewContentLoaded + * @eventOf ui.router.state.directive:ui-view + * @eventType emits on ui-view directive scope + * @description + * Fired once the view is **loaded**, *after* the DOM is rendered. + * + * @param {Object} event Event object. + * @param {string} viewName Name of the view. + */ + currentScope.$emit('$viewContentLoaded', name); + currentScope.$eval(onloadExp); + } + }; + } + }; + + return directive; +} + +$ViewDirectiveFill.$inject = ['$compile', '$controller', '$state', '$interpolate']; +function $ViewDirectiveFill ( $compile, $controller, $state, $interpolate) { + return { + restrict: 'ECA', + priority: -400, + compile: function (tElement) { + var initial = tElement.html(); + return function (scope, $element, attrs) { + var current = $state.$current, + name = getUiViewName(scope, attrs, $element, $interpolate), + locals = current && current.locals[name]; + + if (! locals) { + return; + } + + $element.data('$uiView', { name: name, state: locals.$$state }); + $element.html(locals.$template ? locals.$template : initial); + + var resolveData = angular.extend({}, locals); + scope[locals.$$resolveAs] = resolveData; + + var link = $compile($element.contents()); + + if (locals.$$controller) { + locals.$scope = scope; + locals.$element = $element; + var controller = $controller(locals.$$controller, locals); + if (locals.$$controllerAs) { + scope[locals.$$controllerAs] = controller; + scope[locals.$$controllerAs][locals.$$resolveAs] = resolveData; + } + if (isFunction(controller.$onInit)) controller.$onInit(); + $element.data('$ngControllerController', controller); + $element.children().data('$ngControllerController', controller); + } + + link(scope); + }; + } + }; +} + +/** + * Shared ui-view code for both directives: + * Given scope, element, and its attributes, return the view's name + */ +function getUiViewName(scope, attrs, element, $interpolate) { + var name = $interpolate(attrs.uiView || attrs.name || '')(scope); + var uiViewCreatedBy = element.inheritedData('$uiView'); + return name.indexOf('@') >= 0 ? name : (name + '@' + (uiViewCreatedBy ? uiViewCreatedBy.state.name : '')); +} + +angular.module('ui.router.state').directive('uiView', $ViewDirective); +angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill); + +function parseStateRef(ref, current) { + var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed; + if (preparsed) ref = current + '(' + preparsed[1] + ')'; + parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); + if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'"); + return { state: parsed[1], paramExpr: parsed[3] || null }; +} + +function stateContext(el) { + var stateData = el.parent().inheritedData('$uiView'); + + if (stateData && stateData.state && stateData.state.name) { + return stateData.state; + } +} + +function getTypeInfo(el) { + // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. + var isSvg = Object.prototype.toString.call(el.prop('href')) === '[object SVGAnimatedString]'; + var isForm = el[0].nodeName === "FORM"; + + return { + attr: isForm ? "action" : (isSvg ? 'xlink:href' : 'href'), + isAnchor: el.prop("tagName").toUpperCase() === "A", + clickable: !isForm + }; +} + +function clickHook(el, $state, $timeout, type, current) { + return function(e) { + var button = e.which || e.button, target = current(); + + if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || el.attr('target'))) { + // HACK: This is to allow ng-clicks to be processed before the transition is initiated: + var transition = $timeout(function() { + $state.go(target.state, target.params, target.options); + }); + e.preventDefault(); + + // if the state has no URL, ignore one preventDefault from the directive. + var ignorePreventDefaultCount = type.isAnchor && !target.href ? 1: 0; + + e.preventDefault = function() { + if (ignorePreventDefaultCount-- <= 0) $timeout.cancel(transition); + }; + } + }; +} + +function defaultOpts(el, $state) { + return { relative: stateContext(el) || $state.$current, inherit: true }; +} + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-sref + * + * @requires ui.router.state.$state + * @requires $timeout + * + * @restrict A + * + * @description + * A directive that binds a link (`` tag) to a state. If the state has an associated + * URL, the directive will automatically generate & update the `href` attribute via + * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking + * the link will trigger a state transition with optional parameters. + * + * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be + * handled natively by the browser. + * + * You can also use relative state paths within ui-sref, just like the relative + * paths passed to `$state.go()`. You just need to be aware that the path is relative + * to the state that the link lives in, in other words the state that loaded the + * template containing the link. + * + * You can specify options to pass to {@link ui.router.state.$state#methods_go $state.go()} + * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`, + * and `reload`. + * + * @example + * Here's an example of how you'd use ui-sref and how it would compile. If you have the + * following template: + *
    + * Home | About | Next page
    + *
    + * 
    + * 
    + * + * Then the compiled html would be (assuming Html5Mode is off and current state is contacts): + *
    + * Home | About | Next page
    + *
    + * 
      + *
    • + * Joe + *
    • + *
    • + * Alice + *
    • + *
    • + * Bob + *
    • + *
    + * + * Home + *
    + * + * @param {string} ui-sref 'stateName' can be any valid absolute or relative state + * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#methods_go $state.go()} + */ +$StateRefDirective.$inject = ['$state', '$timeout']; +function $StateRefDirective($state, $timeout) { + return { + restrict: 'A', + require: ['?^uiSrefActive', '?^uiSrefActiveEq'], + link: function(scope, element, attrs, uiSrefActive) { + var ref = parseStateRef(attrs.uiSref, $state.current.name); + var def = { state: ref.state, href: null, params: null }; + var type = getTypeInfo(element); + var active = uiSrefActive[1] || uiSrefActive[0]; + var unlinkInfoFn = null; + var hookFn; + + def.options = extend(defaultOpts(element, $state), attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {}); + + var update = function(val) { + if (val) def.params = angular.copy(val); + def.href = $state.href(ref.state, def.params, def.options); + + if (unlinkInfoFn) unlinkInfoFn(); + if (active) unlinkInfoFn = active.$$addStateInfo(ref.state, def.params); + if (def.href !== null) attrs.$set(type.attr, def.href); + }; + + if (ref.paramExpr) { + scope.$watch(ref.paramExpr, function(val) { if (val !== def.params) update(val); }, true); + def.params = angular.copy(scope.$eval(ref.paramExpr)); + } + update(); + + if (!type.clickable) return; + hookFn = clickHook(element, $state, $timeout, type, function() { return def; }); + element.bind("click", hookFn); + scope.$on('$destroy', function() { + element.unbind("click", hookFn); + }); + } + }; +} + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-state + * + * @requires ui.router.state.uiSref + * + * @restrict A + * + * @description + * Much like ui-sref, but will accept named $scope properties to evaluate for a state definition, + * params and override options. + * + * @param {string} ui-state 'stateName' can be any valid absolute or relative state + * @param {Object} ui-state-params params to pass to {@link ui.router.state.$state#methods_href $state.href()} + * @param {Object} ui-state-opts options to pass to {@link ui.router.state.$state#methods_go $state.go()} + */ +$StateRefDynamicDirective.$inject = ['$state', '$timeout']; +function $StateRefDynamicDirective($state, $timeout) { + return { + restrict: 'A', + require: ['?^uiSrefActive', '?^uiSrefActiveEq'], + link: function(scope, element, attrs, uiSrefActive) { + var type = getTypeInfo(element); + var active = uiSrefActive[1] || uiSrefActive[0]; + var group = [attrs.uiState, attrs.uiStateParams || null, attrs.uiStateOpts || null]; + var watch = '[' + group.map(function(val) { return val || 'null'; }).join(', ') + ']'; + var def = { state: null, params: null, options: null, href: null }; + var unlinkInfoFn = null; + var hookFn; + + function runStateRefLink (group) { + def.state = group[0]; def.params = group[1]; def.options = group[2]; + def.href = $state.href(def.state, def.params, def.options); + + if (unlinkInfoFn) unlinkInfoFn(); + if (active) unlinkInfoFn = active.$$addStateInfo(def.state, def.params); + if (def.href) attrs.$set(type.attr, def.href); + } + + scope.$watch(watch, runStateRefLink, true); + runStateRefLink(scope.$eval(watch)); + + if (!type.clickable) return; + hookFn = clickHook(element, $state, $timeout, type, function() { return def; }); + element.bind("click", hookFn); + scope.$on('$destroy', function() { + element.unbind("click", hookFn); + }); + } + }; +} + + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-sref-active + * + * @requires ui.router.state.$state + * @requires ui.router.state.$stateParams + * @requires $interpolate + * + * @restrict A + * + * @description + * A directive working alongside ui-sref to add classes to an element when the + * related ui-sref directive's state is active, and removing them when it is inactive. + * The primary use-case is to simplify the special appearance of navigation menus + * relying on `ui-sref`, by having the "active" state's menu button appear different, + * distinguishing it from the inactive menu items. + * + * ui-sref-active can live on the same element as ui-sref or on a parent element. The first + * ui-sref-active found at the same level or above the ui-sref will be used. + * + * Will activate when the ui-sref's target state or any child state is active. If you + * need to activate only when the ui-sref target state is active and *not* any of + * it's children, then you will use + * {@link ui.router.state.directive:ui-sref-active-eq ui-sref-active-eq} + * + * @example + * Given the following template: + *
    + * 
    + * 
    + * + * + * When the app state is "app.user" (or any children states), and contains the state parameter "user" with value "bilbobaggins", + * the resulting HTML will appear as (note the 'active' class): + *
    + * 
    + * 
    + * + * The class name is interpolated **once** during the directives link time (any further changes to the + * interpolated value are ignored). + * + * Multiple classes may be specified in a space-separated format: + *
    + * 
      + *
    • + * link + *
    • + *
    + *
    + * + * It is also possible to pass ui-sref-active an expression that evaluates + * to an object hash, whose keys represent active class names and whose + * values represent the respective state names/globs. + * ui-sref-active will match if the current active state **includes** any of + * the specified state names/globs, even the abstract ones. + * + * @Example + * Given the following template, with "admin" being an abstract state: + *
    + * 
    + * Roles + *
    + *
    + * + * When the current state is "admin.roles" the "active" class will be applied + * to both the
    and elements. It is important to note that the state + * names/globs passed to ui-sref-active shadow the state provided by ui-sref. + */ + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-sref-active-eq + * + * @requires ui.router.state.$state + * @requires ui.router.state.$stateParams + * @requires $interpolate + * + * @restrict A + * + * @description + * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate + * when the exact target state used in the `ui-sref` is active; no child states. + * + */ +$StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate']; +function $StateRefActiveDirective($state, $stateParams, $interpolate) { + return { + restrict: "A", + controller: ['$scope', '$element', '$attrs', '$timeout', function ($scope, $element, $attrs, $timeout) { + var states = [], activeClasses = {}, activeEqClass, uiSrefActive; + + // There probably isn't much point in $observing this + // uiSrefActive and uiSrefActiveEq share the same directive object with some + // slight difference in logic routing + activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope); + + try { + uiSrefActive = $scope.$eval($attrs.uiSrefActive); + } catch (e) { + // Do nothing. uiSrefActive is not a valid expression. + // Fall back to using $interpolate below + } + uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope); + if (isObject(uiSrefActive)) { + forEach(uiSrefActive, function(stateOrName, activeClass) { + if (isString(stateOrName)) { + var ref = parseStateRef(stateOrName, $state.current.name); + addState(ref.state, $scope.$eval(ref.paramExpr), activeClass); + } + }); + } + + // Allow uiSref to communicate with uiSrefActive[Equals] + this.$$addStateInfo = function (newState, newParams) { + // we already got an explicit state provided by ui-sref-active, so we + // shadow the one that comes from ui-sref + if (isObject(uiSrefActive) && states.length > 0) { + return; + } + var deregister = addState(newState, newParams, uiSrefActive); + update(); + return deregister; + }; + + $scope.$on('$stateChangeSuccess', update); + + function addState(stateName, stateParams, activeClass) { + var state = $state.get(stateName, stateContext($element)); + var stateHash = createStateHash(stateName, stateParams); + + var stateInfo = { + state: state || { name: stateName }, + params: stateParams, + hash: stateHash + }; + + states.push(stateInfo); + activeClasses[stateHash] = activeClass; + + return function removeState() { + var idx = states.indexOf(stateInfo); + if (idx !== -1) states.splice(idx, 1); + }; + } + + /** + * @param {string} state + * @param {Object|string} [params] + * @return {string} + */ + function createStateHash(state, params) { + if (!isString(state)) { + throw new Error('state should be a string'); + } + if (isObject(params)) { + return state + toJson(params); + } + params = $scope.$eval(params); + if (isObject(params)) { + return state + toJson(params); + } + return state; + } + + // Update route state + function update() { + for (var i = 0; i < states.length; i++) { + if (anyMatch(states[i].state, states[i].params)) { + addClass($element, activeClasses[states[i].hash]); + } else { + removeClass($element, activeClasses[states[i].hash]); + } + + if (exactMatch(states[i].state, states[i].params)) { + addClass($element, activeEqClass); + } else { + removeClass($element, activeEqClass); + } + } + } + + function addClass(el, className) { $timeout(function () { el.addClass(className); }); } + function removeClass(el, className) { el.removeClass(className); } + function anyMatch(state, params) { return $state.includes(state.name, params); } + function exactMatch(state, params) { return $state.is(state.name, params); } + + update(); + }] + }; +} + +angular.module('ui.router.state') + .directive('uiSref', $StateRefDirective) + .directive('uiSrefActive', $StateRefActiveDirective) + .directive('uiSrefActiveEq', $StateRefActiveDirective) + .directive('uiState', $StateRefDynamicDirective); + +/** + * @ngdoc filter + * @name ui.router.state.filter:isState + * + * @requires ui.router.state.$state + * + * @description + * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}. + */ +$IsStateFilter.$inject = ['$state']; +function $IsStateFilter($state) { + var isFilter = function (state, params) { + return $state.is(state, params); + }; + isFilter.$stateful = true; + return isFilter; +} + +/** + * @ngdoc filter + * @name ui.router.state.filter:includedByState + * + * @requires ui.router.state.$state + * + * @description + * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}. + */ +$IncludedByStateFilter.$inject = ['$state']; +function $IncludedByStateFilter($state) { + var includesFilter = function (state, params, options) { + return $state.includes(state, params, options); + }; + includesFilter.$stateful = true; + return includesFilter; +} + +angular.module('ui.router.state') + .filter('isState', $IsStateFilter) + .filter('includedByState', $IncludedByStateFilter); +})(window, window.angular); \ No newline at end of file diff --git a/public/Scripts/angular-ui-router.min.js b/public/Scripts/angular-ui-router.min.js new file mode 100644 index 0000000..ef1e08e --- /dev/null +++ b/public/Scripts/angular-ui-router.min.js @@ -0,0 +1,8 @@ +/** + * State-based routing for AngularJS + * @version v0.3.1 + * @link http://angular-ui.github.com/ + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return R(new(R(function(){},{prototype:a})),b)}function e(a){return Q(arguments,function(b){b!==a&&Q(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path){if(a.path[d]!==b.path[d])break;c.push(a.path[d])}return c}function g(a){if(Object.keys)return Object.keys(a);var b=[];return Q(a,function(a,c){b.push(c)}),b}function h(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function i(a,b,c,d){var e,i=f(c,d),j={},k=[];for(var l in i)if(i[l]&&i[l].params&&(e=g(i[l].params),e.length))for(var m in e)h(k,e[m])>=0||(k.push(e[m]),j[e[m]]=a[e[m]]);return R({},j,b)}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(s[c]=d,N(a))q.push(c,[function(){return b.get(a)}],j);else{var e=b.annotate(a);Q(e,function(a){a!==c&&i.hasOwnProperty(a)&&n(i[a],a)}),q.push(c,a,e)}r.pop(),s[c]=f}}function o(a){return O(a)&&a.then&&a.$$promises}if(!O(i))throw new Error("'invocables' must be an object");var p=g(i||{}),q=[],r=[],s={};return Q(i,n),i=r=s=null,function(d,f,g){function h(){--u||(v||e(t,f.$$values),r.$$values=t,r.$$promises=r.$$promises||!0,delete r.$$inheritedValues,n.resolve(t))}function i(a){r.$$failure=a,n.reject(a)}function j(c,e,f){function j(a){l.reject(a),i(a)}function k(){if(!L(r.$$failure))try{l.resolve(b.invoke(e,g,t)),l.promise.then(function(a){t[c]=a,h()},j)}catch(a){j(a)}}var l=a.defer(),m=0;Q(f,function(a){s.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,s[a].then(function(b){t[a]=b,--m||k()},j))}),m||k(),s[c]=l.promise}if(o(d)&&g===c&&(g=f,f=d,d=null),d){if(!O(d))throw new Error("'locals' must be an object")}else d=k;if(f){if(!o(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=l;var n=a.defer(),r=n.promise,s=r.$$promises={},t=R({},d),u=1+q.length/3,v=!1;if(L(f.$$failure))return i(f.$$failure),r;f.$$inheritedValues&&e(t,m(f.$$inheritedValues,p)),R(s,f.$$promises),f.$$values?(v=e(t,m(f.$$values,p)),r.$$inheritedValues=m(f.$$values,p),h()):(f.$$inheritedValues&&(r.$$inheritedValues=m(f.$$inheritedValues,p)),f.then(h,i));for(var w=0,x=q.length;x>w;w+=3)d.hasOwnProperty(q[w])?h():j(q[w],q[w+1],q[w+2]);return r}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function q(a,b,c){this.fromConfig=function(a,b,c){return L(a.template)?this.fromString(a.template,b):L(a.templateUrl)?this.fromUrl(a.templateUrl,b):L(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return M(a)?a(b):a},this.fromUrl=function(c,d){return M(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b,headers:{Accept:"text/html"}}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function r(a,b,e){function f(b,c,d,e){if(q.push(b),o[b])return o[b];if(!/^\w+([-.]+\w+)*(?:\[\])?$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(p[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");return p[b]=new U.Param(b,c,d,e),p[b]}function g(a,b,c,d){var e=["",""],f=a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!b)return f;switch(c){case!1:e=["(",")"+(d?"?":"")];break;case!0:f=f.replace(/\/$/,""),e=["(?:/(",")|/)?"];break;default:e=["("+c+"|",")?"]}return f+e[0]+b+e[1]}function h(e,f){var g,h,i,j,k;return g=e[2]||e[3],k=b.params[g],i=a.substring(m,e.index),h=f?e[4]:e[4]||("*"==e[1]?".*":null),h&&(j=U.type(h)||d(U.type("string"),{pattern:new RegExp(h,b.caseInsensitive?"i":c)})),{id:g,regexp:h,segment:i,type:j,cfg:k}}b=R({params:{}},O(b)?b:{});var i,j=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,k=/([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,l="^",m=0,n=this.segments=[],o=e?e.params:{},p=this.params=e?e.params.$$new():new U.ParamSet,q=[];this.source=a;for(var r,s,t;(i=j.exec(a))&&(r=h(i,!1),!(r.segment.indexOf("?")>=0));)s=f(r.id,r.type,r.cfg,"path"),l+=g(r.segment,s.type.pattern.source,s.squash,s.isOptional),n.push(r.segment),m=j.lastIndex;t=a.substring(m);var u=t.indexOf("?");if(u>=0){var v=this.sourceSearch=t.substring(u);if(t=t.substring(0,u),this.sourcePath=a.substring(0,m+u),v.length>0)for(m=0;i=k.exec(v);)r=h(i,!0),s=f(r.id,r.type,r.cfg,"search"),m=j.lastIndex}else this.sourcePath=a,this.sourceSearch="";l+=g(t)+(b.strict===!1?"/?":"")+"$",n.push(t),this.regexp=new RegExp(l,b.caseInsensitive?"i":c),this.prefix=n[0],this.$$paramNames=q}function s(a){R(this,a)}function t(){function a(a){return null!=a?a.toString().replace(/~/g,"~~").replace(/\//g,"~2F"):a}function e(a){return null!=a?a.toString().replace(/~2F/g,"/").replace(/~~/g,"~"):a}function f(){return{strict:p,caseInsensitive:m}}function i(a){return M(a)||P(a)&&M(a[a.length-1])}function j(){for(;w.length;){var a=w.shift();if(a.pattern)throw new Error("You cannot override a type's .pattern at runtime.");b.extend(u[a.name],l.invoke(a.def))}}function k(a){R(this,a||{})}U=this;var l,m=!1,p=!0,q=!1,u={},v=!0,w=[],x={string:{encode:a,decode:e,is:function(a){return null==a||!L(a)||"string"==typeof a},pattern:/[^\/]*/},"int":{encode:a,decode:function(a){return parseInt(a,10)},is:function(a){return L(a)&&this.decode(a.toString())===a},pattern:/\d+/},bool:{encode:function(a){return a?1:0},decode:function(a){return 0!==parseInt(a,10)},is:function(a){return a===!0||a===!1},pattern:/0|1/},date:{encode:function(a){return this.is(a)?[a.getFullYear(),("0"+(a.getMonth()+1)).slice(-2),("0"+a.getDate()).slice(-2)].join("-"):c},decode:function(a){if(this.is(a))return a;var b=this.capture.exec(a);return b?new Date(b[1],b[2]-1,b[3]):c},is:function(a){return a instanceof Date&&!isNaN(a.valueOf())},equals:function(a,b){return this.is(a)&&this.is(b)&&a.toISOString()===b.toISOString()},pattern:/[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,capture:/([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/},json:{encode:b.toJson,decode:b.fromJson,is:b.isObject,equals:b.equals,pattern:/[^\/]*/},any:{encode:b.identity,decode:b.identity,equals:b.equals,pattern:/.*/}};t.$$getDefaultValue=function(a){if(!i(a.value))return a.value;if(!l)throw new Error("Injectable functions cannot be called at configuration time");return l.invoke(a.value)},this.caseInsensitive=function(a){return L(a)&&(m=a),m},this.strictMode=function(a){return L(a)&&(p=a),p},this.defaultSquashPolicy=function(a){if(!L(a))return q;if(a!==!0&&a!==!1&&!N(a))throw new Error("Invalid squash policy: "+a+". Valid policies: false, true, arbitrary-string");return q=a,a},this.compile=function(a,b){return new r(a,R(f(),b))},this.isMatcher=function(a){if(!O(a))return!1;var b=!0;return Q(r.prototype,function(c,d){M(c)&&(b=b&&L(a[d])&&M(a[d]))}),b},this.type=function(a,b,c){if(!L(b))return u[a];if(u.hasOwnProperty(a))throw new Error("A type named '"+a+"' has already been defined.");return u[a]=new s(R({name:a},b)),c&&(w.push({name:a,def:c}),v||j()),this},Q(x,function(a,b){u[b]=new s(R({name:b},a))}),u=d(u,{}),this.$get=["$injector",function(a){return l=a,v=!1,j(),Q(x,function(a,b){u[b]||(u[b]=new s(a))}),this}],this.Param=function(a,d,e,f){function j(a){var b=O(a)?g(a):[],c=-1===h(b,"value")&&-1===h(b,"type")&&-1===h(b,"squash")&&-1===h(b,"array");return c&&(a={value:a}),a.$$fn=i(a.value)?a.value:function(){return a.value},a}function k(c,d,e){if(c.type&&d)throw new Error("Param '"+a+"' has two type configurations.");return d?d:c.type?b.isString(c.type)?u[c.type]:c.type instanceof s?c.type:new s(c.type):"config"===e?u.any:u.string}function m(){var b={array:"search"===f?"auto":!1},c=a.match(/\[\]$/)?{array:!0}:{};return R(b,c,e).array}function p(a,b){var c=a.squash;if(!b||c===!1)return!1;if(!L(c)||null==c)return q;if(c===!0||N(c))return c;throw new Error("Invalid squash policy: '"+c+"'. Valid policies: false, true, or arbitrary string")}function r(a,b,d,e){var f,g,i=[{from:"",to:d||b?c:""},{from:null,to:d||b?c:""}];return f=P(a.replace)?a.replace:[],N(e)&&f.push({from:e,to:c}),g=o(f,function(a){return a.from}),n(i,function(a){return-1===h(g,a.from)}).concat(f)}function t(){if(!l)throw new Error("Injectable functions cannot be called at configuration time");var a=l.invoke(e.$$fn);if(null!==a&&a!==c&&!x.type.is(a))throw new Error("Default value ("+a+") for parameter '"+x.id+"' is not an instance of Type ("+x.type.name+")");return a}function v(a){function b(a){return function(b){return b.from===a}}function c(a){var c=o(n(x.replace,b(a)),function(a){return a.to});return c.length?c[0]:a}return a=c(a),L(a)?x.type.$normalize(a):t()}function w(){return"{Param:"+a+" "+d+" squash: '"+A+"' optional: "+z+"}"}var x=this;e=j(e),d=k(e,d,f);var y=m();d=y?d.$asArray(y,"search"===f):d,"string"!==d.name||y||"path"!==f||e.value!==c||(e.value="");var z=e.value!==c,A=p(e,z),B=r(e,y,z,A);R(this,{id:a,type:d,location:f,array:y,squash:A,replace:B,isOptional:z,value:v,dynamic:c,config:e,toString:w})},k.prototype={$$new:function(){return d(this,R(new k,{$$parent:this}))},$$keys:function(){for(var a=[],b=[],c=this,d=g(k.prototype);c;)b.push(c),c=c.$$parent;return b.reverse(),Q(b,function(b){Q(g(b),function(b){-1===h(a,b)&&-1===h(d,b)&&a.push(b)})}),a},$$values:function(a){var b={},c=this;return Q(c.$$keys(),function(d){b[d]=c[d].value(a&&a[d])}),b},$$equals:function(a,b){var c=!0,d=this;return Q(d.$$keys(),function(e){var f=a&&a[e],g=b&&b[e];d[e].type.equals(f,g)||(c=!1)}),c},$$validates:function(a){var d,e,f,g,h,i=this.$$keys();for(d=0;de;e++)if(b(j[e]))return;k&&b(k)}}function o(){return i=i||e.$on("$locationChangeSuccess",n)}var p,q=g.baseHref(),r=d.url();return l||o(),{sync:function(){n()},listen:function(){return o()},update:function(a){return a?void(r=d.url()):void(d.url()!==r&&(d.url(r),d.replace()))},push:function(a,b,e){var f=a.format(b||{});null!==f&&b&&b["#"]&&(f+="#"+b["#"]),d.url(f),p=e&&e.$$avoidResync?d.url():c,e&&e.replace&&d.replace()},href:function(c,e,f){if(!c.validates(e))return null;var g=a.html5Mode();b.isObject(g)&&(g=g.enabled),g=g&&h.history;var i=c.format(e);if(f=f||{},g||null===i||(i="#"+a.hashPrefix()+i),null!==i&&e&&e["#"]&&(i+="#"+e["#"]),i=m(i,g,f.absolute),!f.absolute||!i)return i;var j=!g&&i?"/":"",k=d.port();return k=80===k||443===k?"":":"+k,[d.protocol(),"://",d.host(),k,j,i].join("")}}}var i,j=[],k=null,l=!1;this.rule=function(a){if(!M(a))throw new Error("'rule' must be a function");return j.push(a),this},this.otherwise=function(a){if(N(a)){var b=a;a=function(){return b}}else if(!M(a))throw new Error("'rule' must be a function");return k=a,this},this.when=function(a,b){var c,h=N(b);if(N(a)&&(a=d.compile(a)),!h&&!M(b)&&!P(b))throw new Error("invalid 'handler' in when()");var i={matcher:function(a,b){return h&&(c=d.compile(b),b=["$match",function(a){return c.format(a)}]),R(function(c,d){return g(c,b,a.exec(d.path(),d.search()))},{prefix:N(a.prefix)?a.prefix:""})},regex:function(a,b){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(c=b,b=["$match",function(a){return f(c,a)}]),R(function(c,d){return g(c,b,a.exec(d.path()))},{prefix:e(a)})}},j={matcher:d.isMatcher(a),regex:a instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](a,b));throw new Error("invalid 'what' in when()")},this.deferIntercept=function(a){a===c&&(a=!0),l=a},this.$get=h,h.$inject=["$location","$rootScope","$injector","$browser","$sniffer"]}function v(a,e){function f(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function m(a,b){if(!a)return c;var d=N(a),e=d?a:a.name,g=f(e);if(g){if(!b)throw new Error("No reference point given for path '"+e+"'");b=m(b);for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=z[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function n(a,b){A[a]||(A[a]=[]),A[a].push(b)}function p(a){for(var b=A[a]||[];b.length;)q(b.shift())}function q(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!N(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(z.hasOwnProperty(c))throw new Error("State '"+c+"' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):N(b.parent)?b.parent:O(b.parent)&&N(b.parent.name)?b.parent.name:"";if(e&&!z[e])return n(e,b.self);for(var f in C)M(C[f])&&(b[f]=C[f](b,C.$delegates[f]));return z[c]=b,!b[B]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){y.$current.navigable==b&&j(a,c)||y.transitionTo(b,a,{inherit:!0,location:!1})}]),p(c),b}function r(a){return a.indexOf("*")>-1}function s(a){for(var b=a.split("."),c=y.$current.name.split("."),d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return"**"===b[0]&&(c=c.slice(h(c,b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(h(c,b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length?!1:c.join("")===b.join("")}function t(a,b){return N(a)&&!L(b)?C[a]:M(b)&&N(a)?(C[a]&&!C.$delegates[a]&&(C.$delegates[a]=C[a]),C[a]=b,this):this}function u(a,b){return O(a)?b=a:b.name=a,q(b),this}function v(a,e,f,h,l,n,p,q,t){function u(b,c,d,f){var g=a.$broadcast("$stateNotFound",b,c,d);if(g.defaultPrevented)return p.update(),D;if(!g.retry)return null;if(f.$retry)return p.update(),E;var h=y.transition=e.when(g.retry);return h.then(function(){return h!==y.transition?A:(b.options.$retry=!0,y.transitionTo(b.to,b.toParams,b.options))},function(){return D}),p.update(),h}function v(a,c,d,g,i,j){function m(){var c=[];return Q(a.views,function(d,e){var g=d.resolve&&d.resolve!==a.resolve?d.resolve:{};g.$template=[function(){return f.load(e,{view:d,locals:i.globals,params:n,notify:j.notify})||""}],c.push(l.resolve(g,i.globals,i.resolve,a).then(function(c){if(M(d.controllerProvider)||P(d.controllerProvider)){var f=b.extend({},g,i.globals);c.$$controller=h.invoke(d.controllerProvider,null,f)}else c.$$controller=d.controller;c.$$state=a,c.$$controllerAs=d.controllerAs,c.$$resolveAs=d.resolveAs,i[e]=c}))}),e.all(c).then(function(){return i.globals})}var n=d?c:k(a.params.$$keys(),c),o={$stateParams:n};i.resolve=l.resolve(a.resolve,o,i.resolve,a);var p=[i.resolve.then(function(a){i.globals=a})];return g&&p.push(g),e.all(p).then(m).then(function(a){return i})}var A=e.reject(new Error("transition superseded")),C=e.reject(new Error("transition prevented")),D=e.reject(new Error("transition aborted")),E=e.reject(new Error("transition failed"));return x.locals={resolve:null,globals:{$stateParams:{}}},y={params:{},current:x.self,$current:x,transition:null},y.reload=function(a){return y.transitionTo(y.current,n,{reload:a||!0,inherit:!1,notify:!0})},y.go=function(a,b,c){return y.transitionTo(a,b,R({inherit:!0,relative:y.$current},c))},y.transitionTo=function(b,c,f){c=c||{},f=R({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,j=y.$current,l=y.params,o=j.path,q=m(b,f.relative),r=c["#"];if(!L(q)){var s={to:b,toParams:c,options:f},t=u(s,j.self,l,f);if(t)return t;if(b=s.to,c=s.toParams,f=s.options,q=m(b,f.relative),!L(q)){if(!f.relative)throw new Error("No such state '"+b+"'");throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'")}}if(q[B])throw new Error("Cannot transition to abstract state '"+b+"'");if(f.inherit&&(c=i(n,c||{},y.$current,q)),!q.params.$$validates(c))return E;c=q.params.$$values(c),b=q;var z=b.path,D=0,F=z[D],G=x.locals,H=[];if(f.reload){if(N(f.reload)||O(f.reload)){if(O(f.reload)&&!f.reload.name)throw new Error("Invalid reload state object");var I=f.reload===!0?o[0]:m(f.reload);if(f.reload&&!I)throw new Error("No such reload state '"+(N(f.reload)?f.reload:f.reload.name)+"'");for(;F&&F===o[D]&&F!==I;)G=H[D]=F.locals,D++,F=z[D]}}else for(;F&&F===o[D]&&F.ownParams.$$equals(c,l);)G=H[D]=F.locals,D++,F=z[D];if(w(b,c,j,l,G,f))return r&&(c["#"]=r),y.params=c,S(y.params,n),S(k(b.params.$$keys(),n),b.locals.globals.$stateParams),f.location&&b.navigable&&b.navigable.url&&(p.push(b.navigable.url,c,{$$avoidResync:!0,replace:"replace"===f.location}),p.update(!0)),y.transition=null,e.when(y.current);if(c=k(b.params.$$keys(),c||{}),r&&(c["#"]=r),f.notify&&a.$broadcast("$stateChangeStart",b.self,c,j.self,l,f).defaultPrevented)return a.$broadcast("$stateChangeCancel",b.self,c,j.self,l),null==y.transition&&p.update(),C;for(var J=e.when(G),K=D;K=D;d--)g=o[d],g.self.onExit&&h.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=D;d2?k.enter(a,null,c).then(d):k.enter(a,null,c,d)},leave:function(a,c){b.version.minor>2?k.leave(a).then(c):k.leave(a,c)}};if(j){var e=j&&j(c,a);return{enter:function(a,b,c){e.enter(a,null,b),c()},leave:function(a,b){e.leave(a),b()}}}return d()}var i=g(),j=i("$animator"),k=i("$animate"),l={restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(c,g,i){return function(c,g,j){function k(){if(m&&(m.remove(),m=null),o&&(o.$destroy(),o=null),n){var a=n.data("$uiViewAnim");s.leave(n,function(){a.$$animLeave.resolve(),m=null}),m=n,n=null}}function l(h){var l,m=A(c,j,g,e),t=m&&a.$current&&a.$current.locals[m];if(h||t!==p){l=c.$new(),p=a.$current.locals[m],l.$emit("$viewContentLoading",m);var u=i(l,function(a){var e=f.defer(),h=f.defer(),i={$animEnter:e.promise,$animLeave:h.promise,$$animLeave:h};a.data("$uiViewAnim",i),s.enter(a,g,function(){e.resolve(),o&&o.$emit("$viewContentAnimationEnded"),(b.isDefined(r)&&!r||c.$eval(r))&&d(a)}),k()});n=u,o=l,o.$emit("$viewContentLoaded",m),o.$eval(q)}}var m,n,o,p,q=j.onload||"",r=j.autoscroll,s=h(j,c);g.inheritedData("$uiView");c.$on("$stateChangeSuccess",function(){l(!1)}),l(!0)}}};return l}function z(a,c,d,e){return{restrict:"ECA",priority:-400,compile:function(f){var g=f.html();return function(f,h,i){var j=d.$current,k=A(f,i,h,e),l=j&&j.locals[k];if(l){h.data("$uiView",{name:k,state:l.$$state}),h.html(l.$template?l.$template:g);var m=b.extend({},l);f[l.$$resolveAs]=m;var n=a(h.contents());if(l.$$controller){l.$scope=f,l.$element=h;var o=c(l.$$controller,l);l.$$controllerAs&&(f[l.$$controllerAs]=o,f[l.$$controllerAs][l.$$resolveAs]=m),M(o.$onInit)&&o.$onInit(),h.data("$ngControllerController",o),h.children().data("$ngControllerController",o)}n(f)}}}}}function A(a,b,c,d){var e=d(b.uiView||b.name||"")(a),f=c.inheritedData("$uiView");return e.indexOf("@")>=0?e:e+"@"+(f?f.state.name:"")}function B(a,b){var c,d=a.match(/^\s*({[^}]*})\s*$/);if(d&&(a=b+"("+d[1]+")"),c=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!c||4!==c.length)throw new Error("Invalid state ref '"+a+"'");return{state:c[1],paramExpr:c[3]||null}}function C(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function D(a){var b="[object SVGAnimatedString]"===Object.prototype.toString.call(a.prop("href")),c="FORM"===a[0].nodeName;return{attr:c?"action":b?"xlink:href":"href",isAnchor:"A"===a.prop("tagName").toUpperCase(),clickable:!c}}function E(a,b,c,d,e){return function(f){var g=f.which||f.button,h=e();if(!(g>1||f.ctrlKey||f.metaKey||f.shiftKey||a.attr("target"))){var i=c(function(){b.go(h.state,h.params,h.options)});f.preventDefault();var j=d.isAnchor&&!h.href?1:0;f.preventDefault=function(){j--<=0&&c.cancel(i)}}}}function F(a,b){return{relative:C(a)||b.$current,inherit:!0}}function G(a,c){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(d,e,f,g){var h,i=B(f.uiSref,a.current.name),j={state:i.state,href:null,params:null},k=D(e),l=g[1]||g[0],m=null;j.options=R(F(e,a),f.uiSrefOpts?d.$eval(f.uiSrefOpts):{});var n=function(c){c&&(j.params=b.copy(c)),j.href=a.href(i.state,j.params,j.options),m&&m(),l&&(m=l.$$addStateInfo(i.state,j.params)),null!==j.href&&f.$set(k.attr,j.href)};i.paramExpr&&(d.$watch(i.paramExpr,function(a){a!==j.params&&n(a)},!0),j.params=b.copy(d.$eval(i.paramExpr))),n(),k.clickable&&(h=E(e,a,c,k,function(){return j}),e.bind("click",h),d.$on("$destroy",function(){e.unbind("click",h)}))}}}function H(a,b){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(c,d,e,f){function g(b){m.state=b[0],m.params=b[1],m.options=b[2],m.href=a.href(m.state,m.params,m.options),n&&n(),j&&(n=j.$$addStateInfo(m.state,m.params)),m.href&&e.$set(i.attr,m.href)}var h,i=D(d),j=f[1]||f[0],k=[e.uiState,e.uiStateParams||null,e.uiStateOpts||null],l="["+k.map(function(a){return a||"null"}).join(", ")+"]",m={state:null,params:null,options:null,href:null},n=null;c.$watch(l,g,!0),g(c.$eval(l)),i.clickable&&(h=E(d,a,b,i,function(){return m}),d.bind("click",h),c.$on("$destroy",function(){d.unbind("click",h)}))}}}function I(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs","$timeout",function(b,d,e,f){function g(b,c,e){var f=a.get(b,C(d)),g=h(b,c),i={state:f||{name:b},params:c,hash:g};return p.push(i),q[g]=e,function(){var a=p.indexOf(i);-1!==a&&p.splice(a,1)}}function h(a,c){if(!N(a))throw new Error("state should be a string");return O(c)?a+T(c):(c=b.$eval(c),O(c)?a+T(c):a)}function i(){for(var a=0;a0)){var c=g(a,b,o);return i(),c}},b.$on("$stateChangeSuccess",i),i()}]}}function J(a){var b=function(b,c){return a.is(b,c)};return b.$stateful=!0,b}function K(a){var b=function(b,c,d){return a.includes(b,c,d)};return b.$stateful=!0,b}var L=b.isDefined,M=b.isFunction,N=b.isString,O=b.isObject,P=b.isArray,Q=b.forEach,R=b.extend,S=b.copy,T=b.toJson;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),p.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",p),q.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",q);var U;r.prototype.concat=function(a,b){var c={caseInsensitive:U.caseInsensitive(),strict:U.strictMode(),squash:U.defaultSquashPolicy()};return new r(this.sourcePath+a+this.sourceSearch,R(c,b),this)},r.prototype.toString=function(){return this.source},r.prototype.exec=function(a,b){function c(a){function b(a){return a.split("").reverse().join("")}function c(a){return a.replace(/\\-/g,"-")}var d=b(a).split(/-(?!\\)/),e=o(d,b);return o(e,c).reverse()}var d=this.regexp.exec(a);if(!d)return null;b=b||{};var e,f,g,h=this.parameters(),i=h.length,j=this.segments.length-1,k={};if(j!==d.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");var l,m;for(e=0;j>e;e++){for(g=h[e],l=this.params[g],m=d[e+1],f=0;fe;e++){for(g=h[e],k[g]=this.params[g].value(b[g]),l=this.params[g],m=b[g],f=0;ff;f++){var k=h>f,l=d[f],m=e[l],n=m.value(a[l]),p=m.isOptional&&m.type.equals(m.value(),n),q=p?m.squash:!1,r=m.type.encode(n);if(k){var s=c[f+1],t=f+1===h;if(q===!1)null!=r&&(j+=P(r)?o(r,b).join("-"):encodeURIComponent(r)),j+=s;else if(q===!0){var u=j.match(/\/$/)?/\/?(.*)/:/(.*)/;j+=s.match(u)[1]}else N(q)&&(j+=q+s);t&&m.squash===!0&&"/"===j.slice(-1)&&(j=j.slice(0,-1))}else{if(null==r||p&&q!==!1)continue;if(P(r)||(r=[r]),0===r.length)continue;r=o(r,encodeURIComponent).join("&"+l+"="),j+=(g?"&":"?")+(l+"="+r),g=!0}}return j},s.prototype.is=function(a,b){return!0},s.prototype.encode=function(a,b){return a},s.prototype.decode=function(a,b){return a},s.prototype.equals=function(a,b){return a==b},s.prototype.$subPattern=function(){var a=this.pattern.toString();return a.substr(1,a.length-2)},s.prototype.pattern=/.*/,s.prototype.toString=function(){return"{Type:"+this.name+"}"},s.prototype.$normalize=function(a){return this.is(a)?a:this.decode(a)},s.prototype.$asArray=function(a,b){function d(a,b){function d(a,b){return function(){return a[b].apply(a,arguments)}}function e(a){return P(a)?a:L(a)?[a]:[]}function f(a){switch(a.length){case 0:return c;case 1:return"auto"===b?a[0]:a;default:return a}}function g(a){return!a}function h(a,b){return function(c){if(P(c)&&0===c.length)return c;c=e(c);var d=o(c,a);return b===!0?0===n(d,g).length:f(d)}}function i(a){return function(b,c){var d=e(b),f=e(c);if(d.length!==f.length)return!1;for(var g=0;g= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function'); + +} + +/** + * @ngdoc function + * @name angular.forEach + * @module ng + * @kind function + * + * @description + * Invokes the `iterator` function once for each item in `obj` collection, which can be either an + * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value` + * is the value of an object property or an array element, `key` is the object property key or + * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional. + * + * It is worth noting that `.forEach` does not iterate over inherited properties because it filters + * using the `hasOwnProperty` method. + * + * Unlike ES262's + * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18), + * providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just + * return the value provided. + * + ```js + var values = {name: 'misko', gender: 'male'}; + var log = []; + angular.forEach(values, function(value, key) { + this.push(key + ': ' + value); + }, log); + expect(log).toEqual(['name: misko', 'gender: male']); + ``` + * + * @param {Object|Array} obj Object to iterate over. + * @param {Function} iterator Iterator function. + * @param {Object=} context Object to become context (`this`) for the iterator function. + * @returns {Object|Array} Reference to `obj`. + */ + +function forEach(obj, iterator, context) { + var key, length; + if (obj) { + if (isFunction(obj)) { + for (key in obj) { + // Need to check if hasOwnProperty exists, + // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function + if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (isArray(obj) || isArrayLike(obj)) { + var isPrimitive = typeof obj !== 'object'; + for (key = 0, length = obj.length; key < length; key++) { + if (isPrimitive || key in obj) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (obj.forEach && obj.forEach !== forEach) { + obj.forEach(iterator, context, obj); + } else if (isBlankObject(obj)) { + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty + for (key in obj) { + iterator.call(context, obj[key], key, obj); + } + } else if (typeof obj.hasOwnProperty === 'function') { + // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed + for (key in obj) { + if (obj.hasOwnProperty(key)) { + iterator.call(context, obj[key], key, obj); + } + } + } else { + // Slow path for objects which do not have a method `hasOwnProperty` + for (key in obj) { + if (hasOwnProperty.call(obj, key)) { + iterator.call(context, obj[key], key, obj); + } + } + } + } + return obj; +} + +function forEachSorted(obj, iterator, context) { + var keys = Object.keys(obj).sort(); + for (var i = 0; i < keys.length; i++) { + iterator.call(context, obj[keys[i]], keys[i]); + } + return keys; +} + + +/** + * when using forEach the params are value, key, but it is often useful to have key, value. + * @param {function(string, *)} iteratorFn + * @returns {function(*, string)} + */ +function reverseParams(iteratorFn) { + return function(value, key) {iteratorFn(key, value);}; +} + +/** + * A consistent way of creating unique IDs in angular. + * + * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before + * we hit number precision issues in JavaScript. + * + * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M + * + * @returns {number} an unique alpha-numeric string + */ +function nextUid() { + return ++uid; +} + + +/** + * Set or clear the hashkey for an object. + * @param obj object + * @param h the hashkey (!truthy to delete the hashkey) + */ +function setHashKey(obj, h) { + if (h) { + obj.$$hashKey = h; + } else { + delete obj.$$hashKey; + } +} + + +function baseExtend(dst, objs, deep) { + var h = dst.$$hashKey; + + for (var i = 0, ii = objs.length; i < ii; ++i) { + var obj = objs[i]; + if (!isObject(obj) && !isFunction(obj)) continue; + var keys = Object.keys(obj); + for (var j = 0, jj = keys.length; j < jj; j++) { + var key = keys[j]; + var src = obj[key]; + + if (deep && isObject(src)) { + if (isDate(src)) { + dst[key] = new Date(src.valueOf()); + } else if (isRegExp(src)) { + dst[key] = new RegExp(src); + } else if (src.nodeName) { + dst[key] = src.cloneNode(true); + } else if (isElement(src)) { + dst[key] = src.clone(); + } else { + if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; + baseExtend(dst[key], [src], true); + } + } else { + dst[key] = src; + } + } + } + + setHashKey(dst, h); + return dst; +} + +/** + * @ngdoc function + * @name angular.extend + * @module ng + * @kind function + * + * @description + * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s) + * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so + * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`. + * + * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use + * {@link angular.merge} for this. + * + * @param {Object} dst Destination object. + * @param {...Object} src Source object(s). + * @returns {Object} Reference to `dst`. + */ +function extend(dst) { + return baseExtend(dst, slice.call(arguments, 1), false); +} + + +/** +* @ngdoc function +* @name angular.merge +* @module ng +* @kind function +* +* @description +* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s) +* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so +* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`. +* +* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source +* objects, performing a deep copy. +* +* @param {Object} dst Destination object. +* @param {...Object} src Source object(s). +* @returns {Object} Reference to `dst`. +*/ +function merge(dst) { + return baseExtend(dst, slice.call(arguments, 1), true); +} + + + +function toInt(str) { + return parseInt(str, 10); +} + + +function inherit(parent, extra) { + return extend(Object.create(parent), extra); +} + +/** + * @ngdoc function + * @name angular.noop + * @module ng + * @kind function + * + * @description + * A function that performs no operations. This function can be useful when writing code in the + * functional style. + ```js + function foo(callback) { + var result = calculateResult(); + (callback || angular.noop)(result); + } + ``` + */ +function noop() {} +noop.$inject = []; + + +/** + * @ngdoc function + * @name angular.identity + * @module ng + * @kind function + * + * @description + * A function that returns its first argument. This function is useful when writing code in the + * functional style. + * + ```js + function transformer(transformationFn, value) { + return (transformationFn || angular.identity)(value); + }; + + // E.g. + function getResult(fn, input) { + return (fn || angular.identity)(input); + }; + + getResult(function(n) { return n * 2; }, 21); // returns 42 + getResult(null, 21); // returns 21 + getResult(undefined, 21); // returns 21 + ``` + * + * @param {*} value to be returned. + * @returns {*} the value passed in. + */ +function identity($) {return $;} +identity.$inject = []; + + +function valueFn(value) {return function valueRef() {return value;};} + +function hasCustomToString(obj) { + return isFunction(obj.toString) && obj.toString !== toString; +} + + +/** + * @ngdoc function + * @name angular.isUndefined + * @module ng + * @kind function + * + * @description + * Determines if a reference is undefined. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is undefined. + */ +function isUndefined(value) {return typeof value === 'undefined';} + + +/** + * @ngdoc function + * @name angular.isDefined + * @module ng + * @kind function + * + * @description + * Determines if a reference is defined. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is defined. + */ +function isDefined(value) {return typeof value !== 'undefined';} + + +/** + * @ngdoc function + * @name angular.isObject + * @module ng + * @kind function + * + * @description + * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not + * considered to be objects. Note that JavaScript arrays are objects. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Object` but not `null`. + */ +function isObject(value) { + // http://jsperf.com/isobject4 + return value !== null && typeof value === 'object'; +} + + +/** + * Determine if a value is an object with a null prototype + * + * @returns {boolean} True if `value` is an `Object` with a null prototype + */ +function isBlankObject(value) { + return value !== null && typeof value === 'object' && !getPrototypeOf(value); +} + + +/** + * @ngdoc function + * @name angular.isString + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `String`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `String`. + */ +function isString(value) {return typeof value === 'string';} + + +/** + * @ngdoc function + * @name angular.isNumber + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `Number`. + * + * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`. + * + * If you wish to exclude these then you can use the native + * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite) + * method. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Number`. + */ +function isNumber(value) {return typeof value === 'number';} + + +/** + * @ngdoc function + * @name angular.isDate + * @module ng + * @kind function + * + * @description + * Determines if a value is a date. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Date`. + */ +function isDate(value) { + return toString.call(value) === '[object Date]'; +} + + +/** + * @ngdoc function + * @name angular.isArray + * @module ng + * @kind function + * + * @description + * Determines if a reference is an `Array`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Array`. + */ +var isArray = Array.isArray; + +/** + * @ngdoc function + * @name angular.isFunction + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `Function`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Function`. + */ +function isFunction(value) {return typeof value === 'function';} + + +/** + * Determines if a value is a regular expression object. + * + * @private + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `RegExp`. + */ +function isRegExp(value) { + return toString.call(value) === '[object RegExp]'; +} + + +/** + * Checks if `obj` is a window object. + * + * @private + * @param {*} obj Object to check + * @returns {boolean} True if `obj` is a window obj. + */ +function isWindow(obj) { + return obj && obj.window === obj; +} + + +function isScope(obj) { + return obj && obj.$evalAsync && obj.$watch; +} + + +function isFile(obj) { + return toString.call(obj) === '[object File]'; +} + + +function isFormData(obj) { + return toString.call(obj) === '[object FormData]'; +} + + +function isBlob(obj) { + return toString.call(obj) === '[object Blob]'; +} + + +function isBoolean(value) { + return typeof value === 'boolean'; +} + + +function isPromiseLike(obj) { + return obj && isFunction(obj.then); +} + + +var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/; +function isTypedArray(value) { + return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value)); +} + +function isArrayBuffer(obj) { + return toString.call(obj) === '[object ArrayBuffer]'; +} + + +var trim = function(value) { + return isString(value) ? value.trim() : value; +}; + +// Copied from: +// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021 +// Prereq: s is a string. +var escapeForRegexp = function(s) { + return s.replace(/([-()\[\]{}+?*.$\^|,:#= 0) { + array.splice(index, 1); + } + return index; +} + +/** + * @ngdoc function + * @name angular.copy + * @module ng + * @kind function + * + * @description + * Creates a deep copy of `source`, which should be an object or an array. + * + * * If no destination is supplied, a copy of the object or array is created. + * * If a destination is provided, all of its elements (for arrays) or properties (for objects) + * are deleted and then all elements/properties from the source are copied to it. + * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned. + * * If `source` is identical to `destination` an exception will be thrown. + * + *
    + *
    + * Only enumerable properties are taken into account. Non-enumerable properties (both on `source` + * and on `destination`) will be ignored. + *
    + * + * @param {*} source The source that will be used to make a copy. + * Can be any type, including primitives, `null`, and `undefined`. + * @param {(Object|Array)=} destination Destination into which the source is copied. If + * provided, must be of the same type as `source`. + * @returns {*} The copy or updated `destination`, if `destination` was specified. + * + * @example + + +
    +
    +
    +
    + Gender: +
    + + +
    +
    form = {{user | json}}
    +
    master = {{master | json}}
    +
    +
    + + // Module: copyExample + angular. + module('copyExample', []). + controller('ExampleController', ['$scope', function($scope) { + $scope.master = {}; + + $scope.reset = function() { + // Example with 1 argument + $scope.user = angular.copy($scope.master); + }; + + $scope.update = function(user) { + // Example with 2 arguments + angular.copy(user, $scope.master); + }; + + $scope.reset(); + }]); + +
    + */ +function copy(source, destination) { + var stackSource = []; + var stackDest = []; + + if (destination) { + if (isTypedArray(destination) || isArrayBuffer(destination)) { + throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated."); + } + if (source === destination) { + throw ngMinErr('cpi', "Can't copy! Source and destination are identical."); + } + + // Empty the destination object + if (isArray(destination)) { + destination.length = 0; + } else { + forEach(destination, function(value, key) { + if (key !== '$$hashKey') { + delete destination[key]; + } + }); + } + + stackSource.push(source); + stackDest.push(destination); + return copyRecurse(source, destination); + } + + return copyElement(source); + + function copyRecurse(source, destination) { + var h = destination.$$hashKey; + var key; + if (isArray(source)) { + for (var i = 0, ii = source.length; i < ii; i++) { + destination.push(copyElement(source[i])); + } + } else if (isBlankObject(source)) { + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty + for (key in source) { + destination[key] = copyElement(source[key]); + } + } else if (source && typeof source.hasOwnProperty === 'function') { + // Slow path, which must rely on hasOwnProperty + for (key in source) { + if (source.hasOwnProperty(key)) { + destination[key] = copyElement(source[key]); + } + } + } else { + // Slowest path --- hasOwnProperty can't be called as a method + for (key in source) { + if (hasOwnProperty.call(source, key)) { + destination[key] = copyElement(source[key]); + } + } + } + setHashKey(destination, h); + return destination; + } + + function copyElement(source) { + // Simple values + if (!isObject(source)) { + return source; + } + + // Already copied values + var index = stackSource.indexOf(source); + if (index !== -1) { + return stackDest[index]; + } + + if (isWindow(source) || isScope(source)) { + throw ngMinErr('cpws', + "Can't copy! Making copies of Window or Scope instances is not supported."); + } + + var needsRecurse = false; + var destination = copyType(source); + + if (destination === undefined) { + destination = isArray(source) ? [] : Object.create(getPrototypeOf(source)); + needsRecurse = true; + } + + stackSource.push(source); + stackDest.push(destination); + + return needsRecurse + ? copyRecurse(source, destination) + : destination; + } + + function copyType(source) { + switch (toString.call(source)) { + case '[object Int8Array]': + case '[object Int16Array]': + case '[object Int32Array]': + case '[object Float32Array]': + case '[object Float64Array]': + case '[object Uint8Array]': + case '[object Uint8ClampedArray]': + case '[object Uint16Array]': + case '[object Uint32Array]': + return new source.constructor(copyElement(source.buffer), source.byteOffset, source.length); + + case '[object ArrayBuffer]': + //Support: IE10 + if (!source.slice) { + var copied = new ArrayBuffer(source.byteLength); + new Uint8Array(copied).set(new Uint8Array(source)); + return copied; + } + return source.slice(0); + + case '[object Boolean]': + case '[object Number]': + case '[object String]': + case '[object Date]': + return new source.constructor(source.valueOf()); + + case '[object RegExp]': + var re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); + re.lastIndex = source.lastIndex; + return re; + + case '[object Blob]': + return new source.constructor([source], {type: source.type}); + } + + if (isFunction(source.cloneNode)) { + return source.cloneNode(true); + } + } +} + + +/** + * @ngdoc function + * @name angular.equals + * @module ng + * @kind function + * + * @description + * Determines if two objects or two values are equivalent. Supports value types, regular + * expressions, arrays and objects. + * + * Two objects or values are considered equivalent if at least one of the following is true: + * + * * Both objects or values pass `===` comparison. + * * Both objects or values are of the same type and all of their properties are equal by + * comparing them with `angular.equals`. + * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal) + * * Both values represent the same regular expression (In JavaScript, + * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual + * representation matches). + * + * During a property comparison, properties of `function` type and properties with names + * that begin with `$` are ignored. + * + * Scope and DOMWindow objects are being compared only by identify (`===`). + * + * @param {*} o1 Object or value to compare. + * @param {*} o2 Object or value to compare. + * @returns {boolean} True if arguments are equal. + * + * @example + + +
    +
    +

    User 1

    + Name: + Age: + +

    User 2

    + Name: + Age: + +
    +
    + +
    + User 1:
    {{user1 | json}}
    + User 2:
    {{user2 | json}}
    + Equal:
    {{result}}
    +
    +
    +
    + + angular.module('equalsExample', []).controller('ExampleController', ['$scope', function($scope) { + $scope.user1 = {}; + $scope.user2 = {}; + $scope.result; + $scope.compare = function() { + $scope.result = angular.equals($scope.user1, $scope.user2); + }; + }]); + +
    + */ +function equals(o1, o2) { + if (o1 === o2) return true; + if (o1 === null || o2 === null) return false; + if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN + var t1 = typeof o1, t2 = typeof o2, length, key, keySet; + if (t1 == t2 && t1 == 'object') { + if (isArray(o1)) { + if (!isArray(o2)) return false; + if ((length = o1.length) == o2.length) { + for (key = 0; key < length; key++) { + if (!equals(o1[key], o2[key])) return false; + } + return true; + } + } else if (isDate(o1)) { + if (!isDate(o2)) return false; + return equals(o1.getTime(), o2.getTime()); + } else if (isRegExp(o1)) { + if (!isRegExp(o2)) return false; + return o1.toString() == o2.toString(); + } else { + if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || + isArray(o2) || isDate(o2) || isRegExp(o2)) return false; + keySet = createMap(); + for (key in o1) { + if (key.charAt(0) === '$' || isFunction(o1[key])) continue; + if (!equals(o1[key], o2[key])) return false; + keySet[key] = true; + } + for (key in o2) { + if (!(key in keySet) && + key.charAt(0) !== '$' && + isDefined(o2[key]) && + !isFunction(o2[key])) return false; + } + return true; + } + } + return false; +} + +var csp = function() { + if (!isDefined(csp.rules)) { + + + var ngCspElement = (window.document.querySelector('[ng-csp]') || + window.document.querySelector('[data-ng-csp]')); + + if (ngCspElement) { + var ngCspAttribute = ngCspElement.getAttribute('ng-csp') || + ngCspElement.getAttribute('data-ng-csp'); + csp.rules = { + noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1), + noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1) + }; + } else { + csp.rules = { + noUnsafeEval: noUnsafeEval(), + noInlineStyle: false + }; + } + } + + return csp.rules; + + function noUnsafeEval() { + try { + /* jshint -W031, -W054 */ + new Function(''); + /* jshint +W031, +W054 */ + return false; + } catch (e) { + return true; + } + } +}; + +/** + * @ngdoc directive + * @module ng + * @name ngJq + * + * @element ANY + * @param {string=} ngJq the name of the library available under `window` + * to be used for angular.element + * @description + * Use this directive to force the angular.element library. This should be + * used to force either jqLite by leaving ng-jq blank or setting the name of + * the jquery variable under window (eg. jQuery). + * + * Since angular looks for this directive when it is loaded (doesn't wait for the + * DOMContentLoaded event), it must be placed on an element that comes before the script + * which loads angular. Also, only the first instance of `ng-jq` will be used and all + * others ignored. + * + * @example + * This example shows how to force jqLite using the `ngJq` directive to the `html` tag. + ```html + + + ... + ... + + ``` + * @example + * This example shows how to use a jQuery based library of a different name. + * The library name must be available at the top most 'window'. + ```html + + + ... + ... + + ``` + */ +var jq = function() { + if (isDefined(jq.name_)) return jq.name_; + var el; + var i, ii = ngAttrPrefixes.length, prefix, name; + for (i = 0; i < ii; ++i) { + prefix = ngAttrPrefixes[i]; + if (el = window.document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) { + name = el.getAttribute(prefix + 'jq'); + break; + } + } + + return (jq.name_ = name); +}; + +function concat(array1, array2, index) { + return array1.concat(slice.call(array2, index)); +} + +function sliceArgs(args, startIndex) { + return slice.call(args, startIndex || 0); +} + + +/* jshint -W101 */ +/** + * @ngdoc function + * @name angular.bind + * @module ng + * @kind function + * + * @description + * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for + * `fn`). You can supply optional `args` that are prebound to the function. This feature is also + * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as + * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application). + * + * @param {Object} self Context which `fn` should be evaluated in. + * @param {function()} fn Function to be bound. + * @param {...*} args Optional arguments to be prebound to the `fn` function call. + * @returns {function()} Function that wraps the `fn` with all the specified bindings. + */ +/* jshint +W101 */ +function bind(self, fn) { + var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; + if (isFunction(fn) && !(fn instanceof RegExp)) { + return curryArgs.length + ? function() { + return arguments.length + ? fn.apply(self, concat(curryArgs, arguments, 0)) + : fn.apply(self, curryArgs); + } + : function() { + return arguments.length + ? fn.apply(self, arguments) + : fn.call(self); + }; + } else { + // In IE, native methods are not functions so they cannot be bound (note: they don't need to be). + return fn; + } +} + + +function toJsonReplacer(key, value) { + var val = value; + + if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { + val = undefined; + } else if (isWindow(value)) { + val = '$WINDOW'; + } else if (value && window.document === value) { + val = '$DOCUMENT'; + } else if (isScope(value)) { + val = '$SCOPE'; + } + + return val; +} + + +/** + * @ngdoc function + * @name angular.toJson + * @module ng + * @kind function + * + * @description + * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be + * stripped since angular uses this notation internally. + * + * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. + * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace. + * If set to an integer, the JSON output will contain that many spaces per indentation. + * @returns {string|undefined} JSON-ified string representing `obj`. + * @knownIssue + * + * The Safari browser throws a `RangeError` instead of returning `null` when it tries to stringify a `Date` + * object with an invalid date value. The only reliable way to prevent this is to monkeypatch the + * `Date.prototype.toJSON` method as follows: + * + * ``` + * var _DatetoJSON = Date.prototype.toJSON; + * Date.prototype.toJSON = function() { + * try { + * return _DatetoJSON.call(this); + * } catch(e) { + * if (e instanceof RangeError) { + * return null; + * } + * throw e; + * } + * }; + * ``` + * + * See https://github.com/angular/angular.js/pull/14221 for more information. + */ +function toJson(obj, pretty) { + if (isUndefined(obj)) return undefined; + if (!isNumber(pretty)) { + pretty = pretty ? 2 : null; + } + return JSON.stringify(obj, toJsonReplacer, pretty); +} + + +/** + * @ngdoc function + * @name angular.fromJson + * @module ng + * @kind function + * + * @description + * Deserializes a JSON string. + * + * @param {string} json JSON string to deserialize. + * @returns {Object|Array|string|number} Deserialized JSON string. + */ +function fromJson(json) { + return isString(json) + ? JSON.parse(json) + : json; +} + + +var ALL_COLONS = /:/g; +function timezoneToOffset(timezone, fallback) { + // IE/Edge do not "understand" colon (`:`) in timezone + timezone = timezone.replace(ALL_COLONS, ''); + var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; + return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; +} + + +function addDateMinutes(date, minutes) { + date = new Date(date.getTime()); + date.setMinutes(date.getMinutes() + minutes); + return date; +} + + +function convertTimezoneToLocal(date, timezone, reverse) { + reverse = reverse ? -1 : 1; + var dateTimezoneOffset = date.getTimezoneOffset(); + var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); + return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset)); +} + + +/** + * @returns {string} Returns the string representation of the element. + */ +function startingTag(element) { + element = jqLite(element).clone(); + try { + // turns out IE does not let you set .html() on elements which + // are not allowed to have children. So we just ignore it. + element.empty(); + } catch (e) {} + var elemHtml = jqLite('
    ').append(element).html(); + try { + return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : + elemHtml. + match(/^(<[^>]+>)/)[1]. + replace(/^<([\w\-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);}); + } catch (e) { + return lowercase(elemHtml); + } + +} + + +///////////////////////////////////////////////// + +/** + * Tries to decode the URI component without throwing an exception. + * + * @private + * @param str value potential URI component to check. + * @returns {boolean} True if `value` can be decoded + * with the decodeURIComponent function. + */ +function tryDecodeURIComponent(value) { + try { + return decodeURIComponent(value); + } catch (e) { + // Ignore any invalid uri component. + } +} + + +/** + * Parses an escaped url query string into key-value pairs. + * @returns {Object.} + */ +function parseKeyValue(/**string*/keyValue) { + var obj = {}; + forEach((keyValue || "").split('&'), function(keyValue) { + var splitPoint, key, val; + if (keyValue) { + key = keyValue = keyValue.replace(/\+/g,'%20'); + splitPoint = keyValue.indexOf('='); + if (splitPoint !== -1) { + key = keyValue.substring(0, splitPoint); + val = keyValue.substring(splitPoint + 1); + } + key = tryDecodeURIComponent(key); + if (isDefined(key)) { + val = isDefined(val) ? tryDecodeURIComponent(val) : true; + if (!hasOwnProperty.call(obj, key)) { + obj[key] = val; + } else if (isArray(obj[key])) { + obj[key].push(val); + } else { + obj[key] = [obj[key],val]; + } + } + } + }); + return obj; +} + +function toKeyValue(obj) { + var parts = []; + forEach(obj, function(value, key) { + if (isArray(value)) { + forEach(value, function(arrayValue) { + parts.push(encodeUriQuery(key, true) + + (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true))); + }); + } else { + parts.push(encodeUriQuery(key, true) + + (value === true ? '' : '=' + encodeUriQuery(value, true))); + } + }); + return parts.length ? parts.join('&') : ''; +} + + +/** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path + * segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ +function encodeUriSegment(val) { + return encodeUriQuery(val, true). + replace(/%26/gi, '&'). + replace(/%3D/gi, '='). + replace(/%2B/gi, '+'); +} + + +/** + * This method is intended for encoding *key* or *value* parts of query component. We need a custom + * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be + * encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ +function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%3B/gi, ';'). + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); +} + +var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-']; + +function getNgAttribute(element, ngAttr) { + var attr, i, ii = ngAttrPrefixes.length; + for (i = 0; i < ii; ++i) { + attr = ngAttrPrefixes[i] + ngAttr; + if (isString(attr = element.getAttribute(attr))) { + return attr; + } + } + return null; +} + +/** + * @ngdoc directive + * @name ngApp + * @module ng + * + * @element ANY + * @param {angular.Module} ngApp an optional application + * {@link angular.module module} name to load. + * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be + * created in "strict-di" mode. This means that the application will fail to invoke functions which + * do not use explicit function annotation (and are thus unsuitable for minification), as described + * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in + * tracking down the root of these bugs. + * + * @description + * + * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive + * designates the **root element** of the application and is typically placed near the root element + * of the page - e.g. on the `` or `` tags. + * + * There are a few things to keep in mind when using `ngApp`: + * - only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp` + * found in the document will be used to define the root element to auto-bootstrap as an + * application. To run multiple applications in an HTML document you must manually bootstrap them using + * {@link angular.bootstrap} instead. + * - AngularJS applications cannot be nested within each other. + * - Do not use a directive that uses {@link ng.$compile#transclusion transclusion} on the same element as `ngApp`. + * This includes directives such as {@link ng.ngIf `ngIf`}, {@link ng.ngInclude `ngInclude`} and + * {@link ngRoute.ngView `ngView`}. + * Doing this misplaces the app {@link ng.$rootElement `$rootElement`} and the app's {@link auto.$injector injector}, + * causing animations to stop working and making the injector inaccessible from outside the app. + * + * You can specify an **AngularJS module** to be used as the root module for the application. This + * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It + * should contain the application code needed or have dependencies on other modules that will + * contain the code. See {@link angular.module} for more information. + * + * In the example below if the `ngApp` directive were not placed on the `html` element then the + * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}` + * would not be resolved to `3`. + * + * `ngApp` is the easiest, and most common way to bootstrap an application. + * + + +
    + I can add: {{a}} + {{b}} = {{ a+b }} +
    +
    + + angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) { + $scope.a = 1; + $scope.b = 2; + }); + +
    + * + * Using `ngStrictDi`, you would see something like this: + * + + +
    +
    + I can add: {{a}} + {{b}} = {{ a+b }} + +

    This renders because the controller does not fail to + instantiate, by using explicit annotation style (see + script.js for details) +

    +
    + +
    + Name:
    + Hello, {{name}}! + +

    This renders because the controller does not fail to + instantiate, by using explicit annotation style + (see script.js for details) +

    +
    + +
    + I can add: {{a}} + {{b}} = {{ a+b }} + +

    The controller could not be instantiated, due to relying + on automatic function annotations (which are disabled in + strict mode). As such, the content of this section is not + interpolated, and there should be an error in your web console. +

    +
    +
    +
    + + angular.module('ngAppStrictDemo', []) + // BadController will fail to instantiate, due to relying on automatic function annotation, + // rather than an explicit annotation + .controller('BadController', function($scope) { + $scope.a = 1; + $scope.b = 2; + }) + // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated, + // due to using explicit annotations using the array style and $inject property, respectively. + .controller('GoodController1', ['$scope', function($scope) { + $scope.a = 1; + $scope.b = 2; + }]) + .controller('GoodController2', GoodController2); + function GoodController2($scope) { + $scope.name = "World"; + } + GoodController2.$inject = ['$scope']; + + + div[ng-controller] { + margin-bottom: 1em; + -webkit-border-radius: 4px; + border-radius: 4px; + border: 1px solid; + padding: .5em; + } + div[ng-controller^=Good] { + border-color: #d6e9c6; + background-color: #dff0d8; + color: #3c763d; + } + div[ng-controller^=Bad] { + border-color: #ebccd1; + background-color: #f2dede; + color: #a94442; + margin-bottom: 0; + } + +
    + */ +function angularInit(element, bootstrap) { + var appElement, + module, + config = {}; + + // The element `element` has priority over any other element. + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + 'app'; + + if (!appElement && element.hasAttribute && element.hasAttribute(name)) { + appElement = element; + module = element.getAttribute(name); + } + }); + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + 'app'; + var candidate; + + if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) { + appElement = candidate; + module = candidate.getAttribute(name); + } + }); + if (appElement) { + config.strictDi = getNgAttribute(appElement, "strict-di") !== null; + bootstrap(appElement, module ? [module] : [], config); + } +} + +/** + * @ngdoc function + * @name angular.bootstrap + * @module ng + * @description + * Use this function to manually start up angular application. + * + * For more information, see the {@link guide/bootstrap Bootstrap guide}. + * + * Angular will detect if it has been loaded into the browser more than once and only allow the + * first loaded script to be bootstrapped and will report a warning to the browser console for + * each of the subsequent scripts. This prevents strange results in applications, where otherwise + * multiple instances of Angular try to work on the DOM. + * + *
    + * **Note:** Protractor based end-to-end tests cannot use this function to bootstrap manually. + * They must use {@link ng.directive:ngApp ngApp}. + *
    + * + *
    + * **Note:** Do not bootstrap the app on an element with a directive that uses {@link ng.$compile#transclusion transclusion}, + * such as {@link ng.ngIf `ngIf`}, {@link ng.ngInclude `ngInclude`} and {@link ngRoute.ngView `ngView`}. + * Doing this misplaces the app {@link ng.$rootElement `$rootElement`} and the app's {@link auto.$injector injector}, + * causing animations to stop working and making the injector inaccessible from outside the app. + *
    + * + * ```html + * + * + * + *
    + * {{greeting}} + *
    + * + * + * + * + * + * ``` + * + * @param {DOMElement} element DOM element which is the root of angular application. + * @param {Array=} modules an array of modules to load into the application. + * Each item in the array should be the name of a predefined module or a (DI annotated) + * function that will be invoked by the injector as a `config` block. + * See: {@link angular.module modules} + * @param {Object=} config an object for defining configuration options for the application. The + * following keys are supported: + * + * * `strictDi` - disable automatic function annotation for the application. This is meant to + * assist in finding bugs which break minified code. Defaults to `false`. + * + * @returns {auto.$injector} Returns the newly created injector for this app. + */ +function bootstrap(element, modules, config) { + if (!isObject(config)) config = {}; + var defaultConfig = { + strictDi: false + }; + config = extend(defaultConfig, config); + var doBootstrap = function() { + element = jqLite(element); + + if (element.injector()) { + var tag = (element[0] === window.document) ? 'document' : startingTag(element); + // Encode angle brackets to prevent input from being sanitized to empty string #8683. + throw ngMinErr( + 'btstrpd', + "App already bootstrapped with this element '{0}'", + tag.replace(//,'>')); + } + + modules = modules || []; + modules.unshift(['$provide', function($provide) { + $provide.value('$rootElement', element); + }]); + + if (config.debugInfoEnabled) { + // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`. + modules.push(['$compileProvider', function($compileProvider) { + $compileProvider.debugInfoEnabled(true); + }]); + } + + modules.unshift('ng'); + var injector = createInjector(modules, config.strictDi); + injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', + function bootstrapApply(scope, element, compile, injector) { + scope.$apply(function() { + element.data('$injector', injector); + compile(element)(scope); + }); + }] + ); + return injector; + }; + + var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/; + var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; + + if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) { + config.debugInfoEnabled = true; + window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, ''); + } + + if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { + return doBootstrap(); + } + + window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ''); + angular.resumeBootstrap = function(extraModules) { + forEach(extraModules, function(module) { + modules.push(module); + }); + return doBootstrap(); + }; + + if (isFunction(angular.resumeDeferredBootstrap)) { + angular.resumeDeferredBootstrap(); + } +} + +/** + * @ngdoc function + * @name angular.reloadWithDebugInfo + * @module ng + * @description + * Use this function to reload the current application with debug information turned on. + * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`. + * + * See {@link ng.$compileProvider#debugInfoEnabled} for more. + */ +function reloadWithDebugInfo() { + window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name; + window.location.reload(); +} + +/** + * @name angular.getTestability + * @module ng + * @description + * Get the testability service for the instance of Angular on the given + * element. + * @param {DOMElement} element DOM element which is the root of angular application. + */ +function getTestability(rootElement) { + var injector = angular.element(rootElement).injector(); + if (!injector) { + throw ngMinErr('test', + 'no injector found for element argument to getTestability'); + } + return injector.get('$$testability'); +} + +var SNAKE_CASE_REGEXP = /[A-Z]/g; +function snake_case(name, separator) { + separator = separator || '_'; + return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); +} + +var bindJQueryFired = false; +function bindJQuery() { + var originalCleanData; + + if (bindJQueryFired) { + return; + } + + // bind to jQuery if present; + var jqName = jq(); + jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present) + !jqName ? undefined : // use jqLite + window[jqName]; // use jQuery specified by `ngJq` + + // Use jQuery if it exists with proper functionality, otherwise default to us. + // Angular 1.2+ requires jQuery 1.7+ for on()/off() support. + // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older + // versions. It will not work for sure with jQuery <1.7, though. + if (jQuery && jQuery.fn.on) { + jqLite = jQuery; + extend(jQuery.fn, { + scope: JQLitePrototype.scope, + isolateScope: JQLitePrototype.isolateScope, + controller: JQLitePrototype.controller, + injector: JQLitePrototype.injector, + inheritedData: JQLitePrototype.inheritedData + }); + + // All nodes removed from the DOM via various jQuery APIs like .remove() + // are passed through jQuery.cleanData. Monkey-patch this method to fire + // the $destroy event on all removed nodes. + originalCleanData = jQuery.cleanData; + jQuery.cleanData = function(elems) { + var events; + for (var i = 0, elem; (elem = elems[i]) != null; i++) { + events = jQuery._data(elem, "events"); + if (events && events.$destroy) { + jQuery(elem).triggerHandler('$destroy'); + } + } + originalCleanData(elems); + }; + } else { + jqLite = JQLite; + } + + angular.element = jqLite; + + // Prevent double-proxying. + bindJQueryFired = true; +} + +/** + * throw error if the argument is falsy. + */ +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); + } + return arg; +} + +function assertArgFn(arg, name, acceptArrayAnnotation) { + if (acceptArrayAnnotation && isArray(arg)) { + arg = arg[arg.length - 1]; + } + + assertArg(isFunction(arg), name, 'not a function, got ' + + (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg)); + return arg; +} + +/** + * throw error if the name given is hasOwnProperty + * @param {String} name the name to test + * @param {String} context the context in which the name is used, such as module or directive + */ +function assertNotHasOwnProperty(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context); + } +} + +/** + * Return the value accessible from the object by path. Any undefined traversals are ignored + * @param {Object} obj starting object + * @param {String} path path to traverse + * @param {boolean} [bindFnToScope=true] + * @returns {Object} value as accessible by path + */ +//TODO(misko): this function needs to be removed +function getter(obj, path, bindFnToScope) { + if (!path) return obj; + var keys = path.split('.'); + var key; + var lastInstance = obj; + var len = keys.length; + + for (var i = 0; i < len; i++) { + key = keys[i]; + if (obj) { + obj = (lastInstance = obj)[key]; + } + } + if (!bindFnToScope && isFunction(obj)) { + return bind(lastInstance, obj); + } + return obj; +} + +/** + * Return the DOM siblings between the first and last node in the given array. + * @param {Array} array like object + * @returns {Array} the inputted object or a jqLite collection containing the nodes + */ +function getBlockNodes(nodes) { + // TODO(perf): update `nodes` instead of creating a new object? + var node = nodes[0]; + var endNode = nodes[nodes.length - 1]; + var blockNodes; + + for (var i = 1; node !== endNode && (node = node.nextSibling); i++) { + if (blockNodes || nodes[i] !== node) { + if (!blockNodes) { + blockNodes = jqLite(slice.call(nodes, 0, i)); + } + blockNodes.push(node); + } + } + + return blockNodes || nodes; +} + + +/** + * Creates a new object without a prototype. This object is useful for lookup without having to + * guard against prototypically inherited properties via hasOwnProperty. + * + * Related micro-benchmarks: + * - http://jsperf.com/object-create2 + * - http://jsperf.com/proto-map-lookup/2 + * - http://jsperf.com/for-in-vs-object-keys2 + * + * @returns {Object} + */ +function createMap() { + return Object.create(null); +} + +var NODE_TYPE_ELEMENT = 1; +var NODE_TYPE_ATTRIBUTE = 2; +var NODE_TYPE_TEXT = 3; +var NODE_TYPE_COMMENT = 8; +var NODE_TYPE_DOCUMENT = 9; +var NODE_TYPE_DOCUMENT_FRAGMENT = 11; + +/** + * @ngdoc type + * @name angular.Module + * @module ng + * @description + * + * Interface for configuring angular {@link angular.module modules}. + */ + +function setupModuleLoader(window) { + + var $injectorMinErr = minErr('$injector'); + var ngMinErr = minErr('ng'); + + function ensure(obj, name, factory) { + return obj[name] || (obj[name] = factory()); + } + + var angular = ensure(window, 'angular', Object); + + // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap + angular.$$minErr = angular.$$minErr || minErr; + + return ensure(angular, 'module', function() { + /** @type {Object.} */ + var modules = {}; + + /** + * @ngdoc function + * @name angular.module + * @module ng + * @description + * + * The `angular.module` is a global place for creating, registering and retrieving Angular + * modules. + * All modules (angular core or 3rd party) that should be available to an application must be + * registered using this mechanism. + * + * Passing one argument retrieves an existing {@link angular.Module}, + * whereas passing more than one argument creates a new {@link angular.Module} + * + * + * # Module + * + * A module is a collection of services, directives, controllers, filters, and configuration information. + * `angular.module` is used to configure the {@link auto.$injector $injector}. + * + * ```js + * // Create a new module + * var myModule = angular.module('myModule', []); + * + * // register a new service + * myModule.value('appName', 'MyCoolApp'); + * + * // configure existing services inside initialization blocks. + * myModule.config(['$locationProvider', function($locationProvider) { + * // Configure existing providers + * $locationProvider.hashPrefix('!'); + * }]); + * ``` + * + * Then you can create an injector and load your modules like this: + * + * ```js + * var injector = angular.injector(['ng', 'myModule']) + * ``` + * + * However it's more likely that you'll just use + * {@link ng.directive:ngApp ngApp} or + * {@link angular.bootstrap} to simplify this process for you. + * + * @param {!string} name The name of the module to create or retrieve. + * @param {!Array.=} requires If specified then new module is being created. If + * unspecified then the module is being retrieved for further configuration. + * @param {Function=} configFn Optional configuration function for the module. Same as + * {@link angular.Module#config Module#config()}. + * @returns {angular.Module} new module with the {@link angular.Module} api. + */ + return function module(name, requires, configFn) { + var assertNotHasOwnProperty = function(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); + } + }; + + assertNotHasOwnProperty(name, 'module'); + if (requires && modules.hasOwnProperty(name)) { + modules[name] = null; + } + return ensure(modules, name, function() { + if (!requires) { + throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " + + "the module name or forgot to load it. If registering a module ensure that you " + + "specify the dependencies as the second argument.", name); + } + + /** @type {!Array.>} */ + var invokeQueue = []; + + /** @type {!Array.} */ + var configBlocks = []; + + /** @type {!Array.} */ + var runBlocks = []; + + var config = invokeLater('$injector', 'invoke', 'push', configBlocks); + + /** @type {angular.Module} */ + var moduleInstance = { + // Private state + _invokeQueue: invokeQueue, + _configBlocks: configBlocks, + _runBlocks: runBlocks, + + /** + * @ngdoc property + * @name angular.Module#requires + * @module ng + * + * @description + * Holds the list of modules which the injector will load before the current module is + * loaded. + */ + requires: requires, + + /** + * @ngdoc property + * @name angular.Module#name + * @module ng + * + * @description + * Name of the module. + */ + name: name, + + + /** + * @ngdoc method + * @name angular.Module#provider + * @module ng + * @param {string} name service name + * @param {Function} providerType Construction function for creating new instance of the + * service. + * @description + * See {@link auto.$provide#provider $provide.provider()}. + */ + provider: invokeLaterAndSetModuleName('$provide', 'provider'), + + /** + * @ngdoc method + * @name angular.Module#factory + * @module ng + * @param {string} name service name + * @param {Function} providerFunction Function for creating new instance of the service. + * @description + * See {@link auto.$provide#factory $provide.factory()}. + */ + factory: invokeLaterAndSetModuleName('$provide', 'factory'), + + /** + * @ngdoc method + * @name angular.Module#service + * @module ng + * @param {string} name service name + * @param {Function} constructor A constructor function that will be instantiated. + * @description + * See {@link auto.$provide#service $provide.service()}. + */ + service: invokeLaterAndSetModuleName('$provide', 'service'), + + /** + * @ngdoc method + * @name angular.Module#value + * @module ng + * @param {string} name service name + * @param {*} object Service instance object. + * @description + * See {@link auto.$provide#value $provide.value()}. + */ + value: invokeLater('$provide', 'value'), + + /** + * @ngdoc method + * @name angular.Module#constant + * @module ng + * @param {string} name constant name + * @param {*} object Constant value. + * @description + * Because the constants are fixed, they get applied before other provide methods. + * See {@link auto.$provide#constant $provide.constant()}. + */ + constant: invokeLater('$provide', 'constant', 'unshift'), + + /** + * @ngdoc method + * @name angular.Module#decorator + * @module ng + * @param {string} name The name of the service to decorate. + * @param {Function} decorFn This function will be invoked when the service needs to be + * instantiated and should return the decorated service instance. + * @description + * See {@link auto.$provide#decorator $provide.decorator()}. + */ + decorator: invokeLaterAndSetModuleName('$provide', 'decorator'), + + /** + * @ngdoc method + * @name angular.Module#animation + * @module ng + * @param {string} name animation name + * @param {Function} animationFactory Factory function for creating new instance of an + * animation. + * @description + * + * **NOTE**: animations take effect only if the **ngAnimate** module is loaded. + * + * + * Defines an animation hook that can be later used with + * {@link $animate $animate} service and directives that use this service. + * + * ```js + * module.animation('.animation-name', function($inject1, $inject2) { + * return { + * eventName : function(element, done) { + * //code to run the animation + * //once complete, then run done() + * return function cancellationFunction(element) { + * //code to cancel the animation + * } + * } + * } + * }) + * ``` + * + * See {@link ng.$animateProvider#register $animateProvider.register()} and + * {@link ngAnimate ngAnimate module} for more information. + */ + animation: invokeLaterAndSetModuleName('$animateProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#filter + * @module ng + * @param {string} name Filter name - this must be a valid angular expression identifier + * @param {Function} filterFactory Factory function for creating new instance of filter. + * @description + * See {@link ng.$filterProvider#register $filterProvider.register()}. + * + *
    + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + *
    + */ + filter: invokeLaterAndSetModuleName('$filterProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#controller + * @module ng + * @param {string|Object} name Controller name, or an object map of controllers where the + * keys are the names and the values are the constructors. + * @param {Function} constructor Controller constructor function. + * @description + * See {@link ng.$controllerProvider#register $controllerProvider.register()}. + */ + controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#directive + * @module ng + * @param {string|Object} name Directive name, or an object map of directives where the + * keys are the names and the values are the factories. + * @param {Function} directiveFactory Factory function for creating new instance of + * directives. + * @description + * See {@link ng.$compileProvider#directive $compileProvider.directive()}. + */ + directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'), + + /** + * @ngdoc method + * @name angular.Module#component + * @module ng + * @param {string} name Name of the component in camel-case (i.e. myComp which will match as my-comp) + * @param {Object} options Component definition object (a simplified + * {@link ng.$compile#directive-definition-object directive definition object}) + * + * @description + * See {@link ng.$compileProvider#component $compileProvider.component()}. + */ + component: invokeLaterAndSetModuleName('$compileProvider', 'component'), + + /** + * @ngdoc method + * @name angular.Module#config + * @module ng + * @param {Function} configFn Execute this function on module load. Useful for service + * configuration. + * @description + * Use this method to register work which needs to be performed on module loading. + * For more about how to configure services, see + * {@link providers#provider-recipe Provider Recipe}. + */ + config: config, + + /** + * @ngdoc method + * @name angular.Module#run + * @module ng + * @param {Function} initializationFn Execute this function after injector creation. + * Useful for application initialization. + * @description + * Use this method to register work which should be performed when the injector is done + * loading all modules. + */ + run: function(block) { + runBlocks.push(block); + return this; + } + }; + + if (configFn) { + config(configFn); + } + + return moduleInstance; + + /** + * @param {string} provider + * @param {string} method + * @param {String=} insertMethod + * @returns {angular.Module} + */ + function invokeLater(provider, method, insertMethod, queue) { + if (!queue) queue = invokeQueue; + return function() { + queue[insertMethod || 'push']([provider, method, arguments]); + return moduleInstance; + }; + } + + /** + * @param {string} provider + * @param {string} method + * @returns {angular.Module} + */ + function invokeLaterAndSetModuleName(provider, method) { + return function(recipeName, factoryFunction) { + if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name; + invokeQueue.push([provider, method, arguments]); + return moduleInstance; + }; + } + }); + }; + }); + +} + +/* global shallowCopy: true */ + +/** + * Creates a shallow copy of an object, an array or a primitive. + * + * Assumes that there are no proto properties for objects. + */ +function shallowCopy(src, dst) { + if (isArray(src)) { + dst = dst || []; + + for (var i = 0, ii = src.length; i < ii; i++) { + dst[i] = src[i]; + } + } else if (isObject(src)) { + dst = dst || {}; + + for (var key in src) { + if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) { + dst[key] = src[key]; + } + } + } + + return dst || src; +} + +/* global toDebugString: true */ + +function serializeObject(obj) { + var seen = []; + + return JSON.stringify(obj, function(key, val) { + val = toJsonReplacer(key, val); + if (isObject(val)) { + + if (seen.indexOf(val) >= 0) return '...'; + + seen.push(val); + } + return val; + }); +} + +function toDebugString(obj) { + if (typeof obj === 'function') { + return obj.toString().replace(/ \{[\s\S]*$/, ''); + } else if (isUndefined(obj)) { + return 'undefined'; + } else if (typeof obj !== 'string') { + return serializeObject(obj); + } + return obj; +} + +/* global angularModule: true, + version: true, + + $CompileProvider, + + htmlAnchorDirective, + inputDirective, + inputDirective, + formDirective, + scriptDirective, + selectDirective, + styleDirective, + optionDirective, + ngBindDirective, + ngBindHtmlDirective, + ngBindTemplateDirective, + ngClassDirective, + ngClassEvenDirective, + ngClassOddDirective, + ngCloakDirective, + ngControllerDirective, + ngFormDirective, + ngHideDirective, + ngIfDirective, + ngIncludeDirective, + ngIncludeFillContentDirective, + ngInitDirective, + ngNonBindableDirective, + ngPluralizeDirective, + ngRepeatDirective, + ngShowDirective, + ngStyleDirective, + ngSwitchDirective, + ngSwitchWhenDirective, + ngSwitchDefaultDirective, + ngOptionsDirective, + ngTranscludeDirective, + ngModelDirective, + ngListDirective, + ngChangeDirective, + patternDirective, + patternDirective, + requiredDirective, + requiredDirective, + minlengthDirective, + minlengthDirective, + maxlengthDirective, + maxlengthDirective, + ngValueDirective, + ngModelOptionsDirective, + ngAttributeAliasDirectives, + ngEventDirectives, + + $AnchorScrollProvider, + $AnimateProvider, + $CoreAnimateCssProvider, + $$CoreAnimateJsProvider, + $$CoreAnimateQueueProvider, + $$AnimateRunnerFactoryProvider, + $$AnimateAsyncRunFactoryProvider, + $BrowserProvider, + $CacheFactoryProvider, + $ControllerProvider, + $DateProvider, + $DocumentProvider, + $ExceptionHandlerProvider, + $FilterProvider, + $$ForceReflowProvider, + $InterpolateProvider, + $IntervalProvider, + $$HashMapProvider, + $HttpProvider, + $HttpParamSerializerProvider, + $HttpParamSerializerJQLikeProvider, + $HttpBackendProvider, + $xhrFactoryProvider, + $jsonpCallbacksProvider, + $LocationProvider, + $LogProvider, + $ParseProvider, + $RootScopeProvider, + $QProvider, + $$QProvider, + $$SanitizeUriProvider, + $SceProvider, + $SceDelegateProvider, + $SnifferProvider, + $TemplateCacheProvider, + $TemplateRequestProvider, + $$TestabilityProvider, + $TimeoutProvider, + $$RAFProvider, + $WindowProvider, + $$jqLiteProvider, + $$CookieReaderProvider +*/ + + +/** + * @ngdoc object + * @name angular.version + * @module ng + * @description + * An object that contains information about the current AngularJS version. + * + * This object has the following properties: + * + * - `full` – `{string}` – Full version string, such as "0.9.18". + * - `major` – `{number}` – Major version number, such as "0". + * - `minor` – `{number}` – Minor version number, such as "9". + * - `dot` – `{number}` – Dot version number, such as "18". + * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". + */ +var version = { + full: '1.5.8', // all of these placeholder strings will be replaced by grunt's + major: 1, // package task + minor: 5, + dot: 8, + codeName: 'arbitrary-fallbacks' +}; + + +function publishExternalAPI(angular) { + extend(angular, { + 'bootstrap': bootstrap, + 'copy': copy, + 'extend': extend, + 'merge': merge, + 'equals': equals, + 'element': jqLite, + 'forEach': forEach, + 'injector': createInjector, + 'noop': noop, + 'bind': bind, + 'toJson': toJson, + 'fromJson': fromJson, + 'identity': identity, + 'isUndefined': isUndefined, + 'isDefined': isDefined, + 'isString': isString, + 'isFunction': isFunction, + 'isObject': isObject, + 'isNumber': isNumber, + 'isElement': isElement, + 'isArray': isArray, + 'version': version, + 'isDate': isDate, + 'lowercase': lowercase, + 'uppercase': uppercase, + 'callbacks': {$$counter: 0}, + 'getTestability': getTestability, + '$$minErr': minErr, + '$$csp': csp, + 'reloadWithDebugInfo': reloadWithDebugInfo + }); + + angularModule = setupModuleLoader(window); + + angularModule('ng', ['ngLocale'], ['$provide', + function ngModule($provide) { + // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it. + $provide.provider({ + $$sanitizeUri: $$SanitizeUriProvider + }); + $provide.provider('$compile', $CompileProvider). + directive({ + a: htmlAnchorDirective, + input: inputDirective, + textarea: inputDirective, + form: formDirective, + script: scriptDirective, + select: selectDirective, + style: styleDirective, + option: optionDirective, + ngBind: ngBindDirective, + ngBindHtml: ngBindHtmlDirective, + ngBindTemplate: ngBindTemplateDirective, + ngClass: ngClassDirective, + ngClassEven: ngClassEvenDirective, + ngClassOdd: ngClassOddDirective, + ngCloak: ngCloakDirective, + ngController: ngControllerDirective, + ngForm: ngFormDirective, + ngHide: ngHideDirective, + ngIf: ngIfDirective, + ngInclude: ngIncludeDirective, + ngInit: ngInitDirective, + ngNonBindable: ngNonBindableDirective, + ngPluralize: ngPluralizeDirective, + ngRepeat: ngRepeatDirective, + ngShow: ngShowDirective, + ngStyle: ngStyleDirective, + ngSwitch: ngSwitchDirective, + ngSwitchWhen: ngSwitchWhenDirective, + ngSwitchDefault: ngSwitchDefaultDirective, + ngOptions: ngOptionsDirective, + ngTransclude: ngTranscludeDirective, + ngModel: ngModelDirective, + ngList: ngListDirective, + ngChange: ngChangeDirective, + pattern: patternDirective, + ngPattern: patternDirective, + required: requiredDirective, + ngRequired: requiredDirective, + minlength: minlengthDirective, + ngMinlength: minlengthDirective, + maxlength: maxlengthDirective, + ngMaxlength: maxlengthDirective, + ngValue: ngValueDirective, + ngModelOptions: ngModelOptionsDirective + }). + directive({ + ngInclude: ngIncludeFillContentDirective + }). + directive(ngAttributeAliasDirectives). + directive(ngEventDirectives); + $provide.provider({ + $anchorScroll: $AnchorScrollProvider, + $animate: $AnimateProvider, + $animateCss: $CoreAnimateCssProvider, + $$animateJs: $$CoreAnimateJsProvider, + $$animateQueue: $$CoreAnimateQueueProvider, + $$AnimateRunner: $$AnimateRunnerFactoryProvider, + $$animateAsyncRun: $$AnimateAsyncRunFactoryProvider, + $browser: $BrowserProvider, + $cacheFactory: $CacheFactoryProvider, + $controller: $ControllerProvider, + $document: $DocumentProvider, + $exceptionHandler: $ExceptionHandlerProvider, + $filter: $FilterProvider, + $$forceReflow: $$ForceReflowProvider, + $interpolate: $InterpolateProvider, + $interval: $IntervalProvider, + $http: $HttpProvider, + $httpParamSerializer: $HttpParamSerializerProvider, + $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, + $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, + $jsonpCallbacks: $jsonpCallbacksProvider, + $location: $LocationProvider, + $log: $LogProvider, + $parse: $ParseProvider, + $rootScope: $RootScopeProvider, + $q: $QProvider, + $$q: $$QProvider, + $sce: $SceProvider, + $sceDelegate: $SceDelegateProvider, + $sniffer: $SnifferProvider, + $templateCache: $TemplateCacheProvider, + $templateRequest: $TemplateRequestProvider, + $$testability: $$TestabilityProvider, + $timeout: $TimeoutProvider, + $window: $WindowProvider, + $$rAF: $$RAFProvider, + $$jqLite: $$jqLiteProvider, + $$HashMap: $$HashMapProvider, + $$cookieReader: $$CookieReaderProvider + }); + } + ]); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* global JQLitePrototype: true, + addEventListenerFn: true, + removeEventListenerFn: true, + BOOLEAN_ATTR: true, + ALIASED_ATTR: true, +*/ + +////////////////////////////////// +//JQLite +////////////////////////////////// + +/** + * @ngdoc function + * @name angular.element + * @module ng + * @kind function + * + * @description + * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element. + * + * If jQuery is available, `angular.element` is an alias for the + * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element` + * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or **jqLite**. + * + * jqLite is a tiny, API-compatible subset of jQuery that allows + * Angular to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most + * commonly needed functionality with the goal of having a very small footprint. + * + * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. You can also use the + * {@link ngJq `ngJq`} directive to specify that jqlite should be used over jQuery, or to use a + * specific version of jQuery if multiple versions exist on the page. + * + *
    **Note:** All element references in Angular are always wrapped with jQuery or + * jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.
    + * + *
    **Note:** Keep in mind that this function will not find elements + * by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)` + * or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.
    + * + * ## Angular's jqLite + * jqLite provides only the following jQuery methods: + * + * - [`addClass()`](http://api.jquery.com/addClass/) - Does not support a function as first argument + * - [`after()`](http://api.jquery.com/after/) + * - [`append()`](http://api.jquery.com/append/) + * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters + * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData + * - [`children()`](http://api.jquery.com/children/) - Does not support selectors + * - [`clone()`](http://api.jquery.com/clone/) + * - [`contents()`](http://api.jquery.com/contents/) + * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. + * As a setter, does not convert numbers to strings or append 'px', and also does not have automatic property prefixing. + * - [`data()`](http://api.jquery.com/data/) + * - [`detach()`](http://api.jquery.com/detach/) + * - [`empty()`](http://api.jquery.com/empty/) + * - [`eq()`](http://api.jquery.com/eq/) + * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name + * - [`hasClass()`](http://api.jquery.com/hasClass/) + * - [`html()`](http://api.jquery.com/html/) + * - [`next()`](http://api.jquery.com/next/) - Does not support selectors + * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData + * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter + * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors + * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors + * - [`prepend()`](http://api.jquery.com/prepend/) + * - [`prop()`](http://api.jquery.com/prop/) + * - [`ready()`](http://api.jquery.com/ready/) + * - [`remove()`](http://api.jquery.com/remove/) + * - [`removeAttr()`](http://api.jquery.com/removeAttr/) + * - [`removeClass()`](http://api.jquery.com/removeClass/) - Does not support a function as first argument + * - [`removeData()`](http://api.jquery.com/removeData/) + * - [`replaceWith()`](http://api.jquery.com/replaceWith/) + * - [`text()`](http://api.jquery.com/text/) + * - [`toggleClass()`](http://api.jquery.com/toggleClass/) - Does not support a function as first argument + * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers + * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter + * - [`val()`](http://api.jquery.com/val/) + * - [`wrap()`](http://api.jquery.com/wrap/) + * + * ## jQuery/jqLite Extras + * Angular also provides the following additional methods and events to both jQuery and jqLite: + * + * ### Events + * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event + * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM + * element before it is removed. + * + * ### Methods + * - `controller(name)` - retrieves the controller of the current element or its parent. By default + * retrieves controller associated with the `ngController` directive. If `name` is provided as + * camelCase directive name, then the controller for this directive will be retrieved (e.g. + * `'ngModel'`). + * - `injector()` - retrieves the injector of the current element or its parent. + * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current + * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to + * be enabled. + * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the + * current element. This getter should be used only on elements that contain a directive which starts a new isolate + * scope. Calling `scope()` on this element always returns the original non-isolate scope. + * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled. + * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top + * parent element is reached. + * + * @knownIssue You cannot spy on `angular.element` if you are using Jasmine version 1.x. See + * https://github.com/angular/angular.js/issues/14251 for more information. + * + * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. + * @returns {Object} jQuery object. + */ + +JQLite.expando = 'ng339'; + +var jqCache = JQLite.cache = {}, + jqId = 1, + addEventListenerFn = function(element, type, fn) { + element.addEventListener(type, fn, false); + }, + removeEventListenerFn = function(element, type, fn) { + element.removeEventListener(type, fn, false); + }; + +/* + * !!! This is an undocumented "private" function !!! + */ +JQLite._data = function(node) { + //jQuery always returns an object on cache miss + return this.cache[node[this.expando]] || {}; +}; + +function jqNextId() { return ++jqId; } + + +var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; +var MOZ_HACK_REGEXP = /^moz([A-Z])/; +var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"}; +var jqLiteMinErr = minErr('jqLite'); + +/** + * Converts snake_case to camelCase. + * Also there is special case for Moz prefix starting with upper case letter. + * @param name Name to normalize + */ +function camelCase(name) { + return name. + replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }). + replace(MOZ_HACK_REGEXP, 'Moz$1'); +} + +var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; +var HTML_REGEXP = /<|&#?\w+;/; +var TAG_NAME_REGEXP = /<([\w:-]+)/; +var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; + +var wrapMap = { + 'option': [1, ''], + + 'thead': [1, '', '
    '], + 'col': [2, '', '
    '], + 'tr': [2, '', '
    '], + 'td': [3, '', '
    '], + '_default': [0, "", ""] +}; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function jqLiteIsTextNode(html) { + return !HTML_REGEXP.test(html); +} + +function jqLiteAcceptsData(node) { + // The window object can accept data but has no nodeType + // Otherwise we are only interested in elements (1) and documents (9) + var nodeType = node.nodeType; + return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT; +} + +function jqLiteHasData(node) { + for (var key in jqCache[node.ng339]) { + return true; + } + return false; +} + +function jqLiteCleanData(nodes) { + for (var i = 0, ii = nodes.length; i < ii; i++) { + jqLiteRemoveData(nodes[i]); + } +} + +function jqLiteBuildFragment(html, context) { + var tmp, tag, wrap, + fragment = context.createDocumentFragment(), + nodes = [], i; + + if (jqLiteIsTextNode(html)) { + // Convert non-html into a text node + nodes.push(context.createTextNode(html)); + } else { + // Convert html into DOM nodes + tmp = fragment.appendChild(context.createElement("div")); + tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase(); + wrap = wrapMap[tag] || wrapMap._default; + tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1>") + wrap[2]; + + // Descend through wrappers to the right content + i = wrap[0]; + while (i--) { + tmp = tmp.lastChild; + } + + nodes = concat(nodes, tmp.childNodes); + + tmp = fragment.firstChild; + tmp.textContent = ""; + } + + // Remove wrapper from fragment + fragment.textContent = ""; + fragment.innerHTML = ""; // Clear inner HTML + forEach(nodes, function(node) { + fragment.appendChild(node); + }); + + return fragment; +} + +function jqLiteParseHTML(html, context) { + context = context || window.document; + var parsed; + + if ((parsed = SINGLE_TAG_REGEXP.exec(html))) { + return [context.createElement(parsed[1])]; + } + + if ((parsed = jqLiteBuildFragment(html, context))) { + return parsed.childNodes; + } + + return []; +} + +function jqLiteWrapNode(node, wrapper) { + var parent = node.parentNode; + + if (parent) { + parent.replaceChild(wrapper, node); + } + + wrapper.appendChild(node); +} + + +// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259. +var jqLiteContains = window.Node.prototype.contains || function(arg) { + // jshint bitwise: false + return !!(this.compareDocumentPosition(arg) & 16); + // jshint bitwise: true +}; + +///////////////////////////////////////////// +function JQLite(element) { + if (element instanceof JQLite) { + return element; + } + + var argIsString; + + if (isString(element)) { + element = trim(element); + argIsString = true; + } + if (!(this instanceof JQLite)) { + if (argIsString && element.charAt(0) != '<') { + throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element'); + } + return new JQLite(element); + } + + if (argIsString) { + jqLiteAddNodes(this, jqLiteParseHTML(element)); + } else { + jqLiteAddNodes(this, element); + } +} + +function jqLiteClone(element) { + return element.cloneNode(true); +} + +function jqLiteDealoc(element, onlyDescendants) { + if (!onlyDescendants) jqLiteRemoveData(element); + + if (element.querySelectorAll) { + var descendants = element.querySelectorAll('*'); + for (var i = 0, l = descendants.length; i < l; i++) { + jqLiteRemoveData(descendants[i]); + } + } +} + +function jqLiteOff(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument'); + + var expandoStore = jqLiteExpandoStore(element); + var events = expandoStore && expandoStore.events; + var handle = expandoStore && expandoStore.handle; + + if (!handle) return; //no listeners registered + + if (!type) { + for (type in events) { + if (type !== '$destroy') { + removeEventListenerFn(element, type, handle); + } + delete events[type]; + } + } else { + + var removeHandler = function(type) { + var listenerFns = events[type]; + if (isDefined(fn)) { + arrayRemove(listenerFns || [], fn); + } + if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) { + removeEventListenerFn(element, type, handle); + delete events[type]; + } + }; + + forEach(type.split(' '), function(type) { + removeHandler(type); + if (MOUSE_EVENT_MAP[type]) { + removeHandler(MOUSE_EVENT_MAP[type]); + } + }); + } +} + +function jqLiteRemoveData(element, name) { + var expandoId = element.ng339; + var expandoStore = expandoId && jqCache[expandoId]; + + if (expandoStore) { + if (name) { + delete expandoStore.data[name]; + return; + } + + if (expandoStore.handle) { + if (expandoStore.events.$destroy) { + expandoStore.handle({}, '$destroy'); + } + jqLiteOff(element); + } + delete jqCache[expandoId]; + element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it + } +} + + +function jqLiteExpandoStore(element, createIfNecessary) { + var expandoId = element.ng339, + expandoStore = expandoId && jqCache[expandoId]; + + if (createIfNecessary && !expandoStore) { + element.ng339 = expandoId = jqNextId(); + expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined}; + } + + return expandoStore; +} + + +function jqLiteData(element, key, value) { + if (jqLiteAcceptsData(element)) { + + var isSimpleSetter = isDefined(value); + var isSimpleGetter = !isSimpleSetter && key && !isObject(key); + var massGetter = !key; + var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter); + var data = expandoStore && expandoStore.data; + + if (isSimpleSetter) { // data('key', value) + data[key] = value; + } else { + if (massGetter) { // data() + return data; + } else { + if (isSimpleGetter) { // data('key') + // don't force creation of expandoStore if it doesn't exist yet + return data && data[key]; + } else { // mass-setter: data({key1: val1, key2: val2}) + extend(data, key); + } + } + } + } +} + +function jqLiteHasClass(element, selector) { + if (!element.getAttribute) return false; + return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " "). + indexOf(" " + selector + " ") > -1); +} + +function jqLiteRemoveClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + forEach(cssClasses.split(' '), function(cssClass) { + element.setAttribute('class', trim( + (" " + (element.getAttribute('class') || '') + " ") + .replace(/[\n\t]/g, " ") + .replace(" " + trim(cssClass) + " ", " ")) + ); + }); + } +} + +function jqLiteAddClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ') + .replace(/[\n\t]/g, " "); + + forEach(cssClasses.split(' '), function(cssClass) { + cssClass = trim(cssClass); + if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) { + existingClasses += cssClass + ' '; + } + }); + + element.setAttribute('class', trim(existingClasses)); + } +} + + +function jqLiteAddNodes(root, elements) { + // THIS CODE IS VERY HOT. Don't make changes without benchmarking. + + if (elements) { + + // if a Node (the most common case) + if (elements.nodeType) { + root[root.length++] = elements; + } else { + var length = elements.length; + + // if an Array or NodeList and not a Window + if (typeof length === 'number' && elements.window !== elements) { + if (length) { + for (var i = 0; i < length; i++) { + root[root.length++] = elements[i]; + } + } + } else { + root[root.length++] = elements; + } + } + } +} + + +function jqLiteController(element, name) { + return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller'); +} + +function jqLiteInheritedData(element, name, value) { + // if element is the document object work with the html element instead + // this makes $(document).scope() possible + if (element.nodeType == NODE_TYPE_DOCUMENT) { + element = element.documentElement; + } + var names = isArray(name) ? name : [name]; + + while (element) { + for (var i = 0, ii = names.length; i < ii; i++) { + if (isDefined(value = jqLite.data(element, names[i]))) return value; + } + + // If dealing with a document fragment node with a host element, and no parent, use the host + // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM + // to lookup parent controllers. + element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host); + } +} + +function jqLiteEmpty(element) { + jqLiteDealoc(element, true); + while (element.firstChild) { + element.removeChild(element.firstChild); + } +} + +function jqLiteRemove(element, keepData) { + if (!keepData) jqLiteDealoc(element); + var parent = element.parentNode; + if (parent) parent.removeChild(element); +} + + +function jqLiteDocumentLoaded(action, win) { + win = win || window; + if (win.document.readyState === 'complete') { + // Force the action to be run async for consistent behavior + // from the action's point of view + // i.e. it will definitely not be in a $apply + win.setTimeout(action); + } else { + // No need to unbind this handler as load is only ever called once + jqLite(win).on('load', action); + } +} + +////////////////////////////////////////// +// Functions which are declared directly. +////////////////////////////////////////// +var JQLitePrototype = JQLite.prototype = { + ready: function(fn) { + var fired = false; + + function trigger() { + if (fired) return; + fired = true; + fn(); + } + + // check if document is already loaded + if (window.document.readyState === 'complete') { + window.setTimeout(trigger); + } else { + this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9 + // we can not use jqLite since we are not done loading and jQuery could be loaded later. + // jshint -W064 + JQLite(window).on('load', trigger); // fallback to window.onload for others + // jshint +W064 + } + }, + toString: function() { + var value = []; + forEach(this, function(e) { value.push('' + e);}); + return '[' + value.join(', ') + ']'; + }, + + eq: function(index) { + return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]); + }, + + length: 0, + push: push, + sort: [].sort, + splice: [].splice +}; + +////////////////////////////////////////// +// Functions iterating getter/setters. +// these functions return self on setter and +// value on get. +////////////////////////////////////////// +var BOOLEAN_ATTR = {}; +forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) { + BOOLEAN_ATTR[lowercase(value)] = value; +}); +var BOOLEAN_ELEMENTS = {}; +forEach('input,select,option,textarea,button,form,details'.split(','), function(value) { + BOOLEAN_ELEMENTS[value] = true; +}); +var ALIASED_ATTR = { + 'ngMinlength': 'minlength', + 'ngMaxlength': 'maxlength', + 'ngMin': 'min', + 'ngMax': 'max', + 'ngPattern': 'pattern' +}; + +function getBooleanAttrName(element, name) { + // check dom last since we will most likely fail on name + var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; + + // booleanAttr is here twice to minimize DOM access + return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr; +} + +function getAliasedAttrName(name) { + return ALIASED_ATTR[name]; +} + +forEach({ + data: jqLiteData, + removeData: jqLiteRemoveData, + hasData: jqLiteHasData, + cleanData: jqLiteCleanData +}, function(fn, name) { + JQLite[name] = fn; +}); + +forEach({ + data: jqLiteData, + inheritedData: jqLiteInheritedData, + + scope: function(element) { + // Can't use jqLiteData here directly so we stay compatible with jQuery! + return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']); + }, + + isolateScope: function(element) { + // Can't use jqLiteData here directly so we stay compatible with jQuery! + return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate'); + }, + + controller: jqLiteController, + + injector: function(element) { + return jqLiteInheritedData(element, '$injector'); + }, + + removeAttr: function(element, name) { + element.removeAttribute(name); + }, + + hasClass: jqLiteHasClass, + + css: function(element, name, value) { + name = camelCase(name); + + if (isDefined(value)) { + element.style[name] = value; + } else { + return element.style[name]; + } + }, + + attr: function(element, name, value) { + var nodeType = element.nodeType; + if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) { + return; + } + var lowercasedName = lowercase(name); + if (BOOLEAN_ATTR[lowercasedName]) { + if (isDefined(value)) { + if (!!value) { + element[name] = true; + element.setAttribute(name, lowercasedName); + } else { + element[name] = false; + element.removeAttribute(lowercasedName); + } + } else { + return (element[name] || + (element.attributes.getNamedItem(name) || noop).specified) + ? lowercasedName + : undefined; + } + } else if (isDefined(value)) { + element.setAttribute(name, value); + } else if (element.getAttribute) { + // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code + // some elements (e.g. Document) don't have get attribute, so return undefined + var ret = element.getAttribute(name, 2); + // normalize non-existing attributes to undefined (as jQuery) + return ret === null ? undefined : ret; + } + }, + + prop: function(element, name, value) { + if (isDefined(value)) { + element[name] = value; + } else { + return element[name]; + } + }, + + text: (function() { + getText.$dv = ''; + return getText; + + function getText(element, value) { + if (isUndefined(value)) { + var nodeType = element.nodeType; + return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : ''; + } + element.textContent = value; + } + })(), + + val: function(element, value) { + if (isUndefined(value)) { + if (element.multiple && nodeName_(element) === 'select') { + var result = []; + forEach(element.options, function(option) { + if (option.selected) { + result.push(option.value || option.text); + } + }); + return result.length === 0 ? null : result; + } + return element.value; + } + element.value = value; + }, + + html: function(element, value) { + if (isUndefined(value)) { + return element.innerHTML; + } + jqLiteDealoc(element, true); + element.innerHTML = value; + }, + + empty: jqLiteEmpty +}, function(fn, name) { + /** + * Properties: writes return selection, reads return first value + */ + JQLite.prototype[name] = function(arg1, arg2) { + var i, key; + var nodeCount = this.length; + + // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it + // in a way that survives minification. + // jqLiteEmpty takes no arguments but is a setter. + if (fn !== jqLiteEmpty && + (isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) { + if (isObject(arg1)) { + + // we are a write, but the object properties are the key/values + for (i = 0; i < nodeCount; i++) { + if (fn === jqLiteData) { + // data() takes the whole object in jQuery + fn(this[i], arg1); + } else { + for (key in arg1) { + fn(this[i], key, arg1[key]); + } + } + } + // return self for chaining + return this; + } else { + // we are a read, so read the first child. + // TODO: do we still need this? + var value = fn.$dv; + // Only if we have $dv do we iterate over all, otherwise it is just the first element. + var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount; + for (var j = 0; j < jj; j++) { + var nodeValue = fn(this[j], arg1, arg2); + value = value ? value + nodeValue : nodeValue; + } + return value; + } + } else { + // we are a write, so apply to all children + for (i = 0; i < nodeCount; i++) { + fn(this[i], arg1, arg2); + } + // return self for chaining + return this; + } + }; +}); + +function createEventHandler(element, events) { + var eventHandler = function(event, type) { + // jQuery specific api + event.isDefaultPrevented = function() { + return event.defaultPrevented; + }; + + var eventFns = events[type || event.type]; + var eventFnsLength = eventFns ? eventFns.length : 0; + + if (!eventFnsLength) return; + + if (isUndefined(event.immediatePropagationStopped)) { + var originalStopImmediatePropagation = event.stopImmediatePropagation; + event.stopImmediatePropagation = function() { + event.immediatePropagationStopped = true; + + if (event.stopPropagation) { + event.stopPropagation(); + } + + if (originalStopImmediatePropagation) { + originalStopImmediatePropagation.call(event); + } + }; + } + + event.isImmediatePropagationStopped = function() { + return event.immediatePropagationStopped === true; + }; + + // Some events have special handlers that wrap the real handler + var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper; + + // Copy event handlers in case event handlers array is modified during execution. + if ((eventFnsLength > 1)) { + eventFns = shallowCopy(eventFns); + } + + for (var i = 0; i < eventFnsLength; i++) { + if (!event.isImmediatePropagationStopped()) { + handlerWrapper(element, event, eventFns[i]); + } + } + }; + + // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all + // events on `element` + eventHandler.elem = element; + return eventHandler; +} + +function defaultHandlerWrapper(element, event, handler) { + handler.call(element, event); +} + +function specialMouseHandlerWrapper(target, event, handler) { + // Refer to jQuery's implementation of mouseenter & mouseleave + // Read about mouseenter and mouseleave: + // http://www.quirksmode.org/js/events_mouse.html#link8 + var related = event.relatedTarget; + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if (!related || (related !== target && !jqLiteContains.call(target, related))) { + handler.call(target, event); + } +} + +////////////////////////////////////////// +// Functions iterating traversal. +// These functions chain results into a single +// selector. +////////////////////////////////////////// +forEach({ + removeData: jqLiteRemoveData, + + on: function jqLiteOn(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters'); + + // Do not add event handlers to non-elements because they will not be cleaned up. + if (!jqLiteAcceptsData(element)) { + return; + } + + var expandoStore = jqLiteExpandoStore(element, true); + var events = expandoStore.events; + var handle = expandoStore.handle; + + if (!handle) { + handle = expandoStore.handle = createEventHandler(element, events); + } + + // http://jsperf.com/string-indexof-vs-split + var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type]; + var i = types.length; + + var addHandler = function(type, specialHandlerWrapper, noEventListener) { + var eventFns = events[type]; + + if (!eventFns) { + eventFns = events[type] = []; + eventFns.specialHandlerWrapper = specialHandlerWrapper; + if (type !== '$destroy' && !noEventListener) { + addEventListenerFn(element, type, handle); + } + } + + eventFns.push(fn); + }; + + while (i--) { + type = types[i]; + if (MOUSE_EVENT_MAP[type]) { + addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper); + addHandler(type, undefined, true); + } else { + addHandler(type); + } + } + }, + + off: jqLiteOff, + + one: function(element, type, fn) { + element = jqLite(element); + + //add the listener twice so that when it is called + //you can remove the original function and still be + //able to call element.off(ev, fn) normally + element.on(type, function onFn() { + element.off(type, fn); + element.off(type, onFn); + }); + element.on(type, fn); + }, + + replaceWith: function(element, replaceNode) { + var index, parent = element.parentNode; + jqLiteDealoc(element); + forEach(new JQLite(replaceNode), function(node) { + if (index) { + parent.insertBefore(node, index.nextSibling); + } else { + parent.replaceChild(node, element); + } + index = node; + }); + }, + + children: function(element) { + var children = []; + forEach(element.childNodes, function(element) { + if (element.nodeType === NODE_TYPE_ELEMENT) { + children.push(element); + } + }); + return children; + }, + + contents: function(element) { + return element.contentDocument || element.childNodes || []; + }, + + append: function(element, node) { + var nodeType = element.nodeType; + if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return; + + node = new JQLite(node); + + for (var i = 0, ii = node.length; i < ii; i++) { + var child = node[i]; + element.appendChild(child); + } + }, + + prepend: function(element, node) { + if (element.nodeType === NODE_TYPE_ELEMENT) { + var index = element.firstChild; + forEach(new JQLite(node), function(child) { + element.insertBefore(child, index); + }); + } + }, + + wrap: function(element, wrapNode) { + jqLiteWrapNode(element, jqLite(wrapNode).eq(0).clone()[0]); + }, + + remove: jqLiteRemove, + + detach: function(element) { + jqLiteRemove(element, true); + }, + + after: function(element, newElement) { + var index = element, parent = element.parentNode; + newElement = new JQLite(newElement); + + for (var i = 0, ii = newElement.length; i < ii; i++) { + var node = newElement[i]; + parent.insertBefore(node, index.nextSibling); + index = node; + } + }, + + addClass: jqLiteAddClass, + removeClass: jqLiteRemoveClass, + + toggleClass: function(element, selector, condition) { + if (selector) { + forEach(selector.split(' '), function(className) { + var classCondition = condition; + if (isUndefined(classCondition)) { + classCondition = !jqLiteHasClass(element, className); + } + (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className); + }); + } + }, + + parent: function(element) { + var parent = element.parentNode; + return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null; + }, + + next: function(element) { + return element.nextElementSibling; + }, + + find: function(element, selector) { + if (element.getElementsByTagName) { + return element.getElementsByTagName(selector); + } else { + return []; + } + }, + + clone: jqLiteClone, + + triggerHandler: function(element, event, extraParameters) { + + var dummyEvent, eventFnsCopy, handlerArgs; + var eventName = event.type || event; + var expandoStore = jqLiteExpandoStore(element); + var events = expandoStore && expandoStore.events; + var eventFns = events && events[eventName]; + + if (eventFns) { + // Create a dummy event to pass to the handlers + dummyEvent = { + preventDefault: function() { this.defaultPrevented = true; }, + isDefaultPrevented: function() { return this.defaultPrevented === true; }, + stopImmediatePropagation: function() { this.immediatePropagationStopped = true; }, + isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; }, + stopPropagation: noop, + type: eventName, + target: element + }; + + // If a custom event was provided then extend our dummy event with it + if (event.type) { + dummyEvent = extend(dummyEvent, event); + } + + // Copy event handlers in case event handlers array is modified during execution. + eventFnsCopy = shallowCopy(eventFns); + handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent]; + + forEach(eventFnsCopy, function(fn) { + if (!dummyEvent.isImmediatePropagationStopped()) { + fn.apply(element, handlerArgs); + } + }); + } + } +}, function(fn, name) { + /** + * chaining functions + */ + JQLite.prototype[name] = function(arg1, arg2, arg3) { + var value; + + for (var i = 0, ii = this.length; i < ii; i++) { + if (isUndefined(value)) { + value = fn(this[i], arg1, arg2, arg3); + if (isDefined(value)) { + // any function which returns a value needs to be wrapped + value = jqLite(value); + } + } else { + jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3)); + } + } + return isDefined(value) ? value : this; + }; + + // bind legacy bind/unbind to on/off + JQLite.prototype.bind = JQLite.prototype.on; + JQLite.prototype.unbind = JQLite.prototype.off; +}); + + +// Provider for private $$jqLite service +function $$jqLiteProvider() { + this.$get = function $$jqLite() { + return extend(JQLite, { + hasClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteHasClass(node, classes); + }, + addClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteAddClass(node, classes); + }, + removeClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteRemoveClass(node, classes); + } + }); + }; +} + +/** + * Computes a hash of an 'obj'. + * Hash of a: + * string is string + * number is number as string + * object is either result of calling $$hashKey function on the object or uniquely generated id, + * that is also assigned to the $$hashKey property of the object. + * + * @param obj + * @returns {string} hash string such that the same input will have the same hash string. + * The resulting string key is in 'type:hashKey' format. + */ +function hashKey(obj, nextUidFn) { + var key = obj && obj.$$hashKey; + + if (key) { + if (typeof key === 'function') { + key = obj.$$hashKey(); + } + return key; + } + + var objType = typeof obj; + if (objType == 'function' || (objType == 'object' && obj !== null)) { + key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)(); + } else { + key = objType + ':' + obj; + } + + return key; +} + +/** + * HashMap which can use objects as keys + */ +function HashMap(array, isolatedUid) { + if (isolatedUid) { + var uid = 0; + this.nextUid = function() { + return ++uid; + }; + } + forEach(array, this.put, this); +} +HashMap.prototype = { + /** + * Store key value pair + * @param key key to store can be any type + * @param value value to store can be any type + */ + put: function(key, value) { + this[hashKey(key, this.nextUid)] = value; + }, + + /** + * @param key + * @returns {Object} the value for the key + */ + get: function(key) { + return this[hashKey(key, this.nextUid)]; + }, + + /** + * Remove the key/value pair + * @param key + */ + remove: function(key) { + var value = this[key = hashKey(key, this.nextUid)]; + delete this[key]; + return value; + } +}; + +var $$HashMapProvider = [function() { + this.$get = [function() { + return HashMap; + }]; +}]; + +/** + * @ngdoc function + * @module ng + * @name angular.injector + * @kind function + * + * @description + * Creates an injector object that can be used for retrieving services as well as for + * dependency injection (see {@link guide/di dependency injection}). + * + * @param {Array.} modules A list of module functions or their aliases. See + * {@link angular.module}. The `ng` module must be explicitly added. + * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which + * disallows argument name annotation inference. + * @returns {injector} Injector object. See {@link auto.$injector $injector}. + * + * @example + * Typical usage + * ```js + * // create an injector + * var $injector = angular.injector(['ng']); + * + * // use the injector to kick off your application + * // use the type inference to auto inject arguments, or use implicit injection + * $injector.invoke(function($rootScope, $compile, $document) { + * $compile($document)($rootScope); + * $rootScope.$digest(); + * }); + * ``` + * + * Sometimes you want to get access to the injector of a currently running Angular app + * from outside Angular. Perhaps, you want to inject and compile some markup after the + * application has been bootstrapped. You can do this using the extra `injector()` added + * to JQuery/jqLite elements. See {@link angular.element}. + * + * *This is fairly rare but could be the case if a third party library is injecting the + * markup.* + * + * In the following example a new block of HTML containing a `ng-controller` + * directive is added to the end of the document body by JQuery. We then compile and link + * it into the current AngularJS scope. + * + * ```js + * var $div = $('
    {{content.label}}
    '); + * $(document.body).append($div); + * + * angular.element(document).injector().invoke(function($compile) { + * var scope = angular.element($div).scope(); + * $compile($div)(scope); + * }); + * ``` + */ + + +/** + * @ngdoc module + * @name auto + * @installation + * @description + * + * Implicit module which gets automatically added to each {@link auto.$injector $injector}. + */ + +var ARROW_ARG = /^([^\(]+?)=>/; +var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m; +var FN_ARG_SPLIT = /,/; +var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; +var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; +var $injectorMinErr = minErr('$injector'); + +function stringifyFn(fn) { + // Support: Chrome 50-51 only + // Creating a new string by adding `' '` at the end, to hack around some bug in Chrome v50/51 + // (See https://github.com/angular/angular.js/issues/14487.) + // TODO (gkalpak): Remove workaround when Chrome v52 is released + return Function.prototype.toString.call(fn) + ' '; +} + +function extractArgs(fn) { + var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''), + args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS); + return args; +} + +function anonFn(fn) { + // For anonymous functions, showing at the very least the function signature can help in + // debugging. + var args = extractArgs(fn); + if (args) { + return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')'; + } + return 'fn'; +} + +function annotate(fn, strictDi, name) { + var $inject, + argDecl, + last; + + if (typeof fn === 'function') { + if (!($inject = fn.$inject)) { + $inject = []; + if (fn.length) { + if (strictDi) { + if (!isString(name) || !name) { + name = fn.name || anonFn(fn); + } + throw $injectorMinErr('strictdi', + '{0} is not using explicit annotation and cannot be invoked in strict mode', name); + } + argDecl = extractArgs(fn); + forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) { + arg.replace(FN_ARG, function(all, underscore, name) { + $inject.push(name); + }); + }); + } + fn.$inject = $inject; + } + } else if (isArray(fn)) { + last = fn.length - 1; + assertArgFn(fn[last], 'fn'); + $inject = fn.slice(0, last); + } else { + assertArgFn(fn, 'fn', true); + } + return $inject; +} + +/////////////////////////////////////// + +/** + * @ngdoc service + * @name $injector + * + * @description + * + * `$injector` is used to retrieve object instances as defined by + * {@link auto.$provide provider}, instantiate types, invoke methods, + * and load modules. + * + * The following always holds true: + * + * ```js + * var $injector = angular.injector(); + * expect($injector.get('$injector')).toBe($injector); + * expect($injector.invoke(function($injector) { + * return $injector; + * })).toBe($injector); + * ``` + * + * # Injection Function Annotation + * + * JavaScript does not have annotations, and annotations are needed for dependency injection. The + * following are all valid ways of annotating function with injection arguments and are equivalent. + * + * ```js + * // inferred (only works if code not minified/obfuscated) + * $injector.invoke(function(serviceA){}); + * + * // annotated + * function explicit(serviceA) {}; + * explicit.$inject = ['serviceA']; + * $injector.invoke(explicit); + * + * // inline + * $injector.invoke(['serviceA', function(serviceA){}]); + * ``` + * + * ## Inference + * + * In JavaScript calling `toString()` on a function returns the function definition. The definition + * can then be parsed and the function arguments can be extracted. This method of discovering + * annotations is disallowed when the injector is in strict mode. + * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the + * argument names. + * + * ## `$inject` Annotation + * By adding an `$inject` property onto a function the injection parameters can be specified. + * + * ## Inline + * As an array of injection names, where the last item in the array is the function to call. + */ + +/** + * @ngdoc method + * @name $injector#get + * + * @description + * Return an instance of the service. + * + * @param {string} name The name of the instance to retrieve. + * @param {string=} caller An optional string to provide the origin of the function call for error messages. + * @return {*} The instance. + */ + +/** + * @ngdoc method + * @name $injector#invoke + * + * @description + * Invoke the method and supply the method arguments from the `$injector`. + * + * @param {Function|Array.} fn The injectable function to invoke. Function parameters are + * injected according to the {@link guide/di $inject Annotation} rules. + * @param {Object=} self The `this` for the invoked method. + * @param {Object=} locals Optional object. If preset then any argument names are read from this + * object first, before the `$injector` is consulted. + * @returns {*} the value returned by the invoked `fn` function. + */ + +/** + * @ngdoc method + * @name $injector#has + * + * @description + * Allows the user to query if the particular service exists. + * + * @param {string} name Name of the service to query. + * @returns {boolean} `true` if injector has given service. + */ + +/** + * @ngdoc method + * @name $injector#instantiate + * @description + * Create a new instance of JS type. The method takes a constructor function, invokes the new + * operator, and supplies all of the arguments to the constructor function as specified by the + * constructor annotation. + * + * @param {Function} Type Annotated constructor function. + * @param {Object=} locals Optional object. If preset then any argument names are read from this + * object first, before the `$injector` is consulted. + * @returns {Object} new instance of `Type`. + */ + +/** + * @ngdoc method + * @name $injector#annotate + * + * @description + * Returns an array of service names which the function is requesting for injection. This API is + * used by the injector to determine which services need to be injected into the function when the + * function is invoked. There are three ways in which the function can be annotated with the needed + * dependencies. + * + * # Argument names + * + * The simplest form is to extract the dependencies from the arguments of the function. This is done + * by converting the function into a string using `toString()` method and extracting the argument + * names. + * ```js + * // Given + * function MyController($scope, $route) { + * // ... + * } + * + * // Then + * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); + * ``` + * + * You can disallow this method by using strict injection mode. + * + * This method does not work with code minification / obfuscation. For this reason the following + * annotation strategies are supported. + * + * # The `$inject` property + * + * If a function has an `$inject` property and its value is an array of strings, then the strings + * represent names of services to be injected into the function. + * ```js + * // Given + * var MyController = function(obfuscatedScope, obfuscatedRoute) { + * // ... + * } + * // Define function dependencies + * MyController['$inject'] = ['$scope', '$route']; + * + * // Then + * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); + * ``` + * + * # The array notation + * + * It is often desirable to inline Injected functions and that's when setting the `$inject` property + * is very inconvenient. In these situations using the array notation to specify the dependencies in + * a way that survives minification is a better choice: + * + * ```js + * // We wish to write this (not minification / obfuscation safe) + * injector.invoke(function($compile, $rootScope) { + * // ... + * }); + * + * // We are forced to write break inlining + * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) { + * // ... + * }; + * tmpFn.$inject = ['$compile', '$rootScope']; + * injector.invoke(tmpFn); + * + * // To better support inline function the inline annotation is supported + * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) { + * // ... + * }]); + * + * // Therefore + * expect(injector.annotate( + * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}]) + * ).toEqual(['$compile', '$rootScope']); + * ``` + * + * @param {Function|Array.} fn Function for which dependent service names need to + * be retrieved as described above. + * + * @param {boolean=} [strictDi=false] Disallow argument name annotation inference. + * + * @returns {Array.} The names of the services which the function requires. + */ + + + + +/** + * @ngdoc service + * @name $provide + * + * @description + * + * The {@link auto.$provide $provide} service has a number of methods for registering components + * with the {@link auto.$injector $injector}. Many of these functions are also exposed on + * {@link angular.Module}. + * + * An Angular **service** is a singleton object created by a **service factory**. These **service + * factories** are functions which, in turn, are created by a **service provider**. + * The **service providers** are constructor functions. When instantiated they must contain a + * property called `$get`, which holds the **service factory** function. + * + * When you request a service, the {@link auto.$injector $injector} is responsible for finding the + * correct **service provider**, instantiating it and then calling its `$get` **service factory** + * function to get the instance of the **service**. + * + * Often services have no configuration options and there is no need to add methods to the service + * provider. The provider will be no more than a constructor function with a `$get` property. For + * these cases the {@link auto.$provide $provide} service has additional helper methods to register + * services without specifying a provider. + * + * * {@link auto.$provide#provider provider(name, provider)} - registers a **service provider** with the + * {@link auto.$injector $injector} + * * {@link auto.$provide#constant constant(name, obj)} - registers a value/object that can be accessed by + * providers and services. + * * {@link auto.$provide#value value(name, obj)} - registers a value/object that can only be accessed by + * services, not providers. + * * {@link auto.$provide#factory factory(name, fn)} - registers a service **factory function** + * that will be wrapped in a **service provider** object, whose `$get` property will contain the + * given factory function. + * * {@link auto.$provide#service service(name, Fn)} - registers a **constructor function** + * that will be wrapped in a **service provider** object, whose `$get` property will instantiate + * a new object using the given constructor function. + * * {@link auto.$provide#decorator decorator(name, decorFn)} - registers a **decorator function** that + * will be able to modify or replace the implementation of another service. + * + * See the individual methods for more information and examples. + */ + +/** + * @ngdoc method + * @name $provide#provider + * @description + * + * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions + * are constructor functions, whose instances are responsible for "providing" a factory for a + * service. + * + * Service provider names start with the name of the service they provide followed by `Provider`. + * For example, the {@link ng.$log $log} service has a provider called + * {@link ng.$logProvider $logProvider}. + * + * Service provider objects can have additional methods which allow configuration of the provider + * and its service. Importantly, you can configure what kind of service is created by the `$get` + * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a + * method {@link ng.$logProvider#debugEnabled debugEnabled} + * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the + * console or not. + * + * @param {string} name The name of the instance. NOTE: the provider will be available under `name + + 'Provider'` key. + * @param {(Object|function())} provider If the provider is: + * + * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using + * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created. + * - `Constructor`: a new instance of the provider will be created using + * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`. + * + * @returns {Object} registered provider instance + + * @example + * + * The following example shows how to create a simple event tracking service and register it using + * {@link auto.$provide#provider $provide.provider()}. + * + * ```js + * // Define the eventTracker provider + * function EventTrackerProvider() { + * var trackingUrl = '/track'; + * + * // A provider method for configuring where the tracked events should been saved + * this.setTrackingUrl = function(url) { + * trackingUrl = url; + * }; + * + * // The service factory function + * this.$get = ['$http', function($http) { + * var trackedEvents = {}; + * return { + * // Call this to track an event + * event: function(event) { + * var count = trackedEvents[event] || 0; + * count += 1; + * trackedEvents[event] = count; + * return count; + * }, + * // Call this to save the tracked events to the trackingUrl + * save: function() { + * $http.post(trackingUrl, trackedEvents); + * } + * }; + * }]; + * } + * + * describe('eventTracker', function() { + * var postSpy; + * + * beforeEach(module(function($provide) { + * // Register the eventTracker provider + * $provide.provider('eventTracker', EventTrackerProvider); + * })); + * + * beforeEach(module(function(eventTrackerProvider) { + * // Configure eventTracker provider + * eventTrackerProvider.setTrackingUrl('/custom-track'); + * })); + * + * it('tracks events', inject(function(eventTracker) { + * expect(eventTracker.event('login')).toEqual(1); + * expect(eventTracker.event('login')).toEqual(2); + * })); + * + * it('saves to the tracking url', inject(function(eventTracker, $http) { + * postSpy = spyOn($http, 'post'); + * eventTracker.event('login'); + * eventTracker.save(); + * expect(postSpy).toHaveBeenCalled(); + * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track'); + * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track'); + * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 }); + * })); + * }); + * ``` + */ + +/** + * @ngdoc method + * @name $provide#factory + * @description + * + * Register a **service factory**, which will be called to return the service instance. + * This is short for registering a service where its provider consists of only a `$get` property, + * which is the given service factory function. + * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to + * configure your service in a provider. + * + * @param {string} name The name of the instance. + * @param {Function|Array.} $getFn The injectable $getFn for the instance creation. + * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`. + * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service + * ```js + * $provide.factory('ping', ['$http', function($http) { + * return function ping() { + * return $http.send('/ping'); + * }; + * }]); + * ``` + * You would then inject and use this service like this: + * ```js + * someModule.controller('Ctrl', ['ping', function(ping) { + * ping(); + * }]); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#service + * @description + * + * Register a **service constructor**, which will be invoked with `new` to create the service + * instance. + * This is short for registering a service where its provider's `$get` property is a factory + * function that returns an instance instantiated by the injector from the service constructor + * function. + * + * Internally it looks a bit like this: + * + * ``` + * { + * $get: function() { + * return $injector.instantiate(constructor); + * } + * } + * ``` + * + * + * You should use {@link auto.$provide#service $provide.service(class)} if you define your service + * as a type/class. + * + * @param {string} name The name of the instance. + * @param {Function|Array.} constructor An injectable class (constructor function) + * that will be instantiated. + * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service using + * {@link auto.$provide#service $provide.service(class)}. + * ```js + * var Ping = function($http) { + * this.$http = $http; + * }; + * + * Ping.$inject = ['$http']; + * + * Ping.prototype.send = function() { + * return this.$http.get('/ping'); + * }; + * $provide.service('ping', Ping); + * ``` + * You would then inject and use this service like this: + * ```js + * someModule.controller('Ctrl', ['ping', function(ping) { + * ping.send(); + * }]); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#value + * @description + * + * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a + * number, an array, an object or a function. This is short for registering a service where its + * provider's `$get` property is a factory function that takes no arguments and returns the **value + * service**. That also means it is not possible to inject other services into a value service. + * + * Value services are similar to constant services, except that they cannot be injected into a + * module configuration function (see {@link angular.Module#config}) but they can be overridden by + * an Angular {@link auto.$provide#decorator decorator}. + * + * @param {string} name The name of the instance. + * @param {*} value The value. + * @returns {Object} registered provider instance + * + * @example + * Here are some examples of creating value services. + * ```js + * $provide.value('ADMIN_USER', 'admin'); + * + * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 }); + * + * $provide.value('halfOf', function(value) { + * return value / 2; + * }); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#constant + * @description + * + * Register a **constant service** with the {@link auto.$injector $injector}, such as a string, + * a number, an array, an object or a function. Like the {@link auto.$provide#value value}, it is not + * possible to inject other services into a constant. + * + * But unlike {@link auto.$provide#value value}, a constant can be + * injected into a module configuration function (see {@link angular.Module#config}) and it cannot + * be overridden by an Angular {@link auto.$provide#decorator decorator}. + * + * @param {string} name The name of the constant. + * @param {*} value The constant value. + * @returns {Object} registered instance + * + * @example + * Here a some examples of creating constants: + * ```js + * $provide.constant('SHARD_HEIGHT', 306); + * + * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']); + * + * $provide.constant('double', function(value) { + * return value * 2; + * }); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#decorator + * @description + * + * Register a **decorator function** with the {@link auto.$injector $injector}. A decorator function + * intercepts the creation of a service, allowing it to override or modify the behavior of the + * service. The return value of the decorator function may be the original service, or a new service + * that replaces (or wraps and delegates to) the original service. + * + * You can find out more about using decorators in the {@link guide/decorators} guide. + * + * @param {string} name The name of the service to decorate. + * @param {Function|Array.} decorator This function will be invoked when the service needs to be + * provided and should return the decorated service instance. The function is called using + * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable. + * Local injection arguments: + * + * * `$delegate` - The original service instance, which can be replaced, monkey patched, configured, + * decorated or delegated to. + * + * @example + * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting + * calls to {@link ng.$log#error $log.warn()}. + * ```js + * $provide.decorator('$log', ['$delegate', function($delegate) { + * $delegate.warn = $delegate.error; + * return $delegate; + * }]); + * ``` + */ + + +function createInjector(modulesToLoad, strictDi) { + strictDi = (strictDi === true); + var INSTANTIATING = {}, + providerSuffix = 'Provider', + path = [], + loadedModules = new HashMap([], true), + providerCache = { + $provide: { + provider: supportObject(provider), + factory: supportObject(factory), + service: supportObject(service), + value: supportObject(value), + constant: supportObject(constant), + decorator: decorator + } + }, + providerInjector = (providerCache.$injector = + createInternalInjector(providerCache, function(serviceName, caller) { + if (angular.isString(caller)) { + path.push(caller); + } + throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- ')); + })), + instanceCache = {}, + protoInstanceInjector = + createInternalInjector(instanceCache, function(serviceName, caller) { + var provider = providerInjector.get(serviceName + providerSuffix, caller); + return instanceInjector.invoke( + provider.$get, provider, undefined, serviceName); + }), + instanceInjector = protoInstanceInjector; + + providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) }; + var runBlocks = loadModules(modulesToLoad); + instanceInjector = protoInstanceInjector.get('$injector'); + instanceInjector.strictDi = strictDi; + forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); }); + + return instanceInjector; + + //////////////////////////////////// + // $provider + //////////////////////////////////// + + function supportObject(delegate) { + return function(key, value) { + if (isObject(key)) { + forEach(key, reverseParams(delegate)); + } else { + return delegate(key, value); + } + }; + } + + function provider(name, provider_) { + assertNotHasOwnProperty(name, 'service'); + if (isFunction(provider_) || isArray(provider_)) { + provider_ = providerInjector.instantiate(provider_); + } + if (!provider_.$get) { + throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); + } + return providerCache[name + providerSuffix] = provider_; + } + + function enforceReturnValue(name, factory) { + return function enforcedReturnValue() { + var result = instanceInjector.invoke(factory, this); + if (isUndefined(result)) { + throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name); + } + return result; + }; + } + + function factory(name, factoryFn, enforce) { + return provider(name, { + $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn + }); + } + + function service(name, constructor) { + return factory(name, ['$injector', function($injector) { + return $injector.instantiate(constructor); + }]); + } + + function value(name, val) { return factory(name, valueFn(val), false); } + + function constant(name, value) { + assertNotHasOwnProperty(name, 'constant'); + providerCache[name] = value; + instanceCache[name] = value; + } + + function decorator(serviceName, decorFn) { + var origProvider = providerInjector.get(serviceName + providerSuffix), + orig$get = origProvider.$get; + + origProvider.$get = function() { + var origInstance = instanceInjector.invoke(orig$get, origProvider); + return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); + }; + } + + //////////////////////////////////// + // Module Loading + //////////////////////////////////// + function loadModules(modulesToLoad) { + assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array'); + var runBlocks = [], moduleFn; + forEach(modulesToLoad, function(module) { + if (loadedModules.get(module)) return; + loadedModules.put(module, true); + + function runInvokeQueue(queue) { + var i, ii; + for (i = 0, ii = queue.length; i < ii; i++) { + var invokeArgs = queue[i], + provider = providerInjector.get(invokeArgs[0]); + + provider[invokeArgs[1]].apply(provider, invokeArgs[2]); + } + } + + try { + if (isString(module)) { + moduleFn = angularModule(module); + runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); + runInvokeQueue(moduleFn._invokeQueue); + runInvokeQueue(moduleFn._configBlocks); + } else if (isFunction(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else if (isArray(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else { + assertArgFn(module, 'module'); + } + } catch (e) { + if (isArray(module)) { + module = module[module.length - 1]; + } + if (e.message && e.stack && e.stack.indexOf(e.message) == -1) { + // Safari & FF's stack traces don't contain error.message content + // unlike those of Chrome and IE + // So if stack doesn't contain message, we create a new string that contains both. + // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here. + /* jshint -W022 */ + e = e.message + '\n' + e.stack; + } + throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}", + module, e.stack || e.message || e); + } + }); + return runBlocks; + } + + //////////////////////////////////// + // internal Injector + //////////////////////////////////// + + function createInternalInjector(cache, factory) { + + function getService(serviceName, caller) { + if (cache.hasOwnProperty(serviceName)) { + if (cache[serviceName] === INSTANTIATING) { + throw $injectorMinErr('cdep', 'Circular dependency found: {0}', + serviceName + ' <- ' + path.join(' <- ')); + } + return cache[serviceName]; + } else { + try { + path.unshift(serviceName); + cache[serviceName] = INSTANTIATING; + return cache[serviceName] = factory(serviceName, caller); + } catch (err) { + if (cache[serviceName] === INSTANTIATING) { + delete cache[serviceName]; + } + throw err; + } finally { + path.shift(); + } + } + } + + + function injectionArgs(fn, locals, serviceName) { + var args = [], + $inject = createInjector.$$annotate(fn, strictDi, serviceName); + + for (var i = 0, length = $inject.length; i < length; i++) { + var key = $inject[i]; + if (typeof key !== 'string') { + throw $injectorMinErr('itkn', + 'Incorrect injection token! Expected service name as string, got {0}', key); + } + args.push(locals && locals.hasOwnProperty(key) ? locals[key] : + getService(key, serviceName)); + } + return args; + } + + function isClass(func) { + // IE 9-11 do not support classes and IE9 leaks with the code below. + if (msie <= 11) { + return false; + } + // Support: Edge 12-13 only + // See: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/6156135/ + return typeof func === 'function' + && /^(?:class\b|constructor\()/.test(stringifyFn(func)); + } + + function invoke(fn, self, locals, serviceName) { + if (typeof locals === 'string') { + serviceName = locals; + locals = null; + } + + var args = injectionArgs(fn, locals, serviceName); + if (isArray(fn)) { + fn = fn[fn.length - 1]; + } + + if (!isClass(fn)) { + // http://jsperf.com/angularjs-invoke-apply-vs-switch + // #5388 + return fn.apply(self, args); + } else { + args.unshift(null); + return new (Function.prototype.bind.apply(fn, args))(); + } + } + + + function instantiate(Type, locals, serviceName) { + // Check if Type is annotated and use just the given function at n-1 as parameter + // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); + var ctor = (isArray(Type) ? Type[Type.length - 1] : Type); + var args = injectionArgs(Type, locals, serviceName); + // Empty object at position 0 is ignored for invocation with `new`, but required. + args.unshift(null); + return new (Function.prototype.bind.apply(ctor, args))(); + } + + + return { + invoke: invoke, + instantiate: instantiate, + get: getService, + annotate: createInjector.$$annotate, + has: function(name) { + return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); + } + }; + } +} + +createInjector.$$annotate = annotate; + +/** + * @ngdoc provider + * @name $anchorScrollProvider + * + * @description + * Use `$anchorScrollProvider` to disable automatic scrolling whenever + * {@link ng.$location#hash $location.hash()} changes. + */ +function $AnchorScrollProvider() { + + var autoScrollingEnabled = true; + + /** + * @ngdoc method + * @name $anchorScrollProvider#disableAutoScrolling + * + * @description + * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to + * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.
    + * Use this method to disable automatic scrolling. + * + * If automatic scrolling is disabled, one must explicitly call + * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the + * current hash. + */ + this.disableAutoScrolling = function() { + autoScrollingEnabled = false; + }; + + /** + * @ngdoc service + * @name $anchorScroll + * @kind function + * @requires $window + * @requires $location + * @requires $rootScope + * + * @description + * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the + * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified + * in the + * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#an-indicated-part-of-the-document). + * + * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to + * match any anchor whenever it changes. This can be disabled by calling + * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}. + * + * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a + * vertical scroll-offset (either fixed or dynamic). + * + * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of + * {@link ng.$location#hash $location.hash()} will be used. + * + * @property {(number|function|jqLite)} yOffset + * If set, specifies a vertical scroll-offset. This is often useful when there are fixed + * positioned elements at the top of the page, such as navbars, headers etc. + * + * `yOffset` can be specified in various ways: + * - **number**: A fixed number of pixels to be used as offset.

    + * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return + * a number representing the offset (in pixels).

    + * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from + * the top of the page to the element's bottom will be used as offset.
    + * **Note**: The element will be taken into account only as long as its `position` is set to + * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust + * their height and/or positioning according to the viewport's size. + * + *
    + *
    + * In order for `yOffset` to work properly, scrolling should take place on the document's root and + * not some child element. + *
    + * + * @example + + +
    + Go to bottom + You're at the bottom! +
    + + + angular.module('anchorScrollExample', []) + .controller('ScrollController', ['$scope', '$location', '$anchorScroll', + function ($scope, $location, $anchorScroll) { + $scope.gotoBottom = function() { + // set the location.hash to the id of + // the element you wish to scroll to. + $location.hash('bottom'); + + // call $anchorScroll() + $anchorScroll(); + }; + }]); + + + #scrollArea { + height: 280px; + overflow: auto; + } + + #bottom { + display: block; + margin-top: 2000px; + } + + + * + *
    + * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value). + * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details. + * + * @example + + + +
    + Anchor {{x}} of 5 +
    +
    + + angular.module('anchorScrollOffsetExample', []) + .run(['$anchorScroll', function($anchorScroll) { + $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels + }]) + .controller('headerCtrl', ['$anchorScroll', '$location', '$scope', + function ($anchorScroll, $location, $scope) { + $scope.gotoAnchor = function(x) { + var newHash = 'anchor' + x; + if ($location.hash() !== newHash) { + // set the $location.hash to `newHash` and + // $anchorScroll will automatically scroll to it + $location.hash('anchor' + x); + } else { + // call $anchorScroll() explicitly, + // since $location.hash hasn't changed + $anchorScroll(); + } + }; + } + ]); + + + body { + padding-top: 50px; + } + + .anchor { + border: 2px dashed DarkOrchid; + padding: 10px 10px 200px 10px; + } + + .fixed-header { + background-color: rgba(0, 0, 0, 0.2); + height: 50px; + position: fixed; + top: 0; left: 0; right: 0; + } + + .fixed-header > a { + display: inline-block; + margin: 5px 15px; + } + +
    + */ + this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) { + var document = $window.document; + + // Helper function to get first anchor from a NodeList + // (using `Array#some()` instead of `angular#forEach()` since it's more performant + // and working in all supported browsers.) + function getFirstAnchor(list) { + var result = null; + Array.prototype.some.call(list, function(element) { + if (nodeName_(element) === 'a') { + result = element; + return true; + } + }); + return result; + } + + function getYOffset() { + + var offset = scroll.yOffset; + + if (isFunction(offset)) { + offset = offset(); + } else if (isElement(offset)) { + var elem = offset[0]; + var style = $window.getComputedStyle(elem); + if (style.position !== 'fixed') { + offset = 0; + } else { + offset = elem.getBoundingClientRect().bottom; + } + } else if (!isNumber(offset)) { + offset = 0; + } + + return offset; + } + + function scrollTo(elem) { + if (elem) { + elem.scrollIntoView(); + + var offset = getYOffset(); + + if (offset) { + // `offset` is the number of pixels we should scroll UP in order to align `elem` properly. + // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the + // top of the viewport. + // + // IF the number of pixels from the top of `elem` to the end of the page's content is less + // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some + // way down the page. + // + // This is often the case for elements near the bottom of the page. + // + // In such cases we do not need to scroll the whole `offset` up, just the difference between + // the top of the element and the offset, which is enough to align the top of `elem` at the + // desired position. + var elemTop = elem.getBoundingClientRect().top; + $window.scrollBy(0, elemTop - offset); + } + } else { + $window.scrollTo(0, 0); + } + } + + function scroll(hash) { + hash = isString(hash) ? hash : $location.hash(); + var elm; + + // empty hash, scroll to the top of the page + if (!hash) scrollTo(null); + + // element with given id + else if ((elm = document.getElementById(hash))) scrollTo(elm); + + // first anchor with given name :-D + else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm); + + // no element and hash == 'top', scroll to the top of the page + else if (hash === 'top') scrollTo(null); + } + + // does not scroll when user clicks on anchor link that is currently on + // (no url change, no $location.hash() change), browser native does scroll + if (autoScrollingEnabled) { + $rootScope.$watch(function autoScrollWatch() {return $location.hash();}, + function autoScrollWatchAction(newVal, oldVal) { + // skip the initial scroll if $location.hash is empty + if (newVal === oldVal && newVal === '') return; + + jqLiteDocumentLoaded(function() { + $rootScope.$evalAsync(scroll); + }); + }); + } + + return scroll; + }]; +} + +var $animateMinErr = minErr('$animate'); +var ELEMENT_NODE = 1; +var NG_ANIMATE_CLASSNAME = 'ng-animate'; + +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} + +function extractElementNode(element) { + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType === ELEMENT_NODE) { + return elm; + } + } +} + +function splitClasses(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } + + // Use createMap() to prevent class assumptions involving property names in + // Object.prototype + var obj = createMap(); + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; + } + }); + return obj; +} + +// if any other type of options value besides an Object value is +// passed into the $animate.method() animation then this helper code +// will be run which will ignore it. While this patch is not the +// greatest solution to this, a lot of existing plugins depend on +// $animate to either call the callback (< 1.2) or return a promise +// that can be changed. This helper function ensures that the options +// are wiped clean incase a callback function is provided. +function prepareAnimateOptions(options) { + return isObject(options) + ? options + : {}; +} + +var $$CoreAnimateJsProvider = function() { + this.$get = noop; +}; + +// this is prefixed with Core since it conflicts with +// the animateQueueProvider defined in ngAnimate/animateQueue.js +var $$CoreAnimateQueueProvider = function() { + var postDigestQueue = new HashMap(); + var postDigestElements = []; + + this.$get = ['$$AnimateRunner', '$rootScope', + function($$AnimateRunner, $rootScope) { + return { + enabled: noop, + on: noop, + off: noop, + pin: noop, + + push: function(element, event, options, domOperation) { + domOperation && domOperation(); + + options = options || {}; + options.from && element.css(options.from); + options.to && element.css(options.to); + + if (options.addClass || options.removeClass) { + addRemoveClassesPostDigest(element, options.addClass, options.removeClass); + } + + var runner = new $$AnimateRunner(); // jshint ignore:line + + // since there are no animations to run the runner needs to be + // notified that the animation call is complete. + runner.complete(); + return runner; + } + }; + + + function updateData(data, classes, value) { + var changed = false; + if (classes) { + classes = isString(classes) ? classes.split(' ') : + isArray(classes) ? classes : []; + forEach(classes, function(className) { + if (className) { + changed = true; + data[className] = value; + } + }); + } + return changed; + } + + function handleCSSClassChanges() { + forEach(postDigestElements, function(element) { + var data = postDigestQueue.get(element); + if (data) { + var existing = splitClasses(element.attr('class')); + var toAdd = ''; + var toRemove = ''; + forEach(data, function(status, className) { + var hasClass = !!existing[className]; + if (status !== hasClass) { + if (status) { + toAdd += (toAdd.length ? ' ' : '') + className; + } else { + toRemove += (toRemove.length ? ' ' : '') + className; + } + } + }); + + forEach(element, function(elm) { + toAdd && jqLiteAddClass(elm, toAdd); + toRemove && jqLiteRemoveClass(elm, toRemove); + }); + postDigestQueue.remove(element); + } + }); + postDigestElements.length = 0; + } + + + function addRemoveClassesPostDigest(element, add, remove) { + var data = postDigestQueue.get(element) || {}; + + var classesAdded = updateData(data, add, true); + var classesRemoved = updateData(data, remove, false); + + if (classesAdded || classesRemoved) { + + postDigestQueue.put(element, data); + postDigestElements.push(element); + + if (postDigestElements.length === 1) { + $rootScope.$$postDigest(handleCSSClassChanges); + } + } + } + }]; +}; + +/** + * @ngdoc provider + * @name $animateProvider + * + * @description + * Default implementation of $animate that doesn't perform any animations, instead just + * synchronously performs DOM updates and resolves the returned runner promise. + * + * In order to enable animations the `ngAnimate` module has to be loaded. + * + * To see the functional implementation check out `src/ngAnimate/animate.js`. + */ +var $AnimateProvider = ['$provide', function($provide) { + var provider = this; + + this.$$registeredAnimations = Object.create(null); + + /** + * @ngdoc method + * @name $animateProvider#register + * + * @description + * Registers a new injectable animation factory function. The factory function produces the + * animation object which contains callback functions for each event that is expected to be + * animated. + * + * * `eventFn`: `function(element, ... , doneFunction, options)` + * The element to animate, the `doneFunction` and the options fed into the animation. Depending + * on the type of animation additional arguments will be injected into the animation function. The + * list below explains the function signatures for the different animation methods: + * + * - setClass: function(element, addedClasses, removedClasses, doneFunction, options) + * - addClass: function(element, addedClasses, doneFunction, options) + * - removeClass: function(element, removedClasses, doneFunction, options) + * - enter, leave, move: function(element, doneFunction, options) + * - animate: function(element, fromStyles, toStyles, doneFunction, options) + * + * Make sure to trigger the `doneFunction` once the animation is fully complete. + * + * ```js + * return { + * //enter, leave, move signature + * eventFn : function(element, done, options) { + * //code to run the animation + * //once complete, then run done() + * return function endFunction(wasCancelled) { + * //code to cancel the animation + * } + * } + * } + * ``` + * + * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to). + * @param {Function} factory The factory function that will be executed to return the animation + * object. + */ + this.register = function(name, factory) { + if (name && name.charAt(0) !== '.') { + throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name); + } + + var key = name + '-animation'; + provider.$$registeredAnimations[name.substr(1)] = key; + $provide.factory(key, factory); + }; + + /** + * @ngdoc method + * @name $animateProvider#classNameFilter + * + * @description + * Sets and/or returns the CSS class regular expression that is checked when performing + * an animation. Upon bootstrap the classNameFilter value is not set at all and will + * therefore enable $animate to attempt to perform an animation on any element that is triggered. + * When setting the `classNameFilter` value, animations will only be performed on elements + * that successfully match the filter expression. This in turn can boost performance + * for low-powered devices as well as applications containing a lot of structural operations. + * @param {RegExp=} expression The className expression which will be checked against all animations + * @return {RegExp} The current CSS className expression value. If null then there is no expression value + */ + this.classNameFilter = function(expression) { + if (arguments.length === 1) { + this.$$classNameFilter = (expression instanceof RegExp) ? expression : null; + if (this.$$classNameFilter) { + var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)"); + if (reservedRegex.test(this.$$classNameFilter.toString())) { + throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME); + + } + } + } + return this.$$classNameFilter; + }; + + this.$get = ['$$animateQueue', function($$animateQueue) { + function domInsert(element, parentElement, afterElement) { + // if for some reason the previous element was removed + // from the dom sometime before this code runs then let's + // just stick to using the parent element as the anchor + if (afterElement) { + var afterNode = extractElementNode(afterElement); + if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) { + afterElement = null; + } + } + afterElement ? afterElement.after(element) : parentElement.prepend(element); + } + + /** + * @ngdoc service + * @name $animate + * @description The $animate service exposes a series of DOM utility methods that provide support + * for animation hooks. The default behavior is the application of DOM operations, however, + * when an animation is detected (and animations are enabled), $animate will do the heavy lifting + * to ensure that animation runs with the triggered DOM operation. + * + * By default $animate doesn't trigger any animations. This is because the `ngAnimate` module isn't + * included and only when it is active then the animation hooks that `$animate` triggers will be + * functional. Once active then all structural `ng-` directives will trigger animations as they perform + * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`, + * `ngShow`, `ngHide` and `ngMessages` also provide support for animations. + * + * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives. + * + * To learn more about enabling animation support, click here to visit the + * {@link ngAnimate ngAnimate module page}. + */ + return { + // we don't call it directly since non-existant arguments may + // be interpreted as null within the sub enabled function + + /** + * + * @ngdoc method + * @name $animate#on + * @kind function + * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...) + * has fired on the given element or among any of its children. Once the listener is fired, the provided callback + * is fired with the following params: + * + * ```js + * $animate.on('enter', container, + * function callback(element, phase) { + * // cool we detected an enter animation within the container + * } + * ); + * ``` + * + * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...) + * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself + * as well as among its children + * @param {Function} callback the callback function that will be fired when the listener is triggered + * + * The arguments present in the callback function are: + * * `element` - The captured DOM element that the animation was fired on. + * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends). + */ + on: $$animateQueue.on, + + /** + * + * @ngdoc method + * @name $animate#off + * @kind function + * @description Deregisters an event listener based on the event which has been associated with the provided element. This method + * can be used in three different ways depending on the arguments: + * + * ```js + * // remove all the animation event listeners listening for `enter` + * $animate.off('enter'); + * + * // remove listeners for all animation events from the container element + * $animate.off(container); + * + * // remove all the animation event listeners listening for `enter` on the given element and its children + * $animate.off('enter', container); + * + * // remove the event listener function provided by `callback` that is set + * // to listen for `enter` on the given `container` as well as its children + * $animate.off('enter', container, callback); + * ``` + * + * @param {string|DOMElement} event|container the animation event (e.g. enter, leave, move, + * addClass, removeClass, etc...), or the container element. If it is the element, all other + * arguments are ignored. + * @param {DOMElement=} container the container element the event listener was placed on + * @param {Function=} callback the callback function that was registered as the listener + */ + off: $$animateQueue.off, + + /** + * @ngdoc method + * @name $animate#pin + * @kind function + * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists + * outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the + * element despite being outside the realm of the application or within another application. Say for example if the application + * was bootstrapped on an element that is somewhere inside of the `` tag, but we wanted to allow for an element to be situated + * as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind + * that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association. + * + * Note that this feature is only active when the `ngAnimate` module is used. + * + * @param {DOMElement} element the external element that will be pinned + * @param {DOMElement} parentElement the host parent element that will be associated with the external element + */ + pin: $$animateQueue.pin, + + /** + * + * @ngdoc method + * @name $animate#enabled + * @kind function + * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This + * function can be called in four ways: + * + * ```js + * // returns true or false + * $animate.enabled(); + * + * // changes the enabled state for all animations + * $animate.enabled(false); + * $animate.enabled(true); + * + * // returns true or false if animations are enabled for an element + * $animate.enabled(element); + * + * // changes the enabled state for an element and its children + * $animate.enabled(element, true); + * $animate.enabled(element, false); + * ``` + * + * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state + * @param {boolean=} enabled whether or not the animations will be enabled for the element + * + * @return {boolean} whether or not animations are enabled + */ + enabled: $$animateQueue.enabled, + + /** + * @ngdoc method + * @name $animate#cancel + * @kind function + * @description Cancels the provided animation. + * + * @param {Promise} animationPromise The animation promise that is returned when an animation is started. + */ + cancel: function(runner) { + runner.end && runner.end(); + }, + + /** + * + * @ngdoc method + * @name $animate#enter + * @kind function + * @description Inserts the element into the DOM either after the `after` element (if provided) or + * as the first child within the `parent` element and then triggers an animation. + * A promise is returned that will be resolved during the next digest once the animation + * has completed. + * + * @param {DOMElement} element the element which will be inserted into the DOM + * @param {DOMElement} parent the parent element which will append the element as + * a child (so long as the after element is not present) + * @param {DOMElement=} after the sibling element after which the element will be appended + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` + * + * @return {Promise} the animation callback promise + */ + enter: function(element, parent, after, options) { + parent = parent && jqLite(parent); + after = after && jqLite(after); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options)); + }, + + /** + * + * @ngdoc method + * @name $animate#move + * @kind function + * @description Inserts (moves) the element into its new position in the DOM either after + * the `after` element (if provided) or as the first child within the `parent` element + * and then triggers an animation. A promise is returned that will be resolved + * during the next digest once the animation has completed. + * + * @param {DOMElement} element the element which will be moved into the new DOM position + * @param {DOMElement} parent the parent element which will append the element as + * a child (so long as the after element is not present) + * @param {DOMElement=} after the sibling element after which the element will be appended + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` + * + * @return {Promise} the animation callback promise + */ + move: function(element, parent, after, options) { + parent = parent && jqLite(parent); + after = after && jqLite(after); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, 'move', prepareAnimateOptions(options)); + }, + + /** + * @ngdoc method + * @name $animate#leave + * @kind function + * @description Triggers an animation and then removes the element from the DOM. + * When the function is called a promise is returned that will be resolved during the next + * digest once the animation has completed. + * + * @param {DOMElement} element the element which will be removed from the DOM + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` + * + * @return {Promise} the animation callback promise + */ + leave: function(element, options) { + return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() { + element.remove(); + }); + }, + + /** + * @ngdoc method + * @name $animate#addClass + * @kind function + * + * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon + * execution, the addClass operation will only be handled after the next digest and it will not trigger an + * animation if element already contains the CSS class or if the class is removed at a later step. + * Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` + * + * @return {Promise} the animation callback promise + */ + addClass: function(element, className, options) { + options = prepareAnimateOptions(options); + options.addClass = mergeClasses(options.addclass, className); + return $$animateQueue.push(element, 'addClass', options); + }, + + /** + * @ngdoc method + * @name $animate#removeClass + * @kind function + * + * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon + * execution, the removeClass operation will only be handled after the next digest and it will not trigger an + * animation if element does not contain the CSS class or if the class is added at a later step. + * Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` + * + * @return {Promise} the animation callback promise + */ + removeClass: function(element, className, options) { + options = prepareAnimateOptions(options); + options.removeClass = mergeClasses(options.removeClass, className); + return $$animateQueue.push(element, 'removeClass', options); + }, + + /** + * @ngdoc method + * @name $animate#setClass + * @kind function + * + * @description Performs both the addition and removal of a CSS classes on an element and (during the process) + * triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and + * `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has + * passed. Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces) + * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` + * + * @return {Promise} the animation callback promise + */ + setClass: function(element, add, remove, options) { + options = prepareAnimateOptions(options); + options.addClass = mergeClasses(options.addClass, add); + options.removeClass = mergeClasses(options.removeClass, remove); + return $$animateQueue.push(element, 'setClass', options); + }, + + /** + * @ngdoc method + * @name $animate#animate + * @kind function + * + * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element. + * If any detected CSS transition, keyframe or JavaScript matches the provided className value, then the animation will take + * on the provided styles. For example, if a transition animation is set for the given classNamem, then the provided `from` and + * `to` styles will be applied alongside the given transition. If the CSS style provided in `from` does not have a corresponding + * style in `to`, the style in `from` is applied immediately, and no animation is run. + * If a JavaScript animation is detected then the provided styles will be given in as function parameters into the `animate` + * method (or as part of the `options` parameter): + * + * ```js + * ngModule.animation('.my-inline-animation', function() { + * return { + * animate : function(element, from, to, done, options) { + * //animation + * done(); + * } + * } + * }); + * ``` + * + * @param {DOMElement} element the element which the CSS styles will be applied to + * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation. + * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation. + * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If + * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element. + * (Note that if no animation is detected then this value will not be applied to the element.) + * @param {object=} options an optional collection of options/styles that will be applied to the element. + * The object can have the following properties: + * + * - **addClass** - `{string}` - space-separated CSS classes to add to element + * - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to` + * - **removeClass** - `{string}` - space-separated CSS classes to remove from element + * - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from` + * + * @return {Promise} the animation callback promise + */ + animate: function(element, from, to, className, options) { + options = prepareAnimateOptions(options); + options.from = options.from ? extend(options.from, from) : from; + options.to = options.to ? extend(options.to, to) : to; + + className = className || 'ng-inline-animate'; + options.tempClasses = mergeClasses(options.tempClasses, className); + return $$animateQueue.push(element, 'animate', options); + } + }; + }]; +}]; + +var $$AnimateAsyncRunFactoryProvider = function() { + this.$get = ['$$rAF', function($$rAF) { + var waitQueue = []; + + function waitForTick(fn) { + waitQueue.push(fn); + if (waitQueue.length > 1) return; + $$rAF(function() { + for (var i = 0; i < waitQueue.length; i++) { + waitQueue[i](); + } + waitQueue = []; + }); + } + + return function() { + var passed = false; + waitForTick(function() { + passed = true; + }); + return function(callback) { + passed ? callback() : waitForTick(callback); + }; + }; + }]; +}; + +var $$AnimateRunnerFactoryProvider = function() { + this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout', + function($q, $sniffer, $$animateAsyncRun, $document, $timeout) { + + var INITIAL_STATE = 0; + var DONE_PENDING_STATE = 1; + var DONE_COMPLETE_STATE = 2; + + AnimateRunner.chain = function(chain, callback) { + var index = 0; + + next(); + function next() { + if (index === chain.length) { + callback(true); + return; + } + + chain[index](function(response) { + if (response === false) { + callback(false); + return; + } + index++; + next(); + }); + } + }; + + AnimateRunner.all = function(runners, callback) { + var count = 0; + var status = true; + forEach(runners, function(runner) { + runner.done(onProgress); + }); + + function onProgress(response) { + status = status && response; + if (++count === runners.length) { + callback(status); + } + } + }; + + function AnimateRunner(host) { + this.setHost(host); + + var rafTick = $$animateAsyncRun(); + var timeoutTick = function(fn) { + $timeout(fn, 0, false); + }; + + this._doneCallbacks = []; + this._tick = function(fn) { + var doc = $document[0]; + + // the document may not be ready or attached + // to the module for some internal tests + if (doc && doc.hidden) { + timeoutTick(fn); + } else { + rafTick(fn); + } + }; + this._state = 0; + } + + AnimateRunner.prototype = { + setHost: function(host) { + this.host = host || {}; + }, + + done: function(fn) { + if (this._state === DONE_COMPLETE_STATE) { + fn(); + } else { + this._doneCallbacks.push(fn); + } + }, + + progress: noop, + + getPromise: function() { + if (!this.promise) { + var self = this; + this.promise = $q(function(resolve, reject) { + self.done(function(status) { + status === false ? reject() : resolve(); + }); + }); + } + return this.promise; + }, + + then: function(resolveHandler, rejectHandler) { + return this.getPromise().then(resolveHandler, rejectHandler); + }, + + 'catch': function(handler) { + return this.getPromise()['catch'](handler); + }, + + 'finally': function(handler) { + return this.getPromise()['finally'](handler); + }, + + pause: function() { + if (this.host.pause) { + this.host.pause(); + } + }, + + resume: function() { + if (this.host.resume) { + this.host.resume(); + } + }, + + end: function() { + if (this.host.end) { + this.host.end(); + } + this._resolve(true); + }, + + cancel: function() { + if (this.host.cancel) { + this.host.cancel(); + } + this._resolve(false); + }, + + complete: function(response) { + var self = this; + if (self._state === INITIAL_STATE) { + self._state = DONE_PENDING_STATE; + self._tick(function() { + self._resolve(response); + }); + } + }, + + _resolve: function(response) { + if (this._state !== DONE_COMPLETE_STATE) { + forEach(this._doneCallbacks, function(fn) { + fn(response); + }); + this._doneCallbacks.length = 0; + this._state = DONE_COMPLETE_STATE; + } + } + }; + + return AnimateRunner; + }]; +}; + +/** + * @ngdoc service + * @name $animateCss + * @kind object + * + * @description + * This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included, + * then the `$animateCss` service will actually perform animations. + * + * Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}. + */ +var $CoreAnimateCssProvider = function() { + this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) { + + return function(element, initialOptions) { + // all of the animation functions should create + // a copy of the options data, however, if a + // parent service has already created a copy then + // we should stick to using that + var options = initialOptions || {}; + if (!options.$$prepared) { + options = copy(options); + } + + // there is no point in applying the styles since + // there is no animation that goes on at all in + // this version of $animateCss. + if (options.cleanupStyles) { + options.from = options.to = null; + } + + if (options.from) { + element.css(options.from); + options.from = null; + } + + /* jshint newcap: false */ + var closed, runner = new $$AnimateRunner(); + return { + start: run, + end: run + }; + + function run() { + $$rAF(function() { + applyAnimationContents(); + if (!closed) { + runner.complete(); + } + closed = true; + }); + return runner; + } + + function applyAnimationContents() { + if (options.addClass) { + element.addClass(options.addClass); + options.addClass = null; + } + if (options.removeClass) { + element.removeClass(options.removeClass); + options.removeClass = null; + } + if (options.to) { + element.css(options.to); + options.to = null; + } + } + }; + }]; +}; + +/* global stripHash: true */ + +/** + * ! This is a private undocumented service ! + * + * @name $browser + * @requires $log + * @description + * This object has two goals: + * + * - hide all the global state in the browser caused by the window object + * - abstract away all the browser specific features and inconsistencies + * + * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser` + * service, which can be used for convenient testing of the application without the interaction with + * the real browser apis. + */ +/** + * @param {object} window The global window object. + * @param {object} document jQuery wrapped document. + * @param {object} $log window.console or an object with the same interface. + * @param {object} $sniffer $sniffer service + */ +function Browser(window, document, $log, $sniffer) { + var self = this, + location = window.location, + history = window.history, + setTimeout = window.setTimeout, + clearTimeout = window.clearTimeout, + pendingDeferIds = {}; + + self.isMock = false; + + var outstandingRequestCount = 0; + var outstandingRequestCallbacks = []; + + // TODO(vojta): remove this temporary api + self.$$completeOutstandingRequest = completeOutstandingRequest; + self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; }; + + /** + * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks` + * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed. + */ + function completeOutstandingRequest(fn) { + try { + fn.apply(null, sliceArgs(arguments, 1)); + } finally { + outstandingRequestCount--; + if (outstandingRequestCount === 0) { + while (outstandingRequestCallbacks.length) { + try { + outstandingRequestCallbacks.pop()(); + } catch (e) { + $log.error(e); + } + } + } + } + } + + function getHash(url) { + var index = url.indexOf('#'); + return index === -1 ? '' : url.substr(index); + } + + /** + * @private + * Note: this method is used only by scenario runner + * TODO(vojta): prefix this method with $$ ? + * @param {function()} callback Function that will be called when no outstanding request + */ + self.notifyWhenNoOutstandingRequests = function(callback) { + if (outstandingRequestCount === 0) { + callback(); + } else { + outstandingRequestCallbacks.push(callback); + } + }; + + ////////////////////////////////////////////////////////////// + // URL API + ////////////////////////////////////////////////////////////// + + var cachedState, lastHistoryState, + lastBrowserUrl = location.href, + baseElement = document.find('base'), + pendingLocation = null, + getCurrentState = !$sniffer.history ? noop : function getCurrentState() { + try { + return history.state; + } catch (e) { + // MSIE can reportedly throw when there is no state (UNCONFIRMED). + } + }; + + cacheState(); + lastHistoryState = cachedState; + + /** + * @name $browser#url + * + * @description + * GETTER: + * Without any argument, this method just returns current value of location.href. + * + * SETTER: + * With at least one argument, this method sets url to new value. + * If html5 history api supported, pushState/replaceState is used, otherwise + * location.href/location.replace is used. + * Returns its own instance to allow chaining + * + * NOTE: this api is intended for use only by the $location service. Please use the + * {@link ng.$location $location service} to change url. + * + * @param {string} url New url (when used as setter) + * @param {boolean=} replace Should new url replace current history record? + * @param {object=} state object to use with pushState/replaceState + */ + self.url = function(url, replace, state) { + // In modern browsers `history.state` is `null` by default; treating it separately + // from `undefined` would cause `$browser.url('/foo')` to change `history.state` + // to undefined via `pushState`. Instead, let's change `undefined` to `null` here. + if (isUndefined(state)) { + state = null; + } + + // Android Browser BFCache causes location, history reference to become stale. + if (location !== window.location) location = window.location; + if (history !== window.history) history = window.history; + + // setter + if (url) { + var sameState = lastHistoryState === state; + + // Don't change anything if previous and current URLs and states match. This also prevents + // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode. + // See https://github.com/angular/angular.js/commit/ffb2701 + if (lastBrowserUrl === url && (!$sniffer.history || sameState)) { + return self; + } + var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url); + lastBrowserUrl = url; + lastHistoryState = state; + // Don't use history API if only the hash changed + // due to a bug in IE10/IE11 which leads + // to not firing a `hashchange` nor `popstate` event + // in some cases (see #9143). + if ($sniffer.history && (!sameBase || !sameState)) { + history[replace ? 'replaceState' : 'pushState'](state, '', url); + cacheState(); + // Do the assignment again so that those two variables are referentially identical. + lastHistoryState = cachedState; + } else { + if (!sameBase) { + pendingLocation = url; + } + if (replace) { + location.replace(url); + } else if (!sameBase) { + location.href = url; + } else { + location.hash = getHash(url); + } + if (location.href !== url) { + pendingLocation = url; + } + } + if (pendingLocation) { + pendingLocation = url; + } + return self; + // getter + } else { + // - pendingLocation is needed as browsers don't allow to read out + // the new location.href if a reload happened or if there is a bug like in iOS 9 (see + // https://openradar.appspot.com/22186109). + // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172 + return pendingLocation || location.href.replace(/%27/g,"'"); + } + }; + + /** + * @name $browser#state + * + * @description + * This method is a getter. + * + * Return history.state or null if history.state is undefined. + * + * @returns {object} state + */ + self.state = function() { + return cachedState; + }; + + var urlChangeListeners = [], + urlChangeInit = false; + + function cacheStateAndFireUrlChange() { + pendingLocation = null; + cacheState(); + fireUrlChange(); + } + + // This variable should be used *only* inside the cacheState function. + var lastCachedState = null; + function cacheState() { + // This should be the only place in $browser where `history.state` is read. + cachedState = getCurrentState(); + cachedState = isUndefined(cachedState) ? null : cachedState; + + // Prevent callbacks fo fire twice if both hashchange & popstate were fired. + if (equals(cachedState, lastCachedState)) { + cachedState = lastCachedState; + } + lastCachedState = cachedState; + } + + function fireUrlChange() { + if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) { + return; + } + + lastBrowserUrl = self.url(); + lastHistoryState = cachedState; + forEach(urlChangeListeners, function(listener) { + listener(self.url(), cachedState); + }); + } + + /** + * @name $browser#onUrlChange + * + * @description + * Register callback function that will be called, when url changes. + * + * It's only called when the url is changed from outside of angular: + * - user types different url into address bar + * - user clicks on history (forward/back) button + * - user clicks on a link + * + * It's not called when url is changed by $browser.url() method + * + * The listener gets called with new url as parameter. + * + * NOTE: this api is intended for use only by the $location service. Please use the + * {@link ng.$location $location service} to monitor url changes in angular apps. + * + * @param {function(string)} listener Listener function to be called when url changes. + * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous. + */ + self.onUrlChange = function(callback) { + // TODO(vojta): refactor to use node's syntax for events + if (!urlChangeInit) { + // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera) + // don't fire popstate when user change the address bar and don't fire hashchange when url + // changed by push/replaceState + + // html5 history api - popstate event + if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange); + // hashchange event + jqLite(window).on('hashchange', cacheStateAndFireUrlChange); + + urlChangeInit = true; + } + + urlChangeListeners.push(callback); + return callback; + }; + + /** + * @private + * Remove popstate and hashchange handler from window. + * + * NOTE: this api is intended for use only by $rootScope. + */ + self.$$applicationDestroyed = function() { + jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange); + }; + + /** + * Checks whether the url has changed outside of Angular. + * Needs to be exported to be able to check for changes that have been done in sync, + * as hashchange/popstate events fire in async. + */ + self.$$checkUrlChange = fireUrlChange; + + ////////////////////////////////////////////////////////////// + // Misc API + ////////////////////////////////////////////////////////////// + + /** + * @name $browser#baseHref + * + * @description + * Returns current + * (always relative - without domain) + * + * @returns {string} The current base href + */ + self.baseHref = function() { + var href = baseElement.attr('href'); + return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : ''; + }; + + /** + * @name $browser#defer + * @param {function()} fn A function, who's execution should be deferred. + * @param {number=} [delay=0] of milliseconds to defer the function execution. + * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`. + * + * @description + * Executes a fn asynchronously via `setTimeout(fn, delay)`. + * + * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using + * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed + * via `$browser.defer.flush()`. + * + */ + self.defer = function(fn, delay) { + var timeoutId; + outstandingRequestCount++; + timeoutId = setTimeout(function() { + delete pendingDeferIds[timeoutId]; + completeOutstandingRequest(fn); + }, delay || 0); + pendingDeferIds[timeoutId] = true; + return timeoutId; + }; + + + /** + * @name $browser#defer.cancel + * + * @description + * Cancels a deferred task identified with `deferId`. + * + * @param {*} deferId Token returned by the `$browser.defer` function. + * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully + * canceled. + */ + self.defer.cancel = function(deferId) { + if (pendingDeferIds[deferId]) { + delete pendingDeferIds[deferId]; + clearTimeout(deferId); + completeOutstandingRequest(noop); + return true; + } + return false; + }; + +} + +function $BrowserProvider() { + this.$get = ['$window', '$log', '$sniffer', '$document', + function($window, $log, $sniffer, $document) { + return new Browser($window, $document, $log, $sniffer); + }]; +} + +/** + * @ngdoc service + * @name $cacheFactory + * + * @description + * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to + * them. + * + * ```js + * + * var cache = $cacheFactory('cacheId'); + * expect($cacheFactory.get('cacheId')).toBe(cache); + * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined(); + * + * cache.put("key", "value"); + * cache.put("another key", "another value"); + * + * // We've specified no options on creation + * expect(cache.info()).toEqual({id: 'cacheId', size: 2}); + * + * ``` + * + * + * @param {string} cacheId Name or id of the newly created cache. + * @param {object=} options Options object that specifies the cache behavior. Properties: + * + * - `{number=}` `capacity` — turns the cache into LRU cache. + * + * @returns {object} Newly created cache object with the following set of methods: + * + * - `{object}` `info()` — Returns id, size, and options of cache. + * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns + * it. + * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss. + * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache. + * - `{void}` `removeAll()` — Removes all cached values. + * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory. + * + * @example + + +
    + + + + +

    Cached Values

    +
    + + : + +
    + +

    Cache Info

    +
    + + : + +
    +
    +
    + + angular.module('cacheExampleApp', []). + controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) { + $scope.keys = []; + $scope.cache = $cacheFactory('cacheId'); + $scope.put = function(key, value) { + if (angular.isUndefined($scope.cache.get(key))) { + $scope.keys.push(key); + } + $scope.cache.put(key, angular.isUndefined(value) ? null : value); + }; + }]); + + + p { + margin: 10px 0 3px; + } + +
    + */ +function $CacheFactoryProvider() { + + this.$get = function() { + var caches = {}; + + function cacheFactory(cacheId, options) { + if (cacheId in caches) { + throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId); + } + + var size = 0, + stats = extend({}, options, {id: cacheId}), + data = createMap(), + capacity = (options && options.capacity) || Number.MAX_VALUE, + lruHash = createMap(), + freshEnd = null, + staleEnd = null; + + /** + * @ngdoc type + * @name $cacheFactory.Cache + * + * @description + * A cache object used to store and retrieve data, primarily used by + * {@link $http $http} and the {@link ng.directive:script script} directive to cache + * templates and other data. + * + * ```js + * angular.module('superCache') + * .factory('superCache', ['$cacheFactory', function($cacheFactory) { + * return $cacheFactory('super-cache'); + * }]); + * ``` + * + * Example test: + * + * ```js + * it('should behave like a cache', inject(function(superCache) { + * superCache.put('key', 'value'); + * superCache.put('another key', 'another value'); + * + * expect(superCache.info()).toEqual({ + * id: 'super-cache', + * size: 2 + * }); + * + * superCache.remove('another key'); + * expect(superCache.get('another key')).toBeUndefined(); + * + * superCache.removeAll(); + * expect(superCache.info()).toEqual({ + * id: 'super-cache', + * size: 0 + * }); + * })); + * ``` + */ + return caches[cacheId] = { + + /** + * @ngdoc method + * @name $cacheFactory.Cache#put + * @kind function + * + * @description + * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be + * retrieved later, and incrementing the size of the cache if the key was not already + * present in the cache. If behaving like an LRU cache, it will also remove stale + * entries from the set. + * + * It will not insert undefined values into the cache. + * + * @param {string} key the key under which the cached data is stored. + * @param {*} value the value to store alongside the key. If it is undefined, the key + * will not be stored. + * @returns {*} the value stored. + */ + put: function(key, value) { + if (isUndefined(value)) return; + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key] || (lruHash[key] = {key: key}); + + refresh(lruEntry); + } + + if (!(key in data)) size++; + data[key] = value; + + if (size > capacity) { + this.remove(staleEnd.key); + } + + return value; + }, + + /** + * @ngdoc method + * @name $cacheFactory.Cache#get + * @kind function + * + * @description + * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object. + * + * @param {string} key the key of the data to be retrieved + * @returns {*} the value stored. + */ + get: function(key) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key]; + + if (!lruEntry) return; + + refresh(lruEntry); + } + + return data[key]; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#remove + * @kind function + * + * @description + * Removes an entry from the {@link $cacheFactory.Cache Cache} object. + * + * @param {string} key the key of the entry to be removed + */ + remove: function(key) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key]; + + if (!lruEntry) return; + + if (lruEntry == freshEnd) freshEnd = lruEntry.p; + if (lruEntry == staleEnd) staleEnd = lruEntry.n; + link(lruEntry.n,lruEntry.p); + + delete lruHash[key]; + } + + if (!(key in data)) return; + + delete data[key]; + size--; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#removeAll + * @kind function + * + * @description + * Clears the cache object of any entries. + */ + removeAll: function() { + data = createMap(); + size = 0; + lruHash = createMap(); + freshEnd = staleEnd = null; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#destroy + * @kind function + * + * @description + * Destroys the {@link $cacheFactory.Cache Cache} object entirely, + * removing it from the {@link $cacheFactory $cacheFactory} set. + */ + destroy: function() { + data = null; + stats = null; + lruHash = null; + delete caches[cacheId]; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#info + * @kind function + * + * @description + * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}. + * + * @returns {object} an object with the following properties: + *
      + *
    • **id**: the id of the cache instance
    • + *
    • **size**: the number of entries kept in the cache instance
    • + *
    • **...**: any additional properties from the options object when creating the + * cache.
    • + *
    + */ + info: function() { + return extend({}, stats, {size: size}); + } + }; + + + /** + * makes the `entry` the freshEnd of the LRU linked list + */ + function refresh(entry) { + if (entry != freshEnd) { + if (!staleEnd) { + staleEnd = entry; + } else if (staleEnd == entry) { + staleEnd = entry.n; + } + + link(entry.n, entry.p); + link(entry, freshEnd); + freshEnd = entry; + freshEnd.n = null; + } + } + + + /** + * bidirectionally links two entries of the LRU linked list + */ + function link(nextEntry, prevEntry) { + if (nextEntry != prevEntry) { + if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify + if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify + } + } + } + + + /** + * @ngdoc method + * @name $cacheFactory#info + * + * @description + * Get information about all the caches that have been created + * + * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info` + */ + cacheFactory.info = function() { + var info = {}; + forEach(caches, function(cache, cacheId) { + info[cacheId] = cache.info(); + }); + return info; + }; + + + /** + * @ngdoc method + * @name $cacheFactory#get + * + * @description + * Get access to a cache object by the `cacheId` used when it was created. + * + * @param {string} cacheId Name or id of a cache to access. + * @returns {object} Cache object identified by the cacheId or undefined if no such cache. + */ + cacheFactory.get = function(cacheId) { + return caches[cacheId]; + }; + + + return cacheFactory; + }; +} + +/** + * @ngdoc service + * @name $templateCache + * + * @description + * The first time a template is used, it is loaded in the template cache for quick retrieval. You + * can load templates directly into the cache in a `script` tag, or by consuming the + * `$templateCache` service directly. + * + * Adding via the `script` tag: + * + * ```html + * + * ``` + * + * **Note:** the `script` tag containing the template does not need to be included in the `head` of + * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE, + * element with ng-app attribute), otherwise the template will be ignored. + * + * Adding via the `$templateCache` service: + * + * ```js + * var myApp = angular.module('myApp', []); + * myApp.run(function($templateCache) { + * $templateCache.put('templateId.html', 'This is the content of the template'); + * }); + * ``` + * + * To retrieve the template later, simply use it in your HTML: + * ```html + *
    + * ``` + * + * or get it via Javascript: + * ```js + * $templateCache.get('templateId.html') + * ``` + * + * See {@link ng.$cacheFactory $cacheFactory}. + * + */ +function $TemplateCacheProvider() { + this.$get = ['$cacheFactory', function($cacheFactory) { + return $cacheFactory('templates'); + }]; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE! + * + * DOM-related variables: + * + * - "node" - DOM Node + * - "element" - DOM Element or Node + * - "$node" or "$element" - jqLite-wrapped node or element + * + * + * Compiler related stuff: + * + * - "linkFn" - linking fn of a single directive + * - "nodeLinkFn" - function that aggregates all linking fns for a particular node + * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node + * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList) + */ + + +/** + * @ngdoc service + * @name $compile + * @kind function + * + * @description + * Compiles an HTML string or DOM into a template and produces a template function, which + * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together. + * + * The compilation is a process of walking the DOM tree and matching DOM elements to + * {@link ng.$compileProvider#directive directives}. + * + *
    + * **Note:** This document is an in-depth reference of all directive options. + * For a gentle introduction to directives with examples of common use cases, + * see the {@link guide/directive directive guide}. + *
    + * + * ## Comprehensive Directive API + * + * There are many different options for a directive. + * + * The difference resides in the return value of the factory function. + * You can either return a {@link $compile#directive-definition-object Directive Definition Object (see below)} + * that defines the directive properties, or just the `postLink` function (all other properties will have + * the default values). + * + *
    + * **Best Practice:** It's recommended to use the "directive definition object" form. + *
    + * + * Here's an example directive declared with a Directive Definition Object: + * + * ```js + * var myModule = angular.module(...); + * + * myModule.directive('directiveName', function factory(injectables) { + * var directiveDefinitionObject = { + * priority: 0, + * template: '
    ', // or // function(tElement, tAttrs) { ... }, + * // or + * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... }, + * transclude: false, + * restrict: 'A', + * templateNamespace: 'html', + * scope: false, + * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, + * controllerAs: 'stringIdentifier', + * bindToController: false, + * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], + * compile: function compile(tElement, tAttrs, transclude) { + * return { + * pre: function preLink(scope, iElement, iAttrs, controller) { ... }, + * post: function postLink(scope, iElement, iAttrs, controller) { ... } + * } + * // or + * // return function postLink( ... ) { ... } + * }, + * // or + * // link: { + * // pre: function preLink(scope, iElement, iAttrs, controller) { ... }, + * // post: function postLink(scope, iElement, iAttrs, controller) { ... } + * // } + * // or + * // link: function postLink( ... ) { ... } + * }; + * return directiveDefinitionObject; + * }); + * ``` + * + *
    + * **Note:** Any unspecified options will use the default value. You can see the default values below. + *
    + * + * Therefore the above can be simplified as: + * + * ```js + * var myModule = angular.module(...); + * + * myModule.directive('directiveName', function factory(injectables) { + * var directiveDefinitionObject = { + * link: function postLink(scope, iElement, iAttrs) { ... } + * }; + * return directiveDefinitionObject; + * // or + * // return function postLink(scope, iElement, iAttrs) { ... } + * }); + * ``` + * + * ### Life-cycle hooks + * Directive controllers can provide the following methods that are called by Angular at points in the life-cycle of the + * directive: + * * `$onInit()` - Called on each controller after all the controllers on an element have been constructed and + * had their bindings initialized (and before the pre & post linking functions for the directives on + * this element). This is a good place to put initialization code for your controller. + * * `$onChanges(changesObj)` - Called whenever one-way (`<`) or interpolation (`@`) bindings are updated. The + * `changesObj` is a hash whose keys are the names of the bound properties that have changed, and the values are an + * object of the form `{ currentValue, previousValue, isFirstChange() }`. Use this hook to trigger updates within a + * component such as cloning the bound value to prevent accidental mutation of the outer value. + * * `$doCheck()` - Called on each turn of the digest cycle. Provides an opportunity to detect and act on + * changes. Any actions that you wish to take in response to the changes that you detect must be + * invoked from this hook; implementing this has no effect on when `$onChanges` is called. For example, this hook + * could be useful if you wish to perform a deep equality check, or to check a Date object, changes to which would not + * be detected by Angular's change detector and thus not trigger `$onChanges`. This hook is invoked with no arguments; + * if detecting changes, you must store the previous value(s) for comparison to the current values. + * * `$onDestroy()` - Called on a controller when its containing scope is destroyed. Use this hook for releasing + * external resources, watches and event handlers. Note that components have their `$onDestroy()` hooks called in + * the same order as the `$scope.$broadcast` events are triggered, which is top down. This means that parent + * components will have their `$onDestroy()` hook called before child components. + * * `$postLink()` - Called after this controller's element and its children have been linked. Similar to the post-link + * function this hook can be used to set up DOM event handlers and do direct DOM manipulation. + * Note that child elements that contain `templateUrl` directives will not have been compiled and linked since + * they are waiting for their template to load asynchronously and their own compilation and linking has been + * suspended until that occurs. + * + * #### Comparison with Angular 2 life-cycle hooks + * Angular 2 also uses life-cycle hooks for its components. While the Angular 1 life-cycle hooks are similar there are + * some differences that you should be aware of, especially when it comes to moving your code from Angular 1 to Angular 2: + * + * * Angular 1 hooks are prefixed with `$`, such as `$onInit`. Angular 2 hooks are prefixed with `ng`, such as `ngOnInit`. + * * Angular 1 hooks can be defined on the controller prototype or added to the controller inside its constructor. + * In Angular 2 you can only define hooks on the prototype of the Component class. + * * Due to the differences in change-detection, you may get many more calls to `$doCheck` in Angular 1 than you would to + * `ngDoCheck` in Angular 2 + * * Changes to the model inside `$doCheck` will trigger new turns of the digest loop, which will cause the changes to be + * propagated throughout the application. + * Angular 2 does not allow the `ngDoCheck` hook to trigger a change outside of the component. It will either throw an + * error or do nothing depending upon the state of `enableProdMode()`. + * + * #### Life-cycle hook examples + * + * This example shows how you can check for mutations to a Date object even though the identity of the object + * has not changed. + * + * + * + * angular.module('do-check-module', []) + * .component('app', { + * template: + * 'Month: ' + + * 'Date: {{ $ctrl.date }}' + + * '', + * controller: function() { + * this.date = new Date(); + * this.month = this.date.getMonth(); + * this.updateDate = function() { + * this.date.setMonth(this.month); + * }; + * } + * }) + * .component('test', { + * bindings: { date: '<' }, + * template: + * '
    {{ $ctrl.log | json }}
    ', + * controller: function() { + * var previousValue; + * this.log = []; + * this.$doCheck = function() { + * var currentValue = this.date && this.date.valueOf(); + * if (previousValue !== currentValue) { + * this.log.push('doCheck: date mutated: ' + this.date); + * previousValue = currentValue; + * } + * }; + * } + * }); + *
    + * + * + * + *
    + * + * This example show how you might use `$doCheck` to trigger changes in your component's inputs even if the + * actual identity of the component doesn't change. (Be aware that cloning and deep equality checks on large + * arrays or objects can have a negative impact on your application performance) + * + * + * + *
    + * + * + *
    {{ items }}
    + * + *
    + *
    + * + * angular.module('do-check-module', []) + * .component('test', { + * bindings: { items: '<' }, + * template: + * '
    {{ $ctrl.log | json }}
    ', + * controller: function() { + * this.log = []; + * + * this.$doCheck = function() { + * if (this.items_ref !== this.items) { + * this.log.push('doCheck: items changed'); + * this.items_ref = this.items; + * } + * if (!angular.equals(this.items_clone, this.items)) { + * this.log.push('doCheck: items mutated'); + * this.items_clone = angular.copy(this.items); + * } + * }; + * } + * }); + *
    + *
    + * + * + * ### Directive Definition Object + * + * The directive definition object provides instructions to the {@link ng.$compile + * compiler}. The attributes are: + * + * #### `multiElement` + * When this property is set to true, the HTML compiler will collect DOM nodes between + * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them + * together as the directive elements. It is recommended that this feature be used on directives + * which are not strictly behavioral (such as {@link ngClick}), and which + * do not manipulate or replace child nodes (such as {@link ngInclude}). + * + * #### `priority` + * When there are multiple directives defined on a single DOM element, sometimes it + * is necessary to specify the order in which the directives are applied. The `priority` is used + * to sort the directives before their `compile` functions get called. Priority is defined as a + * number. Directives with greater numerical `priority` are compiled first. Pre-link functions + * are also run in priority order, but post-link functions are run in reverse order. The order + * of directives with the same priority is undefined. The default priority is `0`. + * + * #### `terminal` + * If set to true then the current `priority` will be the last set of directives + * which will execute (any directives at the current priority will still execute + * as the order of execution on same `priority` is undefined). Note that expressions + * and other directives used in the directive's template will also be excluded from execution. + * + * #### `scope` + * The scope property can be `true`, an object or a falsy value: + * + * * **falsy:** No scope will be created for the directive. The directive will use its parent's scope. + * + * * **`true`:** A new child scope that prototypically inherits from its parent will be created for + * the directive's element. If multiple directives on the same element request a new scope, + * only one new scope is created. The new scope rule does not apply for the root of the template + * since the root of the template always gets a new scope. + * + * * **`{...}` (an object hash):** A new "isolate" scope is created for the directive's element. The + * 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent + * scope. This is useful when creating reusable components, which should not accidentally read or modify + * data in the parent scope. + * + * The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the + * directive's element. These local properties are useful for aliasing values for templates. The keys in + * the object hash map to the name of the property on the isolate scope; the values define how the property + * is bound to the parent scope, via matching attributes on the directive's element: + * + * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is + * always a string since DOM attributes are strings. If no `attr` name is specified then the + * attribute name is assumed to be the same as the local name. Given `` and the isolate scope definition `scope: { localName:'@myAttr' }`, + * the directive's scope property `localName` will reflect the interpolated value of `hello + * {{name}}`. As the `name` attribute changes so will the `localName` property on the directive's + * scope. The `name` is read from the parent scope (not the directive's scope). + * + * * `=` or `=attr` - set up a bidirectional binding between a local scope property and an expression + * passed via the attribute `attr`. The expression is evaluated in the context of the parent scope. + * If no `attr` name is specified then the attribute name is assumed to be the same as the local + * name. Given `` and the isolate scope definition `scope: { + * localModel: '=myAttr' }`, the property `localModel` on the directive's scope will reflect the + * value of `parentModel` on the parent scope. Changes to `parentModel` will be reflected in + * `localModel` and vice versa. Optional attributes should be marked as such with a question mark: + * `=?` or `=?attr`. If the binding expression is non-assignable, or if the attribute isn't + * optional and doesn't exist, an exception ({@link error/$compile/nonassign `$compile:nonassign`}) + * will be thrown upon discovering changes to the local value, since it will be impossible to sync + * them back to the parent scope. By default, the {@link ng.$rootScope.Scope#$watch `$watch`} + * method is used for tracking changes, and the equality check is based on object identity. + * However, if an object literal or an array literal is passed as the binding expression, the + * equality check is done by value (using the {@link angular.equals} function). It's also possible + * to watch the evaluated value shallowly with {@link ng.$rootScope.Scope#$watchCollection + * `$watchCollection`}: use `=*` or `=*attr` (`=*?` or `=*?attr` if the attribute is optional). + * + * * `<` or `` and directive definition of + * `scope: { localModel:'` and the isolate scope definition `scope: { + * localFn:'&myAttr' }`, the isolate scope property `localFn` will point to a function wrapper for + * the `count = count + value` expression. Often it's desirable to pass data from the isolated scope + * via an expression to the parent scope. This can be done by passing a map of local variable names + * and values into the expression wrapper fn. For example, if the expression is `increment(amount)` + * then we can specify the amount value by calling the `localFn` as `localFn({amount: 22})`. + * + * In general it's possible to apply more than one directive to one element, but there might be limitations + * depending on the type of scope required by the directives. The following points will help explain these limitations. + * For simplicity only two directives are taken into account, but it is also applicable for several directives: + * + * * **no scope** + **no scope** => Two directives which don't require their own scope will use their parent's scope + * * **child scope** + **no scope** => Both directives will share one single child scope + * * **child scope** + **child scope** => Both directives will share one single child scope + * * **isolated scope** + **no scope** => The isolated directive will use it's own created isolated scope. The other directive will use + * its parent's scope + * * **isolated scope** + **child scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives cannot + * be applied to the same element. + * * **isolated scope** + **isolated scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives + * cannot be applied to the same element. + * + * + * #### `bindToController` + * This property is used to bind scope properties directly to the controller. It can be either + * `true` or an object hash with the same format as the `scope` property. Additionally, a controller + * alias must be set, either by using `controllerAs: 'myAlias'` or by specifying the alias in the controller + * definition: `controller: 'myCtrl as myAlias'`. + * + * When an isolate scope is used for a directive (see above), `bindToController: true` will + * allow a component to have its properties bound to the controller, rather than to scope. + * + * After the controller is instantiated, the initial values of the isolate scope bindings will be bound to the controller + * properties. You can access these bindings once they have been initialized by providing a controller method called + * `$onInit`, which is called after all the controllers on an element have been constructed and had their bindings + * initialized. + * + *
    + * **Deprecation warning:** although bindings for non-ES6 class controllers are currently + * bound to `this` before the controller constructor is called, this use is now deprecated. Please place initialization + * code that relies upon bindings inside a `$onInit` method on the controller, instead. + *
    + * + * It is also possible to set `bindToController` to an object hash with the same format as the `scope` property. + * This will set up the scope bindings to the controller directly. Note that `scope` can still be used + * to define which kind of scope is created. By default, no scope is created. Use `scope: {}` to create an isolate + * scope (useful for component directives). + * + * If both `bindToController` and `scope` are defined and have object hashes, `bindToController` overrides `scope`. + * + * + * #### `controller` + * Controller constructor function. The controller is instantiated before the + * pre-linking phase and can be accessed by other directives (see + * `require` attribute). This allows the directives to communicate with each other and augment + * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals: + * + * * `$scope` - Current scope associated with the element + * * `$element` - Current element + * * `$attrs` - Current attributes object for the element + * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope: + * `function([scope], cloneLinkingFn, futureParentElement, slotName)`: + * * `scope`: (optional) override the scope. + * * `cloneLinkingFn`: (optional) argument to create clones of the original transcluded content. + * * `futureParentElement` (optional): + * * defines the parent to which the `cloneLinkingFn` will add the cloned elements. + * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`. + * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements) + * and when the `cloneLinkinFn` is passed, + * as those elements need to created and cloned in a special way when they are defined outside their + * usual containers (e.g. like ``). + * * See also the `directive.templateNamespace` property. + * * `slotName`: (optional) the name of the slot to transclude. If falsy (e.g. `null`, `undefined` or `''`) + * then the default translusion is provided. + * The `$transclude` function also has a method on it, `$transclude.isSlotFilled(slotName)`, which returns + * `true` if the specified slot contains content (i.e. one or more DOM nodes). + * + * #### `require` + * Require another directive and inject its controller as the fourth argument to the linking function. The + * `require` property can be a string, an array or an object: + * * a **string** containing the name of the directive to pass to the linking function + * * an **array** containing the names of directives to pass to the linking function. The argument passed to the + * linking function will be an array of controllers in the same order as the names in the `require` property + * * an **object** whose property values are the names of the directives to pass to the linking function. The argument + * passed to the linking function will also be an object with matching keys, whose values will hold the corresponding + * controllers. + * + * If the `require` property is an object and `bindToController` is truthy, then the required controllers are + * bound to the controller using the keys of the `require` property. This binding occurs after all the controllers + * have been constructed but before `$onInit` is called. + * If the name of the required controller is the same as the local name (the key), the name can be + * omitted. For example, `{parentDir: '^^'}` is equivalent to `{parentDir: '^^parentDir'}`. + * See the {@link $compileProvider#component} helper for an example of how this can be used. + * If no such required directive(s) can be found, or if the directive does not have a controller, then an error is + * raised (unless no link function is specified and the required controllers are not being bound to the directive + * controller, in which case error checking is skipped). The name can be prefixed with: + * + * * (no prefix) - Locate the required controller on the current element. Throw an error if not found. + * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found. + * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found. + * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found. + * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass + * `null` to the `link` fn if not found. + * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass + * `null` to the `link` fn if not found. + * + * + * #### `controllerAs` + * Identifier name for a reference to the controller in the directive's scope. + * This allows the controller to be referenced from the directive template. This is especially + * useful when a directive is used as component, i.e. with an `isolate` scope. It's also possible + * to use it in a directive without an `isolate` / `new` scope, but you need to be aware that the + * `controllerAs` reference might overwrite a property that already exists on the parent scope. + * + * + * #### `restrict` + * String of subset of `EACM` which restricts the directive to a specific directive + * declaration style. If omitted, the defaults (elements and attributes) are used. + * + * * `E` - Element name (default): `` + * * `A` - Attribute (default): `
    ` + * * `C` - Class: `
    ` + * * `M` - Comment: `` + * + * + * #### `templateNamespace` + * String representing the document type used by the markup in the template. + * AngularJS needs this information as those elements need to be created and cloned + * in a special way when they are defined outside their usual containers like `` and ``. + * + * * `html` - All root nodes in the template are HTML. Root nodes may also be + * top-level elements such as `` or ``. + * * `svg` - The root nodes in the template are SVG elements (excluding ``). + * * `math` - The root nodes in the template are MathML elements (excluding ``). + * + * If no `templateNamespace` is specified, then the namespace is considered to be `html`. + * + * #### `template` + * HTML markup that may: + * * Replace the contents of the directive's element (default). + * * Replace the directive's element itself (if `replace` is true - DEPRECATED). + * * Wrap the contents of the directive's element (if `transclude` is true). + * + * Value may be: + * + * * A string. For example `
    {{delete_str}}
    `. + * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile` + * function api below) and returns a string value. + * + * + * #### `templateUrl` + * This is similar to `template` but the template is loaded from the specified URL, asynchronously. + * + * Because template loading is asynchronous the compiler will suspend compilation of directives on that element + * for later when the template has been resolved. In the meantime it will continue to compile and link + * sibling and parent elements as though this element had not contained any directives. + * + * The compiler does not suspend the entire compilation to wait for templates to be loaded because this + * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the + * case when only one deeply nested directive has `templateUrl`. + * + * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache} + * + * You can specify `templateUrl` as a string representing the URL or as a function which takes two + * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns + * a string value representing the url. In either case, the template URL is passed through {@link + * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}. + * + * + * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0) + * specify what the template should replace. Defaults to `false`. + * + * * `true` - the template will replace the directive's element. + * * `false` - the template will replace the contents of the directive's element. + * + * The replacement process migrates all of the attributes / classes from the old element to the new + * one. See the {@link guide/directive#template-expanding-directive + * Directives Guide} for an example. + * + * There are very few scenarios where element replacement is required for the application function, + * the main one being reusable custom components that are used within SVG contexts + * (because SVG doesn't work with custom elements in the DOM tree). + * + * #### `transclude` + * Extract the contents of the element where the directive appears and make it available to the directive. + * The contents are compiled and provided to the directive as a **transclusion function**. See the + * {@link $compile#transclusion Transclusion} section below. + * + * + * #### `compile` + * + * ```js + * function compile(tElement, tAttrs, transclude) { ... } + * ``` + * + * The compile function deals with transforming the template DOM. Since most directives do not do + * template transformation, it is not used often. The compile function takes the following arguments: + * + * * `tElement` - template element - The element where the directive has been declared. It is + * safe to do template transformation on the element and child elements only. + * + * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared + * between all directive compile functions. + * + * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)` + * + *
    + * **Note:** The template instance and the link instance may be different objects if the template has + * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that + * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration + * should be done in a linking function rather than in a compile function. + *
    + + *
    + * **Note:** The compile function cannot handle directives that recursively use themselves in their + * own templates or compile functions. Compiling these directives results in an infinite loop and + * stack overflow errors. + * + * This can be avoided by manually using $compile in the postLink function to imperatively compile + * a directive's template instead of relying on automatic template compilation via `template` or + * `templateUrl` declaration or manual compilation inside the compile function. + *
    + * + *
    + * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it + * e.g. does not know about the right outer scope. Please use the transclude function that is passed + * to the link function instead. + *
    + + * A compile function can have a return value which can be either a function or an object. + * + * * returning a (post-link) function - is equivalent to registering the linking function via the + * `link` property of the config object when the compile function is empty. + * + * * returning an object with function(s) registered via `pre` and `post` properties - allows you to + * control when a linking function should be called during the linking phase. See info about + * pre-linking and post-linking functions below. + * + * + * #### `link` + * This property is used only if the `compile` property is not defined. + * + * ```js + * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... } + * ``` + * + * The link function is responsible for registering DOM listeners as well as updating the DOM. It is + * executed after the template has been cloned. This is where most of the directive logic will be + * put. + * + * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the + * directive for registering {@link ng.$rootScope.Scope#$watch watches}. + * + * * `iElement` - instance element - The element where the directive is to be used. It is safe to + * manipulate the children of the element only in `postLink` function since the children have + * already been linked. + * + * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared + * between all directive linking functions. + * + * * `controller` - the directive's required controller instance(s) - Instances are shared + * among all directives, which allows the directives to use the controllers as a communication + * channel. The exact value depends on the directive's `require` property: + * * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one + * * `string`: the controller instance + * * `array`: array of controller instances + * + * If a required controller cannot be found, and it is optional, the instance is `null`, + * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown. + * + * Note that you can also require the directive's own controller - it will be made available like + * any other controller. + * + * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope. + * This is the same as the `$transclude` parameter of directive controllers, + * see {@link ng.$compile#-controller- the controller section for details}. + * `function([scope], cloneLinkingFn, futureParentElement)`. + * + * #### Pre-linking function + * + * Executed before the child elements are linked. Not safe to do DOM transformation since the + * compiler linking function will fail to locate the correct elements for linking. + * + * #### Post-linking function + * + * Executed after the child elements are linked. + * + * Note that child elements that contain `templateUrl` directives will not have been compiled + * and linked since they are waiting for their template to load asynchronously and their own + * compilation and linking has been suspended until that occurs. + * + * It is safe to do DOM transformation in the post-linking function on elements that are not waiting + * for their async templates to be resolved. + * + * + * ### Transclusion + * + * Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and + * copying them to another part of the DOM, while maintaining their connection to the original AngularJS + * scope from where they were taken. + * + * Transclusion is used (often with {@link ngTransclude}) to insert the + * original contents of a directive's element into a specified place in the template of the directive. + * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded + * content has access to the properties on the scope from which it was taken, even if the directive + * has isolated scope. + * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}. + * + * This makes it possible for the widget to have private state for its template, while the transcluded + * content has access to its originating scope. + * + *
    + * **Note:** When testing an element transclude directive you must not place the directive at the root of the + * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives + * Testing Transclusion Directives}. + *
    + * + * There are three kinds of transclusion depending upon whether you want to transclude just the contents of the + * directive's element, the entire element or multiple parts of the element contents: + * + * * `true` - transclude the content (i.e. the child nodes) of the directive's element. + * * `'element'` - transclude the whole of the directive's element including any directives on this + * element that defined at a lower priority than this directive. When used, the `template` + * property is ignored. + * * **`{...}` (an object hash):** - map elements of the content onto transclusion "slots" in the template. + * + * **Mult-slot transclusion** is declared by providing an object for the `transclude` property. + * + * This object is a map where the keys are the name of the slot to fill and the value is an element selector + * used to match the HTML to the slot. The element selector should be in normalized form (e.g. `myElement`) + * and will match the standard element variants (e.g. `my-element`, `my:element`, `data-my-element`, etc). + * + * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives} + * + * If the element selector is prefixed with a `?` then that slot is optional. + * + * For example, the transclude object `{ slotA: '?myCustomElement' }` maps `` elements to + * the `slotA` slot, which can be accessed via the `$transclude` function or via the {@link ngTransclude} directive. + * + * Slots that are not marked as optional (`?`) will trigger a compile time error if there are no matching elements + * in the transclude content. If you wish to know if an optional slot was filled with content, then you can call + * `$transclude.isSlotFilled(slotName)` on the transclude function passed to the directive's link function and + * injectable into the directive's controller. + * + * + * #### Transclusion Functions + * + * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion + * function** to the directive's `link` function and `controller`. This transclusion function is a special + * **linking function** that will return the compiled contents linked to a new transclusion scope. + * + *
    + * If you are just using {@link ngTransclude} then you don't need to worry about this function, since + * ngTransclude will deal with it for us. + *
    + * + * If you want to manually control the insertion and removal of the transcluded content in your directive + * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery + * object that contains the compiled DOM, which is linked to the correct transclusion scope. + * + * When you call a transclusion function you can pass in a **clone attach function**. This function accepts + * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded + * content and the `scope` is the newly created transclusion scope, to which the clone is bound. + * + *
    + * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a transclude function + * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope. + *
    + * + * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone + * attach function**: + * + * ```js + * var transcludedContent, transclusionScope; + * + * $transclude(function(clone, scope) { + * element.append(clone); + * transcludedContent = clone; + * transclusionScope = scope; + * }); + * ``` + * + * Later, if you want to remove the transcluded content from your DOM then you should also destroy the + * associated transclusion scope: + * + * ```js + * transcludedContent.remove(); + * transclusionScope.$destroy(); + * ``` + * + *
    + * **Best Practice**: if you intend to add and remove transcluded content manually in your directive + * (by calling the transclude function to get the DOM and calling `element.remove()` to remove it), + * then you are also responsible for calling `$destroy` on the transclusion scope. + *
    + * + * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat} + * automatically destroy their transcluded clones as necessary so you do not need to worry about this if + * you are simply using {@link ngTransclude} to inject the transclusion into your directive. + * + * + * #### Transclusion Scopes + * + * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion + * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed + * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it + * was taken. + * + * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look + * like this: + * + * ```html + *
    + *
    + *
    + *
    + *
    + *
    + * ``` + * + * The `$parent` scope hierarchy will look like this: + * + ``` + - $rootScope + - isolate + - transclusion + ``` + * + * but the scopes will inherit prototypically from different scopes to their `$parent`. + * + ``` + - $rootScope + - transclusion + - isolate + ``` + * + * + * ### Attributes + * + * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the + * `link()` or `compile()` functions. It has a variety of uses. + * + * * *Accessing normalized attribute names:* Directives like 'ngBind' can be expressed in many ways: + * 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. The attributes object allows for normalized access + * to the attributes. + * + * * *Directive inter-communication:* All directives share the same instance of the attributes + * object which allows the directives to use the attributes object as inter directive + * communication. + * + * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object + * allowing other directives to read the interpolated value. + * + * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes + * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also + * the only way to easily get the actual value because during the linking phase the interpolation + * hasn't been evaluated yet and so the value is at this time set to `undefined`. + * + * ```js + * function linkingFn(scope, elm, attrs, ctrl) { + * // get the attribute value + * console.log(attrs.ngModel); + * + * // change the attribute + * attrs.$set('ngModel', 'new value'); + * + * // observe changes to interpolated attribute + * attrs.$observe('ngModel', function(value) { + * console.log('ngModel has changed value to ' + value); + * }); + * } + * ``` + * + * ## Example + * + *
    + * **Note**: Typically directives are registered with `module.directive`. The example below is + * to illustrate how `$compile` works. + *
    + * + + + +
    +
    +
    +
    +
    +
    + + it('should auto compile', function() { + var textarea = $('textarea'); + var output = $('div[compile]'); + // The initial state reads 'Hello Angular'. + expect(output.getText()).toBe('Hello Angular'); + textarea.clear(); + textarea.sendKeys('{{name}}!'); + expect(output.getText()).toBe('Angular!'); + }); + +
    + + * + * + * @param {string|DOMElement} element Element or HTML string to compile into a template function. + * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED. + * + *
    + * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it + * e.g. will not use the right outer scope. Please pass the transclude function as a + * `parentBoundTranscludeFn` to the link function instead. + *
    + * + * @param {number} maxPriority only apply directives lower than given priority (Only effects the + * root element(s), not their children) + * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template + * (a DOM element/tree) to a scope. Where: + * + * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to. + * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the + * `template` and call the `cloneAttachFn` function allowing the caller to attach the + * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is + * called as:
    `cloneAttachFn(clonedElement, scope)` where: + * + * * `clonedElement` - is a clone of the original `element` passed into the compiler. + * * `scope` - is the current scope with which the linking function is working with. + * + * * `options` - An optional object hash with linking options. If `options` is provided, then the following + * keys may be used to control linking behavior: + * + * * `parentBoundTranscludeFn` - the transclude function made available to + * directives; if given, it will be passed through to the link functions of + * directives found in `element` during compilation. + * * `transcludeControllers` - an object hash with keys that map controller names + * to a hash with the key `instance`, which maps to the controller instance; + * if given, it will make the controllers available to directives on the compileNode: + * ``` + * { + * parent: { + * instance: parentControllerInstance + * } + * } + * ``` + * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add + * the cloned elements; only needed for transcludes that are allowed to contain non html + * elements (e.g. SVG elements). See also the directive.controller property. + * + * Calling the linking function returns the element of the template. It is either the original + * element passed in, or the clone of the element if the `cloneAttachFn` is provided. + * + * After linking the view is not updated until after a call to $digest which typically is done by + * Angular automatically. + * + * If you need access to the bound view, there are two ways to do it: + * + * - If you are not asking the linking function to clone the template, create the DOM element(s) + * before you send them to the compiler and keep this reference around. + * ```js + * var element = $compile('

    {{total}}

    ')(scope); + * ``` + * + * - if on the other hand, you need the element to be cloned, the view reference from the original + * example would not point to the clone, but rather to the original template that was cloned. In + * this case, you can access the clone via the cloneAttachFn: + * ```js + * var templateElement = angular.element('

    {{total}}

    '), + * scope = ....; + * + * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) { + * //attach the clone to DOM document at the right place + * }); + * + * //now we have reference to the cloned DOM via `clonedElement` + * ``` + * + * + * For information on how the compiler works, see the + * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide. + */ + +var $compileMinErr = minErr('$compile'); + +function UNINITIALIZED_VALUE() {} +var _UNINITIALIZED_VALUE = new UNINITIALIZED_VALUE(); + +/** + * @ngdoc provider + * @name $compileProvider + * + * @description + */ +$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider']; +function $CompileProvider($provide, $$sanitizeUriProvider) { + var hasDirectives = {}, + Suffix = 'Directive', + COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/, + CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/, + ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'), + REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/; + + // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes + // The assumption is that future DOM event attribute names will begin with + // 'on' and be composed of only English letters. + var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; + var bindingCache = createMap(); + + function parseIsolateBindings(scope, directiveName, isController) { + var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/; + + var bindings = createMap(); + + forEach(scope, function(definition, scopeName) { + if (definition in bindingCache) { + bindings[scopeName] = bindingCache[definition]; + return; + } + var match = definition.match(LOCAL_REGEXP); + + if (!match) { + throw $compileMinErr('iscp', + "Invalid {3} for directive '{0}'." + + " Definition: {... {1}: '{2}' ...}", + directiveName, scopeName, definition, + (isController ? "controller bindings definition" : + "isolate scope definition")); + } + + bindings[scopeName] = { + mode: match[1][0], + collection: match[2] === '*', + optional: match[3] === '?', + attrName: match[4] || scopeName + }; + if (match[4]) { + bindingCache[definition] = bindings[scopeName]; + } + }); + + return bindings; + } + + function parseDirectiveBindings(directive, directiveName) { + var bindings = { + isolateScope: null, + bindToController: null + }; + if (isObject(directive.scope)) { + if (directive.bindToController === true) { + bindings.bindToController = parseIsolateBindings(directive.scope, + directiveName, true); + bindings.isolateScope = {}; + } else { + bindings.isolateScope = parseIsolateBindings(directive.scope, + directiveName, false); + } + } + if (isObject(directive.bindToController)) { + bindings.bindToController = + parseIsolateBindings(directive.bindToController, directiveName, true); + } + if (isObject(bindings.bindToController)) { + var controller = directive.controller; + var controllerAs = directive.controllerAs; + if (!controller) { + // There is no controller, there may or may not be a controllerAs property + throw $compileMinErr('noctrl', + "Cannot bind to controller without directive '{0}'s controller.", + directiveName); + } else if (!identifierForController(controller, controllerAs)) { + // There is a controller, but no identifier or controllerAs property + throw $compileMinErr('noident', + "Cannot bind to controller without identifier for directive '{0}'.", + directiveName); + } + } + return bindings; + } + + function assertValidDirectiveName(name) { + var letter = name.charAt(0); + if (!letter || letter !== lowercase(letter)) { + throw $compileMinErr('baddir', "Directive/Component name '{0}' is invalid. The first character must be a lowercase letter", name); + } + if (name !== name.trim()) { + throw $compileMinErr('baddir', + "Directive/Component name '{0}' is invalid. The name should not contain leading or trailing whitespaces", + name); + } + } + + function getDirectiveRequire(directive) { + var require = directive.require || (directive.controller && directive.name); + + if (!isArray(require) && isObject(require)) { + forEach(require, function(value, key) { + var match = value.match(REQUIRE_PREFIX_REGEXP); + var name = value.substring(match[0].length); + if (!name) require[key] = match[0] + key; + }); + } + + return require; + } + + /** + * @ngdoc method + * @name $compileProvider#directive + * @kind function + * + * @description + * Register a new directive with the compiler. + * + * @param {string|Object} name Name of the directive in camel-case (i.e. ngBind which + * will match as ng-bind), or an object map of directives where the keys are the + * names and the values are the factories. + * @param {Function|Array} directiveFactory An injectable directive factory function. See the + * {@link guide/directive directive guide} and the {@link $compile compile API} for more info. + * @returns {ng.$compileProvider} Self for chaining. + */ + this.directive = function registerDirective(name, directiveFactory) { + assertNotHasOwnProperty(name, 'directive'); + if (isString(name)) { + assertValidDirectiveName(name); + assertArg(directiveFactory, 'directiveFactory'); + if (!hasDirectives.hasOwnProperty(name)) { + hasDirectives[name] = []; + $provide.factory(name + Suffix, ['$injector', '$exceptionHandler', + function($injector, $exceptionHandler) { + var directives = []; + forEach(hasDirectives[name], function(directiveFactory, index) { + try { + var directive = $injector.invoke(directiveFactory); + if (isFunction(directive)) { + directive = { compile: valueFn(directive) }; + } else if (!directive.compile && directive.link) { + directive.compile = valueFn(directive.link); + } + directive.priority = directive.priority || 0; + directive.index = index; + directive.name = directive.name || name; + directive.require = getDirectiveRequire(directive); + directive.restrict = directive.restrict || 'EA'; + directive.$$moduleName = directiveFactory.$$moduleName; + directives.push(directive); + } catch (e) { + $exceptionHandler(e); + } + }); + return directives; + }]); + } + hasDirectives[name].push(directiveFactory); + } else { + forEach(name, reverseParams(registerDirective)); + } + return this; + }; + + /** + * @ngdoc method + * @name $compileProvider#component + * @module ng + * @param {string} name Name of the component in camelCase (i.e. `myComp` which will match ``) + * @param {Object} options Component definition object (a simplified + * {@link ng.$compile#directive-definition-object directive definition object}), + * with the following properties (all optional): + * + * - `controller` – `{(string|function()=}` – controller constructor function that should be + * associated with newly created scope or the name of a {@link ng.$compile#-controller- + * registered controller} if passed as a string. An empty `noop` function by default. + * - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope. + * If present, the controller will be published to scope under the `controllerAs` name. + * If not present, this will default to be `$ctrl`. + * - `template` – `{string=|function()=}` – html template as a string or a function that + * returns an html template as a string which should be used as the contents of this component. + * Empty string by default. + * + * If `template` is a function, then it is {@link auto.$injector#invoke injected} with + * the following locals: + * + * - `$element` - Current element + * - `$attrs` - Current attributes object for the element + * + * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html + * template that should be used as the contents of this component. + * + * If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with + * the following locals: + * + * - `$element` - Current element + * - `$attrs` - Current attributes object for the element + * + * - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties. + * Component properties are always bound to the component controller and not to the scope. + * See {@link ng.$compile#-bindtocontroller- `bindToController`}. + * - `transclude` – `{boolean=}` – whether {@link $compile#transclusion content transclusion} is enabled. + * Disabled by default. + * - `require` - `{Object=}` - requires the controllers of other directives and binds them to + * this component's controller. The object keys specify the property names under which the required + * controllers (object values) will be bound. See {@link ng.$compile#-require- `require`}. + * - `$...` – additional properties to attach to the directive factory function and the controller + * constructor function. (This is used by the component router to annotate) + * + * @returns {ng.$compileProvider} the compile provider itself, for chaining of function calls. + * @description + * Register a **component definition** with the compiler. This is a shorthand for registering a special + * type of directive, which represents a self-contained UI component in your application. Such components + * are always isolated (i.e. `scope: {}`) and are always restricted to elements (i.e. `restrict: 'E'`). + * + * Component definitions are very simple and do not require as much configuration as defining general + * directives. Component definitions usually consist only of a template and a controller backing it. + * + * In order to make the definition easier, components enforce best practices like use of `controllerAs`, + * `bindToController`. They always have **isolate scope** and are restricted to elements. + * + * Here are a few examples of how you would usually define components: + * + * ```js + * var myMod = angular.module(...); + * myMod.component('myComp', { + * template: '
    My name is {{$ctrl.name}}
    ', + * controller: function() { + * this.name = 'shahar'; + * } + * }); + * + * myMod.component('myComp', { + * template: '
    My name is {{$ctrl.name}}
    ', + * bindings: {name: '@'} + * }); + * + * myMod.component('myComp', { + * templateUrl: 'views/my-comp.html', + * controller: 'MyCtrl', + * controllerAs: 'ctrl', + * bindings: {name: '@'} + * }); + * + * ``` + * For more examples, and an in-depth guide, see the {@link guide/component component guide}. + * + *
    + * See also {@link ng.$compileProvider#directive $compileProvider.directive()}. + */ + this.component = function registerComponent(name, options) { + var controller = options.controller || function() {}; + + function factory($injector) { + function makeInjectable(fn) { + if (isFunction(fn) || isArray(fn)) { + return function(tElement, tAttrs) { + return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs}); + }; + } else { + return fn; + } + } + + var template = (!options.template && !options.templateUrl ? '' : options.template); + var ddo = { + controller: controller, + controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl', + template: makeInjectable(template), + templateUrl: makeInjectable(options.templateUrl), + transclude: options.transclude, + scope: {}, + bindToController: options.bindings || {}, + restrict: 'E', + require: options.require + }; + + // Copy annotations (starting with $) over to the DDO + forEach(options, function(val, key) { + if (key.charAt(0) === '$') ddo[key] = val; + }); + + return ddo; + } + + // TODO(pete) remove the following `forEach` before we release 1.6.0 + // The component-router@0.2.0 looks for the annotations on the controller constructor + // Nothing in Angular looks for annotations on the factory function but we can't remove + // it from 1.5.x yet. + + // Copy any annotation properties (starting with $) over to the factory and controller constructor functions + // These could be used by libraries such as the new component router + forEach(options, function(val, key) { + if (key.charAt(0) === '$') { + factory[key] = val; + // Don't try to copy over annotations to named controller + if (isFunction(controller)) controller[key] = val; + } + }); + + factory.$inject = ['$injector']; + + return this.directive(name, factory); + }; + + + /** + * @ngdoc method + * @name $compileProvider#aHrefSanitizationWhitelist + * @kind function + * + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during a[href] sanitization. + * + * The sanitization is a security measure aimed at preventing XSS attacks via html links. + * + * Any url about to be assigned to a[href] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.aHrefSanitizationWhitelist(); + } + }; + + + /** + * @ngdoc method + * @name $compileProvider#imgSrcSanitizationWhitelist + * @kind function + * + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during img[src] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to img[src] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.imgSrcSanitizationWhitelist(); + } + }; + + /** + * @ngdoc method + * @name $compileProvider#debugInfoEnabled + * + * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the + * current debugInfoEnabled state + * @returns {*} current value if used as getter or itself (chaining) if used as setter + * + * @kind function + * + * @description + * Call this method to enable/disable various debug runtime information in the compiler such as adding + * binding information and a reference to the current scope on to DOM elements. + * If enabled, the compiler will add the following to DOM elements that have been bound to the scope + * * `ng-binding` CSS class + * * `$binding` data property containing an array of the binding expressions + * + * You may want to disable this in production for a significant performance boost. See + * {@link guide/production#disabling-debug-data Disabling Debug Data} for more. + * + * The default value is true. + */ + var debugInfoEnabled = true; + this.debugInfoEnabled = function(enabled) { + if (isDefined(enabled)) { + debugInfoEnabled = enabled; + return this; + } + return debugInfoEnabled; + }; + + + var TTL = 10; + /** + * @ngdoc method + * @name $compileProvider#onChangesTtl + * @description + * + * Sets the number of times `$onChanges` hooks can trigger new changes before giving up and + * assuming that the model is unstable. + * + * The current default is 10 iterations. + * + * In complex applications it's possible that dependencies between `$onChanges` hooks and bindings will result + * in several iterations of calls to these hooks. However if an application needs more than the default 10 + * iterations to stabilize then you should investigate what is causing the model to continuously change during + * the `$onChanges` hook execution. + * + * Increasing the TTL could have performance implications, so you should not change it without proper justification. + * + * @param {number} limit The number of `$onChanges` hook iterations. + * @returns {number|object} the current limit (or `this` if called as a setter for chaining) + */ + this.onChangesTtl = function(value) { + if (arguments.length) { + TTL = value; + return this; + } + return TTL; + }; + + this.$get = [ + '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', + '$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri', + function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, + $controller, $rootScope, $sce, $animate, $$sanitizeUri) { + + var SIMPLE_ATTR_NAME = /^\w/; + var specialAttrHolder = window.document.createElement('div'); + + + + var onChangesTtl = TTL; + // The onChanges hooks should all be run together in a single digest + // When changes occur, the call to trigger their hooks will be added to this queue + var onChangesQueue; + + // This function is called in a $$postDigest to trigger all the onChanges hooks in a single digest + function flushOnChangesQueue() { + try { + if (!(--onChangesTtl)) { + // We have hit the TTL limit so reset everything + onChangesQueue = undefined; + throw $compileMinErr('infchng', '{0} $onChanges() iterations reached. Aborting!\n', TTL); + } + // We must run this hook in an apply since the $$postDigest runs outside apply + $rootScope.$apply(function() { + var errors = []; + for (var i = 0, ii = onChangesQueue.length; i < ii; ++i) { + try { + onChangesQueue[i](); + } catch (e) { + errors.push(e); + } + } + // Reset the queue to trigger a new schedule next time there is a change + onChangesQueue = undefined; + if (errors.length) { + throw errors; + } + }); + } finally { + onChangesTtl++; + } + } + + + function Attributes(element, attributesToCopy) { + if (attributesToCopy) { + var keys = Object.keys(attributesToCopy); + var i, l, key; + + for (i = 0, l = keys.length; i < l; i++) { + key = keys[i]; + this[key] = attributesToCopy[key]; + } + } else { + this.$attr = {}; + } + + this.$$element = element; + } + + Attributes.prototype = { + /** + * @ngdoc method + * @name $compile.directive.Attributes#$normalize + * @kind function + * + * @description + * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or + * `data-`) to its normalized, camelCase form. + * + * Also there is special case for Moz prefix starting with upper case letter. + * + * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives} + * + * @param {string} name Name to normalize + */ + $normalize: directiveNormalize, + + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$addClass + * @kind function + * + * @description + * Adds the CSS class value specified by the classVal parameter to the element. If animations + * are enabled then an animation will be triggered for the class addition. + * + * @param {string} classVal The className value that will be added to the element + */ + $addClass: function(classVal) { + if (classVal && classVal.length > 0) { + $animate.addClass(this.$$element, classVal); + } + }, + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$removeClass + * @kind function + * + * @description + * Removes the CSS class value specified by the classVal parameter from the element. If + * animations are enabled then an animation will be triggered for the class removal. + * + * @param {string} classVal The className value that will be removed from the element + */ + $removeClass: function(classVal) { + if (classVal && classVal.length > 0) { + $animate.removeClass(this.$$element, classVal); + } + }, + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$updateClass + * @kind function + * + * @description + * Adds and removes the appropriate CSS class values to the element based on the difference + * between the new and old CSS class values (specified as newClasses and oldClasses). + * + * @param {string} newClasses The current CSS className value + * @param {string} oldClasses The former CSS className value + */ + $updateClass: function(newClasses, oldClasses) { + var toAdd = tokenDifference(newClasses, oldClasses); + if (toAdd && toAdd.length) { + $animate.addClass(this.$$element, toAdd); + } + + var toRemove = tokenDifference(oldClasses, newClasses); + if (toRemove && toRemove.length) { + $animate.removeClass(this.$$element, toRemove); + } + }, + + /** + * Set a normalized attribute on the element in a way such that all directives + * can share the attribute. This function properly handles boolean attributes. + * @param {string} key Normalized key. (ie ngAttribute) + * @param {string|boolean} value The value to set. If `null` attribute will be deleted. + * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute. + * Defaults to true. + * @param {string=} attrName Optional none normalized name. Defaults to key. + */ + $set: function(key, value, writeAttr, attrName) { + // TODO: decide whether or not to throw an error if "class" + //is set through this function since it may cause $updateClass to + //become unstable. + + var node = this.$$element[0], + booleanKey = getBooleanAttrName(node, key), + aliasedKey = getAliasedAttrName(key), + observer = key, + nodeName; + + if (booleanKey) { + this.$$element.prop(key, value); + attrName = booleanKey; + } else if (aliasedKey) { + this[aliasedKey] = value; + observer = aliasedKey; + } + + this[key] = value; + + // translate normalized key to actual key + if (attrName) { + this.$attr[key] = attrName; + } else { + attrName = this.$attr[key]; + if (!attrName) { + this.$attr[key] = attrName = snake_case(key, '-'); + } + } + + nodeName = nodeName_(this.$$element); + + if ((nodeName === 'a' && (key === 'href' || key === 'xlinkHref')) || + (nodeName === 'img' && key === 'src')) { + // sanitize a[href] and img[src] values + this[key] = value = $$sanitizeUri(value, key === 'src'); + } else if (nodeName === 'img' && key === 'srcset' && isDefined(value)) { + // sanitize img[srcset] values + var result = ""; + + // first check if there are spaces because it's not the same pattern + var trimmedSrcset = trim(value); + // ( 999x ,| 999w ,| ,|, ) + var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/; + var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/; + + // split srcset into tuple of uri and descriptor except for the last item + var rawUris = trimmedSrcset.split(pattern); + + // for each tuples + var nbrUrisWith2parts = Math.floor(rawUris.length / 2); + for (var i = 0; i < nbrUrisWith2parts; i++) { + var innerIdx = i * 2; + // sanitize the uri + result += $$sanitizeUri(trim(rawUris[innerIdx]), true); + // add the descriptor + result += (" " + trim(rawUris[innerIdx + 1])); + } + + // split the last item into uri and descriptor + var lastTuple = trim(rawUris[i * 2]).split(/\s/); + + // sanitize the last uri + result += $$sanitizeUri(trim(lastTuple[0]), true); + + // and add the last descriptor if any + if (lastTuple.length === 2) { + result += (" " + trim(lastTuple[1])); + } + this[key] = value = result; + } + + if (writeAttr !== false) { + if (value === null || isUndefined(value)) { + this.$$element.removeAttr(attrName); + } else { + if (SIMPLE_ATTR_NAME.test(attrName)) { + this.$$element.attr(attrName, value); + } else { + setSpecialAttr(this.$$element[0], attrName, value); + } + } + } + + // fire observers + var $$observers = this.$$observers; + $$observers && forEach($$observers[observer], function(fn) { + try { + fn(value); + } catch (e) { + $exceptionHandler(e); + } + }); + }, + + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$observe + * @kind function + * + * @description + * Observes an interpolated attribute. + * + * The observer function will be invoked once during the next `$digest` following + * compilation. The observer is then invoked whenever the interpolated value + * changes. + * + * @param {string} key Normalized key. (ie ngAttribute) . + * @param {function(interpolatedValue)} fn Function that will be called whenever + the interpolated value of the attribute changes. + * See the {@link guide/interpolation#how-text-and-attribute-bindings-work Interpolation + * guide} for more info. + * @returns {function()} Returns a deregistration function for this observer. + */ + $observe: function(key, fn) { + var attrs = this, + $$observers = (attrs.$$observers || (attrs.$$observers = createMap())), + listeners = ($$observers[key] || ($$observers[key] = [])); + + listeners.push(fn); + $rootScope.$evalAsync(function() { + if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) { + // no one registered attribute interpolation function, so lets call it manually + fn(attrs[key]); + } + }); + + return function() { + arrayRemove(listeners, fn); + }; + } + }; + + function setSpecialAttr(element, attrName, value) { + // Attributes names that do not start with letters (such as `(click)`) cannot be set using `setAttribute` + // so we have to jump through some hoops to get such an attribute + // https://github.com/angular/angular.js/pull/13318 + specialAttrHolder.innerHTML = ""; + var attributes = specialAttrHolder.firstChild.attributes; + var attribute = attributes[0]; + // We have to remove the attribute from its container element before we can add it to the destination element + attributes.removeNamedItem(attribute.name); + attribute.value = value; + element.attributes.setNamedItem(attribute); + } + + function safeAddClass($element, className) { + try { + $element.addClass(className); + } catch (e) { + // ignore, since it means that we are trying to set class on + // SVG element, where class name is read-only. + } + } + + + var startSymbol = $interpolate.startSymbol(), + endSymbol = $interpolate.endSymbol(), + denormalizeTemplate = (startSymbol == '{{' && endSymbol == '}}') + ? identity + : function denormalizeTemplate(template) { + return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); + }, + NG_ATTR_BINDING = /^ngAttr[A-Z]/; + var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/; + + compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) { + var bindings = $element.data('$binding') || []; + + if (isArray(binding)) { + bindings = bindings.concat(binding); + } else { + bindings.push(binding); + } + + $element.data('$binding', bindings); + } : noop; + + compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) { + safeAddClass($element, 'ng-binding'); + } : noop; + + compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) { + var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope'; + $element.data(dataName, scope); + } : noop; + + compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) { + safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope'); + } : noop; + + compile.$$createComment = function(directiveName, comment) { + var content = ''; + if (debugInfoEnabled) { + content = ' ' + (directiveName || '') + ': '; + if (comment) content += comment + ' '; + } + return window.document.createComment(content); + }; + + return compile; + + //================================ + + function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, + previousCompileContext) { + if (!($compileNodes instanceof jqLite)) { + // jquery always rewraps, whereas we need to preserve the original selector so that we can + // modify it. + $compileNodes = jqLite($compileNodes); + } + + var NOT_EMPTY = /\S+/; + + // We can not compile top level text elements since text nodes can be merged and we will + // not be able to attach scope data to them, so we will wrap them in + for (var i = 0, len = $compileNodes.length; i < len; i++) { + var domNode = $compileNodes[i]; + + if (domNode.nodeType === NODE_TYPE_TEXT && domNode.nodeValue.match(NOT_EMPTY) /* non-empty */) { + jqLiteWrapNode(domNode, $compileNodes[i] = window.document.createElement('span')); + } + } + + var compositeLinkFn = + compileNodes($compileNodes, transcludeFn, $compileNodes, + maxPriority, ignoreDirective, previousCompileContext); + compile.$$addScopeClass($compileNodes); + var namespace = null; + return function publicLinkFn(scope, cloneConnectFn, options) { + assertArg(scope, 'scope'); + + if (previousCompileContext && previousCompileContext.needsNewScope) { + // A parent directive did a replace and a directive on this element asked + // for transclusion, which caused us to lose a layer of element on which + // we could hold the new transclusion scope, so we will create it manually + // here. + scope = scope.$parent.$new(); + } + + options = options || {}; + var parentBoundTranscludeFn = options.parentBoundTranscludeFn, + transcludeControllers = options.transcludeControllers, + futureParentElement = options.futureParentElement; + + // When `parentBoundTranscludeFn` is passed, it is a + // `controllersBoundTransclude` function (it was previously passed + // as `transclude` to directive.link) so we must unwrap it to get + // its `boundTranscludeFn` + if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) { + parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude; + } + + if (!namespace) { + namespace = detectNamespaceForChildElements(futureParentElement); + } + var $linkNode; + if (namespace !== 'html') { + // When using a directive with replace:true and templateUrl the $compileNodes + // (or a child element inside of them) + // might change, so we need to recreate the namespace adapted compileNodes + // for call to the link function. + // Note: This will already clone the nodes... + $linkNode = jqLite( + wrapTemplate(namespace, jqLite('
    ').append($compileNodes).html()) + ); + } else if (cloneConnectFn) { + // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart + // and sometimes changes the structure of the DOM. + $linkNode = JQLitePrototype.clone.call($compileNodes); + } else { + $linkNode = $compileNodes; + } + + if (transcludeControllers) { + for (var controllerName in transcludeControllers) { + $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance); + } + } + + compile.$$addScopeInfo($linkNode, scope); + + if (cloneConnectFn) cloneConnectFn($linkNode, scope); + if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn); + return $linkNode; + }; + } + + function detectNamespaceForChildElements(parentElement) { + // TODO: Make this detect MathML as well... + var node = parentElement && parentElement[0]; + if (!node) { + return 'html'; + } else { + return nodeName_(node) !== 'foreignobject' && toString.call(node).match(/SVG/) ? 'svg' : 'html'; + } + } + + /** + * Compile function matches each node in nodeList against the directives. Once all directives + * for a particular node are collected their compile functions are executed. The compile + * functions return values - the linking functions - are combined into a composite linking + * function, which is the a linking function for the node. + * + * @param {NodeList} nodeList an array of nodes or NodeList to compile + * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the + * scope argument is auto-generated to the new child of the transcluded parent scope. + * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then + * the rootElement must be set the jqLite collection of the compile root. This is + * needed so that the jqLite collection items can be replaced with widgets. + * @param {number=} maxPriority Max directive priority. + * @returns {Function} A composite linking function of all of the matched directives or null. + */ + function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective, + previousCompileContext) { + var linkFns = [], + attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound; + + for (var i = 0; i < nodeList.length; i++) { + attrs = new Attributes(); + + // we must always refer to nodeList[i] since the nodes can be replaced underneath us. + directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined, + ignoreDirective); + + nodeLinkFn = (directives.length) + ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, + null, [], [], previousCompileContext) + : null; + + if (nodeLinkFn && nodeLinkFn.scope) { + compile.$$addScopeClass(attrs.$$element); + } + + childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || + !(childNodes = nodeList[i].childNodes) || + !childNodes.length) + ? null + : compileNodes(childNodes, + nodeLinkFn ? ( + (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement) + && nodeLinkFn.transclude) : transcludeFn); + + if (nodeLinkFn || childLinkFn) { + linkFns.push(i, nodeLinkFn, childLinkFn); + linkFnFound = true; + nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn; + } + + //use the previous context only for the first element in the virtual group + previousCompileContext = null; + } + + // return a linking function if we have found anything, null otherwise + return linkFnFound ? compositeLinkFn : null; + + function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) { + var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn; + var stableNodeList; + + + if (nodeLinkFnFound) { + // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our + // offsets don't get screwed up + var nodeListLength = nodeList.length; + stableNodeList = new Array(nodeListLength); + + // create a sparse array by only copying the elements which have a linkFn + for (i = 0; i < linkFns.length; i+=3) { + idx = linkFns[i]; + stableNodeList[idx] = nodeList[idx]; + } + } else { + stableNodeList = nodeList; + } + + for (i = 0, ii = linkFns.length; i < ii;) { + node = stableNodeList[linkFns[i++]]; + nodeLinkFn = linkFns[i++]; + childLinkFn = linkFns[i++]; + + if (nodeLinkFn) { + if (nodeLinkFn.scope) { + childScope = scope.$new(); + compile.$$addScopeInfo(jqLite(node), childScope); + } else { + childScope = scope; + } + + if (nodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn( + scope, nodeLinkFn.transclude, parentBoundTranscludeFn); + + } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) { + childBoundTranscludeFn = parentBoundTranscludeFn; + + } else if (!parentBoundTranscludeFn && transcludeFn) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn); + + } else { + childBoundTranscludeFn = null; + } + + nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn); + + } else if (childLinkFn) { + childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn); + } + } + } + } + + function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) { + function boundTranscludeFn(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { + + if (!transcludedScope) { + transcludedScope = scope.$new(false, containingScope); + transcludedScope.$$transcluded = true; + } + + return transcludeFn(transcludedScope, cloneFn, { + parentBoundTranscludeFn: previousBoundTranscludeFn, + transcludeControllers: controllers, + futureParentElement: futureParentElement + }); + } + + // We need to attach the transclusion slots onto the `boundTranscludeFn` + // so that they are available inside the `controllersBoundTransclude` function + var boundSlots = boundTranscludeFn.$$slots = createMap(); + for (var slotName in transcludeFn.$$slots) { + if (transcludeFn.$$slots[slotName]) { + boundSlots[slotName] = createBoundTranscludeFn(scope, transcludeFn.$$slots[slotName], previousBoundTranscludeFn); + } else { + boundSlots[slotName] = null; + } + } + + return boundTranscludeFn; + } + + /** + * Looks for directives on the given node and adds them to the directive collection which is + * sorted. + * + * @param node Node to search. + * @param directives An array to which the directives are added to. This array is sorted before + * the function returns. + * @param attrs The shared attrs object which is used to populate the normalized attributes. + * @param {number=} maxPriority Max directive priority. + */ + function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) { + var nodeType = node.nodeType, + attrsMap = attrs.$attr, + match, + className; + + switch (nodeType) { + case NODE_TYPE_ELEMENT: /* Element */ + // use the node name: + addDirective(directives, + directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective); + + // iterate over the attributes + for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes, + j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { + var attrStartName = false; + var attrEndName = false; + + attr = nAttrs[j]; + name = attr.name; + value = trim(attr.value); + + // support ngAttr attribute binding + ngAttrName = directiveNormalize(name); + if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) { + name = name.replace(PREFIX_REGEXP, '') + .substr(8).replace(/_(.)/g, function(match, letter) { + return letter.toUpperCase(); + }); + } + + var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE); + if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) { + attrStartName = name; + attrEndName = name.substr(0, name.length - 5) + 'end'; + name = name.substr(0, name.length - 6); + } + + nName = directiveNormalize(name.toLowerCase()); + attrsMap[nName] = name; + if (isNgAttr || !attrs.hasOwnProperty(nName)) { + attrs[nName] = value; + if (getBooleanAttrName(node, nName)) { + attrs[nName] = true; // presence means true + } + } + addAttrInterpolateDirective(node, directives, value, nName, isNgAttr); + addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, + attrEndName); + } + + // use class as directive + className = node.className; + if (isObject(className)) { + // Maybe SVGAnimatedString + className = className.animVal; + } + if (isString(className) && className !== '') { + while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { + nName = directiveNormalize(match[2]); + if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[3]); + } + className = className.substr(match.index + match[0].length); + } + } + break; + case NODE_TYPE_TEXT: /* Text Node */ + if (msie === 11) { + // Workaround for #11781 + while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) { + node.nodeValue = node.nodeValue + node.nextSibling.nodeValue; + node.parentNode.removeChild(node.nextSibling); + } + } + addTextInterpolateDirective(directives, node.nodeValue); + break; + case NODE_TYPE_COMMENT: /* Comment */ + collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective); + break; + } + + directives.sort(byPriority); + return directives; + } + + function collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective) { + // function created because of performance, try/catch disables + // the optimization of the whole function #14848 + try { + var match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); + if (match) { + var nName = directiveNormalize(match[1]); + if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[2]); + } + } + } catch (e) { + // turns out that under some circumstances IE9 throws errors when one attempts to read + // comment's node value. + // Just ignore it and continue. (Can't seem to reproduce in test case.) + } + } + + /** + * Given a node with an directive-start it collects all of the siblings until it finds + * directive-end. + * @param node + * @param attrStart + * @param attrEnd + * @returns {*} + */ + function groupScan(node, attrStart, attrEnd) { + var nodes = []; + var depth = 0; + if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) { + do { + if (!node) { + throw $compileMinErr('uterdir', + "Unterminated attribute, found '{0}' but no matching '{1}' found.", + attrStart, attrEnd); + } + if (node.nodeType == NODE_TYPE_ELEMENT) { + if (node.hasAttribute(attrStart)) depth++; + if (node.hasAttribute(attrEnd)) depth--; + } + nodes.push(node); + node = node.nextSibling; + } while (depth > 0); + } else { + nodes.push(node); + } + + return jqLite(nodes); + } + + /** + * Wrapper for linking function which converts normal linking function into a grouped + * linking function. + * @param linkFn + * @param attrStart + * @param attrEnd + * @returns {Function} + */ + function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { + return function groupedElementsLink(scope, element, attrs, controllers, transcludeFn) { + element = groupScan(element[0], attrStart, attrEnd); + return linkFn(scope, element, attrs, controllers, transcludeFn); + }; + } + + /** + * A function generator that is used to support both eager and lazy compilation + * linking function. + * @param eager + * @param $compileNodes + * @param transcludeFn + * @param maxPriority + * @param ignoreDirective + * @param previousCompileContext + * @returns {Function} + */ + function compilationGenerator(eager, $compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) { + var compiled; + + if (eager) { + return compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext); + } + return function lazyCompilation() { + if (!compiled) { + compiled = compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext); + + // Null out all of these references in order to make them eligible for garbage collection + // since this is a potentially long lived closure + $compileNodes = transcludeFn = previousCompileContext = null; + } + return compiled.apply(this, arguments); + }; + } + + /** + * Once the directives have been collected, their compile functions are executed. This method + * is responsible for inlining directive templates as well as terminating the application + * of the directives if the terminal directive has been reached. + * + * @param {Array} directives Array of collected directives to execute their compile function. + * this needs to be pre-sorted by priority order. + * @param {Node} compileNode The raw DOM node to apply the compile functions to + * @param {Object} templateAttrs The shared attribute function + * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the + * scope argument is auto-generated to the new + * child of the transcluded parent scope. + * @param {JQLite} jqCollection If we are working on the root of the compile tree then this + * argument has the root jqLite array so that we can replace nodes + * on it. + * @param {Object=} originalReplaceDirective An optional directive that will be ignored when + * compiling the transclusion. + * @param {Array.} preLinkFns + * @param {Array.} postLinkFns + * @param {Object} previousCompileContext Context used for previous compilation of the current + * node + * @returns {Function} linkFn + */ + function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, + jqCollection, originalReplaceDirective, preLinkFns, postLinkFns, + previousCompileContext) { + previousCompileContext = previousCompileContext || {}; + + var terminalPriority = -Number.MAX_VALUE, + newScopeDirective = previousCompileContext.newScopeDirective, + controllerDirectives = previousCompileContext.controllerDirectives, + newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, + templateDirective = previousCompileContext.templateDirective, + nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, + hasTranscludeDirective = false, + hasTemplate = false, + hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective, + $compileNode = templateAttrs.$$element = jqLite(compileNode), + directive, + directiveName, + $template, + replaceDirective = originalReplaceDirective, + childTranscludeFn = transcludeFn, + linkFn, + didScanForMultipleTransclusion = false, + mightHaveMultipleTransclusionError = false, + directiveValue; + + // executes all directives on the current element + for (var i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + var attrStart = directive.$$start; + var attrEnd = directive.$$end; + + // collect multiblock sections + if (attrStart) { + $compileNode = groupScan(compileNode, attrStart, attrEnd); + } + $template = undefined; + + if (terminalPriority > directive.priority) { + break; // prevent further processing of directives + } + + if (directiveValue = directive.scope) { + + // skip the check for directives with async templates, we'll check the derived sync + // directive when the template arrives + if (!directive.templateUrl) { + if (isObject(directiveValue)) { + // This directive is trying to add an isolated scope. + // Check that there is no scope of any kind already + assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective, + directive, $compileNode); + newIsolateScopeDirective = directive; + } else { + // This directive is trying to add a child scope. + // Check that there is no isolated scope already + assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive, + $compileNode); + } + } + + newScopeDirective = newScopeDirective || directive; + } + + directiveName = directive.name; + + // If we encounter a condition that can result in transclusion on the directive, + // then scan ahead in the remaining directives for others that may cause a multiple + // transclusion error to be thrown during the compilation process. If a matching directive + // is found, then we know that when we encounter a transcluded directive, we need to eagerly + // compile the `transclude` function rather than doing it lazily in order to throw + // exceptions at the correct time + if (!didScanForMultipleTransclusion && ((directive.replace && (directive.templateUrl || directive.template)) + || (directive.transclude && !directive.$$tlb))) { + var candidateDirective; + + for (var scanningIndex = i + 1; candidateDirective = directives[scanningIndex++];) { + if ((candidateDirective.transclude && !candidateDirective.$$tlb) + || (candidateDirective.replace && (candidateDirective.templateUrl || candidateDirective.template))) { + mightHaveMultipleTransclusionError = true; + break; + } + } + + didScanForMultipleTransclusion = true; + } + + if (!directive.templateUrl && directive.controller) { + directiveValue = directive.controller; + controllerDirectives = controllerDirectives || createMap(); + assertNoDuplicate("'" + directiveName + "' controller", + controllerDirectives[directiveName], directive, $compileNode); + controllerDirectives[directiveName] = directive; + } + + if (directiveValue = directive.transclude) { + hasTranscludeDirective = true; + + // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion. + // This option should only be used by directives that know how to safely handle element transclusion, + // where the transcluded nodes are added or replaced after linking. + if (!directive.$$tlb) { + assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode); + nonTlbTranscludeDirective = directive; + } + + if (directiveValue == 'element') { + hasElementTranscludeDirective = true; + terminalPriority = directive.priority; + $template = $compileNode; + $compileNode = templateAttrs.$$element = + jqLite(compile.$$createComment(directiveName, templateAttrs[directiveName])); + compileNode = $compileNode[0]; + replaceWith(jqCollection, sliceArgs($template), compileNode); + + // Support: Chrome < 50 + // https://github.com/angular/angular.js/issues/14041 + + // In the versions of V8 prior to Chrome 50, the document fragment that is created + // in the `replaceWith` function is improperly garbage collected despite still + // being referenced by the `parentNode` property of all of the child nodes. By adding + // a reference to the fragment via a different property, we can avoid that incorrect + // behavior. + // TODO: remove this line after Chrome 50 has been released + $template[0].$$parentNode = $template[0].parentNode; + + childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority, + replaceDirective && replaceDirective.name, { + // Don't pass in: + // - controllerDirectives - otherwise we'll create duplicates controllers + // - newIsolateScopeDirective or templateDirective - combining templates with + // element transclusion doesn't make sense. + // + // We need only nonTlbTranscludeDirective so that we prevent putting transclusion + // on the same element more than once. + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + } else { + + var slots = createMap(); + + $template = jqLite(jqLiteClone(compileNode)).contents(); + + if (isObject(directiveValue)) { + + // We have transclusion slots, + // collect them up, compile them and store their transclusion functions + $template = []; + + var slotMap = createMap(); + var filledSlots = createMap(); + + // Parse the element selectors + forEach(directiveValue, function(elementSelector, slotName) { + // If an element selector starts with a ? then it is optional + var optional = (elementSelector.charAt(0) === '?'); + elementSelector = optional ? elementSelector.substring(1) : elementSelector; + + slotMap[elementSelector] = slotName; + + // We explicitly assign `null` since this implies that a slot was defined but not filled. + // Later when calling boundTransclusion functions with a slot name we only error if the + // slot is `undefined` + slots[slotName] = null; + + // filledSlots contains `true` for all slots that are either optional or have been + // filled. This is used to check that we have not missed any required slots + filledSlots[slotName] = optional; + }); + + // Add the matching elements into their slot + forEach($compileNode.contents(), function(node) { + var slotName = slotMap[directiveNormalize(nodeName_(node))]; + if (slotName) { + filledSlots[slotName] = true; + slots[slotName] = slots[slotName] || []; + slots[slotName].push(node); + } else { + $template.push(node); + } + }); + + // Check for required slots that were not filled + forEach(filledSlots, function(filled, slotName) { + if (!filled) { + throw $compileMinErr('reqslot', 'Required transclusion slot `{0}` was not filled.', slotName); + } + }); + + for (var slotName in slots) { + if (slots[slotName]) { + // Only define a transclusion function if the slot was filled + slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slots[slotName], transcludeFn); + } + } + } + + $compileNode.empty(); // clear contents + childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, undefined, + undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope}); + childTranscludeFn.$$slots = slots; + } + } + + if (directive.template) { + hasTemplate = true; + assertNoDuplicate('template', templateDirective, directive, $compileNode); + templateDirective = directive; + + directiveValue = (isFunction(directive.template)) + ? directive.template($compileNode, templateAttrs) + : directive.template; + + directiveValue = denormalizeTemplate(directiveValue); + + if (directive.replace) { + replaceDirective = directive; + if (jqLiteIsTextNode(directiveValue)) { + $template = []; + } else { + $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue))); + } + compileNode = $template[0]; + + if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { + throw $compileMinErr('tplrt', + "Template for directive '{0}' must have exactly one root element. {1}", + directiveName, ''); + } + + replaceWith(jqCollection, $compileNode, compileNode); + + var newTemplateAttrs = {$attr: {}}; + + // combine directives from the original node and from the template: + // - take the array of directives for this element + // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed) + // - collect directives from the template and sort them by priority + // - combine directives as: processed + template + unprocessed + var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs); + var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); + + if (newIsolateScopeDirective || newScopeDirective) { + // The original directive caused the current element to be replaced but this element + // also needs to have a new scope, so we need to tell the template directives + // that they would need to get their scope from further up, if they require transclusion + markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective); + } + directives = directives.concat(templateDirectives).concat(unprocessedDirectives); + mergeTemplateAttributes(templateAttrs, newTemplateAttrs); + + ii = directives.length; + } else { + $compileNode.html(directiveValue); + } + } + + if (directive.templateUrl) { + hasTemplate = true; + assertNoDuplicate('template', templateDirective, directive, $compileNode); + templateDirective = directive; + + if (directive.replace) { + replaceDirective = directive; + } + + /* jshint -W021 */ + nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, + /* jshint +W021 */ + templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, { + controllerDirectives: controllerDirectives, + newScopeDirective: (newScopeDirective !== directive) && newScopeDirective, + newIsolateScopeDirective: newIsolateScopeDirective, + templateDirective: templateDirective, + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + ii = directives.length; + } else if (directive.compile) { + try { + linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); + var context = directive.$$originalDirective || directive; + if (isFunction(linkFn)) { + addLinkFns(null, bind(context, linkFn), attrStart, attrEnd); + } else if (linkFn) { + addLinkFns(bind(context, linkFn.pre), bind(context, linkFn.post), attrStart, attrEnd); + } + } catch (e) { + $exceptionHandler(e, startingTag($compileNode)); + } + } + + if (directive.terminal) { + nodeLinkFn.terminal = true; + terminalPriority = Math.max(terminalPriority, directive.priority); + } + + } + + nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; + nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective; + nodeLinkFn.templateOnThisElement = hasTemplate; + nodeLinkFn.transclude = childTranscludeFn; + + previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective; + + // might be normal or delayed nodeLinkFn depending on if templateUrl is present + return nodeLinkFn; + + //////////////////// + + function addLinkFns(pre, post, attrStart, attrEnd) { + if (pre) { + if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd); + pre.require = directive.require; + pre.directiveName = directiveName; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + pre = cloneAndAnnotateFn(pre, {isolateScope: true}); + } + preLinkFns.push(pre); + } + if (post) { + if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd); + post.require = directive.require; + post.directiveName = directiveName; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + post = cloneAndAnnotateFn(post, {isolateScope: true}); + } + postLinkFns.push(post); + } + } + + function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) { + var i, ii, linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element, + attrs, scopeBindingInfo; + + if (compileNode === linkNode) { + attrs = templateAttrs; + $element = templateAttrs.$$element; + } else { + $element = jqLite(linkNode); + attrs = new Attributes($element, templateAttrs); + } + + controllerScope = scope; + if (newIsolateScopeDirective) { + isolateScope = scope.$new(true); + } else if (newScopeDirective) { + controllerScope = scope.$parent; + } + + if (boundTranscludeFn) { + // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn` + // is later passed as `parentBoundTranscludeFn` to `publicLinkFn` + transcludeFn = controllersBoundTransclude; + transcludeFn.$$boundTransclude = boundTranscludeFn; + // expose the slots on the `$transclude` function + transcludeFn.isSlotFilled = function(slotName) { + return !!boundTranscludeFn.$$slots[slotName]; + }; + } + + if (controllerDirectives) { + elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective); + } + + if (newIsolateScopeDirective) { + // Initialize isolate scope bindings for new isolate scope directive. + compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || + templateDirective === newIsolateScopeDirective.$$originalDirective))); + compile.$$addScopeClass($element, true); + isolateScope.$$isolateBindings = + newIsolateScopeDirective.$$isolateBindings; + scopeBindingInfo = initializeDirectiveBindings(scope, attrs, isolateScope, + isolateScope.$$isolateBindings, + newIsolateScopeDirective); + if (scopeBindingInfo.removeWatches) { + isolateScope.$on('$destroy', scopeBindingInfo.removeWatches); + } + } + + // Initialize bindToController bindings + for (var name in elementControllers) { + var controllerDirective = controllerDirectives[name]; + var controller = elementControllers[name]; + var bindings = controllerDirective.$$bindings.bindToController; + + if (controller.identifier && bindings) { + controller.bindingInfo = + initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective); + } else { + controller.bindingInfo = {}; + } + + var controllerResult = controller(); + if (controllerResult !== controller.instance) { + // If the controller constructor has a return value, overwrite the instance + // from setupControllers + controller.instance = controllerResult; + $element.data('$' + controllerDirective.name + 'Controller', controllerResult); + controller.bindingInfo.removeWatches && controller.bindingInfo.removeWatches(); + controller.bindingInfo = + initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective); + } + } + + // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy + forEach(controllerDirectives, function(controllerDirective, name) { + var require = controllerDirective.require; + if (controllerDirective.bindToController && !isArray(require) && isObject(require)) { + extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers)); + } + }); + + // Handle the init and destroy lifecycle hooks on all controllers that have them + forEach(elementControllers, function(controller) { + var controllerInstance = controller.instance; + if (isFunction(controllerInstance.$onChanges)) { + try { + controllerInstance.$onChanges(controller.bindingInfo.initialChanges); + } catch (e) { + $exceptionHandler(e); + } + } + if (isFunction(controllerInstance.$onInit)) { + try { + controllerInstance.$onInit(); + } catch (e) { + $exceptionHandler(e); + } + } + if (isFunction(controllerInstance.$doCheck)) { + controllerScope.$watch(function() { controllerInstance.$doCheck(); }); + controllerInstance.$doCheck(); + } + if (isFunction(controllerInstance.$onDestroy)) { + controllerScope.$on('$destroy', function callOnDestroyHook() { + controllerInstance.$onDestroy(); + }); + } + }); + + // PRELINKING + for (i = 0, ii = preLinkFns.length; i < ii; i++) { + linkFn = preLinkFns[i]; + invokeLinkFn(linkFn, + linkFn.isolateScope ? isolateScope : scope, + $element, + attrs, + linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), + transcludeFn + ); + } + + // RECURSION + // We only pass the isolate scope, if the isolate directive has a template, + // otherwise the child elements do not belong to the isolate directive. + var scopeToChild = scope; + if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) { + scopeToChild = isolateScope; + } + childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn); + + // POSTLINKING + for (i = postLinkFns.length - 1; i >= 0; i--) { + linkFn = postLinkFns[i]; + invokeLinkFn(linkFn, + linkFn.isolateScope ? isolateScope : scope, + $element, + attrs, + linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), + transcludeFn + ); + } + + // Trigger $postLink lifecycle hooks + forEach(elementControllers, function(controller) { + var controllerInstance = controller.instance; + if (isFunction(controllerInstance.$postLink)) { + controllerInstance.$postLink(); + } + }); + + // This is the function that is injected as `$transclude`. + // Note: all arguments are optional! + function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) { + var transcludeControllers; + // No scope passed in: + if (!isScope(scope)) { + slotName = futureParentElement; + futureParentElement = cloneAttachFn; + cloneAttachFn = scope; + scope = undefined; + } + + if (hasElementTranscludeDirective) { + transcludeControllers = elementControllers; + } + if (!futureParentElement) { + futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element; + } + if (slotName) { + // slotTranscludeFn can be one of three things: + // * a transclude function - a filled slot + // * `null` - an optional slot that was not filled + // * `undefined` - a slot that was not declared (i.e. invalid) + var slotTranscludeFn = boundTranscludeFn.$$slots[slotName]; + if (slotTranscludeFn) { + return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); + } else if (isUndefined(slotTranscludeFn)) { + throw $compileMinErr('noslot', + 'No parent directive that requires a transclusion with slot name "{0}". ' + + 'Element: {1}', + slotName, startingTag($element)); + } + } else { + return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); + } + } + } + } + + function getControllers(directiveName, require, $element, elementControllers) { + var value; + + if (isString(require)) { + var match = require.match(REQUIRE_PREFIX_REGEXP); + var name = require.substring(match[0].length); + var inheritType = match[1] || match[3]; + var optional = match[2] === '?'; + + //If only parents then start at the parent element + if (inheritType === '^^') { + $element = $element.parent(); + //Otherwise attempt getting the controller from elementControllers in case + //the element is transcluded (and has no data) and to avoid .data if possible + } else { + value = elementControllers && elementControllers[name]; + value = value && value.instance; + } + + if (!value) { + var dataName = '$' + name + 'Controller'; + value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName); + } + + if (!value && !optional) { + throw $compileMinErr('ctreq', + "Controller '{0}', required by directive '{1}', can't be found!", + name, directiveName); + } + } else if (isArray(require)) { + value = []; + for (var i = 0, ii = require.length; i < ii; i++) { + value[i] = getControllers(directiveName, require[i], $element, elementControllers); + } + } else if (isObject(require)) { + value = {}; + forEach(require, function(controller, property) { + value[property] = getControllers(directiveName, controller, $element, elementControllers); + }); + } + + return value || null; + } + + function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective) { + var elementControllers = createMap(); + for (var controllerKey in controllerDirectives) { + var directive = controllerDirectives[controllerKey]; + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }; + + var controller = directive.controller; + if (controller == '@') { + controller = attrs[directive.name]; + } + + var controllerInstance = $controller(controller, locals, true, directive.controllerAs); + + // For directives with element transclusion the element is a comment. + // In this case .data will not attach any data. + // Instead, we save the controllers for the element in a local hash and attach to .data + // later, once we have the actual element. + elementControllers[directive.name] = controllerInstance; + $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + } + return elementControllers; + } + + // Depending upon the context in which a directive finds itself it might need to have a new isolated + // or child scope created. For instance: + // * if the directive has been pulled into a template because another directive with a higher priority + // asked for element transclusion + // * if the directive itself asks for transclusion but it is at the root of a template and the original + // element was replaced. See https://github.com/angular/angular.js/issues/12936 + function markDirectiveScope(directives, isolateScope, newScope) { + for (var j = 0, jj = directives.length; j < jj; j++) { + directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope}); + } + } + + /** + * looks up the directive and decorates it with exception handling and proper parameters. We + * call this the boundDirective. + * + * @param {string} name name of the directive to look up. + * @param {string} location The directive must be found in specific format. + * String containing any of theses characters: + * + * * `E`: element name + * * `A': attribute + * * `C`: class + * * `M`: comment + * @returns {boolean} true if directive was added. + */ + function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName, + endAttrName) { + if (name === ignoreDirective) return null; + var match = null; + if (hasDirectives.hasOwnProperty(name)) { + for (var directive, directives = $injector.get(name + Suffix), + i = 0, ii = directives.length; i < ii; i++) { + try { + directive = directives[i]; + if ((isUndefined(maxPriority) || maxPriority > directive.priority) && + directive.restrict.indexOf(location) != -1) { + if (startAttrName) { + directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName}); + } + if (!directive.$$bindings) { + var bindings = directive.$$bindings = + parseDirectiveBindings(directive, directive.name); + if (isObject(bindings.isolateScope)) { + directive.$$isolateBindings = bindings.isolateScope; + } + } + tDirectives.push(directive); + match = directive; + } + } catch (e) { $exceptionHandler(e); } + } + } + return match; + } + + + /** + * looks up the directive and returns true if it is a multi-element directive, + * and therefore requires DOM nodes between -start and -end markers to be grouped + * together. + * + * @param {string} name name of the directive to look up. + * @returns true if directive was registered as multi-element. + */ + function directiveIsMultiElement(name) { + if (hasDirectives.hasOwnProperty(name)) { + for (var directive, directives = $injector.get(name + Suffix), + i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + if (directive.multiElement) { + return true; + } + } + } + return false; + } + + /** + * When the element is replaced with HTML template then the new attributes + * on the template need to be merged with the existing attributes in the DOM. + * The desired effect is to have both of the attributes present. + * + * @param {object} dst destination attributes (original DOM) + * @param {object} src source attributes (from the directive template) + */ + function mergeTemplateAttributes(dst, src) { + var srcAttr = src.$attr, + dstAttr = dst.$attr, + $element = dst.$$element; + + // reapply the old attributes to the new element + forEach(dst, function(value, key) { + if (key.charAt(0) != '$') { + if (src[key] && src[key] !== value) { + value += (key === 'style' ? ';' : ' ') + src[key]; + } + dst.$set(key, value, true, srcAttr[key]); + } + }); + + // copy the new attributes on the old attrs object + forEach(src, function(value, key) { + // Check if we already set this attribute in the loop above. + // `dst` will never contain hasOwnProperty as DOM parser won't let it. + // You will get an "InvalidCharacterError: DOM Exception 5" error if you + // have an attribute like "has-own-property" or "data-has-own-property", etc. + if (!dst.hasOwnProperty(key) && key.charAt(0) !== '$') { + dst[key] = value; + + if (key !== 'class' && key !== 'style') { + dstAttr[key] = srcAttr[key]; + } + } + }); + } + + + function compileTemplateUrl(directives, $compileNode, tAttrs, + $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { + var linkQueue = [], + afterTemplateNodeLinkFn, + afterTemplateChildLinkFn, + beforeTemplateCompileNode = $compileNode[0], + origAsyncDirective = directives.shift(), + derivedSyncDirective = inherit(origAsyncDirective, { + templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective + }), + templateUrl = (isFunction(origAsyncDirective.templateUrl)) + ? origAsyncDirective.templateUrl($compileNode, tAttrs) + : origAsyncDirective.templateUrl, + templateNamespace = origAsyncDirective.templateNamespace; + + $compileNode.empty(); + + $templateRequest(templateUrl) + .then(function(content) { + var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; + + content = denormalizeTemplate(content); + + if (origAsyncDirective.replace) { + if (jqLiteIsTextNode(content)) { + $template = []; + } else { + $template = removeComments(wrapTemplate(templateNamespace, trim(content))); + } + compileNode = $template[0]; + + if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { + throw $compileMinErr('tplrt', + "Template for directive '{0}' must have exactly one root element. {1}", + origAsyncDirective.name, templateUrl); + } + + tempTemplateAttrs = {$attr: {}}; + replaceWith($rootElement, $compileNode, compileNode); + var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs); + + if (isObject(origAsyncDirective.scope)) { + // the original directive that caused the template to be loaded async required + // an isolate scope + markDirectiveScope(templateDirectives, true); + } + directives = templateDirectives.concat(directives); + mergeTemplateAttributes(tAttrs, tempTemplateAttrs); + } else { + compileNode = beforeTemplateCompileNode; + $compileNode.html(content); + } + + directives.unshift(derivedSyncDirective); + + afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, + childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns, + previousCompileContext); + forEach($rootElement, function(node, i) { + if (node == compileNode) { + $rootElement[i] = $compileNode[0]; + } + }); + afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); + + while (linkQueue.length) { + var scope = linkQueue.shift(), + beforeTemplateLinkNode = linkQueue.shift(), + linkRootElement = linkQueue.shift(), + boundTranscludeFn = linkQueue.shift(), + linkNode = $compileNode[0]; + + if (scope.$$destroyed) continue; + + if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { + var oldClasses = beforeTemplateLinkNode.className; + + if (!(previousCompileContext.hasElementTranscludeDirective && + origAsyncDirective.replace)) { + // it was cloned therefore we have to clone as well. + linkNode = jqLiteClone(compileNode); + } + replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); + + // Copy in CSS classes from original node + safeAddClass(jqLite(linkNode), oldClasses); + } + if (afterTemplateNodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); + } else { + childBoundTranscludeFn = boundTranscludeFn; + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, + childBoundTranscludeFn); + } + linkQueue = null; + }); + + return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) { + var childBoundTranscludeFn = boundTranscludeFn; + if (scope.$$destroyed) return; + if (linkQueue) { + linkQueue.push(scope, + node, + rootElement, + childBoundTranscludeFn); + } else { + if (afterTemplateNodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn); + } + }; + } + + + /** + * Sorting function for bound directives. + */ + function byPriority(a, b) { + var diff = b.priority - a.priority; + if (diff !== 0) return diff; + if (a.name !== b.name) return (a.name < b.name) ? -1 : 1; + return a.index - b.index; + } + + function assertNoDuplicate(what, previousDirective, directive, element) { + + function wrapModuleNameIfDefined(moduleName) { + return moduleName ? + (' (module: ' + moduleName + ')') : + ''; + } + + if (previousDirective) { + throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}', + previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName), + directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element)); + } + } + + + function addTextInterpolateDirective(directives, text) { + var interpolateFn = $interpolate(text, true); + if (interpolateFn) { + directives.push({ + priority: 0, + compile: function textInterpolateCompileFn(templateNode) { + var templateNodeParent = templateNode.parent(), + hasCompileParent = !!templateNodeParent.length; + + // When transcluding a template that has bindings in the root + // we don't have a parent and thus need to add the class during linking fn. + if (hasCompileParent) compile.$$addBindingClass(templateNodeParent); + + return function textInterpolateLinkFn(scope, node) { + var parent = node.parent(); + if (!hasCompileParent) compile.$$addBindingClass(parent); + compile.$$addBindingInfo(parent, interpolateFn.expressions); + scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { + node[0].nodeValue = value; + }); + }; + } + }); + } + } + + + function wrapTemplate(type, template) { + type = lowercase(type || 'html'); + switch (type) { + case 'svg': + case 'math': + var wrapper = window.document.createElement('div'); + wrapper.innerHTML = '<' + type + '>' + template + ''; + return wrapper.childNodes[0].childNodes; + default: + return template; + } + } + + + function getTrustedContext(node, attrNormalizedName) { + if (attrNormalizedName == "srcdoc") { + return $sce.HTML; + } + var tag = nodeName_(node); + // maction[xlink:href] can source SVG. It's not limited to . + if (attrNormalizedName == "xlinkHref" || + (tag == "form" && attrNormalizedName == "action") || + (tag != "img" && (attrNormalizedName == "src" || + attrNormalizedName == "ngSrc"))) { + return $sce.RESOURCE_URL; + } + } + + + function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) { + var trustedContext = getTrustedContext(node, name); + allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing; + + var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing); + + // no interpolation found -> ignore + if (!interpolateFn) return; + + + if (name === "multiple" && nodeName_(node) === "select") { + throw $compileMinErr("selmulti", + "Binding to the 'multiple' attribute is not supported. Element: {0}", + startingTag(node)); + } + + directives.push({ + priority: 100, + compile: function() { + return { + pre: function attrInterpolatePreLinkFn(scope, element, attr) { + var $$observers = (attr.$$observers || (attr.$$observers = createMap())); + + if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { + throw $compileMinErr('nodomevents', + "Interpolations for HTML DOM event attributes are disallowed. Please use the " + + "ng- versions (such as ng-click instead of onclick) instead."); + } + + // If the attribute has changed since last $interpolate()ed + var newValue = attr[name]; + if (newValue !== value) { + // we need to interpolate again since the attribute value has been updated + // (e.g. by another directive's compile function) + // ensure unset/empty values make interpolateFn falsy + interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing); + value = newValue; + } + + // if attribute was updated so that there is no interpolation going on we don't want to + // register any observers + if (!interpolateFn) return; + + // initialize attr object so that it's ready in case we need the value for isolate + // scope initialization, otherwise the value would not be available from isolate + // directive's linking fn during linking phase + attr[name] = interpolateFn(scope); + + ($$observers[name] || ($$observers[name] = [])).$$inter = true; + (attr.$$observers && attr.$$observers[name].$$scope || scope). + $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) { + //special case for class attribute addition + removal + //so that class changes can tap into the animation + //hooks provided by the $animate service. Be sure to + //skip animations when the first digest occurs (when + //both the new and the old values are the same) since + //the CSS classes are the non-interpolated values + if (name === 'class' && newValue != oldValue) { + attr.$updateClass(newValue, oldValue); + } else { + attr.$set(name, newValue); + } + }); + } + }; + } + }); + } + + + /** + * This is a special jqLite.replaceWith, which can replace items which + * have no parents, provided that the containing jqLite collection is provided. + * + * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes + * in the root of the tree. + * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep + * the shell, but replace its DOM node reference. + * @param {Node} newNode The new DOM node. + */ + function replaceWith($rootElement, elementsToRemove, newNode) { + var firstElementToRemove = elementsToRemove[0], + removeCount = elementsToRemove.length, + parent = firstElementToRemove.parentNode, + i, ii; + + if ($rootElement) { + for (i = 0, ii = $rootElement.length; i < ii; i++) { + if ($rootElement[i] == firstElementToRemove) { + $rootElement[i++] = newNode; + for (var j = i, j2 = j + removeCount - 1, + jj = $rootElement.length; + j < jj; j++, j2++) { + if (j2 < jj) { + $rootElement[j] = $rootElement[j2]; + } else { + delete $rootElement[j]; + } + } + $rootElement.length -= removeCount - 1; + + // If the replaced element is also the jQuery .context then replace it + // .context is a deprecated jQuery api, so we should set it only when jQuery set it + // http://api.jquery.com/context/ + if ($rootElement.context === firstElementToRemove) { + $rootElement.context = newNode; + } + break; + } + } + } + + if (parent) { + parent.replaceChild(newNode, firstElementToRemove); + } + + // Append all the `elementsToRemove` to a fragment. This will... + // - remove them from the DOM + // - allow them to still be traversed with .nextSibling + // - allow a single fragment.qSA to fetch all elements being removed + var fragment = window.document.createDocumentFragment(); + for (i = 0; i < removeCount; i++) { + fragment.appendChild(elementsToRemove[i]); + } + + if (jqLite.hasData(firstElementToRemove)) { + // Copy over user data (that includes Angular's $scope etc.). Don't copy private + // data here because there's no public interface in jQuery to do that and copying over + // event listeners (which is the main use of private data) wouldn't work anyway. + jqLite.data(newNode, jqLite.data(firstElementToRemove)); + + // Remove $destroy event listeners from `firstElementToRemove` + jqLite(firstElementToRemove).off('$destroy'); + } + + // Cleanup any data/listeners on the elements and children. + // This includes invoking the $destroy event on any elements with listeners. + jqLite.cleanData(fragment.querySelectorAll('*')); + + // Update the jqLite collection to only contain the `newNode` + for (i = 1; i < removeCount; i++) { + delete elementsToRemove[i]; + } + elementsToRemove[0] = newNode; + elementsToRemove.length = 1; + } + + + function cloneAndAnnotateFn(fn, annotation) { + return extend(function() { return fn.apply(null, arguments); }, fn, annotation); + } + + + function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) { + try { + linkFn(scope, $element, attrs, controllers, transcludeFn); + } catch (e) { + $exceptionHandler(e, startingTag($element)); + } + } + + + // Set up $watches for isolate scope and controller bindings. This process + // only occurs for isolate scopes and new scopes with controllerAs. + function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) { + var removeWatchCollection = []; + var initialChanges = {}; + var changes; + forEach(bindings, function initializeBinding(definition, scopeName) { + var attrName = definition.attrName, + optional = definition.optional, + mode = definition.mode, // @, =, <, or & + lastValue, + parentGet, parentSet, compare, removeWatch; + + switch (mode) { + + case '@': + if (!optional && !hasOwnProperty.call(attrs, attrName)) { + destination[scopeName] = attrs[attrName] = void 0; + } + attrs.$observe(attrName, function(value) { + if (isString(value) || isBoolean(value)) { + var oldValue = destination[scopeName]; + recordChanges(scopeName, value, oldValue); + destination[scopeName] = value; + } + }); + attrs.$$observers[attrName].$$scope = scope; + lastValue = attrs[attrName]; + if (isString(lastValue)) { + // If the attribute has been provided then we trigger an interpolation to ensure + // the value is there for use in the link fn + destination[scopeName] = $interpolate(lastValue)(scope); + } else if (isBoolean(lastValue)) { + // If the attributes is one of the BOOLEAN_ATTR then Angular will have converted + // the value to boolean rather than a string, so we special case this situation + destination[scopeName] = lastValue; + } + initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]); + break; + + case '=': + if (!hasOwnProperty.call(attrs, attrName)) { + if (optional) break; + attrs[attrName] = void 0; + } + if (optional && !attrs[attrName]) break; + + parentGet = $parse(attrs[attrName]); + if (parentGet.literal) { + compare = equals; + } else { + compare = function simpleCompare(a, b) { return a === b || (a !== a && b !== b); }; + } + parentSet = parentGet.assign || function() { + // reset the change, or we will throw this exception on every $digest + lastValue = destination[scopeName] = parentGet(scope); + throw $compileMinErr('nonassign', + "Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!", + attrs[attrName], attrName, directive.name); + }; + lastValue = destination[scopeName] = parentGet(scope); + var parentValueWatch = function parentValueWatch(parentValue) { + if (!compare(parentValue, destination[scopeName])) { + // we are out of sync and need to copy + if (!compare(parentValue, lastValue)) { + // parent changed and it has precedence + destination[scopeName] = parentValue; + } else { + // if the parent can be assigned then do so + parentSet(scope, parentValue = destination[scopeName]); + } + } + return lastValue = parentValue; + }; + parentValueWatch.$stateful = true; + if (definition.collection) { + removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch); + } else { + removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); + } + removeWatchCollection.push(removeWatch); + break; + + case '<': + if (!hasOwnProperty.call(attrs, attrName)) { + if (optional) break; + attrs[attrName] = void 0; + } + if (optional && !attrs[attrName]) break; + + parentGet = $parse(attrs[attrName]); + + var initialValue = destination[scopeName] = parentGet(scope); + initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]); + + removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newValue, oldValue) { + if (oldValue === newValue) { + if (oldValue === initialValue) return; + oldValue = initialValue; + } + recordChanges(scopeName, newValue, oldValue); + destination[scopeName] = newValue; + }, parentGet.literal); + + removeWatchCollection.push(removeWatch); + break; + + case '&': + // Don't assign Object.prototype method to scope + parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop; + + // Don't assign noop to destination if expression is not valid + if (parentGet === noop && optional) break; + + destination[scopeName] = function(locals) { + return parentGet(scope, locals); + }; + break; + } + }); + + function recordChanges(key, currentValue, previousValue) { + if (isFunction(destination.$onChanges) && currentValue !== previousValue) { + // If we have not already scheduled the top level onChangesQueue handler then do so now + if (!onChangesQueue) { + scope.$$postDigest(flushOnChangesQueue); + onChangesQueue = []; + } + // If we have not already queued a trigger of onChanges for this controller then do so now + if (!changes) { + changes = {}; + onChangesQueue.push(triggerOnChangesHook); + } + // If the has been a change on this property already then we need to reuse the previous value + if (changes[key]) { + previousValue = changes[key].previousValue; + } + // Store this change + changes[key] = new SimpleChange(previousValue, currentValue); + } + } + + function triggerOnChangesHook() { + destination.$onChanges(changes); + // Now clear the changes so that we schedule onChanges when more changes arrive + changes = undefined; + } + + return { + initialChanges: initialChanges, + removeWatches: removeWatchCollection.length && function removeWatches() { + for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) { + removeWatchCollection[i](); + } + } + }; + } + }]; +} + +function SimpleChange(previous, current) { + this.previousValue = previous; + this.currentValue = current; +} +SimpleChange.prototype.isFirstChange = function() { return this.previousValue === _UNINITIALIZED_VALUE; }; + + +var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; +/** + * Converts all accepted directives format into proper directive name. + * @param name Name to normalize + */ +function directiveNormalize(name) { + return camelCase(name.replace(PREFIX_REGEXP, '')); +} + +/** + * @ngdoc type + * @name $compile.directive.Attributes + * + * @description + * A shared object between directive compile / linking functions which contains normalized DOM + * element attributes. The values reflect current binding state `{{ }}`. The normalization is + * needed since all of these are treated as equivalent in Angular: + * + * ``` + * + * ``` + */ + +/** + * @ngdoc property + * @name $compile.directive.Attributes#$attr + * + * @description + * A map of DOM element attribute names to the normalized name. This is + * needed to do reverse lookup from normalized name back to actual name. + */ + + +/** + * @ngdoc method + * @name $compile.directive.Attributes#$set + * @kind function + * + * @description + * Set DOM element attribute value. + * + * + * @param {string} name Normalized element attribute name of the property to modify. The name is + * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr} + * property to the original name. + * @param {string} value Value to set the attribute to. The value can be an interpolated string. + */ + + + +/** + * Closure compiler type information + */ + +function nodesetLinkingFn( + /* angular.Scope */ scope, + /* NodeList */ nodeList, + /* Element */ rootElement, + /* function(Function) */ boundTranscludeFn +) {} + +function directiveLinkingFn( + /* nodesetLinkingFn */ nodesetLinkingFn, + /* angular.Scope */ scope, + /* Node */ node, + /* Element */ rootElement, + /* function(Function) */ boundTranscludeFn +) {} + +function tokenDifference(str1, str2) { + var values = '', + tokens1 = str1.split(/\s+/), + tokens2 = str2.split(/\s+/); + + outer: + for (var i = 0; i < tokens1.length; i++) { + var token = tokens1[i]; + for (var j = 0; j < tokens2.length; j++) { + if (token == tokens2[j]) continue outer; + } + values += (values.length > 0 ? ' ' : '') + token; + } + return values; +} + +function removeComments(jqNodes) { + jqNodes = jqLite(jqNodes); + var i = jqNodes.length; + + if (i <= 1) { + return jqNodes; + } + + while (i--) { + var node = jqNodes[i]; + if (node.nodeType === NODE_TYPE_COMMENT) { + splice.call(jqNodes, i, 1); + } + } + return jqNodes; +} + +var $controllerMinErr = minErr('$controller'); + + +var CNTRL_REG = /^(\S+)(\s+as\s+([\w$]+))?$/; +function identifierForController(controller, ident) { + if (ident && isString(ident)) return ident; + if (isString(controller)) { + var match = CNTRL_REG.exec(controller); + if (match) return match[3]; + } +} + + +/** + * @ngdoc provider + * @name $controllerProvider + * @description + * The {@link ng.$controller $controller service} is used by Angular to create new + * controllers. + * + * This provider allows controller registration via the + * {@link ng.$controllerProvider#register register} method. + */ +function $ControllerProvider() { + var controllers = {}, + globals = false; + + /** + * @ngdoc method + * @name $controllerProvider#has + * @param {string} name Controller name to check. + */ + this.has = function(name) { + return controllers.hasOwnProperty(name); + }; + + /** + * @ngdoc method + * @name $controllerProvider#register + * @param {string|Object} name Controller name, or an object map of controllers where the keys are + * the names and the values are the constructors. + * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI + * annotations in the array notation). + */ + this.register = function(name, constructor) { + assertNotHasOwnProperty(name, 'controller'); + if (isObject(name)) { + extend(controllers, name); + } else { + controllers[name] = constructor; + } + }; + + /** + * @ngdoc method + * @name $controllerProvider#allowGlobals + * @description If called, allows `$controller` to find controller constructors on `window` + */ + this.allowGlobals = function() { + globals = true; + }; + + + this.$get = ['$injector', '$window', function($injector, $window) { + + /** + * @ngdoc service + * @name $controller + * @requires $injector + * + * @param {Function|string} constructor If called with a function then it's considered to be the + * controller constructor function. Otherwise it's considered to be a string which is used + * to retrieve the controller constructor using the following steps: + * + * * check if a controller with given name is registered via `$controllerProvider` + * * check if evaluating the string on the current scope returns a constructor + * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global + * `window` object (not recommended) + * + * The string can use the `controller as property` syntax, where the controller instance is published + * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this + * to work correctly. + * + * @param {Object} locals Injection locals for Controller. + * @return {Object} Instance of given controller. + * + * @description + * `$controller` service is responsible for instantiating controllers. + * + * It's just a simple call to {@link auto.$injector $injector}, but extracted into + * a service, so that one can override this service with [BC version](https://gist.github.com/1649788). + */ + return function $controller(expression, locals, later, ident) { + // PRIVATE API: + // param `later` --- indicates that the controller's constructor is invoked at a later time. + // If true, $controller will allocate the object with the correct + // prototype chain, but will not invoke the controller until a returned + // callback is invoked. + // param `ident` --- An optional label which overrides the label parsed from the controller + // expression, if any. + var instance, match, constructor, identifier; + later = later === true; + if (ident && isString(ident)) { + identifier = ident; + } + + if (isString(expression)) { + match = expression.match(CNTRL_REG); + if (!match) { + throw $controllerMinErr('ctrlfmt', + "Badly formed controller string '{0}'. " + + "Must match `__name__ as __id__` or `__name__`.", expression); + } + constructor = match[1], + identifier = identifier || match[3]; + expression = controllers.hasOwnProperty(constructor) + ? controllers[constructor] + : getter(locals.$scope, constructor, true) || + (globals ? getter($window, constructor, true) : undefined); + + assertArgFn(expression, constructor, true); + } + + if (later) { + // Instantiate controller later: + // This machinery is used to create an instance of the object before calling the + // controller's constructor itself. + // + // This allows properties to be added to the controller before the constructor is + // invoked. Primarily, this is used for isolate scope bindings in $compile. + // + // This feature is not intended for use by applications, and is thus not documented + // publicly. + // Object creation: http://jsperf.com/create-constructor/2 + var controllerPrototype = (isArray(expression) ? + expression[expression.length - 1] : expression).prototype; + instance = Object.create(controllerPrototype || null); + + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + + var instantiate; + return instantiate = extend(function $controllerInit() { + var result = $injector.invoke(expression, instance, locals, constructor); + if (result !== instance && (isObject(result) || isFunction(result))) { + instance = result; + if (identifier) { + // If result changed, re-assign controllerAs value to scope. + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + } + return instance; + }, { + instance: instance, + identifier: identifier + }); + } + + instance = $injector.instantiate(expression, locals, constructor); + + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + + return instance; + }; + + function addIdentifier(locals, identifier, instance, name) { + if (!(locals && isObject(locals.$scope))) { + throw minErr('$controller')('noscp', + "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.", + name, identifier); + } + + locals.$scope[identifier] = instance; + } + }]; +} + +/** + * @ngdoc service + * @name $document + * @requires $window + * + * @description + * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object. + * + * @example + + +
    +

    $document title:

    +

    window.document title:

    +
    +
    + + angular.module('documentExample', []) + .controller('ExampleController', ['$scope', '$document', function($scope, $document) { + $scope.title = $document[0].title; + $scope.windowTitle = angular.element(window.document)[0].title; + }]); + +
    + */ +function $DocumentProvider() { + this.$get = ['$window', function(window) { + return jqLite(window.document); + }]; +} + +/** + * @ngdoc service + * @name $exceptionHandler + * @requires ng.$log + * + * @description + * Any uncaught exception in angular expressions is delegated to this service. + * The default implementation simply delegates to `$log.error` which logs it into + * the browser console. + * + * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by + * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing. + * + * ## Example: + * + * The example below will overwrite the default `$exceptionHandler` in order to (a) log uncaught + * errors to the backend for later inspection by the developers and (b) to use `$log.warn()` instead + * of `$log.error()`. + * + * ```js + * angular. + * module('exceptionOverwrite', []). + * factory('$exceptionHandler', ['$log', 'logErrorsToBackend', function($log, logErrorsToBackend) { + * return function myExceptionHandler(exception, cause) { + * logErrorsToBackend(exception, cause); + * $log.warn(exception, cause); + * }; + * }]); + * ``` + * + *
    + * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind` + * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler} + * (unless executed during a digest). + * + * If you wish, you can manually delegate exceptions, e.g. + * `try { ... } catch(e) { $exceptionHandler(e); }` + * + * @param {Error} exception Exception associated with the error. + * @param {string=} cause Optional information about the context in which + * the error was thrown. + * + */ +function $ExceptionHandlerProvider() { + this.$get = ['$log', function($log) { + return function(exception, cause) { + $log.error.apply($log, arguments); + }; + }]; +} + +var $$ForceReflowProvider = function() { + this.$get = ['$document', function($document) { + return function(domNode) { + //the line below will force the browser to perform a repaint so + //that all the animated elements within the animation frame will + //be properly updated and drawn on screen. This is required to + //ensure that the preparation animation is properly flushed so that + //the active state picks up from there. DO NOT REMOVE THIS LINE. + //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH + //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND + //WILL TAKE YEARS AWAY FROM YOUR LIFE. + if (domNode) { + if (!domNode.nodeType && domNode instanceof jqLite) { + domNode = domNode[0]; + } + } else { + domNode = $document[0].body; + } + return domNode.offsetWidth + 1; + }; + }]; +}; + +var APPLICATION_JSON = 'application/json'; +var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'}; +var JSON_START = /^\[|^\{(?!\{)/; +var JSON_ENDS = { + '[': /]$/, + '{': /}$/ +}; +var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; +var $httpMinErr = minErr('$http'); +var $httpMinErrLegacyFn = function(method) { + return function() { + throw $httpMinErr('legacy', 'The method `{0}` on the promise returned from `$http` has been disabled.', method); + }; +}; + +function serializeValue(v) { + if (isObject(v)) { + return isDate(v) ? v.toISOString() : toJson(v); + } + return v; +} + + +function $HttpParamSerializerProvider() { + /** + * @ngdoc service + * @name $httpParamSerializer + * @description + * + * Default {@link $http `$http`} params serializer that converts objects to strings + * according to the following rules: + * + * * `{'foo': 'bar'}` results in `foo=bar` + * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object) + * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element) + * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D` (stringified and encoded representation of an object) + * + * Note that serializer will sort the request parameters alphabetically. + * */ + + this.$get = function() { + return function ngParamSerializer(params) { + if (!params) return ''; + var parts = []; + forEachSorted(params, function(value, key) { + if (value === null || isUndefined(value)) return; + if (isArray(value)) { + forEach(value, function(v) { + parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v))); + }); + } else { + parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value))); + } + }); + + return parts.join('&'); + }; + }; +} + +function $HttpParamSerializerJQLikeProvider() { + /** + * @ngdoc service + * @name $httpParamSerializerJQLike + * @description + * + * Alternative {@link $http `$http`} params serializer that follows + * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic. + * The serializer will also sort the params alphabetically. + * + * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property: + * + * ```js + * $http({ + * url: myUrl, + * method: 'GET', + * params: myParams, + * paramSerializer: '$httpParamSerializerJQLike' + * }); + * ``` + * + * It is also possible to set it as the default `paramSerializer` in the + * {@link $httpProvider#defaults `$httpProvider`}. + * + * Additionally, you can inject the serializer and use it explicitly, for example to serialize + * form data for submission: + * + * ```js + * .controller(function($http, $httpParamSerializerJQLike) { + * //... + * + * $http({ + * url: myUrl, + * method: 'POST', + * data: $httpParamSerializerJQLike(myData), + * headers: { + * 'Content-Type': 'application/x-www-form-urlencoded' + * } + * }); + * + * }); + * ``` + * + * */ + this.$get = function() { + return function jQueryLikeParamSerializer(params) { + if (!params) return ''; + var parts = []; + serialize(params, '', true); + return parts.join('&'); + + function serialize(toSerialize, prefix, topLevel) { + if (toSerialize === null || isUndefined(toSerialize)) return; + if (isArray(toSerialize)) { + forEach(toSerialize, function(value, index) { + serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']'); + }); + } else if (isObject(toSerialize) && !isDate(toSerialize)) { + forEachSorted(toSerialize, function(value, key) { + serialize(value, prefix + + (topLevel ? '' : '[') + + key + + (topLevel ? '' : ']')); + }); + } else { + parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize))); + } + } + }; + }; +} + +function defaultHttpResponseTransform(data, headers) { + if (isString(data)) { + // Strip json vulnerability protection prefix and trim whitespace + var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim(); + + if (tempData) { + var contentType = headers('Content-Type'); + if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) { + data = fromJson(tempData); + } + } + } + + return data; +} + +function isJsonLike(str) { + var jsonStart = str.match(JSON_START); + return jsonStart && JSON_ENDS[jsonStart[0]].test(str); +} + +/** + * Parse headers into key value object + * + * @param {string} headers Raw headers as a string + * @returns {Object} Parsed headers as key value object + */ +function parseHeaders(headers) { + var parsed = createMap(), i; + + function fillInParsed(key, val) { + if (key) { + parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; + } + } + + if (isString(headers)) { + forEach(headers.split('\n'), function(line) { + i = line.indexOf(':'); + fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1))); + }); + } else if (isObject(headers)) { + forEach(headers, function(headerVal, headerKey) { + fillInParsed(lowercase(headerKey), trim(headerVal)); + }); + } + + return parsed; +} + + +/** + * Returns a function that provides access to parsed headers. + * + * Headers are lazy parsed when first requested. + * @see parseHeaders + * + * @param {(string|Object)} headers Headers to provide access to. + * @returns {function(string=)} Returns a getter function which if called with: + * + * - if called with single an argument returns a single header value or null + * - if called with no arguments returns an object containing all headers. + */ +function headersGetter(headers) { + var headersObj; + + return function(name) { + if (!headersObj) headersObj = parseHeaders(headers); + + if (name) { + var value = headersObj[lowercase(name)]; + if (value === void 0) { + value = null; + } + return value; + } + + return headersObj; + }; +} + + +/** + * Chain all given functions + * + * This function is used for both request and response transforming + * + * @param {*} data Data to transform. + * @param {function(string=)} headers HTTP headers getter fn. + * @param {number} status HTTP status code of the response. + * @param {(Function|Array.)} fns Function or an array of functions. + * @returns {*} Transformed data. + */ +function transformData(data, headers, status, fns) { + if (isFunction(fns)) { + return fns(data, headers, status); + } + + forEach(fns, function(fn) { + data = fn(data, headers, status); + }); + + return data; +} + + +function isSuccess(status) { + return 200 <= status && status < 300; +} + + +/** + * @ngdoc provider + * @name $httpProvider + * @description + * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service. + * */ +function $HttpProvider() { + /** + * @ngdoc property + * @name $httpProvider#defaults + * @description + * + * Object containing default values for all {@link ng.$http $http} requests. + * + * - **`defaults.cache`** - {boolean|Object} - A boolean value or object created with + * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of HTTP responses + * by default. See {@link $http#caching $http Caching} for more information. + * + * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token. + * Defaults value is `'XSRF-TOKEN'`. + * + * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the + * XSRF token. Defaults value is `'X-XSRF-TOKEN'`. + * + * - **`defaults.headers`** - {Object} - Default headers for all $http requests. + * Refer to {@link ng.$http#setting-http-headers $http} for documentation on + * setting default headers. + * - **`defaults.headers.common`** + * - **`defaults.headers.post`** + * - **`defaults.headers.put`** + * - **`defaults.headers.patch`** + * + * + * - **`defaults.paramSerializer`** - `{string|function(Object):string}` - A function + * used to the prepare string representation of request parameters (specified as an object). + * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}. + * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}. + * + **/ + var defaults = this.defaults = { + // transform incoming response data + transformResponse: [defaultHttpResponseTransform], + + // transform outgoing request data + transformRequest: [function(d) { + return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d; + }], + + // default headers + headers: { + common: { + 'Accept': 'application/json, text/plain, */*' + }, + post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), + put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), + patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON) + }, + + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', + + paramSerializer: '$httpParamSerializer' + }; + + var useApplyAsync = false; + /** + * @ngdoc method + * @name $httpProvider#useApplyAsync + * @description + * + * Configure $http service to combine processing of multiple http responses received at around + * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in + * significant performance improvement for bigger applications that make many HTTP requests + * concurrently (common during application bootstrap). + * + * Defaults to false. If no value is specified, returns the current configured value. + * + * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred + * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window + * to load and share the same digest cycle. + * + * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining. + * otherwise, returns the current configured value. + **/ + this.useApplyAsync = function(value) { + if (isDefined(value)) { + useApplyAsync = !!value; + return this; + } + return useApplyAsync; + }; + + var useLegacyPromise = true; + /** + * @ngdoc method + * @name $httpProvider#useLegacyPromiseExtensions + * @description + * + * Configure `$http` service to return promises without the shorthand methods `success` and `error`. + * This should be used to make sure that applications work without these methods. + * + * Defaults to true. If no value is specified, returns the current configured value. + * + * @param {boolean=} value If true, `$http` will return a promise with the deprecated legacy `success` and `error` methods. + * + * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining. + * otherwise, returns the current configured value. + **/ + this.useLegacyPromiseExtensions = function(value) { + if (isDefined(value)) { + useLegacyPromise = !!value; + return this; + } + return useLegacyPromise; + }; + + /** + * @ngdoc property + * @name $httpProvider#interceptors + * @description + * + * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http} + * pre-processing of request or postprocessing of responses. + * + * These service factories are ordered by request, i.e. they are applied in the same order as the + * array, on request, but reverse order, on response. + * + * {@link ng.$http#interceptors Interceptors detailed info} + **/ + var interceptorFactories = this.interceptors = []; + + this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector', + function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) { + + var defaultCache = $cacheFactory('$http'); + + /** + * Make sure that default param serializer is exposed as a function + */ + defaults.paramSerializer = isString(defaults.paramSerializer) ? + $injector.get(defaults.paramSerializer) : defaults.paramSerializer; + + /** + * Interceptors stored in reverse order. Inner interceptors before outer interceptors. + * The reversal is needed so that we can build up the interception chain around the + * server request. + */ + var reversedInterceptors = []; + + forEach(interceptorFactories, function(interceptorFactory) { + reversedInterceptors.unshift(isString(interceptorFactory) + ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory)); + }); + + /** + * @ngdoc service + * @kind function + * @name $http + * @requires ng.$httpBackend + * @requires $cacheFactory + * @requires $rootScope + * @requires $q + * @requires $injector + * + * @description + * The `$http` service is a core Angular service that facilitates communication with the remote + * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest) + * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP). + * + * For unit testing applications that use `$http` service, see + * {@link ngMock.$httpBackend $httpBackend mock}. + * + * For a higher level of abstraction, please check out the {@link ngResource.$resource + * $resource} service. + * + * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by + * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage + * it is important to familiarize yourself with these APIs and the guarantees they provide. + * + * + * ## General usage + * The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object} — + * that is used to generate an HTTP request and returns a {@link ng.$q promise}. + * + * ```js + * // Simple GET request example: + * $http({ + * method: 'GET', + * url: '/someUrl' + * }).then(function successCallback(response) { + * // this callback will be called asynchronously + * // when the response is available + * }, function errorCallback(response) { + * // called asynchronously if an error occurs + * // or server returns response with an error status. + * }); + * ``` + * + * The response object has these properties: + * + * - **data** – `{string|Object}` – The response body transformed with the transform + * functions. + * - **status** – `{number}` – HTTP status code of the response. + * - **headers** – `{function([headerName])}` – Header getter function. + * - **config** – `{Object}` – The configuration object that was used to generate the request. + * - **statusText** – `{string}` – HTTP status text of the response. + * + * A response status code between 200 and 299 is considered a success status and will result in + * the success callback being called. Any response status code outside of that range is + * considered an error status and will result in the error callback being called. + * Also, status codes less than -1 are normalized to zero. -1 usually means the request was + * aborted, e.g. using a `config.timeout`. + * Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning + * that the outcome (success or error) will be determined by the final response status code. + * + * + * ## Shortcut methods + * + * Shortcut methods are also available. All shortcut methods require passing in the URL, and + * request data must be passed in for POST/PUT requests. An optional config can be passed as the + * last argument. + * + * ```js + * $http.get('/someUrl', config).then(successCallback, errorCallback); + * $http.post('/someUrl', data, config).then(successCallback, errorCallback); + * ``` + * + * Complete list of shortcut methods: + * + * - {@link ng.$http#get $http.get} + * - {@link ng.$http#head $http.head} + * - {@link ng.$http#post $http.post} + * - {@link ng.$http#put $http.put} + * - {@link ng.$http#delete $http.delete} + * - {@link ng.$http#jsonp $http.jsonp} + * - {@link ng.$http#patch $http.patch} + * + * + * ## Writing Unit Tests that use $http + * When unit testing (using {@link ngMock ngMock}), it is necessary to call + * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending + * request using trained responses. + * + * ``` + * $httpBackend.expectGET(...); + * $http.get(...); + * $httpBackend.flush(); + * ``` + * + * ## Deprecation Notice + *
    + * The `$http` legacy promise methods `success` and `error` have been deprecated. + * Use the standard `then` method instead. + * If {@link $httpProvider#useLegacyPromiseExtensions `$httpProvider.useLegacyPromiseExtensions`} is set to + * `false` then these methods will throw {@link $http:legacy `$http/legacy`} error. + *
    + * + * ## Setting HTTP Headers + * + * The $http service will automatically add certain HTTP headers to all requests. These defaults + * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration + * object, which currently contains this default configuration: + * + * - `$httpProvider.defaults.headers.common` (headers that are common for all requests): + * - `Accept: application/json, text/plain, * / *` + * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests) + * - `Content-Type: application/json` + * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests) + * - `Content-Type: application/json` + * + * To add or overwrite these defaults, simply add or remove a property from these configuration + * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object + * with the lowercased HTTP method name as the key, e.g. + * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`. + * + * The defaults can also be set at runtime via the `$http.defaults` object in the same + * fashion. For example: + * + * ``` + * module.run(function($http) { + * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'; + * }); + * ``` + * + * In addition, you can supply a `headers` property in the config object passed when + * calling `$http(config)`, which overrides the defaults without changing them globally. + * + * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis, + * Use the `headers` property, setting the desired header to `undefined`. For example: + * + * ```js + * var req = { + * method: 'POST', + * url: 'http://example.com', + * headers: { + * 'Content-Type': undefined + * }, + * data: { test: 'test' } + * } + * + * $http(req).then(function(){...}, function(){...}); + * ``` + * + * ## Transforming Requests and Responses + * + * Both requests and responses can be transformed using transformation functions: `transformRequest` + * and `transformResponse`. These properties can be a single function that returns + * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions, + * which allows you to `push` or `unshift` a new transformation function into the transformation chain. + * + *
    + * **Note:** Angular does not make a copy of the `data` parameter before it is passed into the `transformRequest` pipeline. + * That means changes to the properties of `data` are not local to the transform function (since Javascript passes objects by reference). + * For example, when calling `$http.get(url, $scope.myObject)`, modifications to the object's properties in a transformRequest + * function will be reflected on the scope and in any templates where the object is data-bound. + * To prevent this, transform functions should have no side-effects. + * If you need to modify properties, it is recommended to make a copy of the data, or create new object to return. + *
    + * + * ### Default Transformations + * + * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and + * `defaults.transformResponse` properties. If a request does not provide its own transformations + * then these will be applied. + * + * You can augment or replace the default transformations by modifying these properties by adding to or + * replacing the array. + * + * Angular provides the following default transformations: + * + * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`): + * + * - If the `data` property of the request configuration object contains an object, serialize it + * into JSON format. + * + * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`): + * + * - If XSRF prefix is detected, strip it (see Security Considerations section below). + * - If JSON response is detected, deserialize it using a JSON parser. + * + * + * ### Overriding the Default Transformations Per Request + * + * If you wish to override the request/response transformations only for a single request then provide + * `transformRequest` and/or `transformResponse` properties on the configuration object passed + * into `$http`. + * + * Note that if you provide these properties on the config object the default transformations will be + * overwritten. If you wish to augment the default transformations then you must include them in your + * local transformation array. + * + * The following code demonstrates adding a new response transformation to be run after the default response + * transformations have been run. + * + * ```js + * function appendTransform(defaults, transform) { + * + * // We can't guarantee that the default transformation is an array + * defaults = angular.isArray(defaults) ? defaults : [defaults]; + * + * // Append the new transformation to the defaults + * return defaults.concat(transform); + * } + * + * $http({ + * url: '...', + * method: 'GET', + * transformResponse: appendTransform($http.defaults.transformResponse, function(value) { + * return doTransform(value); + * }) + * }); + * ``` + * + * + * ## Caching + * + * {@link ng.$http `$http`} responses are not cached by default. To enable caching, you must + * set the config.cache value or the default cache value to TRUE or to a cache object (created + * with {@link ng.$cacheFactory `$cacheFactory`}). If defined, the value of config.cache takes + * precedence over the default cache value. + * + * In order to: + * * cache all responses - set the default cache value to TRUE or to a cache object + * * cache a specific response - set config.cache value to TRUE or to a cache object + * + * If caching is enabled, but neither the default cache nor config.cache are set to a cache object, + * then the default `$cacheFactory("$http")` object is used. + * + * The default cache value can be set by updating the + * {@link ng.$http#defaults `$http.defaults.cache`} property or the + * {@link $httpProvider#defaults `$httpProvider.defaults.cache`} property. + * + * When caching is enabled, {@link ng.$http `$http`} stores the response from the server using + * the relevant cache object. The next time the same request is made, the response is returned + * from the cache without sending a request to the server. + * + * Take note that: + * + * * Only GET and JSONP requests are cached. + * * The cache key is the request URL including search parameters; headers are not considered. + * * Cached responses are returned asynchronously, in the same way as responses from the server. + * * If multiple identical requests are made using the same cache, which is not yet populated, + * one request will be made to the server and remaining requests will return the same response. + * * A cache-control header on the response does not affect if or how responses are cached. + * + * + * ## Interceptors + * + * Before you start creating interceptors, be sure to understand the + * {@link ng.$q $q and deferred/promise APIs}. + * + * For purposes of global error handling, authentication, or any kind of synchronous or + * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be + * able to intercept requests before they are handed to the server and + * responses before they are handed over to the application code that + * initiated these requests. The interceptors leverage the {@link ng.$q + * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing. + * + * The interceptors are service factories that are registered with the `$httpProvider` by + * adding them to the `$httpProvider.interceptors` array. The factory is called and + * injected with dependencies (if specified) and returns the interceptor. + * + * There are two kinds of interceptors (and two kinds of rejection interceptors): + * + * * `request`: interceptors get called with a http {@link $http#usage config} object. The function is free to + * modify the `config` object or create a new one. The function needs to return the `config` + * object directly, or a promise containing the `config` or a new `config` object. + * * `requestError`: interceptor gets called when a previous interceptor threw an error or + * resolved with a rejection. + * * `response`: interceptors get called with http `response` object. The function is free to + * modify the `response` object or create a new one. The function needs to return the `response` + * object directly, or as a promise containing the `response` or a new `response` object. + * * `responseError`: interceptor gets called when a previous interceptor threw an error or + * resolved with a rejection. + * + * + * ```js + * // register the interceptor as a service + * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) { + * return { + * // optional method + * 'request': function(config) { + * // do something on success + * return config; + * }, + * + * // optional method + * 'requestError': function(rejection) { + * // do something on error + * if (canRecover(rejection)) { + * return responseOrNewPromise + * } + * return $q.reject(rejection); + * }, + * + * + * + * // optional method + * 'response': function(response) { + * // do something on success + * return response; + * }, + * + * // optional method + * 'responseError': function(rejection) { + * // do something on error + * if (canRecover(rejection)) { + * return responseOrNewPromise + * } + * return $q.reject(rejection); + * } + * }; + * }); + * + * $httpProvider.interceptors.push('myHttpInterceptor'); + * + * + * // alternatively, register the interceptor via an anonymous factory + * $httpProvider.interceptors.push(function($q, dependency1, dependency2) { + * return { + * 'request': function(config) { + * // same as above + * }, + * + * 'response': function(response) { + * // same as above + * } + * }; + * }); + * ``` + * + * ## Security Considerations + * + * When designing web applications, consider security threats from: + * + * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) + * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) + * + * Both server and the client must cooperate in order to eliminate these threats. Angular comes + * pre-configured with strategies that address these issues, but for this to work backend server + * cooperation is required. + * + * ### JSON Vulnerability Protection + * + * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) + * allows third party website to turn your JSON resource URL into + * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To + * counter this your server can prefix all JSON requests with following string `")]}',\n"`. + * Angular will automatically strip the prefix before processing it as JSON. + * + * For example if your server needs to return: + * ```js + * ['one','two'] + * ``` + * + * which is vulnerable to attack, your server can return: + * ```js + * )]}', + * ['one','two'] + * ``` + * + * Angular will strip the prefix, before processing the JSON. + * + * + * ### Cross Site Request Forgery (XSRF) Protection + * + * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by + * which the attacker can trick an authenticated user into unknowingly executing actions on your + * website. Angular provides a mechanism to counter XSRF. When performing XHR requests, the + * $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP + * header (`X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read the + * cookie, your server can be assured that the XHR came from JavaScript running on your domain. + * The header will not be set for cross-domain requests. + * + * To take advantage of this, your server needs to set a token in a JavaScript readable session + * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the + * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure + * that only JavaScript running on your domain could have sent the request. The token must be + * unique for each user and must be verifiable by the server (to prevent the JavaScript from + * making up its own tokens). We recommend that the token is a digest of your site's + * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) + * for added security. + * + * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName + * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time, + * or the per-request config object. + * + * In order to prevent collisions in environments where multiple Angular apps share the + * same domain or subdomain, we recommend that each application uses unique cookie name. + * + * @param {object} config Object describing the request to be made and how it should be + * processed. The object has following properties: + * + * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) + * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested. + * - **params** – `{Object.}` – Map of strings or objects which will be serialized + * with the `paramSerializer` and appended as GET parameters. + * - **data** – `{string|Object}` – Data to be sent as the request message data. + * - **headers** – `{Object}` – Map of strings or functions which return strings representing + * HTTP headers to send to the server. If the return value of a function is null, the + * header will not be sent. Functions accept a config object as an argument. + * - **eventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest object. + * To bind events to the XMLHttpRequest upload object, use `uploadEventHandlers`. + * The handler will be called in the context of a `$apply` block. + * - **uploadEventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest upload + * object. To bind events to the XMLHttpRequest object, use `eventHandlers`. + * The handler will be called in the context of a `$apply` block. + * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token. + * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token. + * - **transformRequest** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * request body and headers and returns its transformed (typically serialized) version. + * See {@link ng.$http#overriding-the-default-transformations-per-request + * Overriding the Default Transformations} + * - **transformResponse** – + * `{function(data, headersGetter, status)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * response body, headers and status and returns its transformed (typically deserialized) version. + * See {@link ng.$http#overriding-the-default-transformations-per-request + * Overriding the Default Transformations} + * - **paramSerializer** - `{string|function(Object):string}` - A function used to + * prepare the string representation of request parameters (specified as an object). + * If specified as string, it is interpreted as function registered with the + * {@link $injector $injector}, which means you can create your own serializer + * by registering it as a {@link auto.$provide#service service}. + * The default serializer is the {@link $httpParamSerializer $httpParamSerializer}; + * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike} + * - **cache** – `{boolean|Object}` – A boolean value or object created with + * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of the HTTP response. + * See {@link $http#caching $http Caching} for more information. + * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} + * that should abort the request when resolved. + * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the + * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials) + * for more information. + * - **responseType** - `{string}` - see + * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype). + * + * @returns {HttpPromise} Returns a {@link ng.$q `Promise}` that will be resolved to a response object + * when the request succeeds or fails. + * + * + * @property {Array.} pendingRequests Array of config objects for currently pending + * requests. This is primarily meant to be used for debugging purposes. + * + * + * @example + + +
    + + +
    + + + +
    http status code: {{status}}
    +
    http response data: {{data}}
    +
    +
    + + angular.module('httpExample', []) + .controller('FetchController', ['$scope', '$http', '$templateCache', + function($scope, $http, $templateCache) { + $scope.method = 'GET'; + $scope.url = 'http-hello.html'; + + $scope.fetch = function() { + $scope.code = null; + $scope.response = null; + + $http({method: $scope.method, url: $scope.url, cache: $templateCache}). + then(function(response) { + $scope.status = response.status; + $scope.data = response.data; + }, function(response) { + $scope.data = response.data || "Request failed"; + $scope.status = response.status; + }); + }; + + $scope.updateModel = function(method, url) { + $scope.method = method; + $scope.url = url; + }; + }]); + + + Hello, $http! + + + var status = element(by.binding('status')); + var data = element(by.binding('data')); + var fetchBtn = element(by.id('fetchbtn')); + var sampleGetBtn = element(by.id('samplegetbtn')); + var sampleJsonpBtn = element(by.id('samplejsonpbtn')); + var invalidJsonpBtn = element(by.id('invalidjsonpbtn')); + + it('should make an xhr GET request', function() { + sampleGetBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('200'); + expect(data.getText()).toMatch(/Hello, \$http!/); + }); + +// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185 +// it('should make a JSONP request to angularjs.org', function() { +// sampleJsonpBtn.click(); +// fetchBtn.click(); +// expect(status.getText()).toMatch('200'); +// expect(data.getText()).toMatch(/Super Hero!/); +// }); + + it('should make JSONP request to invalid URL and invoke the error handler', + function() { + invalidJsonpBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('0'); + expect(data.getText()).toMatch('Request failed'); + }); + +
    + */ + function $http(requestConfig) { + + if (!isObject(requestConfig)) { + throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig); + } + + if (!isString(requestConfig.url)) { + throw minErr('$http')('badreq', 'Http request configuration url must be a string. Received: {0}', requestConfig.url); + } + + var config = extend({ + method: 'get', + transformRequest: defaults.transformRequest, + transformResponse: defaults.transformResponse, + paramSerializer: defaults.paramSerializer + }, requestConfig); + + config.headers = mergeHeaders(requestConfig); + config.method = uppercase(config.method); + config.paramSerializer = isString(config.paramSerializer) ? + $injector.get(config.paramSerializer) : config.paramSerializer; + + var requestInterceptors = []; + var responseInterceptors = []; + var promise = $q.when(config); + + // apply interceptors + forEach(reversedInterceptors, function(interceptor) { + if (interceptor.request || interceptor.requestError) { + requestInterceptors.unshift(interceptor.request, interceptor.requestError); + } + if (interceptor.response || interceptor.responseError) { + responseInterceptors.push(interceptor.response, interceptor.responseError); + } + }); + + promise = chainInterceptors(promise, requestInterceptors); + promise = promise.then(serverRequest); + promise = chainInterceptors(promise, responseInterceptors); + + if (useLegacyPromise) { + promise.success = function(fn) { + assertArgFn(fn, 'fn'); + + promise.then(function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + + promise.error = function(fn) { + assertArgFn(fn, 'fn'); + + promise.then(null, function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + } else { + promise.success = $httpMinErrLegacyFn('success'); + promise.error = $httpMinErrLegacyFn('error'); + } + + return promise; + + + function chainInterceptors(promise, interceptors) { + for (var i = 0, ii = interceptors.length; i < ii;) { + var thenFn = interceptors[i++]; + var rejectFn = interceptors[i++]; + + promise = promise.then(thenFn, rejectFn); + } + + interceptors.length = 0; + + return promise; + } + + function executeHeaderFns(headers, config) { + var headerContent, processedHeaders = {}; + + forEach(headers, function(headerFn, header) { + if (isFunction(headerFn)) { + headerContent = headerFn(config); + if (headerContent != null) { + processedHeaders[header] = headerContent; + } + } else { + processedHeaders[header] = headerFn; + } + }); + + return processedHeaders; + } + + function mergeHeaders(config) { + var defHeaders = defaults.headers, + reqHeaders = extend({}, config.headers), + defHeaderName, lowercaseDefHeaderName, reqHeaderName; + + defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); + + // using for-in instead of forEach to avoid unnecessary iteration after header has been found + defaultHeadersIteration: + for (defHeaderName in defHeaders) { + lowercaseDefHeaderName = lowercase(defHeaderName); + + for (reqHeaderName in reqHeaders) { + if (lowercase(reqHeaderName) === lowercaseDefHeaderName) { + continue defaultHeadersIteration; + } + } + + reqHeaders[defHeaderName] = defHeaders[defHeaderName]; + } + + // execute if header value is a function for merged headers + return executeHeaderFns(reqHeaders, shallowCopy(config)); + } + + function serverRequest(config) { + var headers = config.headers; + var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest); + + // strip content-type if data is undefined + if (isUndefined(reqData)) { + forEach(headers, function(value, header) { + if (lowercase(header) === 'content-type') { + delete headers[header]; + } + }); + } + + if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { + config.withCredentials = defaults.withCredentials; + } + + // send request + return sendReq(config, reqData).then(transformResponse, transformResponse); + } + + function transformResponse(response) { + // make a copy since the response must be cacheable + var resp = extend({}, response); + resp.data = transformData(response.data, response.headers, response.status, + config.transformResponse); + return (isSuccess(response.status)) + ? resp + : $q.reject(resp); + } + } + + $http.pendingRequests = []; + + /** + * @ngdoc method + * @name $http#get + * + * @description + * Shortcut method to perform `GET` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#delete + * + * @description + * Shortcut method to perform `DELETE` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#head + * + * @description + * Shortcut method to perform `HEAD` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#jsonp + * + * @description + * Shortcut method to perform `JSONP` request. + * If you would like to customise where and how the callbacks are stored then try overriding + * or decorating the {@link $jsonpCallbacks} service. + * + * @param {string} url Relative or absolute URL specifying the destination of the request. + * The name of the callback should be the string `JSON_CALLBACK`. + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + createShortMethods('get', 'delete', 'head', 'jsonp'); + + /** + * @ngdoc method + * @name $http#post + * + * @description + * Shortcut method to perform `POST` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#put + * + * @description + * Shortcut method to perform `PUT` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#patch + * + * @description + * Shortcut method to perform `PATCH` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + createShortMethodsWithData('post', 'put', 'patch'); + + /** + * @ngdoc property + * @name $http#defaults + * + * @description + * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of + * default headers, withCredentials as well as request and response transformations. + * + * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above. + */ + $http.defaults = defaults; + + + return $http; + + + function createShortMethods(names) { + forEach(arguments, function(name) { + $http[name] = function(url, config) { + return $http(extend({}, config || {}, { + method: name, + url: url + })); + }; + }); + } + + + function createShortMethodsWithData(name) { + forEach(arguments, function(name) { + $http[name] = function(url, data, config) { + return $http(extend({}, config || {}, { + method: name, + url: url, + data: data + })); + }; + }); + } + + + /** + * Makes the request. + * + * !!! ACCESSES CLOSURE VARS: + * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests + */ + function sendReq(config, reqData) { + var deferred = $q.defer(), + promise = deferred.promise, + cache, + cachedResp, + reqHeaders = config.headers, + url = buildUrl(config.url, config.paramSerializer(config.params)); + + $http.pendingRequests.push(config); + promise.then(removePendingReq, removePendingReq); + + + if ((config.cache || defaults.cache) && config.cache !== false && + (config.method === 'GET' || config.method === 'JSONP')) { + cache = isObject(config.cache) ? config.cache + : isObject(defaults.cache) ? defaults.cache + : defaultCache; + } + + if (cache) { + cachedResp = cache.get(url); + if (isDefined(cachedResp)) { + if (isPromiseLike(cachedResp)) { + // cached request has already been sent, but there is no response yet + cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult); + } else { + // serving from cache + if (isArray(cachedResp)) { + resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]); + } else { + resolvePromise(cachedResp, 200, {}, 'OK'); + } + } + } else { + // put the promise for the non-transformed response into cache as a placeholder + cache.put(url, promise); + } + } + + + // if we won't have the response in cache, set the xsrf headers and + // send the request to the backend + if (isUndefined(cachedResp)) { + var xsrfValue = urlIsSameOrigin(config.url) + ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName] + : undefined; + if (xsrfValue) { + reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue; + } + + $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, + config.withCredentials, config.responseType, + createApplyHandlers(config.eventHandlers), + createApplyHandlers(config.uploadEventHandlers)); + } + + return promise; + + function createApplyHandlers(eventHandlers) { + if (eventHandlers) { + var applyHandlers = {}; + forEach(eventHandlers, function(eventHandler, key) { + applyHandlers[key] = function(event) { + if (useApplyAsync) { + $rootScope.$applyAsync(callEventHandler); + } else if ($rootScope.$$phase) { + callEventHandler(); + } else { + $rootScope.$apply(callEventHandler); + } + + function callEventHandler() { + eventHandler(event); + } + }; + }); + return applyHandlers; + } + } + + + /** + * Callback registered to $httpBackend(): + * - caches the response if desired + * - resolves the raw $http promise + * - calls $apply + */ + function done(status, response, headersString, statusText) { + if (cache) { + if (isSuccess(status)) { + cache.put(url, [status, response, parseHeaders(headersString), statusText]); + } else { + // remove promise from the cache + cache.remove(url); + } + } + + function resolveHttpPromise() { + resolvePromise(response, status, headersString, statusText); + } + + if (useApplyAsync) { + $rootScope.$applyAsync(resolveHttpPromise); + } else { + resolveHttpPromise(); + if (!$rootScope.$$phase) $rootScope.$apply(); + } + } + + + /** + * Resolves the raw $http promise. + */ + function resolvePromise(response, status, headers, statusText) { + //status: HTTP response status code, 0, -1 (aborted by timeout / promise) + status = status >= -1 ? status : 0; + + (isSuccess(status) ? deferred.resolve : deferred.reject)({ + data: response, + status: status, + headers: headersGetter(headers), + config: config, + statusText: statusText + }); + } + + function resolvePromiseWithResult(result) { + resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText); + } + + function removePendingReq() { + var idx = $http.pendingRequests.indexOf(config); + if (idx !== -1) $http.pendingRequests.splice(idx, 1); + } + } + + + function buildUrl(url, serializedParams) { + if (serializedParams.length > 0) { + url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams; + } + return url; + } + }]; +} + +/** + * @ngdoc service + * @name $xhrFactory + * + * @description + * Factory function used to create XMLHttpRequest objects. + * + * Replace or decorate this service to create your own custom XMLHttpRequest objects. + * + * ``` + * angular.module('myApp', []) + * .factory('$xhrFactory', function() { + * return function createXhr(method, url) { + * return new window.XMLHttpRequest({mozSystem: true}); + * }; + * }); + * ``` + * + * @param {string} method HTTP method of the request (GET, POST, PUT, ..) + * @param {string} url URL of the request. + */ +function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; +} + +/** + * @ngdoc service + * @name $httpBackend + * @requires $jsonpCallbacks + * @requires $document + * @requires $xhrFactory + * + * @description + * HTTP backend used by the {@link ng.$http service} that delegates to + * XMLHttpRequest object or JSONP and deals with browser incompatibilities. + * + * You should never need to use this service directly, instead use the higher-level abstractions: + * {@link ng.$http $http} or {@link ngResource.$resource $resource}. + * + * During testing this implementation is swapped with {@link ngMock.$httpBackend mock + * $httpBackend} which can be trained with responses. + */ +function $HttpBackendProvider() { + this.$get = ['$browser', '$jsonpCallbacks', '$document', '$xhrFactory', function($browser, $jsonpCallbacks, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $jsonpCallbacks, $document[0]); + }]; +} + +function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { + // TODO(vojta): fix the signature + return function(method, url, post, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers) { + $browser.$$incOutstandingRequestCount(); + url = url || $browser.url(); + + if (lowercase(method) === 'jsonp') { + var callbackPath = callbacks.createCallback(url); + var jsonpDone = jsonpReq(url, callbackPath, function(status, text) { + // jsonpReq only ever sets status to 200 (OK), 404 (ERROR) or -1 (WAITING) + var response = (status === 200) && callbacks.getResponse(callbackPath); + completeRequest(callback, status, response, "", text); + callbacks.removeCallback(callbackPath); + }); + } else { + + var xhr = createXhr(method, url); + + xhr.open(method, url, true); + forEach(headers, function(value, key) { + if (isDefined(value)) { + xhr.setRequestHeader(key, value); + } + }); + + xhr.onload = function requestLoaded() { + var statusText = xhr.statusText || ''; + + // responseText is the old-school way of retrieving response (supported by IE9) + // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) + var response = ('response' in xhr) ? xhr.response : xhr.responseText; + + // normalize IE9 bug (http://bugs.jquery.com/ticket/1450) + var status = xhr.status === 1223 ? 204 : xhr.status; + + // fix status code when it is 0 (0 status is undocumented). + // Occurs when accessing file resources or on Android 4.1 stock browser + // while retrieving files from application cache. + if (status === 0) { + status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0; + } + + completeRequest(callback, + status, + response, + xhr.getAllResponseHeaders(), + statusText); + }; + + var requestError = function() { + // The response is always empty + // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error + completeRequest(callback, -1, null, null, ''); + }; + + xhr.onerror = requestError; + xhr.onabort = requestError; + + forEach(eventHandlers, function(value, key) { + xhr.addEventListener(key, value); + }); + + forEach(uploadEventHandlers, function(value, key) { + xhr.upload.addEventListener(key, value); + }); + + if (withCredentials) { + xhr.withCredentials = true; + } + + if (responseType) { + try { + xhr.responseType = responseType; + } catch (e) { + // WebKit added support for the json responseType value on 09/03/2013 + // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are + // known to throw when setting the value "json" as the response type. Other older + // browsers implementing the responseType + // + // The json response type can be ignored if not supported, because JSON payloads are + // parsed on the client-side regardless. + if (responseType !== 'json') { + throw e; + } + } + } + + xhr.send(isUndefined(post) ? null : post); + } + + if (timeout > 0) { + var timeoutId = $browserDefer(timeoutRequest, timeout); + } else if (isPromiseLike(timeout)) { + timeout.then(timeoutRequest); + } + + + function timeoutRequest() { + jsonpDone && jsonpDone(); + xhr && xhr.abort(); + } + + function completeRequest(callback, status, response, headersString, statusText) { + // cancel timeout and subsequent timeout promise resolution + if (isDefined(timeoutId)) { + $browserDefer.cancel(timeoutId); + } + jsonpDone = xhr = null; + + callback(status, response, headersString, statusText); + $browser.$$completeOutstandingRequest(noop); + } + }; + + function jsonpReq(url, callbackPath, done) { + url = url.replace('JSON_CALLBACK', callbackPath); + // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.: + // - fetches local scripts via XHR and evals them + // - adds and immediately removes script elements from the document + var script = rawDocument.createElement('script'), callback = null; + script.type = "text/javascript"; + script.src = url; + script.async = true; + + callback = function(event) { + removeEventListenerFn(script, "load", callback); + removeEventListenerFn(script, "error", callback); + rawDocument.body.removeChild(script); + script = null; + var status = -1; + var text = "unknown"; + + if (event) { + if (event.type === "load" && !callbacks.wasCalled(callbackPath)) { + event = { type: "error" }; + } + text = event.type; + status = event.type === "error" ? 404 : 200; + } + + if (done) { + done(status, text); + } + }; + + addEventListenerFn(script, "load", callback); + addEventListenerFn(script, "error", callback); + rawDocument.body.appendChild(script); + return callback; + } +} + +var $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate'); +$interpolateMinErr.throwNoconcat = function(text) { + throw $interpolateMinErr('noconcat', + "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + + "interpolations that concatenate multiple expressions when a trusted value is " + + "required. See http://docs.angularjs.org/api/ng.$sce", text); +}; + +$interpolateMinErr.interr = function(text, err) { + return $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString()); +}; + +/** + * @ngdoc provider + * @name $interpolateProvider + * + * @description + * + * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. + * + *
    + * This feature is sometimes used to mix different markup languages, e.g. to wrap an Angular + * template within a Python Jinja template (or any other template language). Mixing templating + * languages is **very dangerous**. The embedding template language will not safely escape Angular + * expressions, so any user-controlled values in the template will cause Cross Site Scripting (XSS) + * security bugs! + *
    + * + * @example + + + +
    + //demo.label// +
    +
    + + it('should interpolate binding with custom symbols', function() { + expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.'); + }); + +
    + */ +function $InterpolateProvider() { + var startSymbol = '{{'; + var endSymbol = '}}'; + + /** + * @ngdoc method + * @name $interpolateProvider#startSymbol + * @description + * Symbol to denote start of expression in the interpolated string. Defaults to `{{`. + * + * @param {string=} value new value to set the starting symbol to. + * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + */ + this.startSymbol = function(value) { + if (value) { + startSymbol = value; + return this; + } else { + return startSymbol; + } + }; + + /** + * @ngdoc method + * @name $interpolateProvider#endSymbol + * @description + * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. + * + * @param {string=} value new value to set the ending symbol to. + * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + */ + this.endSymbol = function(value) { + if (value) { + endSymbol = value; + return this; + } else { + return endSymbol; + } + }; + + + this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) { + var startSymbolLength = startSymbol.length, + endSymbolLength = endSymbol.length, + escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'), + escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g'); + + function escape(ch) { + return '\\\\\\' + ch; + } + + function unescapeText(text) { + return text.replace(escapedStartRegexp, startSymbol). + replace(escapedEndRegexp, endSymbol); + } + + function stringify(value) { + if (value == null) { // null || undefined + return ''; + } + switch (typeof value) { + case 'string': + break; + case 'number': + value = '' + value; + break; + default: + value = toJson(value); + } + + return value; + } + + //TODO: this is the same as the constantWatchDelegate in parse.js + function constantWatchDelegate(scope, listener, objectEquality, constantInterp) { + var unwatch; + return unwatch = scope.$watch(function constantInterpolateWatch(scope) { + unwatch(); + return constantInterp(scope); + }, listener, objectEquality); + } + + /** + * @ngdoc service + * @name $interpolate + * @kind function + * + * @requires $parse + * @requires $sce + * + * @description + * + * Compiles a string with markup into an interpolation function. This service is used by the + * HTML {@link ng.$compile $compile} service for data binding. See + * {@link ng.$interpolateProvider $interpolateProvider} for configuring the + * interpolation markup. + * + * + * ```js + * var $interpolate = ...; // injected + * var exp = $interpolate('Hello {{name | uppercase}}!'); + * expect(exp({name:'Angular'})).toEqual('Hello ANGULAR!'); + * ``` + * + * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is + * `true`, the interpolation function will return `undefined` unless all embedded expressions + * evaluate to a value other than `undefined`. + * + * ```js + * var $interpolate = ...; // injected + * var context = {greeting: 'Hello', name: undefined }; + * + * // default "forgiving" mode + * var exp = $interpolate('{{greeting}} {{name}}!'); + * expect(exp(context)).toEqual('Hello !'); + * + * // "allOrNothing" mode + * exp = $interpolate('{{greeting}} {{name}}!', false, null, true); + * expect(exp(context)).toBeUndefined(); + * context.name = 'Angular'; + * expect(exp(context)).toEqual('Hello Angular!'); + * ``` + * + * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior. + * + * #### Escaped Interpolation + * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers + * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash). + * It will be rendered as a regular start/end marker, and will not be interpreted as an expression + * or binding. + * + * This enables web-servers to prevent script injection attacks and defacing attacks, to some + * degree, while also enabling code examples to work without relying on the + * {@link ng.directive:ngNonBindable ngNonBindable} directive. + * + * **For security purposes, it is strongly encouraged that web servers escape user-supplied data, + * replacing angle brackets (<, >) with &lt; and &gt; respectively, and replacing all + * interpolation start/end markers with their escaped counterparts.** + * + * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered + * output when the $interpolate service processes the text. So, for HTML elements interpolated + * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter + * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such, + * this is typically useful only when user-data is used in rendering a template from the server, or + * when otherwise untrusted data is used by a directive. + * + * + * + *
    + *

    {{apptitle}}: \{\{ username = "defaced value"; \}\} + *

    + *

    {{username}} attempts to inject code which will deface the + * application, but fails to accomplish their task, because the server has correctly + * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash) + * characters.

    + *

    Instead, the result of the attempted script injection is visible, and can be removed + * from the database by an administrator.

    + *
    + *
    + *
    + * + * @knownIssue + * It is currently not possible for an interpolated expression to contain the interpolation end + * symbol. For example, `{{ '}}' }}` will be incorrectly interpreted as `{{ ' }}` + `' }}`, i.e. + * an interpolated expression consisting of a single-quote (`'`) and the `' }}` string. + * + * @knownIssue + * All directives and components must use the standard `{{` `}}` interpolation symbols + * in their templates. If you change the application interpolation symbols the {@link $compile} + * service will attempt to denormalize the standard symbols to the custom symbols. + * The denormalization process is not clever enough to know not to replace instances of the standard + * symbols where they would not normally be treated as interpolation symbols. For example in the following + * code snippet the closing braces of the literal object will get incorrectly denormalized: + * + * ``` + *
    + * ``` + * + * See https://github.com/angular/angular.js/pull/14610#issuecomment-219401099 for more information. + * + * @param {string} text The text with markup to interpolate. + * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have + * embedded expression in order to return an interpolation function. Strings with no + * embedded expression will return null for the interpolation function. + * @param {string=} trustedContext when provided, the returned function passes the interpolated + * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult, + * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that + * provides Strict Contextual Escaping for details. + * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined + * unless all embedded expressions evaluate to a value other than `undefined`. + * @returns {function(context)} an interpolation function which is used to compute the + * interpolated string. The function has these parameters: + * + * - `context`: evaluation context for all expressions embedded in the interpolated text + */ + function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { + // Provide a quick exit and simplified result function for text with no interpolation + if (!text.length || text.indexOf(startSymbol) === -1) { + var constantInterp; + if (!mustHaveExpression) { + var unescapedText = unescapeText(text); + constantInterp = valueFn(unescapedText); + constantInterp.exp = text; + constantInterp.expressions = []; + constantInterp.$$watchDelegate = constantWatchDelegate; + } + return constantInterp; + } + + allOrNothing = !!allOrNothing; + var startIndex, + endIndex, + index = 0, + expressions = [], + parseFns = [], + textLength = text.length, + exp, + concat = [], + expressionPositions = []; + + while (index < textLength) { + if (((startIndex = text.indexOf(startSymbol, index)) != -1) && + ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) { + if (index !== startIndex) { + concat.push(unescapeText(text.substring(index, startIndex))); + } + exp = text.substring(startIndex + startSymbolLength, endIndex); + expressions.push(exp); + parseFns.push($parse(exp, parseStringifyInterceptor)); + index = endIndex + endSymbolLength; + expressionPositions.push(concat.length); + concat.push(''); + } else { + // we did not find an interpolation, so we have to add the remainder to the separators array + if (index !== textLength) { + concat.push(unescapeText(text.substring(index))); + } + break; + } + } + + // Concatenating expressions makes it hard to reason about whether some combination of + // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a + // single expression be used for iframe[src], object[src], etc., we ensure that the value + // that's used is assigned or constructed by some JS code somewhere that is more testable or + // make it obvious that you bound the value to some user controlled value. This helps reduce + // the load when auditing for XSS issues. + if (trustedContext && concat.length > 1) { + $interpolateMinErr.throwNoconcat(text); + } + + if (!mustHaveExpression || expressions.length) { + var compute = function(values) { + for (var i = 0, ii = expressions.length; i < ii; i++) { + if (allOrNothing && isUndefined(values[i])) return; + concat[expressionPositions[i]] = values[i]; + } + return concat.join(''); + }; + + var getValue = function(value) { + return trustedContext ? + $sce.getTrusted(trustedContext, value) : + $sce.valueOf(value); + }; + + return extend(function interpolationFn(context) { + var i = 0; + var ii = expressions.length; + var values = new Array(ii); + + try { + for (; i < ii; i++) { + values[i] = parseFns[i](context); + } + + return compute(values); + } catch (err) { + $exceptionHandler($interpolateMinErr.interr(text, err)); + } + + }, { + // all of these properties are undocumented for now + exp: text, //just for compatibility with regular watchers created via $watch + expressions: expressions, + $$watchDelegate: function(scope, listener) { + var lastValue; + return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) { + var currValue = compute(values); + if (isFunction(listener)) { + listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope); + } + lastValue = currValue; + }); + } + }); + } + + function parseStringifyInterceptor(value) { + try { + value = getValue(value); + return allOrNothing && !isDefined(value) ? value : stringify(value); + } catch (err) { + $exceptionHandler($interpolateMinErr.interr(text, err)); + } + } + } + + + /** + * @ngdoc method + * @name $interpolate#startSymbol + * @description + * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`. + * + * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change + * the symbol. + * + * @returns {string} start symbol. + */ + $interpolate.startSymbol = function() { + return startSymbol; + }; + + + /** + * @ngdoc method + * @name $interpolate#endSymbol + * @description + * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. + * + * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change + * the symbol. + * + * @returns {string} end symbol. + */ + $interpolate.endSymbol = function() { + return endSymbol; + }; + + return $interpolate; + }]; +} + +function $IntervalProvider() { + this.$get = ['$rootScope', '$window', '$q', '$$q', '$browser', + function($rootScope, $window, $q, $$q, $browser) { + var intervals = {}; + + + /** + * @ngdoc service + * @name $interval + * + * @description + * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay` + * milliseconds. + * + * The return value of registering an interval function is a promise. This promise will be + * notified upon each tick of the interval, and will be resolved after `count` iterations, or + * run indefinitely if `count` is not defined. The value of the notification will be the + * number of iterations that have run. + * To cancel an interval, call `$interval.cancel(promise)`. + * + * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to + * move forward by `millis` milliseconds and trigger any functions scheduled to run in that + * time. + * + *
    + * **Note**: Intervals created by this service must be explicitly destroyed when you are finished + * with them. In particular they are not automatically destroyed when a controller's scope or a + * directive's element are destroyed. + * You should take this into consideration and make sure to always cancel the interval at the + * appropriate moment. See the example below for more details on how and when to do this. + *
    + * + * @param {function()} fn A function that should be called repeatedly. + * @param {number} delay Number of milliseconds between each function call. + * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat + * indefinitely. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. + * @returns {promise} A promise which will be notified on each iteration. + * + * @example + * + * + * + * + *
    + *
    + *
    + * Current time is: + *
    + * Blood 1 : {{blood_1}} + * Blood 2 : {{blood_2}} + * + * + * + *
    + *
    + * + *
    + *
    + */ + function interval(fn, delay, count, invokeApply) { + var hasParams = arguments.length > 4, + args = hasParams ? sliceArgs(arguments, 4) : [], + setInterval = $window.setInterval, + clearInterval = $window.clearInterval, + iteration = 0, + skipApply = (isDefined(invokeApply) && !invokeApply), + deferred = (skipApply ? $$q : $q).defer(), + promise = deferred.promise; + + count = isDefined(count) ? count : 0; + + promise.$$intervalId = setInterval(function tick() { + if (skipApply) { + $browser.defer(callback); + } else { + $rootScope.$evalAsync(callback); + } + deferred.notify(iteration++); + + if (count > 0 && iteration >= count) { + deferred.resolve(iteration); + clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + } + + if (!skipApply) $rootScope.$apply(); + + }, delay); + + intervals[promise.$$intervalId] = deferred; + + return promise; + + function callback() { + if (!hasParams) { + fn(iteration); + } else { + fn.apply(null, args); + } + } + } + + + /** + * @ngdoc method + * @name $interval#cancel + * + * @description + * Cancels a task associated with the `promise`. + * + * @param {Promise=} promise returned by the `$interval` function. + * @returns {boolean} Returns `true` if the task was successfully canceled. + */ + interval.cancel = function(promise) { + if (promise && promise.$$intervalId in intervals) { + intervals[promise.$$intervalId].reject('canceled'); + $window.clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + return true; + } + return false; + }; + + return interval; + }]; +} + +/** + * @ngdoc service + * @name $jsonpCallbacks + * @requires $window + * @description + * This service handles the lifecycle of callbacks to handle JSONP requests. + * Override this service if you wish to customise where the callbacks are stored and + * how they vary compared to the requested url. + */ +var $jsonpCallbacksProvider = function() { + this.$get = ['$window', function($window) { + var callbacks = $window.angular.callbacks; + var callbackMap = {}; + + function createCallback(callbackId) { + var callback = function(data) { + callback.data = data; + callback.called = true; + }; + callback.id = callbackId; + return callback; + } + + return { + /** + * @ngdoc method + * @name $jsonpCallbacks#createCallback + * @param {string} url the url of the JSONP request + * @returns {string} the callback path to send to the server as part of the JSONP request + * @description + * {@link $httpBackend} calls this method to create a callback and get hold of the path to the callback + * to pass to the server, which will be used to call the callback with its payload in the JSONP response. + */ + createCallback: function(url) { + var callbackId = '_' + (callbacks.$$counter++).toString(36); + var callbackPath = 'angular.callbacks.' + callbackId; + var callback = createCallback(callbackId); + callbackMap[callbackPath] = callbacks[callbackId] = callback; + return callbackPath; + }, + /** + * @ngdoc method + * @name $jsonpCallbacks#wasCalled + * @param {string} callbackPath the path to the callback that was sent in the JSONP request + * @returns {boolean} whether the callback has been called, as a result of the JSONP response + * @description + * {@link $httpBackend} calls this method to find out whether the JSONP response actually called the + * callback that was passed in the request. + */ + wasCalled: function(callbackPath) { + return callbackMap[callbackPath].called; + }, + /** + * @ngdoc method + * @name $jsonpCallbacks#getResponse + * @param {string} callbackPath the path to the callback that was sent in the JSONP request + * @returns {*} the data received from the response via the registered callback + * @description + * {@link $httpBackend} calls this method to get hold of the data that was provided to the callback + * in the JSONP response. + */ + getResponse: function(callbackPath) { + return callbackMap[callbackPath].data; + }, + /** + * @ngdoc method + * @name $jsonpCallbacks#removeCallback + * @param {string} callbackPath the path to the callback that was sent in the JSONP request + * @description + * {@link $httpBackend} calls this method to remove the callback after the JSONP request has + * completed or timed-out. + */ + removeCallback: function(callbackPath) { + var callback = callbackMap[callbackPath]; + delete callbacks[callback.id]; + delete callbackMap[callbackPath]; + } + }; + }]; +}; + +/** + * @ngdoc service + * @name $locale + * + * @description + * $locale service provides localization rules for various Angular components. As of right now the + * only public api is: + * + * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) + */ + +var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/, + DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21}; +var $locationMinErr = minErr('$location'); + + +/** + * Encode path using encodeUriSegment, ignoring forward slashes + * + * @param {string} path Path to encode + * @returns {string} + */ +function encodePath(path) { + var segments = path.split('/'), + i = segments.length; + + while (i--) { + segments[i] = encodeUriSegment(segments[i]); + } + + return segments.join('/'); +} + +function parseAbsoluteUrl(absoluteUrl, locationObj) { + var parsedUrl = urlResolve(absoluteUrl); + + locationObj.$$protocol = parsedUrl.protocol; + locationObj.$$host = parsedUrl.hostname; + locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; +} + + +function parseAppUrl(relativeUrl, locationObj) { + var prefixed = (relativeUrl.charAt(0) !== '/'); + if (prefixed) { + relativeUrl = '/' + relativeUrl; + } + var match = urlResolve(relativeUrl); + locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ? + match.pathname.substring(1) : match.pathname); + locationObj.$$search = parseKeyValue(match.search); + locationObj.$$hash = decodeURIComponent(match.hash); + + // make sure path starts with '/'; + if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') { + locationObj.$$path = '/' + locationObj.$$path; + } +} + +function startsWith(haystack, needle) { + return haystack.lastIndexOf(needle, 0) === 0; +} + +/** + * + * @param {string} base + * @param {string} url + * @returns {string} returns text from `url` after `base` or `undefined` if it does not begin with + * the expected string. + */ +function stripBaseUrl(base, url) { + if (startsWith(url, base)) { + return url.substr(base.length); + } +} + + +function stripHash(url) { + var index = url.indexOf('#'); + return index == -1 ? url : url.substr(0, index); +} + +function trimEmptyHash(url) { + return url.replace(/(#.+)|#$/, '$1'); +} + + +function stripFile(url) { + return url.substr(0, stripHash(url).lastIndexOf('/') + 1); +} + +/* return the server only (scheme://host:port) */ +function serverBase(url) { + return url.substring(0, url.indexOf('/', url.indexOf('//') + 2)); +} + + +/** + * LocationHtml5Url represents an url + * This object is exposed as $location service when HTML5 mode is enabled and supported + * + * @constructor + * @param {string} appBase application base URL + * @param {string} appBaseNoFile application base URL stripped of any filename + * @param {string} basePrefix url path prefix + */ +function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) { + this.$$html5 = true; + basePrefix = basePrefix || ''; + parseAbsoluteUrl(appBase, this); + + + /** + * Parse given html5 (regular) url string into properties + * @param {string} url HTML5 url + * @private + */ + this.$$parse = function(url) { + var pathUrl = stripBaseUrl(appBaseNoFile, url); + if (!isString(pathUrl)) { + throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url, + appBaseNoFile); + } + + parseAppUrl(pathUrl, this); + + if (!this.$$path) { + this.$$path = '/'; + } + + this.$$compose(); + }; + + /** + * Compose url and update `absUrl` property + * @private + */ + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/' + }; + + this.$$parseLinkUrl = function(url, relHref) { + if (relHref && relHref[0] === '#') { + // special case for links to hash fragments: + // keep the old url and only replace the hash fragment + this.hash(relHref.slice(1)); + return true; + } + var appUrl, prevAppUrl; + var rewrittenUrl; + + if (isDefined(appUrl = stripBaseUrl(appBase, url))) { + prevAppUrl = appUrl; + if (isDefined(appUrl = stripBaseUrl(basePrefix, appUrl))) { + rewrittenUrl = appBaseNoFile + (stripBaseUrl('/', appUrl) || appUrl); + } else { + rewrittenUrl = appBase + prevAppUrl; + } + } else if (isDefined(appUrl = stripBaseUrl(appBaseNoFile, url))) { + rewrittenUrl = appBaseNoFile + appUrl; + } else if (appBaseNoFile == url + '/') { + rewrittenUrl = appBaseNoFile; + } + if (rewrittenUrl) { + this.$$parse(rewrittenUrl); + } + return !!rewrittenUrl; + }; +} + + +/** + * LocationHashbangUrl represents url + * This object is exposed as $location service when developer doesn't opt into html5 mode. + * It also serves as the base class for html5 mode fallback on legacy browsers. + * + * @constructor + * @param {string} appBase application base URL + * @param {string} appBaseNoFile application base URL stripped of any filename + * @param {string} hashPrefix hashbang prefix + */ +function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) { + + parseAbsoluteUrl(appBase, this); + + + /** + * Parse given hashbang url into properties + * @param {string} url Hashbang url + * @private + */ + this.$$parse = function(url) { + var withoutBaseUrl = stripBaseUrl(appBase, url) || stripBaseUrl(appBaseNoFile, url); + var withoutHashUrl; + + if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') { + + // The rest of the url starts with a hash so we have + // got either a hashbang path or a plain hash fragment + withoutHashUrl = stripBaseUrl(hashPrefix, withoutBaseUrl); + if (isUndefined(withoutHashUrl)) { + // There was no hashbang prefix so we just have a hash fragment + withoutHashUrl = withoutBaseUrl; + } + + } else { + // There was no hashbang path nor hash fragment: + // If we are in HTML5 mode we use what is left as the path; + // Otherwise we ignore what is left + if (this.$$html5) { + withoutHashUrl = withoutBaseUrl; + } else { + withoutHashUrl = ''; + if (isUndefined(withoutBaseUrl)) { + appBase = url; + this.replace(); + } + } + } + + parseAppUrl(withoutHashUrl, this); + + this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase); + + this.$$compose(); + + /* + * In Windows, on an anchor node on documents loaded from + * the filesystem, the browser will return a pathname + * prefixed with the drive name ('/C:/path') when a + * pathname without a drive is set: + * * a.setAttribute('href', '/foo') + * * a.pathname === '/C:/foo' //true + * + * Inside of Angular, we're always using pathnames that + * do not include drive names for routing. + */ + function removeWindowsDriveName(path, url, base) { + /* + Matches paths for file protocol on windows, + such as /C:/foo/bar, and captures only /foo/bar. + */ + var windowsFilePathExp = /^\/[A-Z]:(\/.*)/; + + var firstPathSegmentMatch; + + //Get the relative path from the input URL. + if (startsWith(url, base)) { + url = url.replace(base, ''); + } + + // The input URL intentionally contains a first path segment that ends with a colon. + if (windowsFilePathExp.exec(url)) { + return path; + } + + firstPathSegmentMatch = windowsFilePathExp.exec(path); + return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; + } + }; + + /** + * Compose hashbang url and update `absUrl` property + * @private + */ + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : ''); + }; + + this.$$parseLinkUrl = function(url, relHref) { + if (stripHash(appBase) == stripHash(url)) { + this.$$parse(url); + return true; + } + return false; + }; +} + + +/** + * LocationHashbangUrl represents url + * This object is exposed as $location service when html5 history api is enabled but the browser + * does not support it. + * + * @constructor + * @param {string} appBase application base URL + * @param {string} appBaseNoFile application base URL stripped of any filename + * @param {string} hashPrefix hashbang prefix + */ +function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) { + this.$$html5 = true; + LocationHashbangUrl.apply(this, arguments); + + this.$$parseLinkUrl = function(url, relHref) { + if (relHref && relHref[0] === '#') { + // special case for links to hash fragments: + // keep the old url and only replace the hash fragment + this.hash(relHref.slice(1)); + return true; + } + + var rewrittenUrl; + var appUrl; + + if (appBase == stripHash(url)) { + rewrittenUrl = url; + } else if ((appUrl = stripBaseUrl(appBaseNoFile, url))) { + rewrittenUrl = appBase + hashPrefix + appUrl; + } else if (appBaseNoFile === url + '/') { + rewrittenUrl = appBaseNoFile; + } + if (rewrittenUrl) { + this.$$parse(rewrittenUrl); + } + return !!rewrittenUrl; + }; + + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + // include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#' + this.$$absUrl = appBase + hashPrefix + this.$$url; + }; + +} + + +var locationPrototype = { + + /** + * Ensure absolute url is initialized. + * @private + */ + $$absUrl:'', + + /** + * Are we in html5 mode? + * @private + */ + $$html5: false, + + /** + * Has any change been replacing? + * @private + */ + $$replace: false, + + /** + * @ngdoc method + * @name $location#absUrl + * + * @description + * This method is getter only. + * + * Return full url representation with all segments encoded according to rules specified in + * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt). + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var absUrl = $location.absUrl(); + * // => "http://example.com/#/some/path?foo=bar&baz=xoxo" + * ``` + * + * @return {string} full url + */ + absUrl: locationGetter('$$absUrl'), + + /** + * @ngdoc method + * @name $location#url + * + * @description + * This method is getter / setter. + * + * Return url (e.g. `/path?a=b#hash`) when called without any parameter. + * + * Change path, search and hash, when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var url = $location.url(); + * // => "/some/path?foo=bar&baz=xoxo" + * ``` + * + * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`) + * @return {string} url + */ + url: function(url) { + if (isUndefined(url)) { + return this.$$url; + } + + var match = PATH_MATCH.exec(url); + if (match[1] || url === '') this.path(decodeURIComponent(match[1])); + if (match[2] || match[1] || url === '') this.search(match[3] || ''); + this.hash(match[5] || ''); + + return this; + }, + + /** + * @ngdoc method + * @name $location#protocol + * + * @description + * This method is getter only. + * + * Return protocol of current url. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var protocol = $location.protocol(); + * // => "http" + * ``` + * + * @return {string} protocol of current url + */ + protocol: locationGetter('$$protocol'), + + /** + * @ngdoc method + * @name $location#host + * + * @description + * This method is getter only. + * + * Return host of current url. + * + * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var host = $location.host(); + * // => "example.com" + * + * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo + * host = $location.host(); + * // => "example.com" + * host = location.host; + * // => "example.com:8080" + * ``` + * + * @return {string} host of current url. + */ + host: locationGetter('$$host'), + + /** + * @ngdoc method + * @name $location#port + * + * @description + * This method is getter only. + * + * Return port of current url. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var port = $location.port(); + * // => 80 + * ``` + * + * @return {Number} port + */ + port: locationGetter('$$port'), + + /** + * @ngdoc method + * @name $location#path + * + * @description + * This method is getter / setter. + * + * Return path of current url when called without any parameter. + * + * Change path when called with parameter and return `$location`. + * + * Note: Path should always begin with forward slash (/), this method will add the forward slash + * if it is missing. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var path = $location.path(); + * // => "/some/path" + * ``` + * + * @param {(string|number)=} path New path + * @return {(string|object)} path if called with no parameters, or `$location` if called with a parameter + */ + path: locationGetterSetter('$$path', function(path) { + path = path !== null ? path.toString() : ''; + return path.charAt(0) == '/' ? path : '/' + path; + }), + + /** + * @ngdoc method + * @name $location#search + * + * @description + * This method is getter / setter. + * + * Return search part (as object) of current url when called without any parameter. + * + * Change search part when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var searchObject = $location.search(); + * // => {foo: 'bar', baz: 'xoxo'} + * + * // set foo to 'yipee' + * $location.search('foo', 'yipee'); + * // $location.search() => {foo: 'yipee', baz: 'xoxo'} + * ``` + * + * @param {string|Object.|Object.>} search New search params - string or + * hash object. + * + * When called with a single argument the method acts as a setter, setting the `search` component + * of `$location` to the specified value. + * + * If the argument is a hash object containing an array of values, these values will be encoded + * as duplicate search parameters in the url. + * + * @param {(string|Number|Array|boolean)=} paramValue If `search` is a string or number, then `paramValue` + * will override only a single search property. + * + * If `paramValue` is an array, it will override the property of the `search` component of + * `$location` specified via the first argument. + * + * If `paramValue` is `null`, the property specified via the first argument will be deleted. + * + * If `paramValue` is `true`, the property specified via the first argument will be added with no + * value nor trailing equal sign. + * + * @return {Object} If called with no arguments returns the parsed `search` object. If called with + * one or more arguments returns `$location` object itself. + */ + search: function(search, paramValue) { + switch (arguments.length) { + case 0: + return this.$$search; + case 1: + if (isString(search) || isNumber(search)) { + search = search.toString(); + this.$$search = parseKeyValue(search); + } else if (isObject(search)) { + search = copy(search, {}); + // remove object undefined or null properties + forEach(search, function(value, key) { + if (value == null) delete search[key]; + }); + + this.$$search = search; + } else { + throw $locationMinErr('isrcharg', + 'The first argument of the `$location#search()` call must be a string or an object.'); + } + break; + default: + if (isUndefined(paramValue) || paramValue === null) { + delete this.$$search[search]; + } else { + this.$$search[search] = paramValue; + } + } + + this.$$compose(); + return this; + }, + + /** + * @ngdoc method + * @name $location#hash + * + * @description + * This method is getter / setter. + * + * Returns the hash fragment when called without any parameters. + * + * Changes the hash fragment when called with a parameter and returns `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue + * var hash = $location.hash(); + * // => "hashValue" + * ``` + * + * @param {(string|number)=} hash New hash fragment + * @return {string} hash + */ + hash: locationGetterSetter('$$hash', function(hash) { + return hash !== null ? hash.toString() : ''; + }), + + /** + * @ngdoc method + * @name $location#replace + * + * @description + * If called, all changes to $location during the current `$digest` will replace the current history + * record, instead of adding a new one. + */ + replace: function() { + this.$$replace = true; + return this; + } +}; + +forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) { + Location.prototype = Object.create(locationPrototype); + + /** + * @ngdoc method + * @name $location#state + * + * @description + * This method is getter / setter. + * + * Return the history state object when called without any parameter. + * + * Change the history state object when called with one parameter and return `$location`. + * The state object is later passed to `pushState` or `replaceState`. + * + * NOTE: This method is supported only in HTML5 mode and only in browsers supporting + * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support + * older browsers (like IE9 or Android < 4.0), don't use this method. + * + * @param {object=} state State object for pushState or replaceState + * @return {object} state + */ + Location.prototype.state = function(state) { + if (!arguments.length) { + return this.$$state; + } + + if (Location !== LocationHtml5Url || !this.$$html5) { + throw $locationMinErr('nostate', 'History API state support is available only ' + + 'in HTML5 mode and only in browsers supporting HTML5 History API'); + } + // The user might modify `stateObject` after invoking `$location.state(stateObject)` + // but we're changing the $$state reference to $browser.state() during the $digest + // so the modification window is narrow. + this.$$state = isUndefined(state) ? null : state; + + return this; + }; +}); + + +function locationGetter(property) { + return function() { + return this[property]; + }; +} + + +function locationGetterSetter(property, preprocess) { + return function(value) { + if (isUndefined(value)) { + return this[property]; + } + + this[property] = preprocess(value); + this.$$compose(); + + return this; + }; +} + + +/** + * @ngdoc service + * @name $location + * + * @requires $rootElement + * + * @description + * The $location service parses the URL in the browser address bar (based on the + * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL + * available to your application. Changes to the URL in the address bar are reflected into + * $location service and changes to $location are reflected into the browser address bar. + * + * **The $location service:** + * + * - Exposes the current URL in the browser address bar, so you can + * - Watch and observe the URL. + * - Change the URL. + * - Synchronizes the URL with the browser when the user + * - Changes the address bar. + * - Clicks the back or forward button (or clicks a History link). + * - Clicks on a link. + * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash). + * + * For more information see {@link guide/$location Developer Guide: Using $location} + */ + +/** + * @ngdoc provider + * @name $locationProvider + * @description + * Use the `$locationProvider` to configure how the application deep linking paths are stored. + */ +function $LocationProvider() { + var hashPrefix = '', + html5Mode = { + enabled: false, + requireBase: true, + rewriteLinks: true + }; + + /** + * @ngdoc method + * @name $locationProvider#hashPrefix + * @description + * @param {string=} prefix Prefix for hash part (containing path and search) + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.hashPrefix = function(prefix) { + if (isDefined(prefix)) { + hashPrefix = prefix; + return this; + } else { + return hashPrefix; + } + }; + + /** + * @ngdoc method + * @name $locationProvider#html5Mode + * @description + * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value. + * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported + * properties: + * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to + * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not + * support `pushState`. + * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies + * whether or not a tag is required to be present. If `enabled` and `requireBase` are + * true, and a base tag is not present, an error will be thrown when `$location` is injected. + * See the {@link guide/$location $location guide for more information} + * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled, + * enables/disables url rewriting for relative links. + * + * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter + */ + this.html5Mode = function(mode) { + if (isBoolean(mode)) { + html5Mode.enabled = mode; + return this; + } else if (isObject(mode)) { + + if (isBoolean(mode.enabled)) { + html5Mode.enabled = mode.enabled; + } + + if (isBoolean(mode.requireBase)) { + html5Mode.requireBase = mode.requireBase; + } + + if (isBoolean(mode.rewriteLinks)) { + html5Mode.rewriteLinks = mode.rewriteLinks; + } + + return this; + } else { + return html5Mode; + } + }; + + /** + * @ngdoc event + * @name $location#$locationChangeStart + * @eventType broadcast on root scope + * @description + * Broadcasted before a URL will change. + * + * This change can be prevented by calling + * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more + * details about event object. Upon successful change + * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired. + * + * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when + * the browser supports the HTML5 History API. + * + * @param {Object} angularEvent Synthetic event object. + * @param {string} newUrl New URL + * @param {string=} oldUrl URL that was before it was changed. + * @param {string=} newState New history state object + * @param {string=} oldState History state object that was before it was changed. + */ + + /** + * @ngdoc event + * @name $location#$locationChangeSuccess + * @eventType broadcast on root scope + * @description + * Broadcasted after a URL was changed. + * + * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when + * the browser supports the HTML5 History API. + * + * @param {Object} angularEvent Synthetic event object. + * @param {string} newUrl New URL + * @param {string=} oldUrl URL that was before it was changed. + * @param {string=} newState New history state object + * @param {string=} oldState History state object that was before it was changed. + */ + + this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window', + function($rootScope, $browser, $sniffer, $rootElement, $window) { + var $location, + LocationMode, + baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to '' + initialUrl = $browser.url(), + appBase; + + if (html5Mode.enabled) { + if (!baseHref && html5Mode.requireBase) { + throw $locationMinErr('nobase', + "$location in HTML5 mode requires a tag to be present!"); + } + appBase = serverBase(initialUrl) + (baseHref || '/'); + LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url; + } else { + appBase = stripHash(initialUrl); + LocationMode = LocationHashbangUrl; + } + var appBaseNoFile = stripFile(appBase); + + $location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix); + $location.$$parseLinkUrl(initialUrl, initialUrl); + + $location.$$state = $browser.state(); + + var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i; + + function setBrowserUrlWithFallback(url, replace, state) { + var oldUrl = $location.url(); + var oldState = $location.$$state; + try { + $browser.url(url, replace, state); + + // Make sure $location.state() returns referentially identical (not just deeply equal) + // state object; this makes possible quick checking if the state changed in the digest + // loop. Checking deep equality would be too expensive. + $location.$$state = $browser.state(); + } catch (e) { + // Restore old values if pushState fails + $location.url(oldUrl); + $location.$$state = oldState; + + throw e; + } + } + + $rootElement.on('click', function(event) { + // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) + // currently we open nice url link and redirect then + + if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return; + + var elm = jqLite(event.target); + + // traverse the DOM up to find first A tag + while (nodeName_(elm[0]) !== 'a') { + // ignore rewriting if no A tag (reached root element, or no parent - removed from document) + if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; + } + + var absHref = elm.prop('href'); + // get the actual href attribute - see + // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx + var relHref = elm.attr('href') || elm.attr('xlink:href'); + + if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') { + // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during + // an animation. + absHref = urlResolve(absHref.animVal).href; + } + + // Ignore when url is started with javascript: or mailto: + if (IGNORE_URI_REGEXP.test(absHref)) return; + + if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) { + if ($location.$$parseLinkUrl(absHref, relHref)) { + // We do a preventDefault for all urls that are part of the angular application, + // in html5mode and also without, so that we are able to abort navigation without + // getting double entries in the location history. + event.preventDefault(); + // update location manually + if ($location.absUrl() != $browser.url()) { + $rootScope.$apply(); + // hack to work around FF6 bug 684208 when scenario runner clicks on links + $window.angular['ff-684208-preventDefault'] = true; + } + } + } + }); + + + // rewrite hashbang url <> html5 url + if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) { + $browser.url($location.absUrl(), true); + } + + var initializing = true; + + // update $location when $browser url changes + $browser.onUrlChange(function(newUrl, newState) { + + if (isUndefined(stripBaseUrl(appBaseNoFile, newUrl))) { + // If we are navigating outside of the app then force a reload + $window.location.href = newUrl; + return; + } + + $rootScope.$evalAsync(function() { + var oldUrl = $location.absUrl(); + var oldState = $location.$$state; + var defaultPrevented; + newUrl = trimEmptyHash(newUrl); + $location.$$parse(newUrl); + $location.$$state = newState; + + defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, + newState, oldState).defaultPrevented; + + // if the location was changed by a `$locationChangeStart` handler then stop + // processing this location change + if ($location.absUrl() !== newUrl) return; + + if (defaultPrevented) { + $location.$$parse(oldUrl); + $location.$$state = oldState; + setBrowserUrlWithFallback(oldUrl, false, oldState); + } else { + initializing = false; + afterLocationChange(oldUrl, oldState); + } + }); + if (!$rootScope.$$phase) $rootScope.$digest(); + }); + + // update browser + $rootScope.$watch(function $locationWatch() { + var oldUrl = trimEmptyHash($browser.url()); + var newUrl = trimEmptyHash($location.absUrl()); + var oldState = $browser.state(); + var currentReplace = $location.$$replace; + var urlOrStateChanged = oldUrl !== newUrl || + ($location.$$html5 && $sniffer.history && oldState !== $location.$$state); + + if (initializing || urlOrStateChanged) { + initializing = false; + + $rootScope.$evalAsync(function() { + var newUrl = $location.absUrl(); + var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, + $location.$$state, oldState).defaultPrevented; + + // if the location was changed by a `$locationChangeStart` handler then stop + // processing this location change + if ($location.absUrl() !== newUrl) return; + + if (defaultPrevented) { + $location.$$parse(oldUrl); + $location.$$state = oldState; + } else { + if (urlOrStateChanged) { + setBrowserUrlWithFallback(newUrl, currentReplace, + oldState === $location.$$state ? null : $location.$$state); + } + afterLocationChange(oldUrl, oldState); + } + }); + } + + $location.$$replace = false; + + // we don't need to return anything because $evalAsync will make the digest loop dirty when + // there is a change + }); + + return $location; + + function afterLocationChange(oldUrl, oldState) { + $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl, + $location.$$state, oldState); + } +}]; +} + +/** + * @ngdoc service + * @name $log + * @requires $window + * + * @description + * Simple service for logging. Default implementation safely writes the message + * into the browser's console (if present). + * + * The main purpose of this service is to simplify debugging and troubleshooting. + * + * The default is to log `debug` messages. You can use + * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this. + * + * @example + + + angular.module('logExample', []) + .controller('LogController', ['$scope', '$log', function($scope, $log) { + $scope.$log = $log; + $scope.message = 'Hello World!'; + }]); + + +
    +

    Reload this page with open console, enter text and hit the log button...

    + + + + + + +
    +
    +
    + */ + +/** + * @ngdoc provider + * @name $logProvider + * @description + * Use the `$logProvider` to configure how the application logs messages + */ +function $LogProvider() { + var debug = true, + self = this; + + /** + * @ngdoc method + * @name $logProvider#debugEnabled + * @description + * @param {boolean=} flag enable or disable debug level messages + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.debugEnabled = function(flag) { + if (isDefined(flag)) { + debug = flag; + return this; + } else { + return debug; + } + }; + + this.$get = ['$window', function($window) { + return { + /** + * @ngdoc method + * @name $log#log + * + * @description + * Write a log message + */ + log: consoleLog('log'), + + /** + * @ngdoc method + * @name $log#info + * + * @description + * Write an information message + */ + info: consoleLog('info'), + + /** + * @ngdoc method + * @name $log#warn + * + * @description + * Write a warning message + */ + warn: consoleLog('warn'), + + /** + * @ngdoc method + * @name $log#error + * + * @description + * Write an error message + */ + error: consoleLog('error'), + + /** + * @ngdoc method + * @name $log#debug + * + * @description + * Write a debug message + */ + debug: (function() { + var fn = consoleLog('debug'); + + return function() { + if (debug) { + fn.apply(self, arguments); + } + }; + }()) + }; + + function formatError(arg) { + if (arg instanceof Error) { + if (arg.stack) { + arg = (arg.message && arg.stack.indexOf(arg.message) === -1) + ? 'Error: ' + arg.message + '\n' + arg.stack + : arg.stack; + } else if (arg.sourceURL) { + arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line; + } + } + return arg; + } + + function consoleLog(type) { + var console = $window.console || {}, + logFn = console[type] || console.log || noop, + hasApply = false; + + // Note: reading logFn.apply throws an error in IE11 in IE8 document mode. + // The reason behind this is that console.log has type "object" in IE8... + try { + hasApply = !!logFn.apply; + } catch (e) {} + + if (hasApply) { + return function() { + var args = []; + forEach(arguments, function(arg) { + args.push(formatError(arg)); + }); + return logFn.apply(console, args); + }; + } + + // we are IE which either doesn't have window.console => this is noop and we do nothing, + // or we are IE where console.log doesn't have apply so we log at least first 2 args + return function(arg1, arg2) { + logFn(arg1, arg2 == null ? '' : arg2); + }; + } + }]; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +var $parseMinErr = minErr('$parse'); + +// Sandboxing Angular Expressions +// ------------------------------ +// Angular expressions are generally considered safe because these expressions only have direct +// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by +// obtaining a reference to native JS functions such as the Function constructor. +// +// As an example, consider the following Angular expression: +// +// {}.toString.constructor('alert("evil JS code")') +// +// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits +// against the expression language, but not to prevent exploits that were enabled by exposing +// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good +// practice and therefore we are not even trying to protect against interaction with an object +// explicitly exposed in this way. +// +// In general, it is not possible to access a Window object from an angular expression unless a +// window or some DOM object that has a reference to window is published onto a Scope. +// Similarly we prevent invocations of function known to be dangerous, as well as assignments to +// native objects. +// +// See https://docs.angularjs.org/guide/security + + +function ensureSafeMemberName(name, fullExpression) { + if (name === "__defineGetter__" || name === "__defineSetter__" + || name === "__lookupGetter__" || name === "__lookupSetter__" + || name === "__proto__") { + throw $parseMinErr('isecfld', + 'Attempting to access a disallowed field in Angular expressions! ' + + 'Expression: {0}', fullExpression); + } + return name; +} + +function getStringValue(name) { + // Property names must be strings. This means that non-string objects cannot be used + // as keys in an object. Any non-string object, including a number, is typecasted + // into a string via the toString method. + // -- MDN, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names + // + // So, to ensure that we are checking the same `name` that JavaScript would use, we cast it + // to a string. It's not always possible. If `name` is an object and its `toString` method is + // 'broken' (doesn't return a string, isn't a function, etc.), an error will be thrown: + // + // TypeError: Cannot convert object to primitive value + // + // For performance reasons, we don't catch this error here and allow it to propagate up the call + // stack. Note that you'll get the same error in JavaScript if you try to access a property using + // such a 'broken' object as a key. + return name + ''; +} + +function ensureSafeObject(obj, fullExpression) { + // nifty check if obj is Function that is fast and works across iframes and other contexts + if (obj) { + if (obj.constructor === obj) { + throw $parseMinErr('isecfn', + 'Referencing Function in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// isWindow(obj) + obj.window === obj) { + throw $parseMinErr('isecwindow', + 'Referencing the Window in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// isElement(obj) + obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) { + throw $parseMinErr('isecdom', + 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// block Object so that we can't get hold of dangerous Object.* methods + obj === Object) { + throw $parseMinErr('isecobj', + 'Referencing Object in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } + } + return obj; +} + +var CALL = Function.prototype.call; +var APPLY = Function.prototype.apply; +var BIND = Function.prototype.bind; + +function ensureSafeFunction(obj, fullExpression) { + if (obj) { + if (obj.constructor === obj) { + throw $parseMinErr('isecfn', + 'Referencing Function in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (obj === CALL || obj === APPLY || obj === BIND) { + throw $parseMinErr('isecff', + 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } + } +} + +function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === (0).constructor || obj === (false).constructor || obj === ''.constructor || + obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr('isecaf', + 'Assigning to a constructor is disallowed! Expression: {0}', fullExpression); + } + } +} + +var OPERATORS = createMap(); +forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; }); +var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; + + +///////////////////////////////////////// + + +/** + * @constructor + */ +var Lexer = function(options) { + this.options = options; +}; + +Lexer.prototype = { + constructor: Lexer, + + lex: function(text) { + this.text = text; + this.index = 0; + this.tokens = []; + + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + if (ch === '"' || ch === "'") { + this.readString(ch); + } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) { + this.readNumber(); + } else if (this.isIdentifierStart(this.peekMultichar())) { + this.readIdent(); + } else if (this.is(ch, '(){}[].,;:?')) { + this.tokens.push({index: this.index, text: ch}); + this.index++; + } else if (this.isWhitespace(ch)) { + this.index++; + } else { + var ch2 = ch + this.peek(); + var ch3 = ch2 + this.peek(2); + var op1 = OPERATORS[ch]; + var op2 = OPERATORS[ch2]; + var op3 = OPERATORS[ch3]; + if (op1 || op2 || op3) { + var token = op3 ? ch3 : (op2 ? ch2 : ch); + this.tokens.push({index: this.index, text: token, operator: true}); + this.index += token.length; + } else { + this.throwError('Unexpected next character ', this.index, this.index + 1); + } + } + } + return this.tokens; + }, + + is: function(ch, chars) { + return chars.indexOf(ch) !== -1; + }, + + peek: function(i) { + var num = i || 1; + return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false; + }, + + isNumber: function(ch) { + return ('0' <= ch && ch <= '9') && typeof ch === "string"; + }, + + isWhitespace: function(ch) { + // IE treats non-breaking space as \u00A0 + return (ch === ' ' || ch === '\r' || ch === '\t' || + ch === '\n' || ch === '\v' || ch === '\u00A0'); + }, + + isIdentifierStart: function(ch) { + return this.options.isIdentifierStart ? + this.options.isIdentifierStart(ch, this.codePointAt(ch)) : + this.isValidIdentifierStart(ch); + }, + + isValidIdentifierStart: function(ch) { + return ('a' <= ch && ch <= 'z' || + 'A' <= ch && ch <= 'Z' || + '_' === ch || ch === '$'); + }, + + isIdentifierContinue: function(ch) { + return this.options.isIdentifierContinue ? + this.options.isIdentifierContinue(ch, this.codePointAt(ch)) : + this.isValidIdentifierContinue(ch); + }, + + isValidIdentifierContinue: function(ch, cp) { + return this.isValidIdentifierStart(ch, cp) || this.isNumber(ch); + }, + + codePointAt: function(ch) { + if (ch.length === 1) return ch.charCodeAt(0); + /*jshint bitwise: false*/ + return (ch.charCodeAt(0) << 10) + ch.charCodeAt(1) - 0x35FDC00; + /*jshint bitwise: true*/ + }, + + peekMultichar: function() { + var ch = this.text.charAt(this.index); + var peek = this.peek(); + if (!peek) { + return ch; + } + var cp1 = ch.charCodeAt(0); + var cp2 = peek.charCodeAt(0); + if (cp1 >= 0xD800 && cp1 <= 0xDBFF && cp2 >= 0xDC00 && cp2 <= 0xDFFF) { + return ch + peek; + } + return ch; + }, + + isExpOperator: function(ch) { + return (ch === '-' || ch === '+' || this.isNumber(ch)); + }, + + throwError: function(error, start, end) { + end = end || this.index; + var colStr = (isDefined(start) + ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']' + : ' ' + end); + throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].', + error, colStr, this.text); + }, + + readNumber: function() { + var number = ''; + var start = this.index; + while (this.index < this.text.length) { + var ch = lowercase(this.text.charAt(this.index)); + if (ch == '.' || this.isNumber(ch)) { + number += ch; + } else { + var peekCh = this.peek(); + if (ch == 'e' && this.isExpOperator(peekCh)) { + number += ch; + } else if (this.isExpOperator(ch) && + peekCh && this.isNumber(peekCh) && + number.charAt(number.length - 1) == 'e') { + number += ch; + } else if (this.isExpOperator(ch) && + (!peekCh || !this.isNumber(peekCh)) && + number.charAt(number.length - 1) == 'e') { + this.throwError('Invalid exponent'); + } else { + break; + } + } + this.index++; + } + this.tokens.push({ + index: start, + text: number, + constant: true, + value: Number(number) + }); + }, + + readIdent: function() { + var start = this.index; + this.index += this.peekMultichar().length; + while (this.index < this.text.length) { + var ch = this.peekMultichar(); + if (!this.isIdentifierContinue(ch)) { + break; + } + this.index += ch.length; + } + this.tokens.push({ + index: start, + text: this.text.slice(start, this.index), + identifier: true + }); + }, + + readString: function(quote) { + var start = this.index; + this.index++; + var string = ''; + var rawString = quote; + var escape = false; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + rawString += ch; + if (escape) { + if (ch === 'u') { + var hex = this.text.substring(this.index + 1, this.index + 5); + if (!hex.match(/[\da-f]{4}/i)) { + this.throwError('Invalid unicode escape [\\u' + hex + ']'); + } + this.index += 4; + string += String.fromCharCode(parseInt(hex, 16)); + } else { + var rep = ESCAPE[ch]; + string = string + (rep || ch); + } + escape = false; + } else if (ch === '\\') { + escape = true; + } else if (ch === quote) { + this.index++; + this.tokens.push({ + index: start, + text: rawString, + constant: true, + value: string + }); + return; + } else { + string += ch; + } + this.index++; + } + this.throwError('Unterminated quote', start); + } +}; + +var AST = function(lexer, options) { + this.lexer = lexer; + this.options = options; +}; + +AST.Program = 'Program'; +AST.ExpressionStatement = 'ExpressionStatement'; +AST.AssignmentExpression = 'AssignmentExpression'; +AST.ConditionalExpression = 'ConditionalExpression'; +AST.LogicalExpression = 'LogicalExpression'; +AST.BinaryExpression = 'BinaryExpression'; +AST.UnaryExpression = 'UnaryExpression'; +AST.CallExpression = 'CallExpression'; +AST.MemberExpression = 'MemberExpression'; +AST.Identifier = 'Identifier'; +AST.Literal = 'Literal'; +AST.ArrayExpression = 'ArrayExpression'; +AST.Property = 'Property'; +AST.ObjectExpression = 'ObjectExpression'; +AST.ThisExpression = 'ThisExpression'; +AST.LocalsExpression = 'LocalsExpression'; + +// Internal use only +AST.NGValueParameter = 'NGValueParameter'; + +AST.prototype = { + ast: function(text) { + this.text = text; + this.tokens = this.lexer.lex(text); + + var value = this.program(); + + if (this.tokens.length !== 0) { + this.throwError('is an unexpected token', this.tokens[0]); + } + + return value; + }, + + program: function() { + var body = []; + while (true) { + if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']')) + body.push(this.expressionStatement()); + if (!this.expect(';')) { + return { type: AST.Program, body: body}; + } + } + }, + + expressionStatement: function() { + return { type: AST.ExpressionStatement, expression: this.filterChain() }; + }, + + filterChain: function() { + var left = this.expression(); + var token; + while ((token = this.expect('|'))) { + left = this.filter(left); + } + return left; + }, + + expression: function() { + return this.assignment(); + }, + + assignment: function() { + var result = this.ternary(); + if (this.expect('=')) { + result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='}; + } + return result; + }, + + ternary: function() { + var test = this.logicalOR(); + var alternate; + var consequent; + if (this.expect('?')) { + alternate = this.expression(); + if (this.consume(':')) { + consequent = this.expression(); + return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent}; + } + } + return test; + }, + + logicalOR: function() { + var left = this.logicalAND(); + while (this.expect('||')) { + left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() }; + } + return left; + }, + + logicalAND: function() { + var left = this.equality(); + while (this.expect('&&')) { + left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()}; + } + return left; + }, + + equality: function() { + var left = this.relational(); + var token; + while ((token = this.expect('==','!=','===','!=='))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() }; + } + return left; + }, + + relational: function() { + var left = this.additive(); + var token; + while ((token = this.expect('<', '>', '<=', '>='))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() }; + } + return left; + }, + + additive: function() { + var left = this.multiplicative(); + var token; + while ((token = this.expect('+','-'))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() }; + } + return left; + }, + + multiplicative: function() { + var left = this.unary(); + var token; + while ((token = this.expect('*','/','%'))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() }; + } + return left; + }, + + unary: function() { + var token; + if ((token = this.expect('+', '-', '!'))) { + return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() }; + } else { + return this.primary(); + } + }, + + primary: function() { + var primary; + if (this.expect('(')) { + primary = this.filterChain(); + this.consume(')'); + } else if (this.expect('[')) { + primary = this.arrayDeclaration(); + } else if (this.expect('{')) { + primary = this.object(); + } else if (this.selfReferential.hasOwnProperty(this.peek().text)) { + primary = copy(this.selfReferential[this.consume().text]); + } else if (this.options.literals.hasOwnProperty(this.peek().text)) { + primary = { type: AST.Literal, value: this.options.literals[this.consume().text]}; + } else if (this.peek().identifier) { + primary = this.identifier(); + } else if (this.peek().constant) { + primary = this.constant(); + } else { + this.throwError('not a primary expression', this.peek()); + } + + var next; + while ((next = this.expect('(', '[', '.'))) { + if (next.text === '(') { + primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() }; + this.consume(')'); + } else if (next.text === '[') { + primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true }; + this.consume(']'); + } else if (next.text === '.') { + primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false }; + } else { + this.throwError('IMPOSSIBLE'); + } + } + return primary; + }, + + filter: function(baseExpression) { + var args = [baseExpression]; + var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true}; + + while (this.expect(':')) { + args.push(this.expression()); + } + + return result; + }, + + parseArguments: function() { + var args = []; + if (this.peekToken().text !== ')') { + do { + args.push(this.filterChain()); + } while (this.expect(',')); + } + return args; + }, + + identifier: function() { + var token = this.consume(); + if (!token.identifier) { + this.throwError('is not a valid identifier', token); + } + return { type: AST.Identifier, name: token.text }; + }, + + constant: function() { + // TODO check that it is a constant + return { type: AST.Literal, value: this.consume().value }; + }, + + arrayDeclaration: function() { + var elements = []; + if (this.peekToken().text !== ']') { + do { + if (this.peek(']')) { + // Support trailing commas per ES5.1. + break; + } + elements.push(this.expression()); + } while (this.expect(',')); + } + this.consume(']'); + + return { type: AST.ArrayExpression, elements: elements }; + }, + + object: function() { + var properties = [], property; + if (this.peekToken().text !== '}') { + do { + if (this.peek('}')) { + // Support trailing commas per ES5.1. + break; + } + property = {type: AST.Property, kind: 'init'}; + if (this.peek().constant) { + property.key = this.constant(); + property.computed = false; + this.consume(':'); + property.value = this.expression(); + } else if (this.peek().identifier) { + property.key = this.identifier(); + property.computed = false; + if (this.peek(':')) { + this.consume(':'); + property.value = this.expression(); + } else { + property.value = property.key; + } + } else if (this.peek('[')) { + this.consume('['); + property.key = this.expression(); + this.consume(']'); + property.computed = true; + this.consume(':'); + property.value = this.expression(); + } else { + this.throwError("invalid key", this.peek()); + } + properties.push(property); + } while (this.expect(',')); + } + this.consume('}'); + + return {type: AST.ObjectExpression, properties: properties }; + }, + + throwError: function(msg, token) { + throw $parseMinErr('syntax', + 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].', + token.text, msg, (token.index + 1), this.text, this.text.substring(token.index)); + }, + + consume: function(e1) { + if (this.tokens.length === 0) { + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); + } + + var token = this.expect(e1); + if (!token) { + this.throwError('is unexpected, expecting [' + e1 + ']', this.peek()); + } + return token; + }, + + peekToken: function() { + if (this.tokens.length === 0) { + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); + } + return this.tokens[0]; + }, + + peek: function(e1, e2, e3, e4) { + return this.peekAhead(0, e1, e2, e3, e4); + }, + + peekAhead: function(i, e1, e2, e3, e4) { + if (this.tokens.length > i) { + var token = this.tokens[i]; + var t = token.text; + if (t === e1 || t === e2 || t === e3 || t === e4 || + (!e1 && !e2 && !e3 && !e4)) { + return token; + } + } + return false; + }, + + expect: function(e1, e2, e3, e4) { + var token = this.peek(e1, e2, e3, e4); + if (token) { + this.tokens.shift(); + return token; + } + return false; + }, + + selfReferential: { + 'this': {type: AST.ThisExpression }, + '$locals': {type: AST.LocalsExpression } + } +}; + +function ifDefined(v, d) { + return typeof v !== 'undefined' ? v : d; +} + +function plusFn(l, r) { + if (typeof l === 'undefined') return r; + if (typeof r === 'undefined') return l; + return l + r; +} + +function isStateless($filter, filterName) { + var fn = $filter(filterName); + return !fn.$stateful; +} + +function findConstantAndWatchExpressions(ast, $filter) { + var allConstants; + var argsToWatch; + switch (ast.type) { + case AST.Program: + allConstants = true; + forEach(ast.body, function(expr) { + findConstantAndWatchExpressions(expr.expression, $filter); + allConstants = allConstants && expr.expression.constant; + }); + ast.constant = allConstants; + break; + case AST.Literal: + ast.constant = true; + ast.toWatch = []; + break; + case AST.UnaryExpression: + findConstantAndWatchExpressions(ast.argument, $filter); + ast.constant = ast.argument.constant; + ast.toWatch = ast.argument.toWatch; + break; + case AST.BinaryExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch); + break; + case AST.LogicalExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = ast.constant ? [] : [ast]; + break; + case AST.ConditionalExpression: + findConstantAndWatchExpressions(ast.test, $filter); + findConstantAndWatchExpressions(ast.alternate, $filter); + findConstantAndWatchExpressions(ast.consequent, $filter); + ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant; + ast.toWatch = ast.constant ? [] : [ast]; + break; + case AST.Identifier: + ast.constant = false; + ast.toWatch = [ast]; + break; + case AST.MemberExpression: + findConstantAndWatchExpressions(ast.object, $filter); + if (ast.computed) { + findConstantAndWatchExpressions(ast.property, $filter); + } + ast.constant = ast.object.constant && (!ast.computed || ast.property.constant); + ast.toWatch = [ast]; + break; + case AST.CallExpression: + allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false; + argsToWatch = []; + forEach(ast.arguments, function(expr) { + findConstantAndWatchExpressions(expr, $filter); + allConstants = allConstants && expr.constant; + if (!expr.constant) { + argsToWatch.push.apply(argsToWatch, expr.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast]; + break; + case AST.AssignmentExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = [ast]; + break; + case AST.ArrayExpression: + allConstants = true; + argsToWatch = []; + forEach(ast.elements, function(expr) { + findConstantAndWatchExpressions(expr, $filter); + allConstants = allConstants && expr.constant; + if (!expr.constant) { + argsToWatch.push.apply(argsToWatch, expr.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = argsToWatch; + break; + case AST.ObjectExpression: + allConstants = true; + argsToWatch = []; + forEach(ast.properties, function(property) { + findConstantAndWatchExpressions(property.value, $filter); + allConstants = allConstants && property.value.constant && !property.computed; + if (!property.value.constant) { + argsToWatch.push.apply(argsToWatch, property.value.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = argsToWatch; + break; + case AST.ThisExpression: + ast.constant = false; + ast.toWatch = []; + break; + case AST.LocalsExpression: + ast.constant = false; + ast.toWatch = []; + break; + } +} + +function getInputs(body) { + if (body.length != 1) return; + var lastExpression = body[0].expression; + var candidate = lastExpression.toWatch; + if (candidate.length !== 1) return candidate; + return candidate[0] !== lastExpression ? candidate : undefined; +} + +function isAssignable(ast) { + return ast.type === AST.Identifier || ast.type === AST.MemberExpression; +} + +function assignableAST(ast) { + if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) { + return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='}; + } +} + +function isLiteral(ast) { + return ast.body.length === 0 || + ast.body.length === 1 && ( + ast.body[0].expression.type === AST.Literal || + ast.body[0].expression.type === AST.ArrayExpression || + ast.body[0].expression.type === AST.ObjectExpression); +} + +function isConstant(ast) { + return ast.constant; +} + +function ASTCompiler(astBuilder, $filter) { + this.astBuilder = astBuilder; + this.$filter = $filter; +} + +ASTCompiler.prototype = { + compile: function(expression, expensiveChecks) { + var self = this; + var ast = this.astBuilder.ast(expression); + this.state = { + nextId: 0, + filters: {}, + expensiveChecks: expensiveChecks, + fn: {vars: [], body: [], own: {}}, + assign: {vars: [], body: [], own: {}}, + inputs: [] + }; + findConstantAndWatchExpressions(ast, self.$filter); + var extra = ''; + var assignable; + this.stage = 'assign'; + if ((assignable = assignableAST(ast))) { + this.state.computing = 'assign'; + var result = this.nextId(); + this.recurse(assignable, result); + this.return_(result); + extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l'); + } + var toWatch = getInputs(ast.body); + self.stage = 'inputs'; + forEach(toWatch, function(watch, key) { + var fnKey = 'fn' + key; + self.state[fnKey] = {vars: [], body: [], own: {}}; + self.state.computing = fnKey; + var intoId = self.nextId(); + self.recurse(watch, intoId); + self.return_(intoId); + self.state.inputs.push(fnKey); + watch.watchId = key; + }); + this.state.computing = 'fn'; + this.stage = 'main'; + this.recurse(ast); + var fnString = + // The build and minification steps remove the string "use strict" from the code, but this is done using a regex. + // This is a workaround for this until we do a better job at only removing the prefix only when we should. + '"' + this.USE + ' ' + this.STRICT + '";\n' + + this.filterPrefix() + + 'var fn=' + this.generateFunction('fn', 's,l,a,i') + + extra + + this.watchFns() + + 'return fn;'; + + /* jshint -W054 */ + var fn = (new Function('$filter', + 'ensureSafeMemberName', + 'ensureSafeObject', + 'ensureSafeFunction', + 'getStringValue', + 'ensureSafeAssignContext', + 'ifDefined', + 'plus', + 'text', + fnString))( + this.$filter, + ensureSafeMemberName, + ensureSafeObject, + ensureSafeFunction, + getStringValue, + ensureSafeAssignContext, + ifDefined, + plusFn, + expression); + /* jshint +W054 */ + this.state = this.stage = undefined; + fn.literal = isLiteral(ast); + fn.constant = isConstant(ast); + return fn; + }, + + USE: 'use', + + STRICT: 'strict', + + watchFns: function() { + var result = []; + var fns = this.state.inputs; + var self = this; + forEach(fns, function(name) { + result.push('var ' + name + '=' + self.generateFunction(name, 's')); + }); + if (fns.length) { + result.push('fn.inputs=[' + fns.join(',') + '];'); + } + return result.join(''); + }, + + generateFunction: function(name, params) { + return 'function(' + params + '){' + + this.varsPrefix(name) + + this.body(name) + + '};'; + }, + + filterPrefix: function() { + var parts = []; + var self = this; + forEach(this.state.filters, function(id, filter) { + parts.push(id + '=$filter(' + self.escape(filter) + ')'); + }); + if (parts.length) return 'var ' + parts.join(',') + ';'; + return ''; + }, + + varsPrefix: function(section) { + return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : ''; + }, + + body: function(section) { + return this.state[section].body.join(''); + }, + + recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { + var left, right, self = this, args, expression, computed; + recursionFn = recursionFn || noop; + if (!skipWatchIdCheck && isDefined(ast.watchId)) { + intoId = intoId || this.nextId(); + this.if_('i', + this.lazyAssign(intoId, this.computedMember('i', ast.watchId)), + this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true) + ); + return; + } + switch (ast.type) { + case AST.Program: + forEach(ast.body, function(expression, pos) { + self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; }); + if (pos !== ast.body.length - 1) { + self.current().body.push(right, ';'); + } else { + self.return_(right); + } + }); + break; + case AST.Literal: + expression = this.escape(ast.value); + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.UnaryExpression: + this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; }); + expression = ast.operator + '(' + this.ifDefined(right, 0) + ')'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.BinaryExpression: + this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; }); + this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; }); + if (ast.operator === '+') { + expression = this.plus(left, right); + } else if (ast.operator === '-') { + expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0); + } else { + expression = '(' + left + ')' + ast.operator + '(' + right + ')'; + } + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.LogicalExpression: + intoId = intoId || this.nextId(); + self.recurse(ast.left, intoId); + self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId)); + recursionFn(intoId); + break; + case AST.ConditionalExpression: + intoId = intoId || this.nextId(); + self.recurse(ast.test, intoId); + self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId)); + recursionFn(intoId); + break; + case AST.Identifier: + intoId = intoId || this.nextId(); + if (nameId) { + nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s'); + nameId.computed = false; + nameId.name = ast.name; + } + ensureSafeMemberName(ast.name); + self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)), + function() { + self.if_(self.stage === 'inputs' || 's', function() { + if (create && create !== 1) { + self.if_( + self.not(self.nonComputedMember('s', ast.name)), + self.lazyAssign(self.nonComputedMember('s', ast.name), '{}')); + } + self.assign(intoId, self.nonComputedMember('s', ast.name)); + }); + }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name)) + ); + if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) { + self.addEnsureSafeObject(intoId); + } + recursionFn(intoId); + break; + case AST.MemberExpression: + left = nameId && (nameId.context = this.nextId()) || this.nextId(); + intoId = intoId || this.nextId(); + self.recurse(ast.object, left, undefined, function() { + self.if_(self.notNull(left), function() { + if (create && create !== 1) { + self.addEnsureSafeAssignContext(left); + } + if (ast.computed) { + right = self.nextId(); + self.recurse(ast.property, right); + self.getStringValue(right); + self.addEnsureSafeMemberName(right); + if (create && create !== 1) { + self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}')); + } + expression = self.ensureSafeObject(self.computedMember(left, right)); + self.assign(intoId, expression); + if (nameId) { + nameId.computed = true; + nameId.name = right; + } + } else { + ensureSafeMemberName(ast.property.name); + if (create && create !== 1) { + self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}')); + } + expression = self.nonComputedMember(left, ast.property.name); + if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) { + expression = self.ensureSafeObject(expression); + } + self.assign(intoId, expression); + if (nameId) { + nameId.computed = false; + nameId.name = ast.property.name; + } + } + }, function() { + self.assign(intoId, 'undefined'); + }); + recursionFn(intoId); + }, !!create); + break; + case AST.CallExpression: + intoId = intoId || this.nextId(); + if (ast.filter) { + right = self.filter(ast.callee.name); + args = []; + forEach(ast.arguments, function(expr) { + var argument = self.nextId(); + self.recurse(expr, argument); + args.push(argument); + }); + expression = right + '(' + args.join(',') + ')'; + self.assign(intoId, expression); + recursionFn(intoId); + } else { + right = self.nextId(); + left = {}; + args = []; + self.recurse(ast.callee, right, left, function() { + self.if_(self.notNull(right), function() { + self.addEnsureSafeFunction(right); + forEach(ast.arguments, function(expr) { + self.recurse(expr, self.nextId(), undefined, function(argument) { + args.push(self.ensureSafeObject(argument)); + }); + }); + if (left.name) { + if (!self.state.expensiveChecks) { + self.addEnsureSafeObject(left.context); + } + expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')'; + } else { + expression = right + '(' + args.join(',') + ')'; + } + expression = self.ensureSafeObject(expression); + self.assign(intoId, expression); + }, function() { + self.assign(intoId, 'undefined'); + }); + recursionFn(intoId); + }); + } + break; + case AST.AssignmentExpression: + right = this.nextId(); + left = {}; + if (!isAssignable(ast.left)) { + throw $parseMinErr('lval', 'Trying to assign a value to a non l-value'); + } + this.recurse(ast.left, undefined, left, function() { + self.if_(self.notNull(left.context), function() { + self.recurse(ast.right, right); + self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); + expression = self.member(left.context, left.name, left.computed) + ast.operator + right; + self.assign(intoId, expression); + recursionFn(intoId || expression); + }); + }, 1); + break; + case AST.ArrayExpression: + args = []; + forEach(ast.elements, function(expr) { + self.recurse(expr, self.nextId(), undefined, function(argument) { + args.push(argument); + }); + }); + expression = '[' + args.join(',') + ']'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.ObjectExpression: + args = []; + computed = false; + forEach(ast.properties, function(property) { + if (property.computed) { + computed = true; + } + }); + if (computed) { + intoId = intoId || this.nextId(); + this.assign(intoId, '{}'); + forEach(ast.properties, function(property) { + if (property.computed) { + left = self.nextId(); + self.recurse(property.key, left); + } else { + left = property.key.type === AST.Identifier ? + property.key.name : + ('' + property.key.value); + } + right = self.nextId(); + self.recurse(property.value, right); + self.assign(self.member(intoId, left, property.computed), right); + }); + } else { + forEach(ast.properties, function(property) { + self.recurse(property.value, ast.constant ? undefined : self.nextId(), undefined, function(expr) { + args.push(self.escape( + property.key.type === AST.Identifier ? property.key.name : + ('' + property.key.value)) + + ':' + expr); + }); + }); + expression = '{' + args.join(',') + '}'; + this.assign(intoId, expression); + } + recursionFn(intoId || expression); + break; + case AST.ThisExpression: + this.assign(intoId, 's'); + recursionFn('s'); + break; + case AST.LocalsExpression: + this.assign(intoId, 'l'); + recursionFn('l'); + break; + case AST.NGValueParameter: + this.assign(intoId, 'v'); + recursionFn('v'); + break; + } + }, + + getHasOwnProperty: function(element, property) { + var key = element + '.' + property; + var own = this.current().own; + if (!own.hasOwnProperty(key)) { + own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')'); + } + return own[key]; + }, + + assign: function(id, value) { + if (!id) return; + this.current().body.push(id, '=', value, ';'); + return id; + }, + + filter: function(filterName) { + if (!this.state.filters.hasOwnProperty(filterName)) { + this.state.filters[filterName] = this.nextId(true); + } + return this.state.filters[filterName]; + }, + + ifDefined: function(id, defaultValue) { + return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')'; + }, + + plus: function(left, right) { + return 'plus(' + left + ',' + right + ')'; + }, + + return_: function(id) { + this.current().body.push('return ', id, ';'); + }, + + if_: function(test, alternate, consequent) { + if (test === true) { + alternate(); + } else { + var body = this.current().body; + body.push('if(', test, '){'); + alternate(); + body.push('}'); + if (consequent) { + body.push('else{'); + consequent(); + body.push('}'); + } + } + }, + + not: function(expression) { + return '!(' + expression + ')'; + }, + + notNull: function(expression) { + return expression + '!=null'; + }, + + nonComputedMember: function(left, right) { + var SAFE_IDENTIFIER = /[$_a-zA-Z][$_a-zA-Z0-9]*/; + var UNSAFE_CHARACTERS = /[^$_a-zA-Z0-9]/g; + if (SAFE_IDENTIFIER.test(right)) { + return left + '.' + right; + } else { + return left + '["' + right.replace(UNSAFE_CHARACTERS, this.stringEscapeFn) + '"]'; + } + }, + + computedMember: function(left, right) { + return left + '[' + right + ']'; + }, + + member: function(left, right, computed) { + if (computed) return this.computedMember(left, right); + return this.nonComputedMember(left, right); + }, + + addEnsureSafeObject: function(item) { + this.current().body.push(this.ensureSafeObject(item), ';'); + }, + + addEnsureSafeMemberName: function(item) { + this.current().body.push(this.ensureSafeMemberName(item), ';'); + }, + + addEnsureSafeFunction: function(item) { + this.current().body.push(this.ensureSafeFunction(item), ';'); + }, + + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ';'); + }, + + ensureSafeObject: function(item) { + return 'ensureSafeObject(' + item + ',text)'; + }, + + ensureSafeMemberName: function(item) { + return 'ensureSafeMemberName(' + item + ',text)'; + }, + + ensureSafeFunction: function(item) { + return 'ensureSafeFunction(' + item + ',text)'; + }, + + getStringValue: function(item) { + this.assign(item, 'getStringValue(' + item + ')'); + }, + + ensureSafeAssignContext: function(item) { + return 'ensureSafeAssignContext(' + item + ',text)'; + }, + + lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { + var self = this; + return function() { + self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck); + }; + }, + + lazyAssign: function(id, value) { + var self = this; + return function() { + self.assign(id, value); + }; + }, + + stringEscapeRegex: /[^ a-zA-Z0-9]/g, + + stringEscapeFn: function(c) { + return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4); + }, + + escape: function(value) { + if (isString(value)) return "'" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'"; + if (isNumber(value)) return value.toString(); + if (value === true) return 'true'; + if (value === false) return 'false'; + if (value === null) return 'null'; + if (typeof value === 'undefined') return 'undefined'; + + throw $parseMinErr('esc', 'IMPOSSIBLE'); + }, + + nextId: function(skip, init) { + var id = 'v' + (this.state.nextId++); + if (!skip) { + this.current().vars.push(id + (init ? '=' + init : '')); + } + return id; + }, + + current: function() { + return this.state[this.state.computing]; + } +}; + + +function ASTInterpreter(astBuilder, $filter) { + this.astBuilder = astBuilder; + this.$filter = $filter; +} + +ASTInterpreter.prototype = { + compile: function(expression, expensiveChecks) { + var self = this; + var ast = this.astBuilder.ast(expression); + this.expression = expression; + this.expensiveChecks = expensiveChecks; + findConstantAndWatchExpressions(ast, self.$filter); + var assignable; + var assign; + if ((assignable = assignableAST(ast))) { + assign = this.recurse(assignable); + } + var toWatch = getInputs(ast.body); + var inputs; + if (toWatch) { + inputs = []; + forEach(toWatch, function(watch, key) { + var input = self.recurse(watch); + watch.input = input; + inputs.push(input); + watch.watchId = key; + }); + } + var expressions = []; + forEach(ast.body, function(expression) { + expressions.push(self.recurse(expression.expression)); + }); + var fn = ast.body.length === 0 ? noop : + ast.body.length === 1 ? expressions[0] : + function(scope, locals) { + var lastValue; + forEach(expressions, function(exp) { + lastValue = exp(scope, locals); + }); + return lastValue; + }; + if (assign) { + fn.assign = function(scope, value, locals) { + return assign(scope, locals, value); + }; + } + if (inputs) { + fn.inputs = inputs; + } + fn.literal = isLiteral(ast); + fn.constant = isConstant(ast); + return fn; + }, + + recurse: function(ast, context, create) { + var left, right, self = this, args, expression; + if (ast.input) { + return this.inputs(ast.input, ast.watchId); + } + switch (ast.type) { + case AST.Literal: + return this.value(ast.value, context); + case AST.UnaryExpression: + right = this.recurse(ast.argument); + return this['unary' + ast.operator](right, context); + case AST.BinaryExpression: + left = this.recurse(ast.left); + right = this.recurse(ast.right); + return this['binary' + ast.operator](left, right, context); + case AST.LogicalExpression: + left = this.recurse(ast.left); + right = this.recurse(ast.right); + return this['binary' + ast.operator](left, right, context); + case AST.ConditionalExpression: + return this['ternary?:']( + this.recurse(ast.test), + this.recurse(ast.alternate), + this.recurse(ast.consequent), + context + ); + case AST.Identifier: + ensureSafeMemberName(ast.name, self.expression); + return self.identifier(ast.name, + self.expensiveChecks || isPossiblyDangerousMemberName(ast.name), + context, create, self.expression); + case AST.MemberExpression: + left = this.recurse(ast.object, false, !!create); + if (!ast.computed) { + ensureSafeMemberName(ast.property.name, self.expression); + right = ast.property.name; + } + if (ast.computed) right = this.recurse(ast.property); + return ast.computed ? + this.computedMember(left, right, context, create, self.expression) : + this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression); + case AST.CallExpression: + args = []; + forEach(ast.arguments, function(expr) { + args.push(self.recurse(expr)); + }); + if (ast.filter) right = this.$filter(ast.callee.name); + if (!ast.filter) right = this.recurse(ast.callee, true); + return ast.filter ? + function(scope, locals, assign, inputs) { + var values = []; + for (var i = 0; i < args.length; ++i) { + values.push(args[i](scope, locals, assign, inputs)); + } + var value = right.apply(undefined, values, inputs); + return context ? {context: undefined, name: undefined, value: value} : value; + } : + function(scope, locals, assign, inputs) { + var rhs = right(scope, locals, assign, inputs); + var value; + if (rhs.value != null) { + ensureSafeObject(rhs.context, self.expression); + ensureSafeFunction(rhs.value, self.expression); + var values = []; + for (var i = 0; i < args.length; ++i) { + values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression)); + } + value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression); + } + return context ? {value: value} : value; + }; + case AST.AssignmentExpression: + left = this.recurse(ast.left, true, 1); + right = this.recurse(ast.right); + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); + lhs.context[lhs.name] = rhs; + return context ? {value: rhs} : rhs; + }; + case AST.ArrayExpression: + args = []; + forEach(ast.elements, function(expr) { + args.push(self.recurse(expr)); + }); + return function(scope, locals, assign, inputs) { + var value = []; + for (var i = 0; i < args.length; ++i) { + value.push(args[i](scope, locals, assign, inputs)); + } + return context ? {value: value} : value; + }; + case AST.ObjectExpression: + args = []; + forEach(ast.properties, function(property) { + if (property.computed) { + args.push({key: self.recurse(property.key), + computed: true, + value: self.recurse(property.value) + }); + } else { + args.push({key: property.key.type === AST.Identifier ? + property.key.name : + ('' + property.key.value), + computed: false, + value: self.recurse(property.value) + }); + } + }); + return function(scope, locals, assign, inputs) { + var value = {}; + for (var i = 0; i < args.length; ++i) { + if (args[i].computed) { + value[args[i].key(scope, locals, assign, inputs)] = args[i].value(scope, locals, assign, inputs); + } else { + value[args[i].key] = args[i].value(scope, locals, assign, inputs); + } + } + return context ? {value: value} : value; + }; + case AST.ThisExpression: + return function(scope) { + return context ? {value: scope} : scope; + }; + case AST.LocalsExpression: + return function(scope, locals) { + return context ? {value: locals} : locals; + }; + case AST.NGValueParameter: + return function(scope, locals, assign) { + return context ? {value: assign} : assign; + }; + } + }, + + 'unary+': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = argument(scope, locals, assign, inputs); + if (isDefined(arg)) { + arg = +arg; + } else { + arg = 0; + } + return context ? {value: arg} : arg; + }; + }, + 'unary-': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = argument(scope, locals, assign, inputs); + if (isDefined(arg)) { + arg = -arg; + } else { + arg = 0; + } + return context ? {value: arg} : arg; + }; + }, + 'unary!': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = !argument(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary+': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + var arg = plusFn(lhs, rhs); + return context ? {value: arg} : arg; + }; + }, + 'binary-': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0); + return context ? {value: arg} : arg; + }; + }, + 'binary*': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary/': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary%': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary===': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary!==': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary==': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary!=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary<': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary>': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary<=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary>=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary&&': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary||': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'ternary?:': function(test, alternate, consequent, context) { + return function(scope, locals, assign, inputs) { + var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + value: function(value, context) { + return function() { return context ? {context: undefined, name: undefined, value: value} : value; }; + }, + identifier: function(name, expensiveChecks, context, create, expression) { + return function(scope, locals, assign, inputs) { + var base = locals && (name in locals) ? locals : scope; + if (create && create !== 1 && base && !(base[name])) { + base[name] = {}; + } + var value = base ? base[name] : undefined; + if (expensiveChecks) { + ensureSafeObject(value, expression); + } + if (context) { + return {context: base, name: name, value: value}; + } else { + return value; + } + }; + }, + computedMember: function(left, right, context, create, expression) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs; + var value; + if (lhs != null) { + rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); + ensureSafeMemberName(rhs, expression); + if (create && create !== 1) { + ensureSafeAssignContext(lhs); + if (lhs && !(lhs[rhs])) { + lhs[rhs] = {}; + } + } + value = lhs[rhs]; + ensureSafeObject(value, expression); + } + if (context) { + return {context: lhs, name: rhs, value: value}; + } else { + return value; + } + }; + }, + nonComputedMember: function(left, right, expensiveChecks, context, create, expression) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + if (create && create !== 1) { + ensureSafeAssignContext(lhs); + if (lhs && !(lhs[right])) { + lhs[right] = {}; + } + } + var value = lhs != null ? lhs[right] : undefined; + if (expensiveChecks || isPossiblyDangerousMemberName(right)) { + ensureSafeObject(value, expression); + } + if (context) { + return {context: lhs, name: right, value: value}; + } else { + return value; + } + }; + }, + inputs: function(input, watchId) { + return function(scope, value, locals, inputs) { + if (inputs) return inputs[watchId]; + return input(scope, value, locals); + }; + } +}; + +/** + * @constructor + */ +var Parser = function(lexer, $filter, options) { + this.lexer = lexer; + this.$filter = $filter; + this.options = options; + this.ast = new AST(lexer, options); + this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) : + new ASTCompiler(this.ast, $filter); +}; + +Parser.prototype = { + constructor: Parser, + + parse: function(text) { + return this.astCompiler.compile(text, this.options.expensiveChecks); + } +}; + +function isPossiblyDangerousMemberName(name) { + return name == 'constructor'; +} + +var objectValueOf = Object.prototype.valueOf; + +function getValueOf(value) { + return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); +} + +/////////////////////////////////// + +/** + * @ngdoc service + * @name $parse + * @kind function + * + * @description + * + * Converts Angular {@link guide/expression expression} into a function. + * + * ```js + * var getter = $parse('user.name'); + * var setter = getter.assign; + * var context = {user:{name:'angular'}}; + * var locals = {user:{name:'local'}}; + * + * expect(getter(context)).toEqual('angular'); + * setter(context, 'newValue'); + * expect(context.user.name).toEqual('newValue'); + * expect(getter(context, locals)).toEqual('local'); + * ``` + * + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + * + * The returned function also has the following properties: + * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript + * literal. + * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript + * constant literals. + * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be + * set to a function to change its value on the given context. + * + */ + + +/** + * @ngdoc provider + * @name $parseProvider + * + * @description + * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse} + * service. + */ +function $ParseProvider() { + var cacheDefault = createMap(); + var cacheExpensive = createMap(); + var literals = { + 'true': true, + 'false': false, + 'null': null, + 'undefined': undefined + }; + var identStart, identContinue; + + /** + * @ngdoc method + * @name $parseProvider#addLiteral + * @description + * + * Configure $parse service to add literal values that will be present as literal at expressions. + * + * @param {string} literalName Token for the literal value. The literal name value must be a valid literal name. + * @param {*} literalValue Value for this literal. All literal values must be primitives or `undefined`. + * + **/ + this.addLiteral = function(literalName, literalValue) { + literals[literalName] = literalValue; + }; + + /** + * @ngdoc method + * @name $parseProvider#setIdentifierFns + * @description + * + * Allows defining the set of characters that are allowed in Angular expressions. The function + * `identifierStart` will get called to know if a given character is a valid character to be the + * first character for an identifier. The function `identifierContinue` will get called to know if + * a given character is a valid character to be a follow-up identifier character. The functions + * `identifierStart` and `identifierContinue` will receive as arguments the single character to be + * identifier and the character code point. These arguments will be `string` and `numeric`. Keep in + * mind that the `string` parameter can be two characters long depending on the character + * representation. It is expected for the function to return `true` or `false`, whether that + * character is allowed or not. + * + * Since this function will be called extensivelly, keep the implementation of these functions fast, + * as the performance of these functions have a direct impact on the expressions parsing speed. + * + * @param {function=} identifierStart The function that will decide whether the given character is + * a valid identifier start character. + * @param {function=} identifierContinue The function that will decide whether the given character is + * a valid identifier continue character. + */ + this.setIdentifierFns = function(identifierStart, identifierContinue) { + identStart = identifierStart; + identContinue = identifierContinue; + return this; + }; + + this.$get = ['$filter', function($filter) { + var noUnsafeEval = csp().noUnsafeEval; + var $parseOptions = { + csp: noUnsafeEval, + expensiveChecks: false, + literals: copy(literals), + isIdentifierStart: isFunction(identStart) && identStart, + isIdentifierContinue: isFunction(identContinue) && identContinue + }, + $parseOptionsExpensive = { + csp: noUnsafeEval, + expensiveChecks: true, + literals: copy(literals), + isIdentifierStart: isFunction(identStart) && identStart, + isIdentifierContinue: isFunction(identContinue) && identContinue + }; + var runningChecksEnabled = false; + + $parse.$$runningExpensiveChecks = function() { + return runningChecksEnabled; + }; + + return $parse; + + function $parse(exp, interceptorFn, expensiveChecks) { + var parsedExpression, oneTime, cacheKey; + + expensiveChecks = expensiveChecks || runningChecksEnabled; + + switch (typeof exp) { + case 'string': + exp = exp.trim(); + cacheKey = exp; + + var cache = (expensiveChecks ? cacheExpensive : cacheDefault); + parsedExpression = cache[cacheKey]; + + if (!parsedExpression) { + if (exp.charAt(0) === ':' && exp.charAt(1) === ':') { + oneTime = true; + exp = exp.substring(2); + } + var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions; + var lexer = new Lexer(parseOptions); + var parser = new Parser(lexer, $filter, parseOptions); + parsedExpression = parser.parse(exp); + if (parsedExpression.constant) { + parsedExpression.$$watchDelegate = constantWatchDelegate; + } else if (oneTime) { + parsedExpression.$$watchDelegate = parsedExpression.literal ? + oneTimeLiteralWatchDelegate : oneTimeWatchDelegate; + } else if (parsedExpression.inputs) { + parsedExpression.$$watchDelegate = inputsWatchDelegate; + } + if (expensiveChecks) { + parsedExpression = expensiveChecksInterceptor(parsedExpression); + } + cache[cacheKey] = parsedExpression; + } + return addInterceptor(parsedExpression, interceptorFn); + + case 'function': + return addInterceptor(exp, interceptorFn); + + default: + return addInterceptor(noop, interceptorFn); + } + } + + function expensiveChecksInterceptor(fn) { + if (!fn) return fn; + expensiveCheckFn.$$watchDelegate = fn.$$watchDelegate; + expensiveCheckFn.assign = expensiveChecksInterceptor(fn.assign); + expensiveCheckFn.constant = fn.constant; + expensiveCheckFn.literal = fn.literal; + for (var i = 0; fn.inputs && i < fn.inputs.length; ++i) { + fn.inputs[i] = expensiveChecksInterceptor(fn.inputs[i]); + } + expensiveCheckFn.inputs = fn.inputs; + + return expensiveCheckFn; + + function expensiveCheckFn(scope, locals, assign, inputs) { + var expensiveCheckOldValue = runningChecksEnabled; + runningChecksEnabled = true; + try { + return fn(scope, locals, assign, inputs); + } finally { + runningChecksEnabled = expensiveCheckOldValue; + } + } + } + + function expressionInputDirtyCheck(newValue, oldValueOfValue) { + + if (newValue == null || oldValueOfValue == null) { // null/undefined + return newValue === oldValueOfValue; + } + + if (typeof newValue === 'object') { + + // attempt to convert the value to a primitive type + // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can + // be cheaply dirty-checked + newValue = getValueOf(newValue); + + if (typeof newValue === 'object') { + // objects/arrays are not supported - deep-watching them would be too expensive + return false; + } + + // fall-through to the primitive equality check + } + + //Primitive or NaN + return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue); + } + + function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) { + var inputExpressions = parsedExpression.inputs; + var lastResult; + + if (inputExpressions.length === 1) { + var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails + inputExpressions = inputExpressions[0]; + return scope.$watch(function expressionInputWatch(scope) { + var newInputValue = inputExpressions(scope); + if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) { + lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]); + oldInputValueOf = newInputValue && getValueOf(newInputValue); + } + return lastResult; + }, listener, objectEquality, prettyPrintExpression); + } + + var oldInputValueOfValues = []; + var oldInputValues = []; + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails + oldInputValues[i] = null; + } + + return scope.$watch(function expressionInputsWatch(scope) { + var changed = false; + + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + var newInputValue = inputExpressions[i](scope); + if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) { + oldInputValues[i] = newInputValue; + oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue); + } + } + + if (changed) { + lastResult = parsedExpression(scope, undefined, undefined, oldInputValues); + } + + return lastResult; + }, listener, objectEquality, prettyPrintExpression); + } + + function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.apply(this, arguments); + } + if (isDefined(value)) { + scope.$$postDigest(function() { + if (isDefined(lastValue)) { + unwatch(); + } + }); + } + }, objectEquality); + } + + function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.call(this, value, old, scope); + } + if (isAllDefined(value)) { + scope.$$postDigest(function() { + if (isAllDefined(lastValue)) unwatch(); + }); + } + }, objectEquality); + + function isAllDefined(value) { + var allDefined = true; + forEach(value, function(val) { + if (!isDefined(val)) allDefined = false; + }); + return allDefined; + } + } + + function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch; + return unwatch = scope.$watch(function constantWatch(scope) { + unwatch(); + return parsedExpression(scope); + }, listener, objectEquality); + } + + function addInterceptor(parsedExpression, interceptorFn) { + if (!interceptorFn) return parsedExpression; + var watchDelegate = parsedExpression.$$watchDelegate; + var useInputs = false; + + var regularWatch = + watchDelegate !== oneTimeLiteralWatchDelegate && + watchDelegate !== oneTimeWatchDelegate; + + var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) { + var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs); + return interceptorFn(value, scope, locals); + } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) { + var value = parsedExpression(scope, locals, assign, inputs); + var result = interceptorFn(value, scope, locals); + // we only return the interceptor's result if the + // initial value is defined (for bind-once) + return isDefined(value) ? result : value; + }; + + // Propagate $$watchDelegates other then inputsWatchDelegate + if (parsedExpression.$$watchDelegate && + parsedExpression.$$watchDelegate !== inputsWatchDelegate) { + fn.$$watchDelegate = parsedExpression.$$watchDelegate; + } else if (!interceptorFn.$stateful) { + // If there is an interceptor, but no watchDelegate then treat the interceptor like + // we treat filters - it is assumed to be a pure function unless flagged with $stateful + fn.$$watchDelegate = inputsWatchDelegate; + useInputs = !parsedExpression.inputs; + fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression]; + } + + return fn; + } + }]; +} + +/** + * @ngdoc service + * @name $q + * @requires $rootScope + * + * @description + * A service that helps you run functions asynchronously, and use their return values (or exceptions) + * when they are done processing. + * + * This is an implementation of promises/deferred objects inspired by + * [Kris Kowal's Q](https://github.com/kriskowal/q). + * + * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred + * implementations, and the other which resembles ES6 (ES2015) promises to some degree. + * + * # $q constructor + * + * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver` + * function as the first argument. This is similar to the native Promise implementation from ES6, + * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). + * + * While the constructor-style use is supported, not all of the supporting methods from ES6 promises are + * available yet. + * + * It can be used like so: + * + * ```js + * // for the purpose of this example let's assume that variables `$q` and `okToGreet` + * // are available in the current lexical scope (they could have been injected or passed in). + * + * function asyncGreet(name) { + * // perform some asynchronous operation, resolve or reject the promise when appropriate. + * return $q(function(resolve, reject) { + * setTimeout(function() { + * if (okToGreet(name)) { + * resolve('Hello, ' + name + '!'); + * } else { + * reject('Greeting ' + name + ' is not allowed.'); + * } + * }, 1000); + * }); + * } + * + * var promise = asyncGreet('Robin Hood'); + * promise.then(function(greeting) { + * alert('Success: ' + greeting); + * }, function(reason) { + * alert('Failed: ' + reason); + * }); + * ``` + * + * Note: progress/notify callbacks are not currently supported via the ES6-style interface. + * + * Note: unlike ES6 behavior, an exception thrown in the constructor function will NOT implicitly reject the promise. + * + * However, the more traditional CommonJS-style usage is still available, and documented below. + * + * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an + * interface for interacting with an object that represents the result of an action that is + * performed asynchronously, and may or may not be finished at any given point in time. + * + * From the perspective of dealing with error handling, deferred and promise APIs are to + * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. + * + * ```js + * // for the purpose of this example let's assume that variables `$q` and `okToGreet` + * // are available in the current lexical scope (they could have been injected or passed in). + * + * function asyncGreet(name) { + * var deferred = $q.defer(); + * + * setTimeout(function() { + * deferred.notify('About to greet ' + name + '.'); + * + * if (okToGreet(name)) { + * deferred.resolve('Hello, ' + name + '!'); + * } else { + * deferred.reject('Greeting ' + name + ' is not allowed.'); + * } + * }, 1000); + * + * return deferred.promise; + * } + * + * var promise = asyncGreet('Robin Hood'); + * promise.then(function(greeting) { + * alert('Success: ' + greeting); + * }, function(reason) { + * alert('Failed: ' + reason); + * }, function(update) { + * alert('Got notification: ' + update); + * }); + * ``` + * + * At first it might not be obvious why this extra complexity is worth the trouble. The payoff + * comes in the way of guarantees that promise and deferred APIs make, see + * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md. + * + * Additionally the promise api allows for composition that is very hard to do with the + * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. + * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the + * section on serial or parallel joining of promises. + * + * # The Deferred API + * + * A new instance of deferred is constructed by calling `$q.defer()`. + * + * The purpose of the deferred object is to expose the associated Promise instance as well as APIs + * that can be used for signaling the successful or unsuccessful completion, as well as the status + * of the task. + * + * **Methods** + * + * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection + * constructed via `$q.reject`, the promise will be rejected instead. + * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to + * resolving it with a rejection constructed via `$q.reject`. + * - `notify(value)` - provides updates on the status of the promise's execution. This may be called + * multiple times before the promise is either resolved or rejected. + * + * **Properties** + * + * - promise – `{Promise}` – promise object associated with this deferred. + * + * + * # The Promise API + * + * A new promise instance is created when a deferred instance is created and can be retrieved by + * calling `deferred.promise`. + * + * The purpose of the promise object is to allow for interested parties to get access to the result + * of the deferred task when it completes. + * + * **Methods** + * + * - `then(successCallback, [errorCallback], [notifyCallback])` – regardless of when the promise was or + * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously + * as soon as the result is available. The callbacks are called with a single argument: the result + * or rejection reason. Additionally, the notify callback may be called zero or more times to + * provide a progress indication, before the promise is resolved or rejected. + * + * This method *returns a new promise* which is resolved or rejected via the return value of the + * `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved + * with the value which is resolved in that promise using + * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)). + * It also notifies via the return value of the `notifyCallback` method. The promise cannot be + * resolved or rejected from the notifyCallback method. The errorCallback and notifyCallback + * arguments are optional. + * + * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)` + * + * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise, + * but to do so without modifying the final value. This is useful to release resources or do some + * clean-up that needs to be done whether the promise was rejected or resolved. See the [full + * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for + * more information. + * + * # Chaining promises + * + * Because calling the `then` method of a promise returns a new derived promise, it is easily + * possible to create a chain of promises: + * + * ```js + * promiseB = promiseA.then(function(result) { + * return result + 1; + * }); + * + * // promiseB will be resolved immediately after promiseA is resolved and its value + * // will be the result of promiseA incremented by 1 + * ``` + * + * It is possible to create chains of any length and since a promise can be resolved with another + * promise (which will defer its resolution further), it is possible to pause/defer resolution of + * the promises at any point in the chain. This makes it possible to implement powerful APIs like + * $http's response interceptors. + * + * + * # Differences between Kris Kowal's Q and $q + * + * There are two main differences: + * + * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation + * mechanism in angular, which means faster propagation of resolution or rejection into your + * models and avoiding unnecessary browser repaints, which would result in flickering UI. + * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains + * all the important functionality needed for common async tasks. + * + * # Testing + * + * ```js + * it('should simulate promise', inject(function($q, $rootScope) { + * var deferred = $q.defer(); + * var promise = deferred.promise; + * var resolvedValue; + * + * promise.then(function(value) { resolvedValue = value; }); + * expect(resolvedValue).toBeUndefined(); + * + * // Simulate resolving of promise + * deferred.resolve(123); + * // Note that the 'then' function does not get called synchronously. + * // This is because we want the promise API to always be async, whether or not + * // it got called synchronously or asynchronously. + * expect(resolvedValue).toBeUndefined(); + * + * // Propagate promise resolution to 'then' functions using $apply(). + * $rootScope.$apply(); + * expect(resolvedValue).toEqual(123); + * })); + * ``` + * + * @param {function(function, function)} resolver Function which is responsible for resolving or + * rejecting the newly created promise. The first parameter is a function which resolves the + * promise, the second parameter is a function which rejects the promise. + * + * @returns {Promise} The newly created promise. + */ +function $QProvider() { + + this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { + return qFactory(function(callback) { + $rootScope.$evalAsync(callback); + }, $exceptionHandler); + }]; +} + +function $$QProvider() { + this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) { + return qFactory(function(callback) { + $browser.defer(callback); + }, $exceptionHandler); + }]; +} + +/** + * Constructs a promise manager. + * + * @param {function(function)} nextTick Function for executing functions in the next turn. + * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for + * debugging purposes. + * @returns {object} Promise manager. + */ +function qFactory(nextTick, exceptionHandler) { + var $qMinErr = minErr('$q', TypeError); + + /** + * @ngdoc method + * @name ng.$q#defer + * @kind function + * + * @description + * Creates a `Deferred` object which represents a task which will finish in the future. + * + * @returns {Deferred} Returns a new instance of deferred. + */ + var defer = function() { + var d = new Deferred(); + //Necessary to support unbound execution :/ + d.resolve = simpleBind(d, d.resolve); + d.reject = simpleBind(d, d.reject); + d.notify = simpleBind(d, d.notify); + return d; + }; + + function Promise() { + this.$$state = { status: 0 }; + } + + extend(Promise.prototype, { + then: function(onFulfilled, onRejected, progressBack) { + if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) { + return this; + } + var result = new Deferred(); + + this.$$state.pending = this.$$state.pending || []; + this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]); + if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); + + return result.promise; + }, + + "catch": function(callback) { + return this.then(null, callback); + }, + + "finally": function(callback, progressBack) { + return this.then(function(value) { + return handleCallback(value, true, callback); + }, function(error) { + return handleCallback(error, false, callback); + }, progressBack); + } + }); + + //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native + function simpleBind(context, fn) { + return function(value) { + fn.call(context, value); + }; + } + + function processQueue(state) { + var fn, deferred, pending; + + pending = state.pending; + state.processScheduled = false; + state.pending = undefined; + for (var i = 0, ii = pending.length; i < ii; ++i) { + deferred = pending[i][0]; + fn = pending[i][state.status]; + try { + if (isFunction(fn)) { + deferred.resolve(fn(state.value)); + } else if (state.status === 1) { + deferred.resolve(state.value); + } else { + deferred.reject(state.value); + } + } catch (e) { + deferred.reject(e); + exceptionHandler(e); + } + } + } + + function scheduleProcessQueue(state) { + if (state.processScheduled || !state.pending) return; + state.processScheduled = true; + nextTick(function() { processQueue(state); }); + } + + function Deferred() { + this.promise = new Promise(); + } + + extend(Deferred.prototype, { + resolve: function(val) { + if (this.promise.$$state.status) return; + if (val === this.promise) { + this.$$reject($qMinErr( + 'qcycle', + "Expected promise to be resolved with value other than itself '{0}'", + val)); + } else { + this.$$resolve(val); + } + + }, + + $$resolve: function(val) { + var then; + var that = this; + var done = false; + try { + if ((isObject(val) || isFunction(val))) then = val && val.then; + if (isFunction(then)) { + this.promise.$$state.status = -1; + then.call(val, resolvePromise, rejectPromise, simpleBind(this, this.notify)); + } else { + this.promise.$$state.value = val; + this.promise.$$state.status = 1; + scheduleProcessQueue(this.promise.$$state); + } + } catch (e) { + rejectPromise(e); + exceptionHandler(e); + } + + function resolvePromise(val) { + if (done) return; + done = true; + that.$$resolve(val); + } + function rejectPromise(val) { + if (done) return; + done = true; + that.$$reject(val); + } + }, + + reject: function(reason) { + if (this.promise.$$state.status) return; + this.$$reject(reason); + }, + + $$reject: function(reason) { + this.promise.$$state.value = reason; + this.promise.$$state.status = 2; + scheduleProcessQueue(this.promise.$$state); + }, + + notify: function(progress) { + var callbacks = this.promise.$$state.pending; + + if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) { + nextTick(function() { + var callback, result; + for (var i = 0, ii = callbacks.length; i < ii; i++) { + result = callbacks[i][0]; + callback = callbacks[i][3]; + try { + result.notify(isFunction(callback) ? callback(progress) : progress); + } catch (e) { + exceptionHandler(e); + } + } + }); + } + } + }); + + /** + * @ngdoc method + * @name $q#reject + * @kind function + * + * @description + * Creates a promise that is resolved as rejected with the specified `reason`. This api should be + * used to forward rejection in a chain of promises. If you are dealing with the last promise in + * a promise chain, you don't need to worry about it. + * + * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of + * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via + * a promise error callback and you want to forward the error to the promise derived from the + * current promise, you have to "rethrow" the error by returning a rejection constructed via + * `reject`. + * + * ```js + * promiseB = promiseA.then(function(result) { + * // success: do something and resolve promiseB + * // with the old or a new result + * return result; + * }, function(reason) { + * // error: handle the error if possible and + * // resolve promiseB with newPromiseOrValue, + * // otherwise forward the rejection to promiseB + * if (canHandle(reason)) { + * // handle the error and recover + * return newPromiseOrValue; + * } + * return $q.reject(reason); + * }); + * ``` + * + * @param {*} reason Constant, message, exception or an object representing the rejection reason. + * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. + */ + var reject = function(reason) { + var result = new Deferred(); + result.reject(reason); + return result.promise; + }; + + var makePromise = function makePromise(value, resolved) { + var result = new Deferred(); + if (resolved) { + result.resolve(value); + } else { + result.reject(value); + } + return result.promise; + }; + + var handleCallback = function handleCallback(value, isResolved, callback) { + var callbackOutput = null; + try { + if (isFunction(callback)) callbackOutput = callback(); + } catch (e) { + return makePromise(e, false); + } + if (isPromiseLike(callbackOutput)) { + return callbackOutput.then(function() { + return makePromise(value, isResolved); + }, function(error) { + return makePromise(error, false); + }); + } else { + return makePromise(value, isResolved); + } + }; + + /** + * @ngdoc method + * @name $q#when + * @kind function + * + * @description + * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. + * This is useful when you are dealing with an object that might or might not be a promise, or if + * the promise comes from a source that can't be trusted. + * + * @param {*} value Value or a promise + * @param {Function=} successCallback + * @param {Function=} errorCallback + * @param {Function=} progressCallback + * @returns {Promise} Returns a promise of the passed value or promise + */ + + + var when = function(value, callback, errback, progressBack) { + var result = new Deferred(); + result.resolve(value); + return result.promise.then(callback, errback, progressBack); + }; + + /** + * @ngdoc method + * @name $q#resolve + * @kind function + * + * @description + * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6. + * + * @param {*} value Value or a promise + * @param {Function=} successCallback + * @param {Function=} errorCallback + * @param {Function=} progressCallback + * @returns {Promise} Returns a promise of the passed value or promise + */ + var resolve = when; + + /** + * @ngdoc method + * @name $q#all + * @kind function + * + * @description + * Combines multiple promises into a single promise that is resolved when all of the input + * promises are resolved. + * + * @param {Array.|Object.} promises An array or hash of promises. + * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, + * each value corresponding to the promise at the same index/key in the `promises` array/hash. + * If any of the promises is resolved with a rejection, this resulting promise will be rejected + * with the same rejection value. + */ + + function all(promises) { + var deferred = new Deferred(), + counter = 0, + results = isArray(promises) ? [] : {}; + + forEach(promises, function(promise, key) { + counter++; + when(promise).then(function(value) { + if (results.hasOwnProperty(key)) return; + results[key] = value; + if (!(--counter)) deferred.resolve(results); + }, function(reason) { + if (results.hasOwnProperty(key)) return; + deferred.reject(reason); + }); + }); + + if (counter === 0) { + deferred.resolve(results); + } + + return deferred.promise; + } + + /** + * @ngdoc method + * @name $q#race + * @kind function + * + * @description + * Returns a promise that resolves or rejects as soon as one of those promises + * resolves or rejects, with the value or reason from that promise. + * + * @param {Array.|Object.} promises An array or hash of promises. + * @returns {Promise} a promise that resolves or rejects as soon as one of the `promises` + * resolves or rejects, with the value or reason from that promise. + */ + + function race(promises) { + var deferred = defer(); + + forEach(promises, function(promise) { + when(promise).then(deferred.resolve, deferred.reject); + }); + + return deferred.promise; + } + + var $Q = function Q(resolver) { + if (!isFunction(resolver)) { + throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver); + } + + var deferred = new Deferred(); + + function resolveFn(value) { + deferred.resolve(value); + } + + function rejectFn(reason) { + deferred.reject(reason); + } + + resolver(resolveFn, rejectFn); + + return deferred.promise; + }; + + // Let's make the instanceof operator work for promises, so that + // `new $q(fn) instanceof $q` would evaluate to true. + $Q.prototype = Promise.prototype; + + $Q.defer = defer; + $Q.reject = reject; + $Q.when = when; + $Q.resolve = resolve; + $Q.all = all; + $Q.race = race; + + return $Q; +} + +function $$RAFProvider() { //rAF + this.$get = ['$window', '$timeout', function($window, $timeout) { + var requestAnimationFrame = $window.requestAnimationFrame || + $window.webkitRequestAnimationFrame; + + var cancelAnimationFrame = $window.cancelAnimationFrame || + $window.webkitCancelAnimationFrame || + $window.webkitCancelRequestAnimationFrame; + + var rafSupported = !!requestAnimationFrame; + var raf = rafSupported + ? function(fn) { + var id = requestAnimationFrame(fn); + return function() { + cancelAnimationFrame(id); + }; + } + : function(fn) { + var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666 + return function() { + $timeout.cancel(timer); + }; + }; + + raf.supported = rafSupported; + + return raf; + }]; +} + +/** + * DESIGN NOTES + * + * The design decisions behind the scope are heavily favored for speed and memory consumption. + * + * The typical use of scope is to watch the expressions, which most of the time return the same + * value as last time so we optimize the operation. + * + * Closures construction is expensive in terms of speed as well as memory: + * - No closures, instead use prototypical inheritance for API + * - Internal state needs to be stored on scope directly, which means that private state is + * exposed as $$____ properties + * + * Loop operations are optimized by using while(count--) { ... } + * - This means that in order to keep the same order of execution as addition we have to add + * items to the array at the beginning (unshift) instead of at the end (push) + * + * Child scopes are created and removed often + * - Using an array would be slow since inserts in the middle are expensive; so we use linked lists + * + * There are fewer watches than observers. This is why you don't want the observer to be implemented + * in the same way as watch. Watch requires return of the initialization function which is expensive + * to construct. + */ + + +/** + * @ngdoc provider + * @name $rootScopeProvider + * @description + * + * Provider for the $rootScope service. + */ + +/** + * @ngdoc method + * @name $rootScopeProvider#digestTtl + * @description + * + * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and + * assuming that the model is unstable. + * + * The current default is 10 iterations. + * + * In complex applications it's possible that the dependencies between `$watch`s will result in + * several digest iterations. However if an application needs more than the default 10 digest + * iterations for its model to stabilize then you should investigate what is causing the model to + * continuously change during the digest. + * + * Increasing the TTL could have performance implications, so you should not change it without + * proper justification. + * + * @param {number} limit The number of digest iterations. + */ + + +/** + * @ngdoc service + * @name $rootScope + * @description + * + * Every application has a single root {@link ng.$rootScope.Scope scope}. + * All other scopes are descendant scopes of the root scope. Scopes provide separation + * between the model and the view, via a mechanism for watching the model for changes. + * They also provide event emission/broadcast and subscription facility. See the + * {@link guide/scope developer guide on scopes}. + */ +function $RootScopeProvider() { + var TTL = 10; + var $rootScopeMinErr = minErr('$rootScope'); + var lastDirtyWatch = null; + var applyAsyncId = null; + + this.digestTtl = function(value) { + if (arguments.length) { + TTL = value; + } + return TTL; + }; + + function createChildScopeClass(parent) { + function ChildScope() { + this.$$watchers = this.$$nextSibling = + this.$$childHead = this.$$childTail = null; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$watchersCount = 0; + this.$id = nextUid(); + this.$$ChildScope = null; + } + ChildScope.prototype = parent; + return ChildScope; + } + + this.$get = ['$exceptionHandler', '$parse', '$browser', + function($exceptionHandler, $parse, $browser) { + + function destroyChildScope($event) { + $event.currentScope.$$destroyed = true; + } + + function cleanUpScope($scope) { + + if (msie === 9) { + // There is a memory leak in IE9 if all child scopes are not disconnected + // completely when a scope is destroyed. So this code will recurse up through + // all this scopes children + // + // See issue https://github.com/angular/angular.js/issues/10706 + $scope.$$childHead && cleanUpScope($scope.$$childHead); + $scope.$$nextSibling && cleanUpScope($scope.$$nextSibling); + } + + // The code below works around IE9 and V8's memory leaks + // + // See: + // - https://code.google.com/p/v8/issues/detail?id=2073#c26 + // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909 + // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 + + $scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead = + $scope.$$childTail = $scope.$root = $scope.$$watchers = null; + } + + /** + * @ngdoc type + * @name $rootScope.Scope + * + * @description + * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the + * {@link auto.$injector $injector}. Child scopes are created using the + * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when + * compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for + * an in-depth introduction and usage examples. + * + * + * # Inheritance + * A scope can inherit from a parent scope, as in this example: + * ```js + var parent = $rootScope; + var child = parent.$new(); + + parent.salutation = "Hello"; + expect(child.salutation).toEqual('Hello'); + + child.salutation = "Welcome"; + expect(child.salutation).toEqual('Welcome'); + expect(parent.salutation).toEqual('Hello'); + * ``` + * + * When interacting with `Scope` in tests, additional helper methods are available on the + * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional + * details. + * + * + * @param {Object.=} providers Map of service factory which need to be + * provided for the current scope. Defaults to {@link ng}. + * @param {Object.=} instanceCache Provides pre-instantiated services which should + * append/override services provided by `providers`. This is handy + * when unit-testing and having the need to override a default + * service. + * @returns {Object} Newly created scope. + * + */ + function Scope() { + this.$id = nextUid(); + this.$$phase = this.$parent = this.$$watchers = + this.$$nextSibling = this.$$prevSibling = + this.$$childHead = this.$$childTail = null; + this.$root = this; + this.$$destroyed = false; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$watchersCount = 0; + this.$$isolateBindings = null; + } + + /** + * @ngdoc property + * @name $rootScope.Scope#$id + * + * @description + * Unique scope ID (monotonically increasing) useful for debugging. + */ + + /** + * @ngdoc property + * @name $rootScope.Scope#$parent + * + * @description + * Reference to the parent scope. + */ + + /** + * @ngdoc property + * @name $rootScope.Scope#$root + * + * @description + * Reference to the root scope. + */ + + Scope.prototype = { + constructor: Scope, + /** + * @ngdoc method + * @name $rootScope.Scope#$new + * @kind function + * + * @description + * Creates a new child {@link ng.$rootScope.Scope scope}. + * + * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event. + * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}. + * + * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is + * desired for the scope and its child scopes to be permanently detached from the parent and + * thus stop participating in model change detection and listener notification by invoking. + * + * @param {boolean} isolate If true, then the scope does not prototypically inherit from the + * parent scope. The scope is isolated, as it can not see parent scope properties. + * When creating widgets, it is useful for the widget to not accidentally read parent + * state. + * + * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent` + * of the newly created scope. Defaults to `this` scope if not provided. + * This is used when creating a transclude scope to correctly place it + * in the scope hierarchy while maintaining the correct prototypical + * inheritance. + * + * @returns {Object} The newly created child scope. + * + */ + $new: function(isolate, parent) { + var child; + + parent = parent || this; + + if (isolate) { + child = new Scope(); + child.$root = this.$root; + } else { + // Only create a child scope class if somebody asks for one, + // but cache it to allow the VM to optimize lookups. + if (!this.$$ChildScope) { + this.$$ChildScope = createChildScopeClass(this); + } + child = new this.$$ChildScope(); + } + child.$parent = parent; + child.$$prevSibling = parent.$$childTail; + if (parent.$$childHead) { + parent.$$childTail.$$nextSibling = child; + parent.$$childTail = child; + } else { + parent.$$childHead = parent.$$childTail = child; + } + + // When the new scope is not isolated or we inherit from `this`, and + // the parent scope is destroyed, the property `$$destroyed` is inherited + // prototypically. In all other cases, this property needs to be set + // when the parent scope is destroyed. + // The listener needs to be added after the parent is set + if (isolate || parent != this) child.$on('$destroy', destroyChildScope); + + return child; + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$watch + * @kind function + * + * @description + * Registers a `listener` callback to be executed whenever the `watchExpression` changes. + * + * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest + * $digest()} and should return the value that will be watched. (`watchExpression` should not change + * its value when executed multiple times with the same input because it may be executed multiple + * times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be + * [idempotent](http://en.wikipedia.org/wiki/Idempotence). + * - The `listener` is called only when the value from the current `watchExpression` and the + * previous call to `watchExpression` are not equal (with the exception of the initial run, + * see below). Inequality is determined according to reference inequality, + * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators) + * via the `!==` Javascript operator, unless `objectEquality == true` + * (see next point) + * - When `objectEquality == true`, inequality of the `watchExpression` is determined + * according to the {@link angular.equals} function. To save the value of the object for + * later comparison, the {@link angular.copy} function is used. This therefore means that + * watching complex objects will have adverse memory and performance implications. + * - The watch `listener` may change the model, which may trigger other `listener`s to fire. + * This is achieved by rerunning the watchers until no changes are detected. The rerun + * iteration limit is 10 to prevent an infinite loop deadlock. + * + * + * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, + * you can register a `watchExpression` function with no `listener`. (Be prepared for + * multiple calls to your `watchExpression` because it will execute multiple times in a + * single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.) + * + * After a watcher is registered with the scope, the `listener` fn is called asynchronously + * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the + * watcher. In rare cases, this is undesirable because the listener is called when the result + * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you + * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the + * listener was called due to initialization. + * + * + * + * # Example + * ```js + // let's assume that scope was dependency injected as the $rootScope + var scope = $rootScope; + scope.name = 'misko'; + scope.counter = 0; + + expect(scope.counter).toEqual(0); + scope.$watch('name', function(newValue, oldValue) { + scope.counter = scope.counter + 1; + }); + expect(scope.counter).toEqual(0); + + scope.$digest(); + // the listener is always called during the first $digest loop after it was registered + expect(scope.counter).toEqual(1); + + scope.$digest(); + // but now it will not be called unless the value changes + expect(scope.counter).toEqual(1); + + scope.name = 'adam'; + scope.$digest(); + expect(scope.counter).toEqual(2); + + + + // Using a function as a watchExpression + var food; + scope.foodCounter = 0; + expect(scope.foodCounter).toEqual(0); + scope.$watch( + // This function returns the value being watched. It is called for each turn of the $digest loop + function() { return food; }, + // This is the change listener, called when the value returned from the above function changes + function(newValue, oldValue) { + if ( newValue !== oldValue ) { + // Only increment the counter if the value changed + scope.foodCounter = scope.foodCounter + 1; + } + } + ); + // No digest has been run so the counter will be zero + expect(scope.foodCounter).toEqual(0); + + // Run the digest but since food has not changed count will still be zero + scope.$digest(); + expect(scope.foodCounter).toEqual(0); + + // Update food and run digest. Now the counter will increment + food = 'cheeseburger'; + scope.$digest(); + expect(scope.foodCounter).toEqual(1); + + * ``` + * + * + * + * @param {(function()|string)} watchExpression Expression that is evaluated on each + * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers + * a call to the `listener`. + * + * - `string`: Evaluated as {@link guide/expression expression} + * - `function(scope)`: called with current `scope` as a parameter. + * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value + * of `watchExpression` changes. + * + * - `newVal` contains the current value of the `watchExpression` + * - `oldVal` contains the previous value of the `watchExpression` + * - `scope` refers to the current scope + * @param {boolean=} [objectEquality=false] Compare for object equality using {@link angular.equals} instead of + * comparing for reference equality. + * @returns {function()} Returns a deregistration function for this listener. + */ + $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) { + var get = $parse(watchExp); + + if (get.$$watchDelegate) { + return get.$$watchDelegate(this, listener, objectEquality, get, watchExp); + } + var scope = this, + array = scope.$$watchers, + watcher = { + fn: listener, + last: initWatchVal, + get: get, + exp: prettyPrintExpression || watchExp, + eq: !!objectEquality + }; + + lastDirtyWatch = null; + + if (!isFunction(listener)) { + watcher.fn = noop; + } + + if (!array) { + array = scope.$$watchers = []; + } + // we use unshift since we use a while loop in $digest for speed. + // the while loop reads in reverse order. + array.unshift(watcher); + incrementWatchersCount(this, 1); + + return function deregisterWatch() { + if (arrayRemove(array, watcher) >= 0) { + incrementWatchersCount(scope, -1); + } + lastDirtyWatch = null; + }; + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$watchGroup + * @kind function + * + * @description + * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`. + * If any one expression in the collection changes the `listener` is executed. + * + * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every + * call to $digest() to see if any items changes. + * - The `listener` is called whenever any expression in the `watchExpressions` array changes. + * + * @param {Array.} watchExpressions Array of expressions that will be individually + * watched using {@link ng.$rootScope.Scope#$watch $watch()} + * + * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any + * expression in `watchExpressions` changes + * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching + * those of `watchExpression` + * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching + * those of `watchExpression` + * The `scope` refers to the current scope. + * @returns {function()} Returns a de-registration function for all listeners. + */ + $watchGroup: function(watchExpressions, listener) { + var oldValues = new Array(watchExpressions.length); + var newValues = new Array(watchExpressions.length); + var deregisterFns = []; + var self = this; + var changeReactionScheduled = false; + var firstRun = true; + + if (!watchExpressions.length) { + // No expressions means we call the listener ASAP + var shouldCall = true; + self.$evalAsync(function() { + if (shouldCall) listener(newValues, newValues, self); + }); + return function deregisterWatchGroup() { + shouldCall = false; + }; + } + + if (watchExpressions.length === 1) { + // Special case size of one + return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) { + newValues[0] = value; + oldValues[0] = oldValue; + listener(newValues, (value === oldValue) ? newValues : oldValues, scope); + }); + } + + forEach(watchExpressions, function(expr, i) { + var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) { + newValues[i] = value; + oldValues[i] = oldValue; + if (!changeReactionScheduled) { + changeReactionScheduled = true; + self.$evalAsync(watchGroupAction); + } + }); + deregisterFns.push(unwatchFn); + }); + + function watchGroupAction() { + changeReactionScheduled = false; + + if (firstRun) { + firstRun = false; + listener(newValues, newValues, self); + } else { + listener(newValues, oldValues, self); + } + } + + return function deregisterWatchGroup() { + while (deregisterFns.length) { + deregisterFns.shift()(); + } + }; + }, + + + /** + * @ngdoc method + * @name $rootScope.Scope#$watchCollection + * @kind function + * + * @description + * Shallow watches the properties of an object and fires whenever any of the properties change + * (for arrays, this implies watching the array items; for object maps, this implies watching + * the properties). If a change is detected, the `listener` callback is fired. + * + * - The `obj` collection is observed via standard $watch operation and is examined on every + * call to $digest() to see if any items have been added, removed, or moved. + * - The `listener` is called whenever anything within the `obj` has changed. Examples include + * adding, removing, and moving items belonging to an object or array. + * + * + * # Example + * ```js + $scope.names = ['igor', 'matias', 'misko', 'james']; + $scope.dataCount = 4; + + $scope.$watchCollection('names', function(newNames, oldNames) { + $scope.dataCount = newNames.length; + }); + + expect($scope.dataCount).toEqual(4); + $scope.$digest(); + + //still at 4 ... no changes + expect($scope.dataCount).toEqual(4); + + $scope.names.pop(); + $scope.$digest(); + + //now there's been a change + expect($scope.dataCount).toEqual(3); + * ``` + * + * + * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The + * expression value should evaluate to an object or an array which is observed on each + * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the + * collection will trigger a call to the `listener`. + * + * @param {function(newCollection, oldCollection, scope)} listener a callback function called + * when a change is detected. + * - The `newCollection` object is the newly modified data obtained from the `obj` expression + * - The `oldCollection` object is a copy of the former collection data. + * Due to performance considerations, the`oldCollection` value is computed only if the + * `listener` function declares two or more arguments. + * - The `scope` argument refers to the current scope. + * + * @returns {function()} Returns a de-registration function for this listener. When the + * de-registration function is executed, the internal watch operation is terminated. + */ + $watchCollection: function(obj, listener) { + $watchCollectionInterceptor.$stateful = true; + + var self = this; + // the current value, updated on each dirty-check run + var newValue; + // a shallow copy of the newValue from the last dirty-check run, + // updated to match newValue during dirty-check run + var oldValue; + // a shallow copy of the newValue from when the last change happened + var veryOldValue; + // only track veryOldValue if the listener is asking for it + var trackVeryOldValue = (listener.length > 1); + var changeDetected = 0; + var changeDetector = $parse(obj, $watchCollectionInterceptor); + var internalArray = []; + var internalObject = {}; + var initRun = true; + var oldLength = 0; + + function $watchCollectionInterceptor(_value) { + newValue = _value; + var newLength, key, bothNaN, newItem, oldItem; + + // If the new value is undefined, then return undefined as the watch may be a one-time watch + if (isUndefined(newValue)) return; + + if (!isObject(newValue)) { // if primitive + if (oldValue !== newValue) { + oldValue = newValue; + changeDetected++; + } + } else if (isArrayLike(newValue)) { + if (oldValue !== internalArray) { + // we are transitioning from something which was not an array into array. + oldValue = internalArray; + oldLength = oldValue.length = 0; + changeDetected++; + } + + newLength = newValue.length; + + if (oldLength !== newLength) { + // if lengths do not match we need to trigger change notification + changeDetected++; + oldValue.length = oldLength = newLength; + } + // copy the items to oldValue and look for changes. + for (var i = 0; i < newLength; i++) { + oldItem = oldValue[i]; + newItem = newValue[i]; + + bothNaN = (oldItem !== oldItem) && (newItem !== newItem); + if (!bothNaN && (oldItem !== newItem)) { + changeDetected++; + oldValue[i] = newItem; + } + } + } else { + if (oldValue !== internalObject) { + // we are transitioning from something which was not an object into object. + oldValue = internalObject = {}; + oldLength = 0; + changeDetected++; + } + // copy the items to oldValue and look for changes. + newLength = 0; + for (key in newValue) { + if (hasOwnProperty.call(newValue, key)) { + newLength++; + newItem = newValue[key]; + oldItem = oldValue[key]; + + if (key in oldValue) { + bothNaN = (oldItem !== oldItem) && (newItem !== newItem); + if (!bothNaN && (oldItem !== newItem)) { + changeDetected++; + oldValue[key] = newItem; + } + } else { + oldLength++; + oldValue[key] = newItem; + changeDetected++; + } + } + } + if (oldLength > newLength) { + // we used to have more keys, need to find them and destroy them. + changeDetected++; + for (key in oldValue) { + if (!hasOwnProperty.call(newValue, key)) { + oldLength--; + delete oldValue[key]; + } + } + } + } + return changeDetected; + } + + function $watchCollectionAction() { + if (initRun) { + initRun = false; + listener(newValue, newValue, self); + } else { + listener(newValue, veryOldValue, self); + } + + // make a copy for the next time a collection is changed + if (trackVeryOldValue) { + if (!isObject(newValue)) { + //primitive + veryOldValue = newValue; + } else if (isArrayLike(newValue)) { + veryOldValue = new Array(newValue.length); + for (var i = 0; i < newValue.length; i++) { + veryOldValue[i] = newValue[i]; + } + } else { // if object + veryOldValue = {}; + for (var key in newValue) { + if (hasOwnProperty.call(newValue, key)) { + veryOldValue[key] = newValue[key]; + } + } + } + } + } + + return this.$watch(changeDetector, $watchCollectionAction); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$digest + * @kind function + * + * @description + * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and + * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change + * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} + * until no more listeners are firing. This means that it is possible to get into an infinite + * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of + * iterations exceeds 10. + * + * Usually, you don't call `$digest()` directly in + * {@link ng.directive:ngController controllers} or in + * {@link ng.$compileProvider#directive directives}. + * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within + * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`. + * + * If you want to be notified whenever `$digest()` is called, + * you can register a `watchExpression` function with + * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`. + * + * In unit tests, you may need to call `$digest()` to simulate the scope life cycle. + * + * # Example + * ```js + var scope = ...; + scope.name = 'misko'; + scope.counter = 0; + + expect(scope.counter).toEqual(0); + scope.$watch('name', function(newValue, oldValue) { + scope.counter = scope.counter + 1; + }); + expect(scope.counter).toEqual(0); + + scope.$digest(); + // the listener is always called during the first $digest loop after it was registered + expect(scope.counter).toEqual(1); + + scope.$digest(); + // but now it will not be called unless the value changes + expect(scope.counter).toEqual(1); + + scope.name = 'adam'; + scope.$digest(); + expect(scope.counter).toEqual(2); + * ``` + * + */ + $digest: function() { + var watch, value, last, fn, get, + watchers, + length, + dirty, ttl = TTL, + next, current, target = this, + watchLog = [], + logIdx, asyncTask; + + beginPhase('$digest'); + // Check for changes to browser url that happened in sync before the call to $digest + $browser.$$checkUrlChange(); + + if (this === $rootScope && applyAsyncId !== null) { + // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then + // cancel the scheduled $apply and flush the queue of expressions to be evaluated. + $browser.defer.cancel(applyAsyncId); + flushApplyAsync(); + } + + lastDirtyWatch = null; + + do { // "while dirty" loop + dirty = false; + current = target; + + // It's safe for asyncQueuePosition to be a local variable here because this loop can't + // be reentered recursively. Calling $digest from a function passed to $applyAsync would + // lead to a '$digest already in progress' error. + for (var asyncQueuePosition = 0; asyncQueuePosition < asyncQueue.length; asyncQueuePosition++) { + try { + asyncTask = asyncQueue[asyncQueuePosition]; + asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals); + } catch (e) { + $exceptionHandler(e); + } + lastDirtyWatch = null; + } + asyncQueue.length = 0; + + traverseScopesLoop: + do { // "traverse the scopes" loop + if ((watchers = current.$$watchers)) { + // process our watches + length = watchers.length; + while (length--) { + try { + watch = watchers[length]; + // Most common watches are on primitives, in which case we can short + // circuit it with === operator, only when === fails do we use .equals + if (watch) { + get = watch.get; + if ((value = get(current)) !== (last = watch.last) && + !(watch.eq + ? equals(value, last) + : (typeof value === 'number' && typeof last === 'number' + && isNaN(value) && isNaN(last)))) { + dirty = true; + lastDirtyWatch = watch; + watch.last = watch.eq ? copy(value, null) : value; + fn = watch.fn; + fn(value, ((last === initWatchVal) ? value : last), current); + if (ttl < 5) { + logIdx = 4 - ttl; + if (!watchLog[logIdx]) watchLog[logIdx] = []; + watchLog[logIdx].push({ + msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp, + newVal: value, + oldVal: last + }); + } + } else if (watch === lastDirtyWatch) { + // If the most recently dirty watcher is now clean, short circuit since the remaining watchers + // have already been tested. + dirty = false; + break traverseScopesLoop; + } + } + } catch (e) { + $exceptionHandler(e); + } + } + } + + // Insanity Warning: scope depth-first traversal + // yes, this code is a bit crazy, but it works and we have tests to prove it! + // this piece should be kept in sync with the traversal in $broadcast + if (!(next = ((current.$$watchersCount && current.$$childHead) || + (current !== target && current.$$nextSibling)))) { + while (current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } while ((current = next)); + + // `break traverseScopesLoop;` takes us to here + + if ((dirty || asyncQueue.length) && !(ttl--)) { + clearPhase(); + throw $rootScopeMinErr('infdig', + '{0} $digest() iterations reached. Aborting!\n' + + 'Watchers fired in the last 5 iterations: {1}', + TTL, watchLog); + } + + } while (dirty || asyncQueue.length); + + clearPhase(); + + // postDigestQueuePosition isn't local here because this loop can be reentered recursively. + while (postDigestQueuePosition < postDigestQueue.length) { + try { + postDigestQueue[postDigestQueuePosition++](); + } catch (e) { + $exceptionHandler(e); + } + } + postDigestQueue.length = postDigestQueuePosition = 0; + }, + + + /** + * @ngdoc event + * @name $rootScope.Scope#$destroy + * @eventType broadcast on scope being destroyed + * + * @description + * Broadcasted when a scope and its children are being destroyed. + * + * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to + * clean up DOM bindings before an element is removed from the DOM. + */ + + /** + * @ngdoc method + * @name $rootScope.Scope#$destroy + * @kind function + * + * @description + * Removes the current scope (and all of its children) from the parent scope. Removal implies + * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer + * propagate to the current scope and its children. Removal also implies that the current + * scope is eligible for garbage collection. + * + * The `$destroy()` is usually used by directives such as + * {@link ng.directive:ngRepeat ngRepeat} for managing the + * unrolling of the loop. + * + * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope. + * Application code can register a `$destroy` event handler that will give it a chance to + * perform any necessary cleanup. + * + * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to + * clean up DOM bindings before an element is removed from the DOM. + */ + $destroy: function() { + // We can't destroy a scope that has been already destroyed. + if (this.$$destroyed) return; + var parent = this.$parent; + + this.$broadcast('$destroy'); + this.$$destroyed = true; + + if (this === $rootScope) { + //Remove handlers attached to window when $rootScope is removed + $browser.$$applicationDestroyed(); + } + + incrementWatchersCount(this, -this.$$watchersCount); + for (var eventName in this.$$listenerCount) { + decrementListenerCount(this, this.$$listenerCount[eventName], eventName); + } + + // sever all the references to parent scopes (after this cleanup, the current scope should + // not be retained by any of our references and should be eligible for garbage collection) + if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; + if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; + if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; + if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; + + // Disable listeners, watchers and apply/digest methods + this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop; + this.$on = this.$watch = this.$watchGroup = function() { return noop; }; + this.$$listeners = {}; + + // Disconnect the next sibling to prevent `cleanUpScope` destroying those too + this.$$nextSibling = null; + cleanUpScope(this); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$eval + * @kind function + * + * @description + * Executes the `expression` on the current scope and returns the result. Any exceptions in + * the expression are propagated (uncaught). This is useful when evaluating Angular + * expressions. + * + * # Example + * ```js + var scope = ng.$rootScope.Scope(); + scope.a = 1; + scope.b = 2; + + expect(scope.$eval('a+b')).toEqual(3); + expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3); + * ``` + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + * @param {(object)=} locals Local variables object, useful for overriding values in scope. + * @returns {*} The result of evaluating the expression. + */ + $eval: function(expr, locals) { + return $parse(expr)(this, locals); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$evalAsync + * @kind function + * + * @description + * Executes the expression on the current scope at a later point in time. + * + * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only + * that: + * + * - it will execute after the function that scheduled the evaluation (preferably before DOM + * rendering). + * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after + * `expression` execution. + * + * Any exceptions from the execution of the expression are forwarded to the + * {@link ng.$exceptionHandler $exceptionHandler} service. + * + * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle + * will be scheduled. However, it is encouraged to always call code that changes the model + * from within an `$apply` call. That includes code evaluated via `$evalAsync`. + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + * @param {(object)=} locals Local variables object, useful for overriding values in scope. + */ + $evalAsync: function(expr, locals) { + // if we are outside of an $digest loop and this is the first time we are scheduling async + // task also schedule async auto-flush + if (!$rootScope.$$phase && !asyncQueue.length) { + $browser.defer(function() { + if (asyncQueue.length) { + $rootScope.$digest(); + } + }); + } + + asyncQueue.push({scope: this, expression: $parse(expr), locals: locals}); + }, + + $$postDigest: function(fn) { + postDigestQueue.push(fn); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$apply + * @kind function + * + * @description + * `$apply()` is used to execute an expression in angular from outside of the angular + * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). + * Because we are calling into the angular framework we need to perform proper scope life + * cycle of {@link ng.$exceptionHandler exception handling}, + * {@link ng.$rootScope.Scope#$digest executing watches}. + * + * ## Life cycle + * + * # Pseudo-Code of `$apply()` + * ```js + function $apply(expr) { + try { + return $eval(expr); + } catch (e) { + $exceptionHandler(e); + } finally { + $root.$digest(); + } + } + * ``` + * + * + * Scope's `$apply()` method transitions through the following stages: + * + * 1. The {@link guide/expression expression} is executed using the + * {@link ng.$rootScope.Scope#$eval $eval()} method. + * 2. Any exceptions from the execution of the expression are forwarded to the + * {@link ng.$exceptionHandler $exceptionHandler} service. + * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the + * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method. + * + * + * @param {(string|function())=} exp An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with current `scope` parameter. + * + * @returns {*} The result of evaluating the expression. + */ + $apply: function(expr) { + try { + beginPhase('$apply'); + try { + return this.$eval(expr); + } finally { + clearPhase(); + } + } catch (e) { + $exceptionHandler(e); + } finally { + try { + $rootScope.$digest(); + } catch (e) { + $exceptionHandler(e); + throw e; + } + } + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$applyAsync + * @kind function + * + * @description + * Schedule the invocation of $apply to occur at a later time. The actual time difference + * varies across browsers, but is typically around ~10 milliseconds. + * + * This can be used to queue up multiple expressions which need to be evaluated in the same + * digest. + * + * @param {(string|function())=} exp An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with current `scope` parameter. + */ + $applyAsync: function(expr) { + var scope = this; + expr && applyAsyncQueue.push($applyAsyncExpression); + expr = $parse(expr); + scheduleApplyAsync(); + + function $applyAsyncExpression() { + scope.$eval(expr); + } + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$on + * @kind function + * + * @description + * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for + * discussion of event life cycle. + * + * The event listener function format is: `function(event, args...)`. The `event` object + * passed into the listener has the following attributes: + * + * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or + * `$broadcast`-ed. + * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the + * event propagates through the scope hierarchy, this property is set to null. + * - `name` - `{string}`: name of the event. + * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel + * further event propagation (available only for events that were `$emit`-ed). + * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag + * to true. + * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called. + * + * @param {string} name Event name to listen on. + * @param {function(event, ...args)} listener Function to call when the event is emitted. + * @returns {function()} Returns a deregistration function for this listener. + */ + $on: function(name, listener) { + var namedListeners = this.$$listeners[name]; + if (!namedListeners) { + this.$$listeners[name] = namedListeners = []; + } + namedListeners.push(listener); + + var current = this; + do { + if (!current.$$listenerCount[name]) { + current.$$listenerCount[name] = 0; + } + current.$$listenerCount[name]++; + } while ((current = current.$parent)); + + var self = this; + return function() { + var indexOfListener = namedListeners.indexOf(listener); + if (indexOfListener !== -1) { + namedListeners[indexOfListener] = null; + decrementListenerCount(self, 1, name); + } + }; + }, + + + /** + * @ngdoc method + * @name $rootScope.Scope#$emit + * @kind function + * + * @description + * Dispatches an event `name` upwards through the scope hierarchy notifying the + * registered {@link ng.$rootScope.Scope#$on} listeners. + * + * The event life cycle starts at the scope on which `$emit` was called. All + * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get + * notified. Afterwards, the event traverses upwards toward the root scope and calls all + * registered listeners along the way. The event will stop propagating if one of the listeners + * cancels it. + * + * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed + * onto the {@link ng.$exceptionHandler $exceptionHandler} service. + * + * @param {string} name Event name to emit. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. + * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}). + */ + $emit: function(name, args) { + var empty = [], + namedListeners, + scope = this, + stopPropagation = false, + event = { + name: name, + targetScope: scope, + stopPropagation: function() {stopPropagation = true;}, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }, + listenerArgs = concat([event], arguments, 1), + i, length; + + do { + namedListeners = scope.$$listeners[name] || empty; + event.currentScope = scope; + for (i = 0, length = namedListeners.length; i < length; i++) { + + // if listeners were deregistered, defragment the array + if (!namedListeners[i]) { + namedListeners.splice(i, 1); + i--; + length--; + continue; + } + try { + //allow all listeners attached to the current scope to run + namedListeners[i].apply(null, listenerArgs); + } catch (e) { + $exceptionHandler(e); + } + } + //if any listener on the current scope stops propagation, prevent bubbling + if (stopPropagation) { + event.currentScope = null; + return event; + } + //traverse upwards + scope = scope.$parent; + } while (scope); + + event.currentScope = null; + + return event; + }, + + + /** + * @ngdoc method + * @name $rootScope.Scope#$broadcast + * @kind function + * + * @description + * Dispatches an event `name` downwards to all child scopes (and their children) notifying the + * registered {@link ng.$rootScope.Scope#$on} listeners. + * + * The event life cycle starts at the scope on which `$broadcast` was called. All + * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get + * notified. Afterwards, the event propagates to all direct and indirect scopes of the current + * scope and calls all registered listeners along the way. The event cannot be canceled. + * + * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed + * onto the {@link ng.$exceptionHandler $exceptionHandler} service. + * + * @param {string} name Event name to broadcast. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. + * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on} + */ + $broadcast: function(name, args) { + var target = this, + current = target, + next = target, + event = { + name: name, + targetScope: target, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }; + + if (!target.$$listenerCount[name]) return event; + + var listenerArgs = concat([event], arguments, 1), + listeners, i, length; + + //down while you can, then up and next sibling or up and next sibling until back at root + while ((current = next)) { + event.currentScope = current; + listeners = current.$$listeners[name] || []; + for (i = 0, length = listeners.length; i < length; i++) { + // if listeners were deregistered, defragment the array + if (!listeners[i]) { + listeners.splice(i, 1); + i--; + length--; + continue; + } + + try { + listeners[i].apply(null, listenerArgs); + } catch (e) { + $exceptionHandler(e); + } + } + + // Insanity Warning: scope depth-first traversal + // yes, this code is a bit crazy, but it works and we have tests to prove it! + // this piece should be kept in sync with the traversal in $digest + // (though it differs due to having the extra check for $$listenerCount) + if (!(next = ((current.$$listenerCount[name] && current.$$childHead) || + (current !== target && current.$$nextSibling)))) { + while (current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } + + event.currentScope = null; + return event; + } + }; + + var $rootScope = new Scope(); + + //The internal queues. Expose them on the $rootScope for debugging/testing purposes. + var asyncQueue = $rootScope.$$asyncQueue = []; + var postDigestQueue = $rootScope.$$postDigestQueue = []; + var applyAsyncQueue = $rootScope.$$applyAsyncQueue = []; + + var postDigestQueuePosition = 0; + + return $rootScope; + + + function beginPhase(phase) { + if ($rootScope.$$phase) { + throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase); + } + + $rootScope.$$phase = phase; + } + + function clearPhase() { + $rootScope.$$phase = null; + } + + function incrementWatchersCount(current, count) { + do { + current.$$watchersCount += count; + } while ((current = current.$parent)); + } + + function decrementListenerCount(current, count, name) { + do { + current.$$listenerCount[name] -= count; + + if (current.$$listenerCount[name] === 0) { + delete current.$$listenerCount[name]; + } + } while ((current = current.$parent)); + } + + /** + * function used as an initial value for watchers. + * because it's unique we can easily tell it apart from other values + */ + function initWatchVal() {} + + function flushApplyAsync() { + while (applyAsyncQueue.length) { + try { + applyAsyncQueue.shift()(); + } catch (e) { + $exceptionHandler(e); + } + } + applyAsyncId = null; + } + + function scheduleApplyAsync() { + if (applyAsyncId === null) { + applyAsyncId = $browser.defer(function() { + $rootScope.$apply(flushApplyAsync); + }); + } + } + }]; +} + +/** + * @ngdoc service + * @name $rootElement + * + * @description + * The root element of Angular application. This is either the element where {@link + * ng.directive:ngApp ngApp} was declared or the element passed into + * {@link angular.bootstrap}. The element represents the root element of application. It is also the + * location where the application's {@link auto.$injector $injector} service gets + * published, and can be retrieved using `$rootElement.injector()`. + */ + + +// the implementation is in angular.bootstrap + +/** + * @description + * Private service to sanitize uris for links and images. Used by $compile and $sanitize. + */ +function $$SanitizeUriProvider() { + var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/, + imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/; + + /** + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during a[href] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to a[href] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + aHrefSanitizationWhitelist = regexp; + return this; + } + return aHrefSanitizationWhitelist; + }; + + + /** + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during img[src] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to img[src] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + imgSrcSanitizationWhitelist = regexp; + return this; + } + return imgSrcSanitizationWhitelist; + }; + + this.$get = function() { + return function sanitizeUri(uri, isImage) { + var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist; + var normalizedVal; + normalizedVal = urlResolve(uri).href; + if (normalizedVal !== '' && !normalizedVal.match(regex)) { + return 'unsafe:' + normalizedVal; + } + return uri; + }; + }; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +var $sceMinErr = minErr('$sce'); + +var SCE_CONTEXTS = { + HTML: 'html', + CSS: 'css', + URL: 'url', + // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a + // url. (e.g. ng-include, script src, templateUrl) + RESOURCE_URL: 'resourceUrl', + JS: 'js' +}; + +// Helper functions follow. + +function adjustMatcher(matcher) { + if (matcher === 'self') { + return matcher; + } else if (isString(matcher)) { + // Strings match exactly except for 2 wildcards - '*' and '**'. + // '*' matches any character except those from the set ':/.?&'. + // '**' matches any character (like .* in a RegExp). + // More than 2 *'s raises an error as it's ill defined. + if (matcher.indexOf('***') > -1) { + throw $sceMinErr('iwcard', + 'Illegal sequence *** in string matcher. String: {0}', matcher); + } + matcher = escapeForRegexp(matcher). + replace('\\*\\*', '.*'). + replace('\\*', '[^:/.?&;]*'); + return new RegExp('^' + matcher + '$'); + } else if (isRegExp(matcher)) { + // The only other type of matcher allowed is a Regexp. + // Match entire URL / disallow partial matches. + // Flags are reset (i.e. no global, ignoreCase or multiline) + return new RegExp('^' + matcher.source + '$'); + } else { + throw $sceMinErr('imatcher', + 'Matchers may only be "self", string patterns or RegExp objects'); + } +} + + +function adjustMatchers(matchers) { + var adjustedMatchers = []; + if (isDefined(matchers)) { + forEach(matchers, function(matcher) { + adjustedMatchers.push(adjustMatcher(matcher)); + }); + } + return adjustedMatchers; +} + + +/** + * @ngdoc service + * @name $sceDelegate + * @kind function + * + * @description + * + * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict + * Contextual Escaping (SCE)} services to AngularJS. + * + * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of + * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is + * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to + * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things + * work because `$sce` delegates to `$sceDelegate` for these operations. + * + * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service. + * + * The default instance of `$sceDelegate` should work out of the box with little pain. While you + * can override it completely to change the behavior of `$sce`, the common case would + * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting + * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as + * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist + * $sceDelegateProvider.resourceUrlWhitelist} and {@link + * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + */ + +/** + * @ngdoc provider + * @name $sceDelegateProvider + * @description + * + * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate + * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure + * that the URLs used for sourcing Angular templates are safe. Refer {@link + * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and + * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + * + * For the general details about this service in Angular, read the main page for {@link ng.$sce + * Strict Contextual Escaping (SCE)}. + * + * **Example**: Consider the following case. + * + * - your app is hosted at url `http://myapp.example.com/` + * - but some of your templates are hosted on other domains you control such as + * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc. + * - and you have an open redirect at `http://myapp.example.com/clickThru?...`. + * + * Here is what a secure configuration for this scenario might look like: + * + * ``` + * angular.module('myApp', []).config(function($sceDelegateProvider) { + * $sceDelegateProvider.resourceUrlWhitelist([ + * // Allow same origin resource loads. + * 'self', + * // Allow loading from our assets domain. Notice the difference between * and **. + * 'http://srv*.assets.example.com/**' + * ]); + * + * // The blacklist overrides the whitelist so the open redirect here is blocked. + * $sceDelegateProvider.resourceUrlBlacklist([ + * 'http://myapp.example.com/clickThru**' + * ]); + * }); + * ``` + */ + +function $SceDelegateProvider() { + this.SCE_CONTEXTS = SCE_CONTEXTS; + + // Resource URLs can also be trusted by policy. + var resourceUrlWhitelist = ['self'], + resourceUrlBlacklist = []; + + /** + * @ngdoc method + * @name $sceDelegateProvider#resourceUrlWhitelist + * @kind function + * + * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. + * + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. + * + *
    + * **Note:** an empty whitelist array will block all URLs! + *
    + * + * @return {Array} the currently set whitelist array. + * + * The **default value** when no whitelist has been explicitly set is `['self']` allowing only + * same origin resource requests. + * + * @description + * Sets/Gets the whitelist of trusted resource URLs. + */ + this.resourceUrlWhitelist = function(value) { + if (arguments.length) { + resourceUrlWhitelist = adjustMatchers(value); + } + return resourceUrlWhitelist; + }; + + /** + * @ngdoc method + * @name $sceDelegateProvider#resourceUrlBlacklist + * @kind function + * + * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. + * + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. + * + * The typical usage for the blacklist is to **block + * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as + * these would otherwise be trusted but actually return content from the redirected domain. + * + * Finally, **the blacklist overrides the whitelist** and has the final say. + * + * @return {Array} the currently set blacklist array. + * + * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there + * is no blacklist.) + * + * @description + * Sets/Gets the blacklist of trusted resource URLs. + */ + + this.resourceUrlBlacklist = function(value) { + if (arguments.length) { + resourceUrlBlacklist = adjustMatchers(value); + } + return resourceUrlBlacklist; + }; + + this.$get = ['$injector', function($injector) { + + var htmlSanitizer = function htmlSanitizer(html) { + throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); + }; + + if ($injector.has('$sanitize')) { + htmlSanitizer = $injector.get('$sanitize'); + } + + + function matchUrl(matcher, parsedUrl) { + if (matcher === 'self') { + return urlIsSameOrigin(parsedUrl); + } else { + // definitely a regex. See adjustMatchers() + return !!matcher.exec(parsedUrl.href); + } + } + + function isResourceUrlAllowedByPolicy(url) { + var parsedUrl = urlResolve(url.toString()); + var i, n, allowed = false; + // Ensure that at least one item from the whitelist allows this url. + for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) { + if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) { + allowed = true; + break; + } + } + if (allowed) { + // Ensure that no item from the blacklist blocked this url. + for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) { + if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) { + allowed = false; + break; + } + } + } + return allowed; + } + + function generateHolderType(Base) { + var holderType = function TrustedValueHolderType(trustedValue) { + this.$$unwrapTrustedValue = function() { + return trustedValue; + }; + }; + if (Base) { + holderType.prototype = new Base(); + } + holderType.prototype.valueOf = function sceValueOf() { + return this.$$unwrapTrustedValue(); + }; + holderType.prototype.toString = function sceToString() { + return this.$$unwrapTrustedValue().toString(); + }; + return holderType; + } + + var trustedValueHolderBase = generateHolderType(), + byType = {}; + + byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]); + + /** + * @ngdoc method + * @name $sceDelegate#trustAs + * + * @description + * Returns an object that is trusted by angular for use in specified strict + * contextual escaping contexts (such as ng-bind-html, ng-include, any src + * attribute interpolation, any dom event binding attribute interpolation + * such as for onclick, etc.) that uses the provided value. + * See {@link ng.$sce $sce} for enabling strict contextual escaping. + * + * @param {string} type The kind of context in which this value is safe for use. e.g. url, + * resourceUrl, html, js and css. + * @param {*} value The value that that should be considered trusted/safe. + * @returns {*} A value that can be used to stand in for the provided `value` in places + * where Angular expects a $sce.trustAs() return value. + */ + function trustAs(type, trustedValue) { + var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null); + if (!Constructor) { + throw $sceMinErr('icontext', + 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}', + type, trustedValue); + } + if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') { + return trustedValue; + } + // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting + // mutable objects, we ensure here that the value passed in is actually a string. + if (typeof trustedValue !== 'string') { + throw $sceMinErr('itype', + 'Attempted to trust a non-string value in a content requiring a string: Context: {0}', + type); + } + return new Constructor(trustedValue); + } + + /** + * @ngdoc method + * @name $sceDelegate#valueOf + * + * @description + * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link + * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. + * + * If the passed parameter is not a value that had been returned by {@link + * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is. + * + * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} + * call or anything else. + * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns + * `value` unchanged. + */ + function valueOf(maybeTrusted) { + if (maybeTrusted instanceof trustedValueHolderBase) { + return maybeTrusted.$$unwrapTrustedValue(); + } else { + return maybeTrusted; + } + } + + /** + * @ngdoc method + * @name $sceDelegate#getTrusted + * + * @description + * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and + * returns the originally supplied value if the queried context type is a supertype of the + * created type. If this condition isn't satisfied, throws an exception. + * + *
    + * Disabling auto-escaping is extremely dangerous, it usually creates a Cross Site Scripting + * (XSS) vulnerability in your application. + *
    + * + * @param {string} type The kind of context in which this value is to be used. + * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} call. + * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception. + */ + function getTrusted(type, maybeTrusted) { + if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') { + return maybeTrusted; + } + var constructor = (byType.hasOwnProperty(type) ? byType[type] : null); + if (constructor && maybeTrusted instanceof constructor) { + return maybeTrusted.$$unwrapTrustedValue(); + } + // If we get here, then we may only take one of two actions. + // 1. sanitize the value for the requested type, or + // 2. throw an exception. + if (type === SCE_CONTEXTS.RESOURCE_URL) { + if (isResourceUrlAllowedByPolicy(maybeTrusted)) { + return maybeTrusted; + } else { + throw $sceMinErr('insecurl', + 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}', + maybeTrusted.toString()); + } + } else if (type === SCE_CONTEXTS.HTML) { + return htmlSanitizer(maybeTrusted); + } + throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); + } + + return { trustAs: trustAs, + getTrusted: getTrusted, + valueOf: valueOf }; + }]; +} + + +/** + * @ngdoc provider + * @name $sceProvider + * @description + * + * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service. + * - enable/disable Strict Contextual Escaping (SCE) in a module + * - override the default implementation with a custom delegate + * + * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}. + */ + +/* jshint maxlen: false*/ + +/** + * @ngdoc service + * @name $sce + * @kind function + * + * @description + * + * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS. + * + * # Strict Contextual Escaping + * + * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain + * contexts to result in a value that is marked as safe to use for that context. One example of + * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer + * to these contexts as privileged or SCE contexts. + * + * As of version 1.2, Angular ships with SCE enabled by default. + * + * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow + * one to execute arbitrary javascript by the use of the expression() syntax. Refer + * to learn more about them. + * You can ensure your document is in standards mode and not quirks mode by adding `` + * to the top of your HTML document. + * + * SCE assists in writing code in a way that (a) is secure by default and (b) makes auditing for + * security vulnerabilities such as XSS, clickjacking, etc. a lot easier. + * + * Here's an example of a binding in a privileged context: + * + * ``` + * + *
    + * ``` + * + * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE + * disabled, this application allows the user to render arbitrary HTML into the DIV. + * In a more realistic example, one may be rendering user comments, blog articles, etc. via + * bindings. (HTML is just one example of a context where rendering user controlled input creates + * security vulnerabilities.) + * + * For the case of HTML, you might use a library, either on the client side, or on the server side, + * to sanitize unsafe HTML before binding to the value and rendering it in the document. + * + * How would you ensure that every place that used these types of bindings was bound to a value that + * was sanitized by your library (or returned as safe for rendering by your server?) How can you + * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some + * properties/fields and forgot to update the binding to the sanitized value? + * + * To be secure by default, you want to ensure that any such bindings are disallowed unless you can + * determine that something explicitly says it's safe to use a value for binding in that + * context. You can then audit your code (a simple grep would do) to ensure that this is only done + * for those values that you can easily tell are safe - because they were received from your server, + * sanitized by your library, etc. You can organize your codebase to help with this - perhaps + * allowing only the files in a specific directory to do this. Ensuring that the internal API + * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task. + * + * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs} + * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to + * obtain values that will be accepted by SCE / privileged contexts. + * + * + * ## How does it work? + * + * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted + * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link + * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the + * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals. + * + * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link + * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly + * simplified): + * + * ``` + * var ngBindHtmlDirective = ['$sce', function($sce) { + * return function(scope, element, attr) { + * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) { + * element.html(value || ''); + * }); + * }; + * }]; + * ``` + * + * ## Impact on loading templates + * + * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as + * `templateUrl`'s specified by {@link guide/directive directives}. + * + * By default, Angular only loads templates from the same domain and protocol as the application + * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl + * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or + * protocols, you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist + * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value. + * + * *Please note*: + * The browser's + * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) + * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/) + * policy apply in addition to this and may further restrict whether the template is successfully + * loaded. This means that without the right CORS policy, loading templates from a different domain + * won't work on all browsers. Also, loading templates from `file://` URL does not work on some + * browsers. + * + * ## This feels like too much overhead + * + * It's important to remember that SCE only applies to interpolation expressions. + * + * If your expressions are constant literals, they're automatically trusted and you don't need to + * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g. + * `
    `) just works. + * + * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them + * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here. + * + * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load + * templates in `ng-include` from your application's domain without having to even know about SCE. + * It blocks loading templates from other domains or loading templates over http from an https + * served document. You can change these by setting your own custom {@link + * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link + * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs. + * + * This significantly reduces the overhead. It is far easier to pay the small overhead and have an + * application that's secure and can be audited to verify that with much more ease than bolting + * security onto an application later. + * + * + * ## What trusted context types are supported? + * + * | Context | Notes | + * |---------------------|----------------| + * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. | + * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. | + * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`
    Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. | + * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. | + * + * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist}
    + * + * Each element in these arrays must be one of the following: + * + * - **'self'** + * - The special **string**, `'self'`, can be used to match against all URLs of the **same + * domain** as the application document using the **same protocol**. + * - **String** (except the special value `'self'`) + * - The string is matched against the full *normalized / absolute URL* of the resource + * being tested (substring matches are not good enough.) + * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters + * match themselves. + * - `*`: matches zero or more occurrences of any character other than one of the following 6 + * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and '`;`'. It's a useful wildcard for use + * in a whitelist. + * - `**`: matches zero or more occurrences of *any* character. As such, it's not + * appropriate for use in a scheme, domain, etc. as it would match too much. (e.g. + * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might + * not have been the intention.) Its usage at the very end of the path is ok. (e.g. + * http://foo.example.com/templates/**). + * - **RegExp** (*see caveat below*) + * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax + * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to + * accidentally introduce a bug when one updates a complex expression (imho, all regexes should + * have good test coverage). For instance, the use of `.` in the regex is correct only in a + * small number of cases. A `.` character in the regex used when matching the scheme or a + * subdomain could be matched against a `:` or literal `.` that was likely not intended. It + * is highly recommended to use the string patterns and only fall back to regular expressions + * as a last resort. + * - The regular expression must be an instance of RegExp (i.e. not a string.) It is + * matched against the **entire** *normalized / absolute URL* of the resource being tested + * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags + * present on the RegExp (such as multiline, global, ignoreCase) are ignored. + * - If you are generating your JavaScript from some other templating engine (not + * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)), + * remember to escape your regular expression (and be aware that you might need more than + * one level of escaping depending on your templating engine and the way you interpolated + * the value.) Do make use of your platform's escaping mechanism as it might be good + * enough before coding your own. E.g. Ruby has + * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape) + * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape). + * Javascript lacks a similar built in function for escaping. Take a look at Google + * Closure library's [goog.string.regExpEscape(s)]( + * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962). + * + * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example. + * + * ## Show me an example using SCE. + * + * + * + *
    + *

    + * User comments
    + * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when + * $sanitize is available. If $sanitize isn't available, this results in an error instead of an + * exploit. + *
    + *
    + * {{userComment.name}}: + * + *
    + *
    + *
    + *
    + *
    + * + * + * angular.module('mySceApp', ['ngSanitize']) + * .controller('AppController', ['$http', '$templateCache', '$sce', + * function($http, $templateCache, $sce) { + * var self = this; + * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) { + * self.userComments = userComments; + * }); + * self.explicitlyTrustedHtml = $sce.trustAsHtml( + * 'Hover over this text.'); + * }]); + * + * + * + * [ + * { "name": "Alice", + * "htmlComment": + * "Is anyone reading this?" + * }, + * { "name": "Bob", + * "htmlComment": "Yes! Am I the only other one?" + * } + * ] + * + * + * + * describe('SCE doc demo', function() { + * it('should sanitize untrusted values', function() { + * expect(element.all(by.css('.htmlComment')).first().getInnerHtml()) + * .toBe('Is anyone reading this?'); + * }); + * + * it('should NOT sanitize explicitly trusted values', function() { + * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe( + * 'Hover over this text.'); + * }); + * }); + * + *
    + * + * + * + * ## Can I disable SCE completely? + * + * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits + * for little coding overhead. It will be much harder to take an SCE disabled application and + * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE + * for cases where you have a lot of existing code that was written before SCE was introduced and + * you're migrating them a module at a time. + * + * That said, here's how you can completely disable SCE: + * + * ``` + * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) { + * // Completely disable SCE. For demonstration purposes only! + * // Do not use in new projects. + * $sceProvider.enabled(false); + * }); + * ``` + * + */ +/* jshint maxlen: 100 */ + +function $SceProvider() { + var enabled = true; + + /** + * @ngdoc method + * @name $sceProvider#enabled + * @kind function + * + * @param {boolean=} value If provided, then enables/disables SCE. + * @return {boolean} true if SCE is enabled, false otherwise. + * + * @description + * Enables/disables SCE and returns the current value. + */ + this.enabled = function(value) { + if (arguments.length) { + enabled = !!value; + } + return enabled; + }; + + + /* Design notes on the default implementation for SCE. + * + * The API contract for the SCE delegate + * ------------------------------------- + * The SCE delegate object must provide the following 3 methods: + * + * - trustAs(contextEnum, value) + * This method is used to tell the SCE service that the provided value is OK to use in the + * contexts specified by contextEnum. It must return an object that will be accepted by + * getTrusted() for a compatible contextEnum and return this value. + * + * - valueOf(value) + * For values that were not produced by trustAs(), return them as is. For values that were + * produced by trustAs(), return the corresponding input value to trustAs. Basically, if + * trustAs is wrapping the given values into some type, this operation unwraps it when given + * such a value. + * + * - getTrusted(contextEnum, value) + * This function should return the a value that is safe to use in the context specified by + * contextEnum or throw and exception otherwise. + * + * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be + * opaque or wrapped in some holder object. That happens to be an implementation detail. For + * instance, an implementation could maintain a registry of all trusted objects by context. In + * such a case, trustAs() would return the same object that was passed in. getTrusted() would + * return the same object passed in if it was found in the registry under a compatible context or + * throw an exception otherwise. An implementation might only wrap values some of the time based + * on some criteria. getTrusted() might return a value and not throw an exception for special + * constants or objects even if not wrapped. All such implementations fulfill this contract. + * + * + * A note on the inheritance model for SCE contexts + * ------------------------------------------------ + * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This + * is purely an implementation details. + * + * The contract is simply this: + * + * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value) + * will also succeed. + * + * Inheritance happens to capture this in a natural way. In some future, we + * may not use inheritance anymore. That is OK because no code outside of + * sce.js and sceSpecs.js would need to be aware of this detail. + */ + + this.$get = ['$parse', '$sceDelegate', function( + $parse, $sceDelegate) { + // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow + // the "expression(javascript expression)" syntax which is insecure. + if (enabled && msie < 8) { + throw $sceMinErr('iequirks', + 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' + + 'mode. You can fix this by adding the text to the top of your HTML ' + + 'document. See http://docs.angularjs.org/api/ng.$sce for more information.'); + } + + var sce = shallowCopy(SCE_CONTEXTS); + + /** + * @ngdoc method + * @name $sce#isEnabled + * @kind function + * + * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you + * have to do it at module config time on {@link ng.$sceProvider $sceProvider}. + * + * @description + * Returns a boolean indicating if SCE is enabled. + */ + sce.isEnabled = function() { + return enabled; + }; + sce.trustAs = $sceDelegate.trustAs; + sce.getTrusted = $sceDelegate.getTrusted; + sce.valueOf = $sceDelegate.valueOf; + + if (!enabled) { + sce.trustAs = sce.getTrusted = function(type, value) { return value; }; + sce.valueOf = identity; + } + + /** + * @ngdoc method + * @name $sce#parseAs + * + * @description + * Converts Angular {@link guide/expression expression} into a function. This is like {@link + * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it + * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*, + * *result*)} + * + * @param {string} type The kind of SCE context in which this result will be used. + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + sce.parseAs = function sceParseAs(type, expr) { + var parsed = $parse(expr); + if (parsed.literal && parsed.constant) { + return parsed; + } else { + return $parse(expr, function(value) { + return sce.getTrusted(type, value); + }); + } + }; + + /** + * @ngdoc method + * @name $sce#trustAs + * + * @description + * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such, + * returns an object that is trusted by angular for use in specified strict contextual + * escaping contexts (such as ng-bind-html, ng-include, any src attribute + * interpolation, any dom event binding attribute interpolation such as for onclick, etc.) + * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual + * escaping. + * + * @param {string} type The kind of context in which this value is safe for use. e.g. url, + * resourceUrl, html, js and css. + * @param {*} value The value that that should be considered trusted/safe. + * @returns {*} A value that can be used to stand in for the provided `value` in places + * where Angular expects a $sce.trustAs() return value. + */ + + /** + * @ngdoc method + * @name $sce#trustAsHtml + * + * @description + * Shorthand method. `$sce.trustAsHtml(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml + * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#trustAsUrl + * + * @description + * Shorthand method. `$sce.trustAsUrl(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl + * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#trustAsResourceUrl + * + * @description + * Shorthand method. `$sce.trustAsResourceUrl(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl + * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the return + * value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#trustAsJs + * + * @description + * Shorthand method. `$sce.trustAsJs(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs + * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#getTrusted + * + * @description + * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such, + * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the + * originally supplied value if the queried context type is a supertype of the created type. + * If this condition isn't satisfied, throws an exception. + * + * @param {string} type The kind of context in which this value is to be used. + * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`} + * call. + * @returns {*} The value the was originally provided to + * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context. + * Otherwise, throws an exception. + */ + + /** + * @ngdoc method + * @name $sce#getTrustedHtml + * + * @description + * Shorthand method. `$sce.getTrustedHtml(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedCss + * + * @description + * Shorthand method. `$sce.getTrustedCss(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedUrl + * + * @description + * Shorthand method. `$sce.getTrustedUrl(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedResourceUrl + * + * @description + * Shorthand method. `$sce.getTrustedResourceUrl(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`} + * + * @param {*} value The value to pass to `$sceDelegate.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedJs + * + * @description + * Shorthand method. `$sce.getTrustedJs(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)` + */ + + /** + * @ngdoc method + * @name $sce#parseAsHtml + * + * @description + * Shorthand method. `$sce.parseAsHtml(expression string)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsCss + * + * @description + * Shorthand method. `$sce.parseAsCss(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsUrl + * + * @description + * Shorthand method. `$sce.parseAsUrl(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsResourceUrl + * + * @description + * Shorthand method. `$sce.parseAsResourceUrl(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsJs + * + * @description + * Shorthand method. `$sce.parseAsJs(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + // Shorthand delegations. + var parse = sce.parseAs, + getTrusted = sce.getTrusted, + trustAs = sce.trustAs; + + forEach(SCE_CONTEXTS, function(enumValue, name) { + var lName = lowercase(name); + sce[camelCase("parse_as_" + lName)] = function(expr) { + return parse(enumValue, expr); + }; + sce[camelCase("get_trusted_" + lName)] = function(value) { + return getTrusted(enumValue, value); + }; + sce[camelCase("trust_as_" + lName)] = function(value) { + return trustAs(enumValue, value); + }; + }); + + return sce; + }]; +} + +/** + * !!! This is an undocumented "private" service !!! + * + * @name $sniffer + * @requires $window + * @requires $document + * + * @property {boolean} history Does the browser support html5 history api ? + * @property {boolean} transitions Does the browser support CSS transition events ? + * @property {boolean} animations Does the browser support CSS animation events ? + * + * @description + * This is very simple implementation of testing browser's features. + */ +function $SnifferProvider() { + this.$get = ['$window', '$document', function($window, $document) { + var eventSupport = {}, + // Chrome Packaged Apps are not allowed to access `history.pushState`. They can be detected by + // the presence of `chrome.app.runtime` (see https://developer.chrome.com/apps/api_index) + isChromePackagedApp = $window.chrome && $window.chrome.app && $window.chrome.app.runtime, + hasHistoryPushState = !isChromePackagedApp && $window.history && $window.history.pushState, + android = + toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), + boxee = /Boxee/i.test(($window.navigator || {}).userAgent), + document = $document[0] || {}, + vendorPrefix, + vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/, + bodyStyle = document.body && document.body.style, + transitions = false, + animations = false, + match; + + if (bodyStyle) { + for (var prop in bodyStyle) { + if (match = vendorRegex.exec(prop)) { + vendorPrefix = match[0]; + vendorPrefix = vendorPrefix[0].toUpperCase() + vendorPrefix.substr(1); + break; + } + } + + if (!vendorPrefix) { + vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit'; + } + + transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle)); + animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle)); + + if (android && (!transitions || !animations)) { + transitions = isString(bodyStyle.webkitTransition); + animations = isString(bodyStyle.webkitAnimation); + } + } + + + return { + // Android has history.pushState, but it does not update location correctly + // so let's not use the history API at all. + // http://code.google.com/p/android/issues/detail?id=17471 + // https://github.com/angular/angular.js/issues/904 + + // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has + // so let's not use the history API also + // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined + // jshint -W018 + history: !!(hasHistoryPushState && !(android < 4) && !boxee), + // jshint +W018 + hasEvent: function(event) { + // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have + // it. In particular the event is not fired when backspace or delete key are pressed or + // when cut operation is performed. + // IE10+ implements 'input' event but it erroneously fires under various situations, + // e.g. when placeholder changes, or a form is focused. + if (event === 'input' && msie <= 11) return false; + + if (isUndefined(eventSupport[event])) { + var divElm = document.createElement('div'); + eventSupport[event] = 'on' + event in divElm; + } + + return eventSupport[event]; + }, + csp: csp(), + vendorPrefix: vendorPrefix, + transitions: transitions, + animations: animations, + android: android + }; + }]; +} + +var $templateRequestMinErr = minErr('$compile'); + +/** + * @ngdoc provider + * @name $templateRequestProvider + * @description + * Used to configure the options passed to the {@link $http} service when making a template request. + * + * For example, it can be used for specifying the "Accept" header that is sent to the server, when + * requesting a template. + */ +function $TemplateRequestProvider() { + + var httpOptions; + + /** + * @ngdoc method + * @name $templateRequestProvider#httpOptions + * @description + * The options to be passed to the {@link $http} service when making the request. + * You can use this to override options such as the "Accept" header for template requests. + * + * The {@link $templateRequest} will set the `cache` and the `transformResponse` properties of the + * options if not overridden here. + * + * @param {string=} value new value for the {@link $http} options. + * @returns {string|self} Returns the {@link $http} options when used as getter and self if used as setter. + */ + this.httpOptions = function(val) { + if (val) { + httpOptions = val; + return this; + } + return httpOptions; + }; + + /** + * @ngdoc service + * @name $templateRequest + * + * @description + * The `$templateRequest` service runs security checks then downloads the provided template using + * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request + * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the + * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the + * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted + * when `tpl` is of type string and `$templateCache` has the matching entry. + * + * If you want to pass custom options to the `$http` service, such as setting the Accept header you + * can configure this via {@link $templateRequestProvider#httpOptions}. + * + * @param {string|TrustedResourceUrl} tpl The HTTP request template URL + * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty + * + * @return {Promise} a promise for the HTTP response data of the given URL. + * + * @property {number} totalPendingRequests total amount of pending template requests being downloaded. + */ + this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) { + + function handleRequestFn(tpl, ignoreRequestError) { + handleRequestFn.totalPendingRequests++; + + // We consider the template cache holds only trusted templates, so + // there's no need to go through whitelisting again for keys that already + // are included in there. This also makes Angular accept any script + // directive, no matter its name. However, we still need to unwrap trusted + // types. + if (!isString(tpl) || isUndefined($templateCache.get(tpl))) { + tpl = $sce.getTrustedResourceUrl(tpl); + } + + var transformResponse = $http.defaults && $http.defaults.transformResponse; + + if (isArray(transformResponse)) { + transformResponse = transformResponse.filter(function(transformer) { + return transformer !== defaultHttpResponseTransform; + }); + } else if (transformResponse === defaultHttpResponseTransform) { + transformResponse = null; + } + + return $http.get(tpl, extend({ + cache: $templateCache, + transformResponse: transformResponse + }, httpOptions)) + ['finally'](function() { + handleRequestFn.totalPendingRequests--; + }) + .then(function(response) { + $templateCache.put(tpl, response.data); + return response.data; + }, handleError); + + function handleError(resp) { + if (!ignoreRequestError) { + throw $templateRequestMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})', + tpl, resp.status, resp.statusText); + } + return $q.reject(resp); + } + } + + handleRequestFn.totalPendingRequests = 0; + + return handleRequestFn; + }]; +} + +function $$TestabilityProvider() { + this.$get = ['$rootScope', '$browser', '$location', + function($rootScope, $browser, $location) { + + /** + * @name $testability + * + * @description + * The private $$testability service provides a collection of methods for use when debugging + * or by automated test and debugging tools. + */ + var testability = {}; + + /** + * @name $$testability#findBindings + * + * @description + * Returns an array of elements that are bound (via ng-bind or {{}}) + * to expressions matching the input. + * + * @param {Element} element The element root to search from. + * @param {string} expression The binding expression to match. + * @param {boolean} opt_exactMatch If true, only returns exact matches + * for the expression. Filters and whitespace are ignored. + */ + testability.findBindings = function(element, expression, opt_exactMatch) { + var bindings = element.getElementsByClassName('ng-binding'); + var matches = []; + forEach(bindings, function(binding) { + var dataBinding = angular.element(binding).data('$binding'); + if (dataBinding) { + forEach(dataBinding, function(bindingName) { + if (opt_exactMatch) { + var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)'); + if (matcher.test(bindingName)) { + matches.push(binding); + } + } else { + if (bindingName.indexOf(expression) != -1) { + matches.push(binding); + } + } + }); + } + }); + return matches; + }; + + /** + * @name $$testability#findModels + * + * @description + * Returns an array of elements that are two-way found via ng-model to + * expressions matching the input. + * + * @param {Element} element The element root to search from. + * @param {string} expression The model expression to match. + * @param {boolean} opt_exactMatch If true, only returns exact matches + * for the expression. + */ + testability.findModels = function(element, expression, opt_exactMatch) { + var prefixes = ['ng-', 'data-ng-', 'ng\\:']; + for (var p = 0; p < prefixes.length; ++p) { + var attributeEquals = opt_exactMatch ? '=' : '*='; + var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]'; + var elements = element.querySelectorAll(selector); + if (elements.length) { + return elements; + } + } + }; + + /** + * @name $$testability#getLocation + * + * @description + * Shortcut for getting the location in a browser agnostic way. Returns + * the path, search, and hash. (e.g. /path?a=b#hash) + */ + testability.getLocation = function() { + return $location.url(); + }; + + /** + * @name $$testability#setLocation + * + * @description + * Shortcut for navigating to a location without doing a full page reload. + * + * @param {string} url The location url (path, search and hash, + * e.g. /path?a=b#hash) to go to. + */ + testability.setLocation = function(url) { + if (url !== $location.url()) { + $location.url(url); + $rootScope.$digest(); + } + }; + + /** + * @name $$testability#whenStable + * + * @description + * Calls the callback when $timeout and $http requests are completed. + * + * @param {function} callback + */ + testability.whenStable = function(callback) { + $browser.notifyWhenNoOutstandingRequests(callback); + }; + + return testability; + }]; +} + +function $TimeoutProvider() { + this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler', + function($rootScope, $browser, $q, $$q, $exceptionHandler) { + + var deferreds = {}; + + + /** + * @ngdoc service + * @name $timeout + * + * @description + * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch + * block and delegates any exceptions to + * {@link ng.$exceptionHandler $exceptionHandler} service. + * + * The return value of calling `$timeout` is a promise, which will be resolved when + * the delay has passed and the timeout function, if provided, is executed. + * + * To cancel a timeout request, call `$timeout.cancel(promise)`. + * + * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to + * synchronously flush the queue of deferred functions. + * + * If you only want a promise that will be resolved after some specified delay + * then you can call `$timeout` without the `fn` function. + * + * @param {function()=} fn A function, whose execution should be delayed. + * @param {number=} [delay=0] Delay in milliseconds. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. + * @returns {Promise} Promise that will be resolved when the timeout is reached. The promise + * will be resolved with the return value of the `fn` function. + * + */ + function timeout(fn, delay, invokeApply) { + if (!isFunction(fn)) { + invokeApply = delay; + delay = fn; + fn = noop; + } + + var args = sliceArgs(arguments, 3), + skipApply = (isDefined(invokeApply) && !invokeApply), + deferred = (skipApply ? $$q : $q).defer(), + promise = deferred.promise, + timeoutId; + + timeoutId = $browser.defer(function() { + try { + deferred.resolve(fn.apply(null, args)); + } catch (e) { + deferred.reject(e); + $exceptionHandler(e); + } + finally { + delete deferreds[promise.$$timeoutId]; + } + + if (!skipApply) $rootScope.$apply(); + }, delay); + + promise.$$timeoutId = timeoutId; + deferreds[timeoutId] = deferred; + + return promise; + } + + + /** + * @ngdoc method + * @name $timeout#cancel + * + * @description + * Cancels a task associated with the `promise`. As a result of this, the promise will be + * resolved with a rejection. + * + * @param {Promise=} promise Promise returned by the `$timeout` function. + * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully + * canceled. + */ + timeout.cancel = function(promise) { + if (promise && promise.$$timeoutId in deferreds) { + deferreds[promise.$$timeoutId].reject('canceled'); + delete deferreds[promise.$$timeoutId]; + return $browser.defer.cancel(promise.$$timeoutId); + } + return false; + }; + + return timeout; + }]; +} + +// NOTE: The usage of window and document instead of $window and $document here is +// deliberate. This service depends on the specific behavior of anchor nodes created by the +// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and +// cause us to break tests. In addition, when the browser resolves a URL for XHR, it +// doesn't know about mocked locations and resolves URLs to the real document - which is +// exactly the behavior needed here. There is little value is mocking these out for this +// service. +var urlParsingNode = window.document.createElement("a"); +var originUrl = urlResolve(window.location.href); + + +/** + * + * Implementation Notes for non-IE browsers + * ---------------------------------------- + * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM, + * results both in the normalizing and parsing of the URL. Normalizing means that a relative + * URL will be resolved into an absolute URL in the context of the application document. + * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related + * properties are all populated to reflect the normalized URL. This approach has wide + * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * + * Implementation Notes for IE + * --------------------------- + * IE <= 10 normalizes the URL when assigned to the anchor node similar to the other + * browsers. However, the parsed components will not be set if the URL assigned did not specify + * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We + * work around that by performing the parsing in a 2nd step by taking a previously normalized + * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the + * properties such as protocol, hostname, port, etc. + * + * References: + * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * http://url.spec.whatwg.org/#urlutils + * https://github.com/angular/angular.js/pull/2902 + * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ + * + * @kind function + * @param {string} url The URL to be parsed. + * @description Normalizes and parses a URL. + * @returns {object} Returns the normalized URL as a dictionary. + * + * | member name | Description | + * |---------------|----------------| + * | href | A normalized version of the provided URL if it was not an absolute URL | + * | protocol | The protocol including the trailing colon | + * | host | The host and port (if the port is non-default) of the normalizedUrl | + * | search | The search params, minus the question mark | + * | hash | The hash string, minus the hash symbol + * | hostname | The hostname + * | port | The port, without ":" + * | pathname | The pathname, beginning with "/" + * + */ +function urlResolve(url) { + var href = url; + + if (msie) { + // Normalize before parse. Refer Implementation Notes on why this is + // done in two steps on IE. + urlParsingNode.setAttribute("href", href); + href = urlParsingNode.href; + } + + urlParsingNode.setAttribute('href', href); + + // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils + return { + href: urlParsingNode.href, + protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', + host: urlParsingNode.host, + search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', + hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', + hostname: urlParsingNode.hostname, + port: urlParsingNode.port, + pathname: (urlParsingNode.pathname.charAt(0) === '/') + ? urlParsingNode.pathname + : '/' + urlParsingNode.pathname + }; +} + +/** + * Parse a request URL and determine whether this is a same-origin request as the application document. + * + * @param {string|object} requestUrl The url of the request as a string that will be resolved + * or a parsed URL object. + * @returns {boolean} Whether the request is for the same origin as the application document. + */ +function urlIsSameOrigin(requestUrl) { + var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl; + return (parsed.protocol === originUrl.protocol && + parsed.host === originUrl.host); +} + +/** + * @ngdoc service + * @name $window + * + * @description + * A reference to the browser's `window` object. While `window` + * is globally available in JavaScript, it causes testability problems, because + * it is a global variable. In angular we always refer to it through the + * `$window` service, so it may be overridden, removed or mocked for testing. + * + * Expressions, like the one defined for the `ngClick` directive in the example + * below, are evaluated with respect to the current scope. Therefore, there is + * no risk of inadvertently coding in a dependency on a global value in such an + * expression. + * + * @example + + + +
    + + +
    +
    + + it('should display the greeting in the input box', function() { + element(by.model('greeting')).sendKeys('Hello, E2E Tests'); + // If we click the button it will block the test runner + // element(':button').click(); + }); + +
    + */ +function $WindowProvider() { + this.$get = valueFn(window); +} + +/** + * @name $$cookieReader + * @requires $document + * + * @description + * This is a private service for reading cookies used by $http and ngCookies + * + * @return {Object} a key/value map of the current cookies + */ +function $$CookieReader($document) { + var rawDocument = $document[0] || {}; + var lastCookies = {}; + var lastCookieString = ''; + + function safeDecodeURIComponent(str) { + try { + return decodeURIComponent(str); + } catch (e) { + return str; + } + } + + return function() { + var cookieArray, cookie, i, index, name; + var currentCookieString = rawDocument.cookie || ''; + + if (currentCookieString !== lastCookieString) { + lastCookieString = currentCookieString; + cookieArray = lastCookieString.split('; '); + lastCookies = {}; + + for (i = 0; i < cookieArray.length; i++) { + cookie = cookieArray[i]; + index = cookie.indexOf('='); + if (index > 0) { //ignore nameless cookies + name = safeDecodeURIComponent(cookie.substring(0, index)); + // the first value that is seen for a cookie is the most + // specific one. values for the same cookie name that + // follow are for less specific paths. + if (isUndefined(lastCookies[name])) { + lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); + } + } + } + } + return lastCookies; + }; +} + +$$CookieReader.$inject = ['$document']; + +function $$CookieReaderProvider() { + this.$get = $$CookieReader; +} + +/* global currencyFilter: true, + dateFilter: true, + filterFilter: true, + jsonFilter: true, + limitToFilter: true, + lowercaseFilter: true, + numberFilter: true, + orderByFilter: true, + uppercaseFilter: true, + */ + +/** + * @ngdoc provider + * @name $filterProvider + * @description + * + * Filters are just functions which transform input to an output. However filters need to be + * Dependency Injected. To achieve this a filter definition consists of a factory function which is + * annotated with dependencies and is responsible for creating a filter function. + * + *
    + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + *
    + * + * ```js + * // Filter registration + * function MyModule($provide, $filterProvider) { + * // create a service to demonstrate injection (not always needed) + * $provide.value('greet', function(name){ + * return 'Hello ' + name + '!'; + * }); + * + * // register a filter factory which uses the + * // greet service to demonstrate DI. + * $filterProvider.register('greet', function(greet){ + * // return the filter function which uses the greet service + * // to generate salutation + * return function(text) { + * // filters need to be forgiving so check input validity + * return text && greet(text) || text; + * }; + * }); + * } + * ``` + * + * The filter function is registered with the `$injector` under the filter name suffix with + * `Filter`. + * + * ```js + * it('should be the same instance', inject( + * function($filterProvider) { + * $filterProvider.register('reverse', function(){ + * return ...; + * }); + * }, + * function($filter, reverseFilter) { + * expect($filter('reverse')).toBe(reverseFilter); + * }); + * ``` + * + * + * For more information about how angular filters work, and how to create your own filters, see + * {@link guide/filter Filters} in the Angular Developer Guide. + */ + +/** + * @ngdoc service + * @name $filter + * @kind function + * @description + * Filters are used for formatting data displayed to the user. + * + * The general syntax in templates is as follows: + * + * {{ expression [| filter_name[:parameter_value] ... ] }} + * + * @param {String} name Name of the filter function to retrieve + * @return {Function} the filter function + * @example + + +
    +

    {{ originalText }}

    +

    {{ filteredText }}

    +
    +
    + + + angular.module('filterExample', []) + .controller('MainCtrl', function($scope, $filter) { + $scope.originalText = 'hello'; + $scope.filteredText = $filter('uppercase')($scope.originalText); + }); + +
    + */ +$FilterProvider.$inject = ['$provide']; +function $FilterProvider($provide) { + var suffix = 'Filter'; + + /** + * @ngdoc method + * @name $filterProvider#register + * @param {string|Object} name Name of the filter function, or an object map of filters where + * the keys are the filter names and the values are the filter factories. + * + *
    + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + *
    + * @param {Function} factory If the first argument was a string, a factory function for the filter to be registered. + * @returns {Object} Registered filter instance, or if a map of filters was provided then a map + * of the registered filter instances. + */ + function register(name, factory) { + if (isObject(name)) { + var filters = {}; + forEach(name, function(filter, key) { + filters[key] = register(key, filter); + }); + return filters; + } else { + return $provide.factory(name + suffix, factory); + } + } + this.register = register; + + this.$get = ['$injector', function($injector) { + return function(name) { + return $injector.get(name + suffix); + }; + }]; + + //////////////////////////////////////// + + /* global + currencyFilter: false, + dateFilter: false, + filterFilter: false, + jsonFilter: false, + limitToFilter: false, + lowercaseFilter: false, + numberFilter: false, + orderByFilter: false, + uppercaseFilter: false, + */ + + register('currency', currencyFilter); + register('date', dateFilter); + register('filter', filterFilter); + register('json', jsonFilter); + register('limitTo', limitToFilter); + register('lowercase', lowercaseFilter); + register('number', numberFilter); + register('orderBy', orderByFilter); + register('uppercase', uppercaseFilter); +} + +/** + * @ngdoc filter + * @name filter + * @kind function + * + * @description + * Selects a subset of items from `array` and returns it as a new array. + * + * @param {Array} array The source array. + * @param {string|Object|function()} expression The predicate to be used for selecting items from + * `array`. + * + * Can be one of: + * + * - `string`: The string is used for matching against the contents of the `array`. All strings or + * objects with string properties in `array` that match this string will be returned. This also + * applies to nested object properties. + * The predicate can be negated by prefixing the string with `!`. + * + * - `Object`: A pattern object can be used to filter specific properties on objects contained + * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items + * which have property `name` containing "M" and property `phone` containing "1". A special + * property name (`$` by default) can be used (e.g. as in `{$: "text"}`) to accept a match + * against any property of the object or its nested object properties. That's equivalent to the + * simple substring match with a `string` as described above. The special property name can be + * overwritten, using the `anyPropertyKey` parameter. + * The predicate can be negated by prefixing the string with `!`. + * For example `{name: "!M"}` predicate will return an array of items which have property `name` + * not containing "M". + * + * Note that a named property will match properties on the same level only, while the special + * `$` property will match properties on the same level or deeper. E.g. an array item like + * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but + * **will** be matched by `{$: 'John'}`. + * + * - `function(value, index, array)`: A predicate function can be used to write arbitrary filters. + * The function is called for each element of the array, with the element, its index, and + * the entire array itself as arguments. + * + * The final result is an array of those elements that the predicate returned true for. + * + * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in + * determining if the expected value (from the filter expression) and actual value (from + * the object in the array) should be considered a match. + * + * Can be one of: + * + * - `function(actual, expected)`: + * The function will be given the object value and the predicate value to compare and + * should return true if both values should be considered equal. + * + * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`. + * This is essentially strict comparison of expected and actual. + * + * - `false|undefined`: A short hand for a function which will look for a substring match in case + * insensitive way. + * + * Primitive values are converted to strings. Objects are not compared against primitives, + * unless they have a custom `toString` method (e.g. `Date` objects). + * + * @param {string=} anyPropertyKey The special property name that matches against any property. + * By default `$`. + * + * @example + + +
    + + + + + + + + +
    NamePhone
    {{friend.name}}{{friend.phone}}
    +
    +
    +
    +
    +
    + + + + + + +
    NamePhone
    {{friendObj.name}}{{friendObj.phone}}
    +
    + + var expectFriendNames = function(expectedNames, key) { + element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) { + arr.forEach(function(wd, i) { + expect(wd.getText()).toMatch(expectedNames[i]); + }); + }); + }; + + it('should search across all fields when filtering with a string', function() { + var searchText = element(by.model('searchText')); + searchText.clear(); + searchText.sendKeys('m'); + expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend'); + + searchText.clear(); + searchText.sendKeys('76'); + expectFriendNames(['John', 'Julie'], 'friend'); + }); + + it('should search in specific fields when filtering with a predicate object', function() { + var searchAny = element(by.model('search.$')); + searchAny.clear(); + searchAny.sendKeys('i'); + expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj'); + }); + it('should use a equal comparison when comparator is true', function() { + var searchName = element(by.model('search.name')); + var strict = element(by.model('strict')); + searchName.clear(); + searchName.sendKeys('Julie'); + strict.click(); + expectFriendNames(['Julie'], 'friendObj'); + }); + +
    + */ + +function filterFilter() { + return function(array, expression, comparator, anyPropertyKey) { + if (!isArrayLike(array)) { + if (array == null) { + return array; + } else { + throw minErr('filter')('notarray', 'Expected array but received: {0}', array); + } + } + + anyPropertyKey = anyPropertyKey || '$'; + var expressionType = getTypeForFilter(expression); + var predicateFn; + var matchAgainstAnyProp; + + switch (expressionType) { + case 'function': + predicateFn = expression; + break; + case 'boolean': + case 'null': + case 'number': + case 'string': + matchAgainstAnyProp = true; + //jshint -W086 + case 'object': + //jshint +W086 + predicateFn = createPredicateFn(expression, comparator, anyPropertyKey, matchAgainstAnyProp); + break; + default: + return array; + } + + return Array.prototype.filter.call(array, predicateFn); + }; +} + +// Helper functions for `filterFilter` +function createPredicateFn(expression, comparator, anyPropertyKey, matchAgainstAnyProp) { + var shouldMatchPrimitives = isObject(expression) && (anyPropertyKey in expression); + var predicateFn; + + if (comparator === true) { + comparator = equals; + } else if (!isFunction(comparator)) { + comparator = function(actual, expected) { + if (isUndefined(actual)) { + // No substring matching against `undefined` + return false; + } + if ((actual === null) || (expected === null)) { + // No substring matching against `null`; only match against `null` + return actual === expected; + } + if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) { + // Should not compare primitives against objects, unless they have custom `toString` method + return false; + } + + actual = lowercase('' + actual); + expected = lowercase('' + expected); + return actual.indexOf(expected) !== -1; + }; + } + + predicateFn = function(item) { + if (shouldMatchPrimitives && !isObject(item)) { + return deepCompare(item, expression[anyPropertyKey], comparator, anyPropertyKey, false); + } + return deepCompare(item, expression, comparator, anyPropertyKey, matchAgainstAnyProp); + }; + + return predicateFn; +} + +function deepCompare(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject) { + var actualType = getTypeForFilter(actual); + var expectedType = getTypeForFilter(expected); + + if ((expectedType === 'string') && (expected.charAt(0) === '!')) { + return !deepCompare(actual, expected.substring(1), comparator, anyPropertyKey, matchAgainstAnyProp); + } else if (isArray(actual)) { + // In case `actual` is an array, consider it a match + // if ANY of it's items matches `expected` + return actual.some(function(item) { + return deepCompare(item, expected, comparator, anyPropertyKey, matchAgainstAnyProp); + }); + } + + switch (actualType) { + case 'object': + var key; + if (matchAgainstAnyProp) { + for (key in actual) { + if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, anyPropertyKey, true)) { + return true; + } + } + return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, anyPropertyKey, false); + } else if (expectedType === 'object') { + for (key in expected) { + var expectedVal = expected[key]; + if (isFunction(expectedVal) || isUndefined(expectedVal)) { + continue; + } + + var matchAnyProperty = key === anyPropertyKey; + var actualVal = matchAnyProperty ? actual : actual[key]; + if (!deepCompare(actualVal, expectedVal, comparator, anyPropertyKey, matchAnyProperty, matchAnyProperty)) { + return false; + } + } + return true; + } else { + return comparator(actual, expected); + } + break; + case 'function': + return false; + default: + return comparator(actual, expected); + } +} + +// Used for easily differentiating between `null` and actual `object` +function getTypeForFilter(val) { + return (val === null) ? 'null' : typeof val; +} + +var MAX_DIGITS = 22; +var DECIMAL_SEP = '.'; +var ZERO_CHAR = '0'; + +/** + * @ngdoc filter + * @name currency + * @kind function + * + * @description + * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default + * symbol for current locale is used. + * + * @param {number} amount Input to filter. + * @param {string=} symbol Currency symbol or identifier to be displayed. + * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale + * @returns {string} Formatted number. + * + * + * @example + + + +
    +
    + default currency symbol ($): {{amount | currency}}
    + custom currency identifier (USD$): {{amount | currency:"USD$"}} + no fractions (0): {{amount | currency:"USD$":0}} +
    +
    + + it('should init with 1234.56', function() { + expect(element(by.id('currency-default')).getText()).toBe('$1,234.56'); + expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56'); + expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235'); + }); + it('should update', function() { + if (browser.params.browser == 'safari') { + // Safari does not understand the minus key. See + // https://github.com/angular/protractor/issues/481 + return; + } + element(by.model('amount')).clear(); + element(by.model('amount')).sendKeys('-1234'); + expect(element(by.id('currency-default')).getText()).toBe('-$1,234.00'); + expect(element(by.id('currency-custom')).getText()).toBe('-USD$1,234.00'); + expect(element(by.id('currency-no-fractions')).getText()).toBe('-USD$1,234'); + }); + +
    + */ +currencyFilter.$inject = ['$locale']; +function currencyFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(amount, currencySymbol, fractionSize) { + if (isUndefined(currencySymbol)) { + currencySymbol = formats.CURRENCY_SYM; + } + + if (isUndefined(fractionSize)) { + fractionSize = formats.PATTERNS[1].maxFrac; + } + + // if null or undefined pass it through + return (amount == null) + ? amount + : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize). + replace(/\u00A4/g, currencySymbol); + }; +} + +/** + * @ngdoc filter + * @name number + * @kind function + * + * @description + * Formats a number as text. + * + * If the input is null or undefined, it will just be returned. + * If the input is infinite (Infinity or -Infinity), the Infinity symbol '∞' or '-∞' is returned, respectively. + * If the input is not a number an empty string is returned. + * + * + * @param {number|string} number Number to format. + * @param {(number|string)=} fractionSize Number of decimal places to round the number to. + * If this is not provided then the fraction size is computed from the current locale's number + * formatting pattern. In the case of the default locale, it will be 3. + * @returns {string} Number rounded to `fractionSize` appropriately formatted based on the current + * locale (e.g., in the en_US locale it will have "." as the decimal separator and + * include "," group separators after each third digit). + * + * @example + + + +
    +
    + Default formatting: {{val | number}}
    + No fractions: {{val | number:0}}
    + Negative number: {{-val | number:4}} +
    +
    + + it('should format numbers', function() { + expect(element(by.id('number-default')).getText()).toBe('1,234.568'); + expect(element(by.binding('val | number:0')).getText()).toBe('1,235'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679'); + }); + + it('should update', function() { + element(by.model('val')).clear(); + element(by.model('val')).sendKeys('3374.333'); + expect(element(by.id('number-default')).getText()).toBe('3,374.333'); + expect(element(by.binding('val | number:0')).getText()).toBe('3,374'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330'); + }); + +
    + */ +numberFilter.$inject = ['$locale']; +function numberFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(number, fractionSize) { + + // if null or undefined pass it through + return (number == null) + ? number + : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, + fractionSize); + }; +} + +/** + * Parse a number (as a string) into three components that can be used + * for formatting the number. + * + * (Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/) + * + * @param {string} numStr The number to parse + * @return {object} An object describing this number, containing the following keys: + * - d : an array of digits containing leading zeros as necessary + * - i : the number of the digits in `d` that are to the left of the decimal point + * - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d` + * + */ +function parse(numStr) { + var exponent = 0, digits, numberOfIntegerDigits; + var i, j, zeros; + + // Decimal point? + if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) { + numStr = numStr.replace(DECIMAL_SEP, ''); + } + + // Exponential form? + if ((i = numStr.search(/e/i)) > 0) { + // Work out the exponent. + if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i; + numberOfIntegerDigits += +numStr.slice(i + 1); + numStr = numStr.substring(0, i); + } else if (numberOfIntegerDigits < 0) { + // There was no decimal point or exponent so it is an integer. + numberOfIntegerDigits = numStr.length; + } + + // Count the number of leading zeros. + for (i = 0; numStr.charAt(i) == ZERO_CHAR; i++) {/* jshint noempty: false */} + + if (i == (zeros = numStr.length)) { + // The digits are all zero. + digits = [0]; + numberOfIntegerDigits = 1; + } else { + // Count the number of trailing zeros + zeros--; + while (numStr.charAt(zeros) == ZERO_CHAR) zeros--; + + // Trailing zeros are insignificant so ignore them + numberOfIntegerDigits -= i; + digits = []; + // Convert string to array of digits without leading/trailing zeros. + for (j = 0; i <= zeros; i++, j++) { + digits[j] = +numStr.charAt(i); + } + } + + // If the number overflows the maximum allowed digits then use an exponent. + if (numberOfIntegerDigits > MAX_DIGITS) { + digits = digits.splice(0, MAX_DIGITS - 1); + exponent = numberOfIntegerDigits - 1; + numberOfIntegerDigits = 1; + } + + return { d: digits, e: exponent, i: numberOfIntegerDigits }; +} + +/** + * Round the parsed number to the specified number of decimal places + * This function changed the parsedNumber in-place + */ +function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) { + var digits = parsedNumber.d; + var fractionLen = digits.length - parsedNumber.i; + + // determine fractionSize if it is not specified; `+fractionSize` converts it to a number + fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize; + + // The index of the digit to where rounding is to occur + var roundAt = fractionSize + parsedNumber.i; + var digit = digits[roundAt]; + + if (roundAt > 0) { + // Drop fractional digits beyond `roundAt` + digits.splice(Math.max(parsedNumber.i, roundAt)); + + // Set non-fractional digits beyond `roundAt` to 0 + for (var j = roundAt; j < digits.length; j++) { + digits[j] = 0; + } + } else { + // We rounded to zero so reset the parsedNumber + fractionLen = Math.max(0, fractionLen); + parsedNumber.i = 1; + digits.length = Math.max(1, roundAt = fractionSize + 1); + digits[0] = 0; + for (var i = 1; i < roundAt; i++) digits[i] = 0; + } + + if (digit >= 5) { + if (roundAt - 1 < 0) { + for (var k = 0; k > roundAt; k--) { + digits.unshift(0); + parsedNumber.i++; + } + digits.unshift(1); + parsedNumber.i++; + } else { + digits[roundAt - 1]++; + } + } + + // Pad out with zeros to get the required fraction length + for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0); + + + // Do any carrying, e.g. a digit was rounded up to 10 + var carry = digits.reduceRight(function(carry, d, i, digits) { + d = d + carry; + digits[i] = d % 10; + return Math.floor(d / 10); + }, 0); + if (carry) { + digits.unshift(carry); + parsedNumber.i++; + } +} + +/** + * Format a number into a string + * @param {number} number The number to format + * @param {{ + * minFrac, // the minimum number of digits required in the fraction part of the number + * maxFrac, // the maximum number of digits required in the fraction part of the number + * gSize, // number of digits in each group of separated digits + * lgSize, // number of digits in the last group of digits before the decimal separator + * negPre, // the string to go in front of a negative number (e.g. `-` or `(`)) + * posPre, // the string to go in front of a positive number + * negSuf, // the string to go after a negative number (e.g. `)`) + * posSuf // the string to go after a positive number + * }} pattern + * @param {string} groupSep The string to separate groups of number (e.g. `,`) + * @param {string} decimalSep The string to act as the decimal separator (e.g. `.`) + * @param {[type]} fractionSize The size of the fractional part of the number + * @return {string} The number formatted as a string + */ +function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { + + if (!(isString(number) || isNumber(number)) || isNaN(number)) return ''; + + var isInfinity = !isFinite(number); + var isZero = false; + var numStr = Math.abs(number) + '', + formattedText = '', + parsedNumber; + + if (isInfinity) { + formattedText = '\u221e'; + } else { + parsedNumber = parse(numStr); + + roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac); + + var digits = parsedNumber.d; + var integerLen = parsedNumber.i; + var exponent = parsedNumber.e; + var decimals = []; + isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true); + + // pad zeros for small numbers + while (integerLen < 0) { + digits.unshift(0); + integerLen++; + } + + // extract decimals digits + if (integerLen > 0) { + decimals = digits.splice(integerLen, digits.length); + } else { + decimals = digits; + digits = [0]; + } + + // format the integer digits with grouping separators + var groups = []; + if (digits.length >= pattern.lgSize) { + groups.unshift(digits.splice(-pattern.lgSize, digits.length).join('')); + } + while (digits.length > pattern.gSize) { + groups.unshift(digits.splice(-pattern.gSize, digits.length).join('')); + } + if (digits.length) { + groups.unshift(digits.join('')); + } + formattedText = groups.join(groupSep); + + // append the decimal digits + if (decimals.length) { + formattedText += decimalSep + decimals.join(''); + } + + if (exponent) { + formattedText += 'e+' + exponent; + } + } + if (number < 0 && !isZero) { + return pattern.negPre + formattedText + pattern.negSuf; + } else { + return pattern.posPre + formattedText + pattern.posSuf; + } +} + +function padNumber(num, digits, trim, negWrap) { + var neg = ''; + if (num < 0 || (negWrap && num <= 0)) { + if (negWrap) { + num = -num + 1; + } else { + num = -num; + neg = '-'; + } + } + num = '' + num; + while (num.length < digits) num = ZERO_CHAR + num; + if (trim) { + num = num.substr(num.length - digits); + } + return neg + num; +} + + +function dateGetter(name, size, offset, trim, negWrap) { + offset = offset || 0; + return function(date) { + var value = date['get' + name](); + if (offset > 0 || value > -offset) { + value += offset; + } + if (value === 0 && offset == -12) value = 12; + return padNumber(value, size, trim, negWrap); + }; +} + +function dateStrGetter(name, shortForm, standAlone) { + return function(date, formats) { + var value = date['get' + name](); + var propPrefix = (standAlone ? 'STANDALONE' : '') + (shortForm ? 'SHORT' : ''); + var get = uppercase(propPrefix + name); + + return formats[get][value]; + }; +} + +function timeZoneGetter(date, formats, offset) { + var zone = -1 * offset; + var paddedZone = (zone >= 0) ? "+" : ""; + + paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) + + padNumber(Math.abs(zone % 60), 2); + + return paddedZone; +} + +function getFirstThursdayOfYear(year) { + // 0 = index of January + var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay(); + // 4 = index of Thursday (+1 to account for 1st = 5) + // 11 = index of *next* Thursday (+1 account for 1st = 12) + return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst); +} + +function getThursdayThisWeek(datetime) { + return new Date(datetime.getFullYear(), datetime.getMonth(), + // 4 = index of Thursday + datetime.getDate() + (4 - datetime.getDay())); +} + +function weekGetter(size) { + return function(date) { + var firstThurs = getFirstThursdayOfYear(date.getFullYear()), + thisThurs = getThursdayThisWeek(date); + + var diff = +thisThurs - +firstThurs, + result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week + + return padNumber(result, size); + }; +} + +function ampmGetter(date, formats) { + return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; +} + +function eraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1]; +} + +function longEraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1]; +} + +var DATE_FORMATS = { + yyyy: dateGetter('FullYear', 4, 0, false, true), + yy: dateGetter('FullYear', 2, 0, true, true), + y: dateGetter('FullYear', 1, 0, false, true), + MMMM: dateStrGetter('Month'), + MMM: dateStrGetter('Month', true), + MM: dateGetter('Month', 2, 1), + M: dateGetter('Month', 1, 1), + LLLL: dateStrGetter('Month', false, true), + dd: dateGetter('Date', 2), + d: dateGetter('Date', 1), + HH: dateGetter('Hours', 2), + H: dateGetter('Hours', 1), + hh: dateGetter('Hours', 2, -12), + h: dateGetter('Hours', 1, -12), + mm: dateGetter('Minutes', 2), + m: dateGetter('Minutes', 1), + ss: dateGetter('Seconds', 2), + s: dateGetter('Seconds', 1), + // while ISO 8601 requires fractions to be prefixed with `.` or `,` + // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions + sss: dateGetter('Milliseconds', 3), + EEEE: dateStrGetter('Day'), + EEE: dateStrGetter('Day', true), + a: ampmGetter, + Z: timeZoneGetter, + ww: weekGetter(2), + w: weekGetter(1), + G: eraGetter, + GG: eraGetter, + GGG: eraGetter, + GGGG: longEraGetter +}; + +var DATE_FORMATS_SPLIT = /((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/, + NUMBER_STRING = /^\-?\d+$/; + +/** + * @ngdoc filter + * @name date + * @kind function + * + * @description + * Formats `date` to a string based on the requested `format`. + * + * `format` string can be composed of the following elements: + * + * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) + * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) + * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) + * * `'MMMM'`: Month in year (January-December) + * * `'MMM'`: Month in year (Jan-Dec) + * * `'MM'`: Month in year, padded (01-12) + * * `'M'`: Month in year (1-12) + * * `'LLLL'`: Stand-alone month in year (January-December) + * * `'dd'`: Day in month, padded (01-31) + * * `'d'`: Day in month (1-31) + * * `'EEEE'`: Day in Week,(Sunday-Saturday) + * * `'EEE'`: Day in Week, (Sun-Sat) + * * `'HH'`: Hour in day, padded (00-23) + * * `'H'`: Hour in day (0-23) + * * `'hh'`: Hour in AM/PM, padded (01-12) + * * `'h'`: Hour in AM/PM, (1-12) + * * `'mm'`: Minute in hour, padded (00-59) + * * `'m'`: Minute in hour (0-59) + * * `'ss'`: Second in minute, padded (00-59) + * * `'s'`: Second in minute (0-59) + * * `'sss'`: Millisecond in second, padded (000-999) + * * `'a'`: AM/PM marker + * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) + * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year + * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year + * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD') + * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini') + * + * `format` string can also be one of the following predefined + * {@link guide/i18n localizable formats}: + * + * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale + * (e.g. Sep 3, 2010 12:05:08 PM) + * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM) + * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale + * (e.g. Friday, September 3, 2010) + * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010) + * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010) + * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10) + * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM) + * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM) + * + * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g. + * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence + * (e.g. `"h 'o''clock'"`). + * + * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or + * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its + * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is + * specified in the string input, the time is considered to be in the local timezone. + * @param {string=} format Formatting rules (see Description). If not specified, + * `mediumDate` is used. + * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the + * continental US time zone abbreviations, but for general use, use a time zone offset, for + * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian) + * If not specified, the timezone of the browser will be used. + * @returns {string} Formatted string or the input if input is not recognized as date/millis. + * + * @example + + + {{1288323623006 | date:'medium'}}: + {{1288323623006 | date:'medium'}}
    + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
    + {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: + {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
    + {{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}: + {{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}
    +
    + + it('should format date', function() { + expect(element(by.binding("1288323623006 | date:'medium'")).getText()). + toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); + expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()). + toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/); + expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()). + toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); + expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()). + toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/); + }); + +
    + */ +dateFilter.$inject = ['$locale']; +function dateFilter($locale) { + + + var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; + // 1 2 3 4 5 6 7 8 9 10 11 + function jsonStringToDate(string) { + var match; + if (match = string.match(R_ISO8601_STR)) { + var date = new Date(0), + tzHour = 0, + tzMin = 0, + dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear, + timeSetter = match[8] ? date.setUTCHours : date.setHours; + + if (match[9]) { + tzHour = toInt(match[9] + match[10]); + tzMin = toInt(match[9] + match[11]); + } + dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3])); + var h = toInt(match[4] || 0) - tzHour; + var m = toInt(match[5] || 0) - tzMin; + var s = toInt(match[6] || 0); + var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000); + timeSetter.call(date, h, m, s, ms); + return date; + } + return string; + } + + + return function(date, format, timezone) { + var text = '', + parts = [], + fn, match; + + format = format || 'mediumDate'; + format = $locale.DATETIME_FORMATS[format] || format; + if (isString(date)) { + date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date); + } + + if (isNumber(date)) { + date = new Date(date); + } + + if (!isDate(date) || !isFinite(date.getTime())) { + return date; + } + + while (format) { + match = DATE_FORMATS_SPLIT.exec(format); + if (match) { + parts = concat(parts, match, 1); + format = parts.pop(); + } else { + parts.push(format); + format = null; + } + } + + var dateTimezoneOffset = date.getTimezoneOffset(); + if (timezone) { + dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); + date = convertTimezoneToLocal(date, timezone, true); + } + forEach(parts, function(value) { + fn = DATE_FORMATS[value]; + text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset) + : value === "''" ? "'" : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); + }); + + return text; + }; +} + + +/** + * @ngdoc filter + * @name json + * @kind function + * + * @description + * Allows you to convert a JavaScript object into JSON string. + * + * This filter is mostly useful for debugging. When using the double curly {{value}} notation + * the binding is automatically converted to JSON. + * + * @param {*} object Any JavaScript object (including arrays and primitive types) to filter. + * @param {number=} spacing The number of spaces to use per indentation, defaults to 2. + * @returns {string} JSON string. + * + * + * @example + + +
    {{ {'name':'value'} | json }}
    +
    {{ {'name':'value'} | json:4 }}
    +
    + + it('should jsonify filtered objects', function() { + expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/); + expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/); + }); + +
    + * + */ +function jsonFilter() { + return function(object, spacing) { + if (isUndefined(spacing)) { + spacing = 2; + } + return toJson(object, spacing); + }; +} + + +/** + * @ngdoc filter + * @name lowercase + * @kind function + * @description + * Converts string to lowercase. + * @see angular.lowercase + */ +var lowercaseFilter = valueFn(lowercase); + + +/** + * @ngdoc filter + * @name uppercase + * @kind function + * @description + * Converts string to uppercase. + * @see angular.uppercase + */ +var uppercaseFilter = valueFn(uppercase); + +/** + * @ngdoc filter + * @name limitTo + * @kind function + * + * @description + * Creates a new array or string containing only a specified number of elements. The elements are + * taken from either the beginning or the end of the source array, string or number, as specified by + * the value and sign (positive or negative) of `limit`. Other array-like objects are also supported + * (e.g. array subclasses, NodeLists, jqLite/jQuery collections etc). If a number is used as input, + * it is converted to a string. + * + * @param {Array|ArrayLike|string|number} input - Array/array-like, string or number to be limited. + * @param {string|number} limit - The length of the returned array or string. If the `limit` number + * is positive, `limit` number of items from the beginning of the source array/string are copied. + * If the number is negative, `limit` number of items from the end of the source array/string + * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined, + * the input will be returned unchanged. + * @param {(string|number)=} begin - Index at which to begin limitation. As a negative index, + * `begin` indicates an offset from the end of `input`. Defaults to `0`. + * @returns {Array|string} A new sub-array or substring of length `limit` or less if the input had + * less than `limit` elements. + * + * @example + + + +
    + +

    Output numbers: {{ numbers | limitTo:numLimit }}

    + +

    Output letters: {{ letters | limitTo:letterLimit }}

    + +

    Output long number: {{ longNumber | limitTo:longNumberLimit }}

    +
    +
    + + var numLimitInput = element(by.model('numLimit')); + var letterLimitInput = element(by.model('letterLimit')); + var longNumberLimitInput = element(by.model('longNumberLimit')); + var limitedNumbers = element(by.binding('numbers | limitTo:numLimit')); + var limitedLetters = element(by.binding('letters | limitTo:letterLimit')); + var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit')); + + it('should limit the number array to first three items', function() { + expect(numLimitInput.getAttribute('value')).toBe('3'); + expect(letterLimitInput.getAttribute('value')).toBe('3'); + expect(longNumberLimitInput.getAttribute('value')).toBe('3'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]'); + expect(limitedLetters.getText()).toEqual('Output letters: abc'); + expect(limitedLongNumber.getText()).toEqual('Output long number: 234'); + }); + + // There is a bug in safari and protractor that doesn't like the minus key + // it('should update the output when -3 is entered', function() { + // numLimitInput.clear(); + // numLimitInput.sendKeys('-3'); + // letterLimitInput.clear(); + // letterLimitInput.sendKeys('-3'); + // longNumberLimitInput.clear(); + // longNumberLimitInput.sendKeys('-3'); + // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]'); + // expect(limitedLetters.getText()).toEqual('Output letters: ghi'); + // expect(limitedLongNumber.getText()).toEqual('Output long number: 342'); + // }); + + it('should not exceed the maximum size of input array', function() { + numLimitInput.clear(); + numLimitInput.sendKeys('100'); + letterLimitInput.clear(); + letterLimitInput.sendKeys('100'); + longNumberLimitInput.clear(); + longNumberLimitInput.sendKeys('100'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]'); + expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi'); + expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342'); + }); + +
    +*/ +function limitToFilter() { + return function(input, limit, begin) { + if (Math.abs(Number(limit)) === Infinity) { + limit = Number(limit); + } else { + limit = toInt(limit); + } + if (isNaN(limit)) return input; + + if (isNumber(input)) input = input.toString(); + if (!isArrayLike(input)) return input; + + begin = (!begin || isNaN(begin)) ? 0 : toInt(begin); + begin = (begin < 0) ? Math.max(0, input.length + begin) : begin; + + if (limit >= 0) { + return sliceFn(input, begin, begin + limit); + } else { + if (begin === 0) { + return sliceFn(input, limit, input.length); + } else { + return sliceFn(input, Math.max(0, begin + limit), begin); + } + } + }; +} + +function sliceFn(input, begin, end) { + if (isString(input)) return input.slice(begin, end); + + return slice.call(input, begin, end); +} + +/** + * @ngdoc filter + * @name orderBy + * @kind function + * + * @description + * Returns an array containing the items from the specified `collection`, ordered by a `comparator` + * function based on the values computed using the `expression` predicate. + * + * For example, `[{id: 'foo'}, {id: 'bar'}] | orderBy:'id'` would result in + * `[{id: 'bar'}, {id: 'foo'}]`. + * + * The `collection` can be an Array or array-like object (e.g. NodeList, jQuery object, TypedArray, + * String, etc). + * + * The `expression` can be a single predicate, or a list of predicates each serving as a tie-breaker + * for the preceeding one. The `expression` is evaluated against each item and the output is used + * for comparing with other items. + * + * You can change the sorting order by setting `reverse` to `true`. By default, items are sorted in + * ascending order. + * + * The comparison is done using the `comparator` function. If none is specified, a default, built-in + * comparator is used (see below for details - in a nutshell, it compares numbers numerically and + * strings alphabetically). + * + * ### Under the hood + * + * Ordering the specified `collection` happens in two phases: + * + * 1. All items are passed through the predicate (or predicates), and the returned values are saved + * along with their type (`string`, `number` etc). For example, an item `{label: 'foo'}`, passed + * through a predicate that extracts the value of the `label` property, would be transformed to: + * ``` + * { + * value: 'foo', + * type: 'string', + * index: ... + * } + * ``` + * 2. The comparator function is used to sort the items, based on the derived values, types and + * indices. + * + * If you use a custom comparator, it will be called with pairs of objects of the form + * `{value: ..., type: '...', index: ...}` and is expected to return `0` if the objects are equal + * (as far as the comparator is concerned), `-1` if the 1st one should be ranked higher than the + * second, or `1` otherwise. + * + * In order to ensure that the sorting will be deterministic across platforms, if none of the + * specified predicates can distinguish between two items, `orderBy` will automatically introduce a + * dummy predicate that returns the item's index as `value`. + * (If you are using a custom comparator, make sure it can handle this predicate as well.) + * + * Finally, in an attempt to simplify things, if a predicate returns an object as the extracted + * value for an item, `orderBy` will try to convert that object to a primitive value, before passing + * it to the comparator. The following rules govern the conversion: + * + * 1. If the object has a `valueOf()` method that returns a primitive, its return value will be + * used instead.
    + * (If the object has a `valueOf()` method that returns another object, then the returned object + * will be used in subsequent steps.) + * 2. If the object has a custom `toString()` method (i.e. not the one inherited from `Object`) that + * returns a primitive, its return value will be used instead.
    + * (If the object has a `toString()` method that returns another object, then the returned object + * will be used in subsequent steps.) + * 3. No conversion; the object itself is used. + * + * ### The default comparator + * + * The default, built-in comparator should be sufficient for most usecases. In short, it compares + * numbers numerically, strings alphabetically (and case-insensitively), for objects falls back to + * using their index in the original collection, and sorts values of different types by type. + * + * More specifically, it follows these steps to determine the relative order of items: + * + * 1. If the compared values are of different types, compare the types themselves alphabetically. + * 2. If both values are of type `string`, compare them alphabetically in a case- and + * locale-insensitive way. + * 3. If both values are objects, compare their indices instead. + * 4. Otherwise, return: + * - `0`, if the values are equal (by strict equality comparison, i.e. using `===`). + * - `-1`, if the 1st value is "less than" the 2nd value (compared using the `<` operator). + * - `1`, otherwise. + * + * **Note:** If you notice numbers not being sorted as expected, make sure they are actually being + * saved as numbers and not strings. + * + * @param {Array|ArrayLike} collection - The collection (array or array-like object) to sort. + * @param {(Function|string|Array.)=} expression - A predicate (or list of + * predicates) to be used by the comparator to determine the order of elements. + * + * Can be one of: + * + * - `Function`: A getter function. This function will be called with each item as argument and + * the return value will be used for sorting. + * - `string`: An Angular expression. This expression will be evaluated against each item and the + * result will be used for sorting. For example, use `'label'` to sort by a property called + * `label` or `'label.substring(0, 3)'` to sort by the first 3 characters of the `label` + * property.
    + * (The result of a constant expression is interpreted as a property name to be used for + * comparison. For example, use `'"special name"'` (note the extra pair of quotes) to sort by a + * property called `special name`.)
    + * An expression can be optionally prefixed with `+` or `-` to control the sorting direction, + * ascending or descending. For example, `'+label'` or `'-label'`. If no property is provided, + * (e.g. `'+'` or `'-'`), the collection element itself is used in comparisons. + * - `Array`: An array of function and/or string predicates. If a predicate cannot determine the + * relative order of two items, the next predicate is used as a tie-breaker. + * + * **Note:** If the predicate is missing or empty then it defaults to `'+'`. + * + * @param {boolean=} reverse - If `true`, reverse the sorting order. + * @param {(Function)=} comparator - The comparator function used to determine the relative order of + * value pairs. If omitted, the built-in comparator will be used. + * + * @returns {Array} - The sorted array. + * + * + * @example + * ### Ordering a table with `ngRepeat` + * + * The example below demonstrates a simple {@link ngRepeat ngRepeat}, where the data is sorted by + * age in descending order (expression is set to `'-age'`). The `comparator` is not set, which means + * it defaults to the built-in comparator. + * + + +
    + + + + + + + + + + + +
    NamePhone NumberAge
    {{friend.name}}{{friend.phone}}{{friend.age}}
    +
    +
    + + angular.module('orderByExample1', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.friends = [ + {name: 'John', phone: '555-1212', age: 10}, + {name: 'Mary', phone: '555-9876', age: 19}, + {name: 'Mike', phone: '555-4321', age: 21}, + {name: 'Adam', phone: '555-5678', age: 35}, + {name: 'Julie', phone: '555-8765', age: 29} + ]; + }]); + + + .friends { + border-collapse: collapse; + } + + .friends th { + border-bottom: 1px solid; + } + .friends td, .friends th { + border-left: 1px solid; + padding: 5px 10px; + } + .friends td:first-child, .friends th:first-child { + border-left: none; + } + + + // Element locators + var names = element.all(by.repeater('friends').column('friend.name')); + + it('should sort friends by age in reverse order', function() { + expect(names.get(0).getText()).toBe('Adam'); + expect(names.get(1).getText()).toBe('Julie'); + expect(names.get(2).getText()).toBe('Mike'); + expect(names.get(3).getText()).toBe('Mary'); + expect(names.get(4).getText()).toBe('John'); + }); + +
    + *
    + * + * @example + * ### Changing parameters dynamically + * + * All parameters can be changed dynamically. The next example shows how you can make the columns of + * a table sortable, by binding the `expression` and `reverse` parameters to scope properties. + * + + +
    +
    Sort by = {{propertyName}}; reverse = {{reverse}}
    +
    + +
    + + + + + + + + + + + +
    + + + + + + + + +
    {{friend.name}}{{friend.phone}}{{friend.age}}
    +
    +
    + + angular.module('orderByExample2', []) + .controller('ExampleController', ['$scope', function($scope) { + var friends = [ + {name: 'John', phone: '555-1212', age: 10}, + {name: 'Mary', phone: '555-9876', age: 19}, + {name: 'Mike', phone: '555-4321', age: 21}, + {name: 'Adam', phone: '555-5678', age: 35}, + {name: 'Julie', phone: '555-8765', age: 29} + ]; + + $scope.propertyName = 'age'; + $scope.reverse = true; + $scope.friends = friends; + + $scope.sortBy = function(propertyName) { + $scope.reverse = ($scope.propertyName === propertyName) ? !$scope.reverse : false; + $scope.propertyName = propertyName; + }; + }]); + + + .friends { + border-collapse: collapse; + } + + .friends th { + border-bottom: 1px solid; + } + .friends td, .friends th { + border-left: 1px solid; + padding: 5px 10px; + } + .friends td:first-child, .friends th:first-child { + border-left: none; + } + + .sortorder:after { + content: '\25b2'; // BLACK UP-POINTING TRIANGLE + } + .sortorder.reverse:after { + content: '\25bc'; // BLACK DOWN-POINTING TRIANGLE + } + + + // Element locators + var unsortButton = element(by.partialButtonText('unsorted')); + var nameHeader = element(by.partialButtonText('Name')); + var phoneHeader = element(by.partialButtonText('Phone')); + var ageHeader = element(by.partialButtonText('Age')); + var firstName = element(by.repeater('friends').column('friend.name').row(0)); + var lastName = element(by.repeater('friends').column('friend.name').row(4)); + + it('should sort friends by some property, when clicking on the column header', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + + phoneHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Mary'); + + nameHeader.click(); + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('Mike'); + + ageHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Adam'); + }); + + it('should sort friends in reverse order, when clicking on the same column', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + + ageHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Adam'); + + ageHeader.click(); + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + }); + + it('should restore the original order, when clicking "Set to unsorted"', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + + unsortButton.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Julie'); + }); + +
    + *
    + * + * @example + * ### Using `orderBy` inside a controller + * + * It is also possible to call the `orderBy` filter manually, by injecting `orderByFilter`, and + * calling it with the desired parameters. (Alternatively, you could inject the `$filter` factory + * and retrieve the `orderBy` filter with `$filter('orderBy')`.) + * + + +
    +
    Sort by = {{propertyName}}; reverse = {{reverse}}
    +
    + +
    + + + + + + + + + + + +
    + + + + + + + + +
    {{friend.name}}{{friend.phone}}{{friend.age}}
    +
    +
    + + angular.module('orderByExample3', []) + .controller('ExampleController', ['$scope', 'orderByFilter', function($scope, orderBy) { + var friends = [ + {name: 'John', phone: '555-1212', age: 10}, + {name: 'Mary', phone: '555-9876', age: 19}, + {name: 'Mike', phone: '555-4321', age: 21}, + {name: 'Adam', phone: '555-5678', age: 35}, + {name: 'Julie', phone: '555-8765', age: 29} + ]; + + $scope.propertyName = 'age'; + $scope.reverse = true; + $scope.friends = orderBy(friends, $scope.propertyName, $scope.reverse); + + $scope.sortBy = function(propertyName) { + $scope.reverse = (propertyName !== null && $scope.propertyName === propertyName) + ? !$scope.reverse : false; + $scope.propertyName = propertyName; + $scope.friends = orderBy(friends, $scope.propertyName, $scope.reverse); + }; + }]); + + + .friends { + border-collapse: collapse; + } + + .friends th { + border-bottom: 1px solid; + } + .friends td, .friends th { + border-left: 1px solid; + padding: 5px 10px; + } + .friends td:first-child, .friends th:first-child { + border-left: none; + } + + .sortorder:after { + content: '\25b2'; // BLACK UP-POINTING TRIANGLE + } + .sortorder.reverse:after { + content: '\25bc'; // BLACK DOWN-POINTING TRIANGLE + } + + + // Element locators + var unsortButton = element(by.partialButtonText('unsorted')); + var nameHeader = element(by.partialButtonText('Name')); + var phoneHeader = element(by.partialButtonText('Phone')); + var ageHeader = element(by.partialButtonText('Age')); + var firstName = element(by.repeater('friends').column('friend.name').row(0)); + var lastName = element(by.repeater('friends').column('friend.name').row(4)); + + it('should sort friends by some property, when clicking on the column header', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + + phoneHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Mary'); + + nameHeader.click(); + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('Mike'); + + ageHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Adam'); + }); + + it('should sort friends in reverse order, when clicking on the same column', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + + ageHeader.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Adam'); + + ageHeader.click(); + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + }); + + it('should restore the original order, when clicking "Set to unsorted"', function() { + expect(firstName.getText()).toBe('Adam'); + expect(lastName.getText()).toBe('John'); + + unsortButton.click(); + expect(firstName.getText()).toBe('John'); + expect(lastName.getText()).toBe('Julie'); + }); + +
    + *
    + * + * @example + * ### Using a custom comparator + * + * If you have very specific requirements about the way items are sorted, you can pass your own + * comparator function. For example, you might need to compare some strings in a locale-sensitive + * way. (When specifying a custom comparator, you also need to pass a value for the `reverse` + * argument - passing `false` retains the default sorting order, i.e. ascending.) + * + + +
    +
    +

    Locale-sensitive Comparator

    + + + + + + + + + +
    NameFavorite Letter
    {{friend.name}}{{friend.favoriteLetter}}
    +
    +
    +

    Default Comparator

    + + + + + + + + + +
    NameFavorite Letter
    {{friend.name}}{{friend.favoriteLetter}}
    +
    +
    +
    + + angular.module('orderByExample4', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.friends = [ + {name: 'John', favoriteLetter: 'Ä'}, + {name: 'Mary', favoriteLetter: 'Ü'}, + {name: 'Mike', favoriteLetter: 'Ö'}, + {name: 'Adam', favoriteLetter: 'H'}, + {name: 'Julie', favoriteLetter: 'Z'} + ]; + + $scope.localeSensitiveComparator = function(v1, v2) { + // If we don't get strings, just compare by index + if (v1.type !== 'string' || v2.type !== 'string') { + return (v1.index < v2.index) ? -1 : 1; + } + + // Compare strings alphabetically, taking locale into account + return v1.value.localeCompare(v2.value); + }; + }]); + + + .friends-container { + display: inline-block; + margin: 0 30px; + } + + .friends { + border-collapse: collapse; + } + + .friends th { + border-bottom: 1px solid; + } + .friends td, .friends th { + border-left: 1px solid; + padding: 5px 10px; + } + .friends td:first-child, .friends th:first-child { + border-left: none; + } + + + // Element locators + var container = element(by.css('.custom-comparator')); + var names = container.all(by.repeater('friends').column('friend.name')); + + it('should sort friends by favorite letter (in correct alphabetical order)', function() { + expect(names.get(0).getText()).toBe('John'); + expect(names.get(1).getText()).toBe('Adam'); + expect(names.get(2).getText()).toBe('Mike'); + expect(names.get(3).getText()).toBe('Mary'); + expect(names.get(4).getText()).toBe('Julie'); + }); + +
    + * + */ +orderByFilter.$inject = ['$parse']; +function orderByFilter($parse) { + return function(array, sortPredicate, reverseOrder, compareFn) { + + if (array == null) return array; + if (!isArrayLike(array)) { + throw minErr('orderBy')('notarray', 'Expected array but received: {0}', array); + } + + if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; } + if (sortPredicate.length === 0) { sortPredicate = ['+']; } + + var predicates = processPredicates(sortPredicate); + + var descending = reverseOrder ? -1 : 1; + + // Define the `compare()` function. Use a default comparator if none is specified. + var compare = isFunction(compareFn) ? compareFn : defaultCompare; + + // The next three lines are a version of a Swartzian Transform idiom from Perl + // (sometimes called the Decorate-Sort-Undecorate idiom) + // See https://en.wikipedia.org/wiki/Schwartzian_transform + var compareValues = Array.prototype.map.call(array, getComparisonObject); + compareValues.sort(doComparison); + array = compareValues.map(function(item) { return item.value; }); + + return array; + + function getComparisonObject(value, index) { + // NOTE: We are adding an extra `tieBreaker` value based on the element's index. + // This will be used to keep the sort stable when none of the input predicates can + // distinguish between two elements. + return { + value: value, + tieBreaker: {value: index, type: 'number', index: index}, + predicateValues: predicates.map(function(predicate) { + return getPredicateValue(predicate.get(value), index); + }) + }; + } + + function doComparison(v1, v2) { + for (var i = 0, ii = predicates.length; i < ii; i++) { + var result = compare(v1.predicateValues[i], v2.predicateValues[i]); + if (result) { + return result * predicates[i].descending * descending; + } + } + + return compare(v1.tieBreaker, v2.tieBreaker) * descending; + } + }; + + function processPredicates(sortPredicates) { + return sortPredicates.map(function(predicate) { + var descending = 1, get = identity; + + if (isFunction(predicate)) { + get = predicate; + } else if (isString(predicate)) { + if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { + descending = predicate.charAt(0) == '-' ? -1 : 1; + predicate = predicate.substring(1); + } + if (predicate !== '') { + get = $parse(predicate); + if (get.constant) { + var key = get(); + get = function(value) { return value[key]; }; + } + } + } + return {get: get, descending: descending}; + }); + } + + function isPrimitive(value) { + switch (typeof value) { + case 'number': /* falls through */ + case 'boolean': /* falls through */ + case 'string': + return true; + default: + return false; + } + } + + function objectValue(value) { + // If `valueOf` is a valid function use that + if (isFunction(value.valueOf)) { + value = value.valueOf(); + if (isPrimitive(value)) return value; + } + // If `toString` is a valid function and not the one from `Object.prototype` use that + if (hasCustomToString(value)) { + value = value.toString(); + if (isPrimitive(value)) return value; + } + + return value; + } + + function getPredicateValue(value, index) { + var type = typeof value; + if (value === null) { + type = 'string'; + value = 'null'; + } else if (type === 'object') { + value = objectValue(value); + } + return {value: value, type: type, index: index}; + } + + function defaultCompare(v1, v2) { + var result = 0; + var type1 = v1.type; + var type2 = v2.type; + + if (type1 === type2) { + var value1 = v1.value; + var value2 = v2.value; + + if (type1 === 'string') { + // Compare strings case-insensitively + value1 = value1.toLowerCase(); + value2 = value2.toLowerCase(); + } else if (type1 === 'object') { + // For basic objects, use the position of the object + // in the collection instead of the value + if (isObject(value1)) value1 = v1.index; + if (isObject(value2)) value2 = v2.index; + } + + if (value1 !== value2) { + result = value1 < value2 ? -1 : 1; + } + } else { + result = type1 < type2 ? -1 : 1; + } + + return result; + } +} + +function ngDirective(directive) { + if (isFunction(directive)) { + directive = { + link: directive + }; + } + directive.restrict = directive.restrict || 'AC'; + return valueFn(directive); +} + +/** + * @ngdoc directive + * @name a + * @restrict E + * + * @description + * Modifies the default behavior of the html A tag so that the default action is prevented when + * the href attribute is empty. + * + * This change permits the easy creation of action links with the `ngClick` directive + * without changing the location or causing page reloads, e.g.: + * `Add Item` + */ +var htmlAnchorDirective = valueFn({ + restrict: 'E', + compile: function(element, attr) { + if (!attr.href && !attr.xlinkHref) { + return function(scope, element) { + // If the linked element is not an anchor tag anymore, do nothing + if (element[0].nodeName.toLowerCase() !== 'a') return; + + // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. + var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ? + 'xlink:href' : 'href'; + element.on('click', function(event) { + // if we have no href url, then don't navigate anywhere. + if (!element.attr(href)) { + event.preventDefault(); + } + }); + }; + } + } +}); + +/** + * @ngdoc directive + * @name ngHref + * @restrict A + * @priority 99 + * + * @description + * Using Angular markup like `{{hash}}` in an href attribute will + * make the link go to the wrong URL if the user clicks it before + * Angular has a chance to replace the `{{hash}}` markup with its + * value. Until Angular replaces the markup the link will be broken + * and will most likely return a 404 error. The `ngHref` directive + * solves this problem. + * + * The wrong way to write it: + * ```html + * link1 + * ``` + * + * The correct way to write it: + * ```html + * link1 + * ``` + * + * @element A + * @param {template} ngHref any string which can contain `{{}}` markup. + * + * @example + * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes + * in links and their different behaviors: + + +
    + link 1 (link, don't reload)
    + link 2 (link, don't reload)
    + link 3 (link, reload!)
    + anchor (link, don't reload)
    + anchor (no link)
    + link (link, change location) +
    + + it('should execute ng-click but not reload when href without value', function() { + element(by.id('link-1')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('1'); + expect(element(by.id('link-1')).getAttribute('href')).toBe(''); + }); + + it('should execute ng-click but not reload when href empty string', function() { + element(by.id('link-2')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('2'); + expect(element(by.id('link-2')).getAttribute('href')).toBe(''); + }); + + it('should execute ng-click and change url when ng-href specified', function() { + expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/); + + element(by.id('link-3')).click(); + + // At this point, we navigate away from an Angular page, so we need + // to use browser.driver to get the base webdriver. + + browser.wait(function() { + return browser.driver.getCurrentUrl().then(function(url) { + return url.match(/\/123$/); + }); + }, 5000, 'page should navigate to /123'); + }); + + it('should execute ng-click but not reload when href empty string and name specified', function() { + element(by.id('link-4')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('4'); + expect(element(by.id('link-4')).getAttribute('href')).toBe(''); + }); + + it('should execute ng-click but not reload when no href but name specified', function() { + element(by.id('link-5')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('5'); + expect(element(by.id('link-5')).getAttribute('href')).toBe(null); + }); + + it('should only change url when only ng-href', function() { + element(by.model('value')).clear(); + element(by.model('value')).sendKeys('6'); + expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/); + + element(by.id('link-6')).click(); + + // At this point, we navigate away from an Angular page, so we need + // to use browser.driver to get the base webdriver. + browser.wait(function() { + return browser.driver.getCurrentUrl().then(function(url) { + return url.match(/\/6$/); + }); + }, 5000, 'page should navigate to /6'); + }); + +
    + */ + +/** + * @ngdoc directive + * @name ngSrc + * @restrict A + * @priority 99 + * + * @description + * Using Angular markup like `{{hash}}` in a `src` attribute doesn't + * work right: The browser will fetch from the URL with the literal + * text `{{hash}}` until Angular replaces the expression inside + * `{{hash}}`. The `ngSrc` directive solves this problem. + * + * The buggy way to write it: + * ```html + * Description + * ``` + * + * The correct way to write it: + * ```html + * Description + * ``` + * + * @element IMG + * @param {template} ngSrc any string which can contain `{{}}` markup. + */ + +/** + * @ngdoc directive + * @name ngSrcset + * @restrict A + * @priority 99 + * + * @description + * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't + * work right: The browser will fetch from the URL with the literal + * text `{{hash}}` until Angular replaces the expression inside + * `{{hash}}`. The `ngSrcset` directive solves this problem. + * + * The buggy way to write it: + * ```html + * Description + * ``` + * + * The correct way to write it: + * ```html + * Description + * ``` + * + * @element IMG + * @param {template} ngSrcset any string which can contain `{{}}` markup. + */ + +/** + * @ngdoc directive + * @name ngDisabled + * @restrict A + * @priority 100 + * + * @description + * + * This directive sets the `disabled` attribute on the element if the + * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy. + * + * A special directive is necessary because we cannot use interpolation inside the `disabled` + * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * + * @example + + +
    + +
    + + it('should toggle button', function() { + expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy(); + }); + +
    + * + * @element INPUT + * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy, + * then the `disabled` attribute will be set on the element + */ + + +/** + * @ngdoc directive + * @name ngChecked + * @restrict A + * @priority 100 + * + * @description + * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy. + * + * Note that this directive should not be used together with {@link ngModel `ngModel`}, + * as this can lead to unexpected behavior. + * + * A special directive is necessary because we cannot use interpolation inside the `checked` + * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * + * @example + + +
    + +
    + + it('should check both checkBoxes', function() { + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy(); + element(by.model('master')).click(); + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy(); + }); + +
    + * + * @element INPUT + * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, + * then the `checked` attribute will be set on the element + */ + + +/** + * @ngdoc directive + * @name ngReadonly + * @restrict A + * @priority 100 + * + * @description + * + * Sets the `readonly` attribute on the element, if the expression inside `ngReadonly` is truthy. + * Note that `readonly` applies only to `input` elements with specific types. [See the input docs on + * MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-readonly) for more information. + * + * A special directive is necessary because we cannot use interpolation inside the `readonly` + * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * + * @example + + +
    + +
    + + it('should toggle readonly attr', function() { + expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy(); + }); + +
    + * + * @element INPUT + * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy, + * then special attribute "readonly" will be set on the element + */ + + +/** + * @ngdoc directive + * @name ngSelected + * @restrict A + * @priority 100 + * + * @description + * + * Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy. + * + * A special directive is necessary because we cannot use interpolation inside the `selected` + * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * + *
    + * **Note:** `ngSelected` does not interact with the `select` and `ngModel` directives, it only + * sets the `selected` attribute on the element. If you are using `ngModel` on the select, you + * should not use `ngSelected` on the options, as `ngModel` will set the select value and + * selected options. + *
    + * + * @example + + +
    + +
    + + it('should select Greetings!', function() { + expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy(); + element(by.model('selected')).click(); + expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy(); + }); + +
    + * + * @element OPTION + * @param {expression} ngSelected If the {@link guide/expression expression} is truthy, + * then special attribute "selected" will be set on the element + */ + +/** + * @ngdoc directive + * @name ngOpen + * @restrict A + * @priority 100 + * + * @description + * + * Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy. + * + * A special directive is necessary because we cannot use interpolation inside the `open` + * attribute. See the {@link guide/interpolation interpolation guide} for more info. + * + * ## A note about browser compatibility + * + * Edge, Firefox, and Internet Explorer do not support the `details` element, it is + * recommended to use {@link ng.ngShow} and {@link ng.ngHide} instead. + * + * @example + + +
    +
    + Show/Hide me +
    +
    + + it('should toggle open', function() { + expect(element(by.id('details')).getAttribute('open')).toBeFalsy(); + element(by.model('open')).click(); + expect(element(by.id('details')).getAttribute('open')).toBeTruthy(); + }); + +
    + * + * @element DETAILS + * @param {expression} ngOpen If the {@link guide/expression expression} is truthy, + * then special attribute "open" will be set on the element + */ + +var ngAttributeAliasDirectives = {}; + +// boolean attrs are evaluated +forEach(BOOLEAN_ATTR, function(propName, attrName) { + // binding to multiple is not supported + if (propName == "multiple") return; + + function defaultLinkFn(scope, element, attr) { + scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { + attr.$set(attrName, !!value); + }); + } + + var normalized = directiveNormalize('ng-' + attrName); + var linkFn = defaultLinkFn; + + if (propName === 'checked') { + linkFn = function(scope, element, attr) { + // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input + if (attr.ngModel !== attr[normalized]) { + defaultLinkFn(scope, element, attr); + } + }; + } + + ngAttributeAliasDirectives[normalized] = function() { + return { + restrict: 'A', + priority: 100, + link: linkFn + }; + }; +}); + +// aliased input attrs are evaluated +forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) { + ngAttributeAliasDirectives[ngAttr] = function() { + return { + priority: 100, + link: function(scope, element, attr) { + //special case ngPattern when a literal regular expression value + //is used as the expression (this way we don't have to watch anything). + if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") { + var match = attr.ngPattern.match(REGEX_STRING_REGEXP); + if (match) { + attr.$set("ngPattern", new RegExp(match[1], match[2])); + return; + } + } + + scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) { + attr.$set(ngAttr, value); + }); + } + }; + }; +}); + +// ng-src, ng-srcset, ng-href are interpolated +forEach(['src', 'srcset', 'href'], function(attrName) { + var normalized = directiveNormalize('ng-' + attrName); + ngAttributeAliasDirectives[normalized] = function() { + return { + priority: 99, // it needs to run after the attributes are interpolated + link: function(scope, element, attr) { + var propName = attrName, + name = attrName; + + if (attrName === 'href' && + toString.call(element.prop('href')) === '[object SVGAnimatedString]') { + name = 'xlinkHref'; + attr.$attr[name] = 'xlink:href'; + propName = null; + } + + attr.$observe(normalized, function(value) { + if (!value) { + if (attrName === 'href') { + attr.$set(name, null); + } + return; + } + + attr.$set(name, value); + + // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist + // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need + // to set the property as well to achieve the desired effect. + // we use attr[attrName] value since $set can sanitize the url. + if (msie && propName) element.prop(propName, attr[name]); + }); + } + }; + }; +}); + +/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true + */ +var nullFormCtrl = { + $addControl: noop, + $$renameControl: nullFormRenameControl, + $removeControl: noop, + $setValidity: noop, + $setDirty: noop, + $setPristine: noop, + $setSubmitted: noop +}, +SUBMITTED_CLASS = 'ng-submitted'; + +function nullFormRenameControl(control, name) { + control.$name = name; +} + +/** + * @ngdoc type + * @name form.FormController + * + * @property {boolean} $pristine True if user has not interacted with the form yet. + * @property {boolean} $dirty True if user has already interacted with the form. + * @property {boolean} $valid True if all of the containing forms and controls are valid. + * @property {boolean} $invalid True if at least one containing control or form is invalid. + * @property {boolean} $pending True if at least one containing control or form is pending. + * @property {boolean} $submitted True if user has submitted the form even if its invalid. + * + * @property {Object} $error Is an object hash, containing references to controls or + * forms with failing validators, where: + * + * - keys are validation tokens (error names), + * - values are arrays of controls or forms that have a failing validator for given error name. + * + * Built-in validation tokens: + * + * - `email` + * - `max` + * - `maxlength` + * - `min` + * - `minlength` + * - `number` + * - `pattern` + * - `required` + * - `url` + * - `date` + * - `datetimelocal` + * - `time` + * - `week` + * - `month` + * + * @description + * `FormController` keeps track of all its controls and nested forms as well as the state of them, + * such as being valid/invalid or dirty/pristine. + * + * Each {@link ng.directive:form form} directive creates an instance + * of `FormController`. + * + */ +//asks for $scope to fool the BC controller module +FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate']; +function FormController(element, attrs, $scope, $animate, $interpolate) { + var form = this, + controls = []; + + // init state + form.$error = {}; + form.$$success = {}; + form.$pending = undefined; + form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope); + form.$dirty = false; + form.$pristine = true; + form.$valid = true; + form.$invalid = false; + form.$submitted = false; + form.$$parentForm = nullFormCtrl; + + /** + * @ngdoc method + * @name form.FormController#$rollbackViewValue + * + * @description + * Rollback all form controls pending updates to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. This method is typically needed by the reset button of + * a form that uses `ng-model-options` to pend updates. + */ + form.$rollbackViewValue = function() { + forEach(controls, function(control) { + control.$rollbackViewValue(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$commitViewValue + * + * @description + * Commit all form controls pending updates to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. This method is rarely needed as `NgModelController` + * usually handles calling this in response to input events. + */ + form.$commitViewValue = function() { + forEach(controls, function(control) { + control.$commitViewValue(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$addControl + * @param {object} control control object, either a {@link form.FormController} or an + * {@link ngModel.NgModelController} + * + * @description + * Register a control with the form. Input elements using ngModelController do this automatically + * when they are linked. + * + * Note that the current state of the control will not be reflected on the new parent form. This + * is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine` + * state. + * + * However, if the method is used programmatically, for example by adding dynamically created controls, + * or controls that have been previously removed without destroying their corresponding DOM element, + * it's the developers responsibility to make sure the current state propagates to the parent form. + * + * For example, if an input control is added that is already `$dirty` and has `$error` properties, + * calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form. + */ + form.$addControl = function(control) { + // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored + // and not added to the scope. Now we throw an error. + assertNotHasOwnProperty(control.$name, 'input'); + controls.push(control); + + if (control.$name) { + form[control.$name] = control; + } + + control.$$parentForm = form; + }; + + // Private API: rename a form control + form.$$renameControl = function(control, newName) { + var oldName = control.$name; + + if (form[oldName] === control) { + delete form[oldName]; + } + form[newName] = control; + control.$name = newName; + }; + + /** + * @ngdoc method + * @name form.FormController#$removeControl + * @param {object} control control object, either a {@link form.FormController} or an + * {@link ngModel.NgModelController} + * + * @description + * Deregister a control from the form. + * + * Input elements using ngModelController do this automatically when they are destroyed. + * + * Note that only the removed control's validation state (`$errors`etc.) will be removed from the + * form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be + * different from case to case. For example, removing the only `$dirty` control from a form may or + * may not mean that the form is still `$dirty`. + */ + form.$removeControl = function(control) { + if (control.$name && form[control.$name] === control) { + delete form[control.$name]; + } + forEach(form.$pending, function(value, name) { + form.$setValidity(name, null, control); + }); + forEach(form.$error, function(value, name) { + form.$setValidity(name, null, control); + }); + forEach(form.$$success, function(value, name) { + form.$setValidity(name, null, control); + }); + + arrayRemove(controls, control); + control.$$parentForm = nullFormCtrl; + }; + + + /** + * @ngdoc method + * @name form.FormController#$setValidity + * + * @description + * Sets the validity of a form control. + * + * This method will also propagate to parent forms. + */ + addSetValidityMethod({ + ctrl: this, + $element: element, + set: function(object, property, controller) { + var list = object[property]; + if (!list) { + object[property] = [controller]; + } else { + var index = list.indexOf(controller); + if (index === -1) { + list.push(controller); + } + } + }, + unset: function(object, property, controller) { + var list = object[property]; + if (!list) { + return; + } + arrayRemove(list, controller); + if (list.length === 0) { + delete object[property]; + } + }, + $animate: $animate + }); + + /** + * @ngdoc method + * @name form.FormController#$setDirty + * + * @description + * Sets the form to a dirty state. + * + * This method can be called to add the 'ng-dirty' class and set the form to a dirty + * state (ng-dirty class). This method will also propagate to parent forms. + */ + form.$setDirty = function() { + $animate.removeClass(element, PRISTINE_CLASS); + $animate.addClass(element, DIRTY_CLASS); + form.$dirty = true; + form.$pristine = false; + form.$$parentForm.$setDirty(); + }; + + /** + * @ngdoc method + * @name form.FormController#$setPristine + * + * @description + * Sets the form to its pristine state. + * + * This method can be called to remove the 'ng-dirty' class and set the form to its pristine + * state (ng-pristine class). This method will also propagate to all the controls contained + * in this form. + * + * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after + * saving or resetting it. + */ + form.$setPristine = function() { + $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS); + form.$dirty = false; + form.$pristine = true; + form.$submitted = false; + forEach(controls, function(control) { + control.$setPristine(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$setUntouched + * + * @description + * Sets the form to its untouched state. + * + * This method can be called to remove the 'ng-touched' class and set the form controls to their + * untouched state (ng-untouched class). + * + * Setting a form controls back to their untouched state is often useful when setting the form + * back to its pristine state. + */ + form.$setUntouched = function() { + forEach(controls, function(control) { + control.$setUntouched(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$setSubmitted + * + * @description + * Sets the form to its submitted state. + */ + form.$setSubmitted = function() { + $animate.addClass(element, SUBMITTED_CLASS); + form.$submitted = true; + form.$$parentForm.$setSubmitted(); + }; +} + +/** + * @ngdoc directive + * @name ngForm + * @restrict EAC + * + * @description + * Nestable alias of {@link ng.directive:form `form`} directive. HTML + * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a + * sub-group of controls needs to be determined. + * + * Note: the purpose of `ngForm` is to group controls, + * but not to be a replacement for the `
    ` tag with all of its capabilities + * (e.g. posting to the server, ...). + * + * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into + * related scope, under this name. + * + */ + + /** + * @ngdoc directive + * @name form + * @restrict E + * + * @description + * Directive that instantiates + * {@link form.FormController FormController}. + * + * If the `name` attribute is specified, the form controller is published onto the current scope under + * this name. + * + * # Alias: {@link ng.directive:ngForm `ngForm`} + * + * In Angular, forms can be nested. This means that the outer form is valid when all of the child + * forms are valid as well. However, browsers do not allow nesting of `` elements, so + * Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to + * `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group + * of controls needs to be determined. + * + * # CSS classes + * - `ng-valid` is set if the form is valid. + * - `ng-invalid` is set if the form is invalid. + * - `ng-pending` is set if the form is pending. + * - `ng-pristine` is set if the form is pristine. + * - `ng-dirty` is set if the form is dirty. + * - `ng-submitted` is set if the form was submitted. + * + * Keep in mind that ngAnimate can detect each of these classes when added and removed. + * + * + * # Submitting a form and preventing the default action + * + * Since the role of forms in client-side Angular applications is different than in classical + * roundtrip apps, it is desirable for the browser not to translate the form submission into a full + * page reload that sends the data to the server. Instead some javascript logic should be triggered + * to handle the form submission in an application-specific way. + * + * For this reason, Angular prevents the default action (form submission to the server) unless the + * `` element has an `action` attribute specified. + * + * You can use one of the following two ways to specify what javascript method should be called when + * a form is submitted: + * + * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element + * - {@link ng.directive:ngClick ngClick} directive on the first + * button or input field of type submit (input[type=submit]) + * + * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit} + * or {@link ng.directive:ngClick ngClick} directives. + * This is because of the following form submission rules in the HTML specification: + * + * - If a form has only one input field then hitting enter in this field triggers form submit + * (`ngSubmit`) + * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter + * doesn't trigger submit + * - if a form has one or more input fields and one or more buttons or input[type=submit] then + * hitting enter in any of the input fields will trigger the click handler on the *first* button or + * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`) + * + * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is + * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` + * to have access to the updated model. + * + * ## Animation Hooks + * + * Animations in ngForm are triggered when any of the associated CSS classes are added and removed. + * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any + * other validations that are performed within the form. Animations in ngForm are similar to how + * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well + * as JS animations. + * + * The following example shows a simple way to utilize CSS transitions to style a form element + * that has been rendered as invalid after it has been validated: + * + *
    + * //be sure to include ngAnimate as a module to hook into more
    + * //advanced animations
    + * .my-form {
    + *   transition:0.5s linear all;
    + *   background: white;
    + * }
    + * .my-form.ng-invalid {
    + *   background: red;
    + *   color:white;
    + * }
    + * 
    + * + * @example + + + + + + userType: + Required!
    + userType = {{userType}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    + +
    + + it('should initialize to model', function() { + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + + expect(userType.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + var userInput = element(by.model('userType')); + + userInput.clear(); + userInput.sendKeys(''); + + expect(userType.getText()).toEqual('userType ='); + expect(valid.getText()).toContain('false'); + }); + +
    + * + * @param {string=} name Name of the form. If specified, the form controller will be published into + * related scope, under this name. + */ +var formDirectiveFactory = function(isNgForm) { + return ['$timeout', '$parse', function($timeout, $parse) { + var formDirective = { + name: 'form', + restrict: isNgForm ? 'EAC' : 'E', + require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form + controller: FormController, + compile: function ngFormCompile(formElement, attr) { + // Setup initial state of the control + formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS); + + var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false); + + return { + pre: function ngFormPreLink(scope, formElement, attr, ctrls) { + var controller = ctrls[0]; + + // if `action` attr is not present on the form, prevent the default action (submission) + if (!('action' in attr)) { + // we can't use jq events because if a form is destroyed during submission the default + // action is not prevented. see #1238 + // + // IE 9 is not affected because it doesn't fire a submit event and try to do a full + // page reload if the form was destroyed by submission of the form via a click handler + // on a button in the form. Looks like an IE9 specific bug. + var handleFormSubmission = function(event) { + scope.$apply(function() { + controller.$commitViewValue(); + controller.$setSubmitted(); + }); + + event.preventDefault(); + }; + + addEventListenerFn(formElement[0], 'submit', handleFormSubmission); + + // unregister the preventDefault listener so that we don't not leak memory but in a + // way that will achieve the prevention of the default action. + formElement.on('$destroy', function() { + $timeout(function() { + removeEventListenerFn(formElement[0], 'submit', handleFormSubmission); + }, 0, false); + }); + } + + var parentFormCtrl = ctrls[1] || controller.$$parentForm; + parentFormCtrl.$addControl(controller); + + var setter = nameAttr ? getSetter(controller.$name) : noop; + + if (nameAttr) { + setter(scope, controller); + attr.$observe(nameAttr, function(newValue) { + if (controller.$name === newValue) return; + setter(scope, undefined); + controller.$$parentForm.$$renameControl(controller, newValue); + setter = getSetter(controller.$name); + setter(scope, controller); + }); + } + formElement.on('$destroy', function() { + controller.$$parentForm.$removeControl(controller); + setter(scope, undefined); + extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards + }); + } + }; + } + }; + + return formDirective; + + function getSetter(expression) { + if (expression === '') { + //create an assignable expression, so forms with an empty name can be renamed later + return $parse('this[""]').assign; + } + return $parse(expression).assign || noop; + } + }]; +}; + +var formDirective = formDirectiveFactory(); +var ngFormDirective = formDirectiveFactory(true); + +/* global VALID_CLASS: false, + INVALID_CLASS: false, + PRISTINE_CLASS: false, + DIRTY_CLASS: false, + UNTOUCHED_CLASS: false, + TOUCHED_CLASS: false, + ngModelMinErr: false, +*/ + +// Regex code was initially obtained from SO prior to modification: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231 +var ISO_DATE_REGEXP = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/; +// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987) +// Note: We are being more lenient, because browsers are too. +// 1. Scheme +// 2. Slashes +// 3. Username +// 4. Password +// 5. Hostname +// 6. Port +// 7. Path +// 8. Query +// 9. Fragment +// 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999 +var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; +/* jshint maxlen:220 */ +var EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/; +/* jshint maxlen:200 */ +var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; +var DATE_REGEXP = /^(\d{4,})-(\d{2})-(\d{2})$/; +var DATETIMELOCAL_REGEXP = /^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; +var WEEK_REGEXP = /^(\d{4,})-W(\d\d)$/; +var MONTH_REGEXP = /^(\d{4,})-(\d\d)$/; +var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; + +var PARTIAL_VALIDATION_EVENTS = 'keydown wheel mousedown'; +var PARTIAL_VALIDATION_TYPES = createMap(); +forEach('date,datetime-local,month,time,week'.split(','), function(type) { + PARTIAL_VALIDATION_TYPES[type] = true; +}); + +var inputType = { + + /** + * @ngdoc input + * @name input[text] + * + * @description + * Standard HTML text input with angular data binding, inherited by most of the `input` elements. + * + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Adds `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * does not match a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + * This parameter is ignored for input[type=password] controls, which will never trim the + * input. + * + * @example + + + +
    + +
    + + Required! + + Single word only! +
    + text = {{example.text}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var text = element(by.binding('example.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if multi word', function() { + input.clear(); + input.sendKeys('hello world'); + + expect(valid.getText()).toContain('false'); + }); + +
    + */ + 'text': textInputType, + + /** + * @ngdoc input + * @name input[date] + * + * @description + * Input with date validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601 + * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many + * modern browsers do not yet support this input type, it is important to provide cues to users on the + * expected input format via a placeholder or label. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute + * (e.g. `min="{{minDate | date:'yyyy-MM-dd'}}"`). Note that `min` will also add native HTML5 + * constraint validation. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute + * (e.g. `max="{{maxDate | date:'yyyy-MM-dd'}}"`). Note that `max` will also add native HTML5 + * constraint validation. + * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string + * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. + * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string + * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + + +
    + + Required! + + Not a valid date! +
    + value = {{example.value | date: "yyyy-MM-dd"}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value | date: "yyyy-MM-dd"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (see https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-10-22'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01-01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
    + */ + 'date': createDateInputType('date', DATE_REGEXP, + createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']), + 'yyyy-MM-dd'), + + /** + * @ngdoc input + * @name input[datetime-local] + * + * @description + * Input with datetime validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation + * inside this attribute (e.g. `min="{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`). + * Note that `min` will also add native HTML5 constraint validation. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation + * inside this attribute (e.g. `max="{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`). + * Note that `max` will also add native HTML5 constraint validation. + * @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string + * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. + * @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string + * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + + +
    + + Required! + + Not a valid date! +
    + value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2010-12-28T14:57:00'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01-01T23:59:00'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
    + */ + 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP, + createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']), + 'yyyy-MM-ddTHH:mm:ss.sss'), + + /** + * @ngdoc input + * @name input[time] + * + * @description + * Input with time validation and transformation. In browsers that do not yet support + * the HTML5 time input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a + * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this + * attribute (e.g. `min="{{minTime | date:'HH:mm:ss'}}"`). Note that `min` will also add + * native HTML5 constraint validation. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this + * attribute (e.g. `max="{{maxTime | date:'HH:mm:ss'}}"`). Note that `max` will also add + * native HTML5 constraint validation. + * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the + * `ngMin` expression evaluates to. Note that it does not set the `min` attribute. + * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the + * `ngMax` expression evaluates to. Note that it does not set the `max` attribute. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + + +
    + + Required! + + Not a valid date! +
    + value = {{example.value | date: "HH:mm:ss"}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value | date: "HH:mm:ss"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('14:57:00'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('23:59:00'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
    + */ + 'time': createDateInputType('time', TIME_REGEXP, + createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']), + 'HH:mm:ss.sss'), + + /** + * @ngdoc input + * @name input[week] + * + * @description + * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support + * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * week format (yyyy-W##), for example: `2013-W02`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this + * attribute (e.g. `min="{{minWeek | date:'yyyy-Www'}}"`). Note that `min` will also add + * native HTML5 constraint validation. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this + * attribute (e.g. `max="{{maxWeek | date:'yyyy-Www'}}"`). Note that `max` will also add + * native HTML5 constraint validation. + * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string + * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. + * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string + * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + +
    + + Required! + + Not a valid date! +
    + value = {{example.value | date: "yyyy-Www"}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value | date: "yyyy-Www"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-W01'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-W01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
    + */ + 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'), + + /** + * @ngdoc input + * @name input[month] + * + * @description + * Input with month validation and transformation. In browsers that do not yet support + * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * month format (yyyy-MM), for example: `2009-01`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * If the model is not set to the first of the month, the next view to model update will set it + * to the first of the month. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this + * attribute (e.g. `min="{{minMonth | date:'yyyy-MM'}}"`). Note that `min` will also add + * native HTML5 constraint validation. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this + * attribute (e.g. `max="{{maxMonth | date:'yyyy-MM'}}"`). Note that `max` will also add + * native HTML5 constraint validation. + * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string + * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. + * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string + * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. + + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + + +
    + + Required! + + Not a valid month! +
    + value = {{example.value | date: "yyyy-MM"}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value | date: "yyyy-MM"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-10'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
    + */ + 'month': createDateInputType('month', MONTH_REGEXP, + createDateParser(MONTH_REGEXP, ['yyyy', 'MM']), + 'yyyy-MM'), + + /** + * @ngdoc input + * @name input[number] + * + * @description + * Text input with number validation and transformation. Sets the `number` validation + * error if not a valid number. + * + *
    + * The model must always be of type `number` otherwise Angular will throw an error. + * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt} + * error docs for more information and an example of how to convert your model if necessary. + *
    + * + * ## Issues with HTML5 constraint validation + * + * In browsers that follow the + * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29), + * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}. + * If a non-number is entered in the input, the browser will report the value as an empty string, + * which means the view / model values in `ngModel` and subsequently the scope value + * will also be an empty string. + * + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * does not match a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + +
    + + Required! + + Not valid number! +
    + value = {{example.value}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + it('should initialize to model', function() { + expect(value.getText()).toContain('12'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if over max', function() { + input.clear(); + input.sendKeys('123'); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); + }); + +
    + */ + 'number': numberInputType, + + + /** + * @ngdoc input + * @name input[url] + * + * @description + * Text input with URL validation. Sets the `url` validation error key if the content is not a + * valid URL. + * + *
    + * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex + * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify + * the built-in validators (see the {@link guide/forms Forms guide}) + *
    + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * does not match a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    +
    + + var text = element(by.binding('url.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('url.text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('http://google.com'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if not url', function() { + input.clear(); + input.sendKeys('box'); + + expect(valid.getText()).toContain('false'); + }); + +
    + */ + 'url': urlInputType, + + + /** + * @ngdoc input + * @name input[email] + * + * @description + * Text input with email validation. Sets the `email` validation error key if not a valid email + * address. + * + *
    + * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex + * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can + * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide}) + *
    + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * does not match a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + +
    + + Required! + + Not valid email! +
    + text = {{email.text}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    + myForm.$error.email = {{!!myForm.$error.email}}
    +
    +
    + + var text = element(by.binding('email.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('email.text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('me@example.com'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if not email', function() { + input.clear(); + input.sendKeys('xxx'); + + expect(valid.getText()).toContain('false'); + }); + +
    + */ + 'email': emailInputType, + + + /** + * @ngdoc input + * @name input[radio] + * + * @description + * HTML radio button. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string} value The value to which the `ngModel` expression should be set when selected. + * Note that `value` only supports `string` values, i.e. the scope model needs to be a string, + * too. Use `ngValue` if you need complex models (`number`, `object`, ...). + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {string} ngValue Angular expression to which `ngModel` will be be set when the radio + * is selected. Should be used instead of the `value` attribute if you need + * a non-string `ngModel` (`boolean`, `array`, ...). + * + * @example + + + +
    +
    +
    +
    + color = {{color.name | json}}
    +
    + Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`. +
    + + it('should change state', function() { + var color = element(by.binding('color.name')); + + expect(color.getText()).toContain('blue'); + + element.all(by.model('color.name')).get(0).click(); + + expect(color.getText()).toContain('red'); + }); + +
    + */ + 'radio': radioInputType, + + + /** + * @ngdoc input + * @name input[checkbox] + * + * @description + * HTML checkbox. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {expression=} ngTrueValue The value to which the expression should be set when selected. + * @param {expression=} ngFalseValue The value to which the expression should be set when not selected. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    +
    +
    + value1 = {{checkboxModel.value1}}
    + value2 = {{checkboxModel.value2}}
    +
    +
    + + it('should change state', function() { + var value1 = element(by.binding('checkboxModel.value1')); + var value2 = element(by.binding('checkboxModel.value2')); + + expect(value1.getText()).toContain('true'); + expect(value2.getText()).toContain('YES'); + + element(by.model('checkboxModel.value1')).click(); + element(by.model('checkboxModel.value2')).click(); + + expect(value1.getText()).toContain('false'); + expect(value2.getText()).toContain('NO'); + }); + +
    + */ + 'checkbox': checkboxInputType, + + 'hidden': noop, + 'button': noop, + 'submit': noop, + 'reset': noop, + 'file': noop +}; + +function stringBasedInputType(ctrl) { + ctrl.$formatters.push(function(value) { + return ctrl.$isEmpty(value) ? value : value.toString(); + }); +} + +function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); +} + +function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { + var type = lowercase(element[0].type); + + // In composition mode, users are still inputing intermediate text buffer, + // hold the listener until composition is done. + // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent + if (!$sniffer.android) { + var composing = false; + + element.on('compositionstart', function() { + composing = true; + }); + + element.on('compositionend', function() { + composing = false; + listener(); + }); + } + + var timeout; + + var listener = function(ev) { + if (timeout) { + $browser.defer.cancel(timeout); + timeout = null; + } + if (composing) return; + var value = element.val(), + event = ev && ev.type; + + // By default we will trim the value + // If the attribute ng-trim exists we will avoid trimming + // If input type is 'password', the value is never trimmed + if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) { + value = trim(value); + } + + // If a control is suffering from bad input (due to native validators), browsers discard its + // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the + // control's value is the same empty value twice in a row. + if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) { + ctrl.$setViewValue(value, event); + } + }; + + // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the + // input event on backspace, delete or cut + if ($sniffer.hasEvent('input')) { + element.on('input', listener); + } else { + var deferListener = function(ev, input, origValue) { + if (!timeout) { + timeout = $browser.defer(function() { + timeout = null; + if (!input || input.value !== origValue) { + listener(ev); + } + }); + } + }; + + element.on('keydown', function(event) { + var key = event.keyCode; + + // ignore + // command modifiers arrows + if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; + + deferListener(event, this, this.value); + }); + + // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it + if ($sniffer.hasEvent('paste')) { + element.on('paste cut', deferListener); + } + } + + // if user paste into input using mouse on older browser + // or form autocomplete on newer browser, we need "change" event to catch it + element.on('change', listener); + + // Some native input types (date-family) have the ability to change validity without + // firing any input/change events. + // For these event types, when native validators are present and the browser supports the type, + // check for validity changes on various DOM events. + if (PARTIAL_VALIDATION_TYPES[type] && ctrl.$$hasNativeValidators && type === attr.type) { + element.on(PARTIAL_VALIDATION_EVENTS, function(ev) { + if (!timeout) { + var validity = this[VALIDITY_STATE_PROPERTY]; + var origBadInput = validity.badInput; + var origTypeMismatch = validity.typeMismatch; + timeout = $browser.defer(function() { + timeout = null; + if (validity.badInput !== origBadInput || validity.typeMismatch !== origTypeMismatch) { + listener(ev); + } + }); + } + }); + } + + ctrl.$render = function() { + // Workaround for Firefox validation #12102. + var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue; + if (element.val() !== value) { + element.val(value); + } + }; +} + +function weekParser(isoWeek, existingDate) { + if (isDate(isoWeek)) { + return isoWeek; + } + + if (isString(isoWeek)) { + WEEK_REGEXP.lastIndex = 0; + var parts = WEEK_REGEXP.exec(isoWeek); + if (parts) { + var year = +parts[1], + week = +parts[2], + hours = 0, + minutes = 0, + seconds = 0, + milliseconds = 0, + firstThurs = getFirstThursdayOfYear(year), + addDays = (week - 1) * 7; + + if (existingDate) { + hours = existingDate.getHours(); + minutes = existingDate.getMinutes(); + seconds = existingDate.getSeconds(); + milliseconds = existingDate.getMilliseconds(); + } + + return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds); + } + } + + return NaN; +} + +function createDateParser(regexp, mapping) { + return function(iso, date) { + var parts, map; + + if (isDate(iso)) { + return iso; + } + + if (isString(iso)) { + // When a date is JSON'ified to wraps itself inside of an extra + // set of double quotes. This makes the date parsing code unable + // to match the date string and parse it as a date. + if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') { + iso = iso.substring(1, iso.length - 1); + } + if (ISO_DATE_REGEXP.test(iso)) { + return new Date(iso); + } + regexp.lastIndex = 0; + parts = regexp.exec(iso); + + if (parts) { + parts.shift(); + if (date) { + map = { + yyyy: date.getFullYear(), + MM: date.getMonth() + 1, + dd: date.getDate(), + HH: date.getHours(), + mm: date.getMinutes(), + ss: date.getSeconds(), + sss: date.getMilliseconds() / 1000 + }; + } else { + map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 }; + } + + forEach(parts, function(part, index) { + if (index < mapping.length) { + map[mapping[index]] = +part; + } + }); + return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0); + } + } + + return NaN; + }; +} + +function createDateInputType(type, regexp, parseDate, format) { + return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) { + badInputChecker(scope, element, attr, ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + var timezone = ctrl && ctrl.$options && ctrl.$options.timezone; + var previousDate; + + ctrl.$$parserName = type; + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (regexp.test(value)) { + // Note: We cannot read ctrl.$modelValue, as there might be a different + // parser/formatter in the processing chain so that the model + // contains some different data format! + var parsedDate = parseDate(value, previousDate); + if (timezone) { + parsedDate = convertTimezoneToLocal(parsedDate, timezone); + } + return parsedDate; + } + return undefined; + }); + + ctrl.$formatters.push(function(value) { + if (value && !isDate(value)) { + throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value); + } + if (isValidDate(value)) { + previousDate = value; + if (previousDate && timezone) { + previousDate = convertTimezoneToLocal(previousDate, timezone, true); + } + return $filter('date')(value, format, timezone); + } else { + previousDate = null; + return ''; + } + }); + + if (isDefined(attr.min) || attr.ngMin) { + var minVal; + ctrl.$validators.min = function(value) { + return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal; + }; + attr.$observe('min', function(val) { + minVal = parseObservedDateValue(val); + ctrl.$validate(); + }); + } + + if (isDefined(attr.max) || attr.ngMax) { + var maxVal; + ctrl.$validators.max = function(value) { + return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal; + }; + attr.$observe('max', function(val) { + maxVal = parseObservedDateValue(val); + ctrl.$validate(); + }); + } + + function isValidDate(value) { + // Invalid Date: getTime() returns NaN + return value && !(value.getTime && value.getTime() !== value.getTime()); + } + + function parseObservedDateValue(val) { + return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val; + } + }; +} + +function badInputChecker(scope, element, attr, ctrl) { + var node = element[0]; + var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity); + if (nativeValidation) { + ctrl.$parsers.push(function(value) { + var validity = element.prop(VALIDITY_STATE_PROPERTY) || {}; + return validity.badInput || validity.typeMismatch ? undefined : value; + }); + } +} + +function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { + badInputChecker(scope, element, attr, ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + + ctrl.$$parserName = 'number'; + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (NUMBER_REGEXP.test(value)) return parseFloat(value); + return undefined; + }); + + ctrl.$formatters.push(function(value) { + if (!ctrl.$isEmpty(value)) { + if (!isNumber(value)) { + throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value); + } + value = value.toString(); + } + return value; + }); + + if (isDefined(attr.min) || attr.ngMin) { + var minVal; + ctrl.$validators.min = function(value) { + return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal; + }; + + attr.$observe('min', function(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val); + } + minVal = isNumber(val) && !isNaN(val) ? val : undefined; + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + }); + } + + if (isDefined(attr.max) || attr.ngMax) { + var maxVal; + ctrl.$validators.max = function(value) { + return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal; + }; + + attr.$observe('max', function(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val); + } + maxVal = isNumber(val) && !isNaN(val) ? val : undefined; + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + }); + } +} + +function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // Note: no badInputChecker here by purpose as `url` is only a validation + // in browsers, i.e. we can always read out input.value even if it is not valid! + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + + ctrl.$$parserName = 'url'; + ctrl.$validators.url = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || URL_REGEXP.test(value); + }; +} + +function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // Note: no badInputChecker here by purpose as `url` is only a validation + // in browsers, i.e. we can always read out input.value even if it is not valid! + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + + ctrl.$$parserName = 'email'; + ctrl.$validators.email = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value); + }; +} + +function radioInputType(scope, element, attr, ctrl) { + // make the name unique, if not defined + if (isUndefined(attr.name)) { + element.attr('name', nextUid()); + } + + var listener = function(ev) { + if (element[0].checked) { + ctrl.$setViewValue(attr.value, ev && ev.type); + } + }; + + element.on('click', listener); + + ctrl.$render = function() { + var value = attr.value; + element[0].checked = (value == ctrl.$viewValue); + }; + + attr.$observe('value', ctrl.$render); +} + +function parseConstantExpr($parse, context, name, expression, fallback) { + var parseFn; + if (isDefined(expression)) { + parseFn = $parse(expression); + if (!parseFn.constant) { + throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' + + '`{1}`.', name, expression); + } + return parseFn(context); + } + return fallback; +} + +function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { + var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true); + var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false); + + var listener = function(ev) { + ctrl.$setViewValue(element[0].checked, ev && ev.type); + }; + + element.on('click', listener); + + ctrl.$render = function() { + element[0].checked = ctrl.$viewValue; + }; + + // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false` + // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert + // it to a boolean. + ctrl.$isEmpty = function(value) { + return value === false; + }; + + ctrl.$formatters.push(function(value) { + return equals(value, trueValue); + }); + + ctrl.$parsers.push(function(value) { + return value ? trueValue : falseValue; + }); +} + + +/** + * @ngdoc directive + * @name textarea + * @restrict E + * + * @description + * HTML textarea element control with angular data-binding. The data-binding and validation + * properties of this element are exactly the same as those of the + * {@link ng.directive:input input element}. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any + * length. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * does not match a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + */ + + +/** + * @ngdoc directive + * @name input + * @restrict E + * + * @description + * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding, + * input state control, and validation. + * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers. + * + *
    + * **Note:** Not every feature offered is available for all input types. + * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`. + *
    + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {boolean=} ngRequired Sets `required` attribute if set to true + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any + * length. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * value does not match a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + * This parameter is ignored for input[type=password] controls, which will never trim the + * input. + * + * @example + + + +
    +
    + +
    + + Required! +
    + +
    + + Too short! + + Too long! +
    +
    +
    + user = {{user}}
    + myForm.userName.$valid = {{myForm.userName.$valid}}
    + myForm.userName.$error = {{myForm.userName.$error}}
    + myForm.lastName.$valid = {{myForm.lastName.$valid}}
    + myForm.lastName.$error = {{myForm.lastName.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    + myForm.$error.minlength = {{!!myForm.$error.minlength}}
    + myForm.$error.maxlength = {{!!myForm.$error.maxlength}}
    +
    +
    + + var user = element(by.exactBinding('user')); + var userNameValid = element(by.binding('myForm.userName.$valid')); + var lastNameValid = element(by.binding('myForm.lastName.$valid')); + var lastNameError = element(by.binding('myForm.lastName.$error')); + var formValid = element(by.binding('myForm.$valid')); + var userNameInput = element(by.model('user.name')); + var userLastInput = element(by.model('user.last')); + + it('should initialize to model', function() { + expect(user.getText()).toContain('{"name":"guest","last":"visitor"}'); + expect(userNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); + }); + + it('should be invalid if empty when required', function() { + userNameInput.clear(); + userNameInput.sendKeys(''); + + expect(user.getText()).toContain('{"last":"visitor"}'); + expect(userNameValid.getText()).toContain('false'); + expect(formValid.getText()).toContain('false'); + }); + + it('should be valid if empty when min length is set', function() { + userLastInput.clear(); + userLastInput.sendKeys(''); + + expect(user.getText()).toContain('{"name":"guest","last":""}'); + expect(lastNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); + }); + + it('should be invalid if less than required min length', function() { + userLastInput.clear(); + userLastInput.sendKeys('xx'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('minlength'); + expect(formValid.getText()).toContain('false'); + }); + + it('should be invalid if longer than max length', function() { + userLastInput.clear(); + userLastInput.sendKeys('some ridiculously long name'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('maxlength'); + expect(formValid.getText()).toContain('false'); + }); + +
    + */ +var inputDirective = ['$browser', '$sniffer', '$filter', '$parse', + function($browser, $sniffer, $filter, $parse) { + return { + restrict: 'E', + require: ['?ngModel'], + link: { + pre: function(scope, element, attr, ctrls) { + if (ctrls[0]) { + (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer, + $browser, $filter, $parse); + } + } + } + }; +}]; + + + +var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; +/** + * @ngdoc directive + * @name ngValue + * + * @description + * Binds the given expression to the value of `
    + + + it('should show correct pluralized string', function() { + var withoutOffset = element.all(by.css('ng-pluralize')).get(0); + var withOffset = element.all(by.css('ng-pluralize')).get(1); + var countInput = element(by.model('personCount')); + + expect(withoutOffset.getText()).toEqual('1 person is viewing.'); + expect(withOffset.getText()).toEqual('Igor is viewing.'); + + countInput.clear(); + countInput.sendKeys('0'); + + expect(withoutOffset.getText()).toEqual('Nobody is viewing.'); + expect(withOffset.getText()).toEqual('Nobody is viewing.'); + + countInput.clear(); + countInput.sendKeys('2'); + + expect(withoutOffset.getText()).toEqual('2 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor and Misko are viewing.'); + + countInput.clear(); + countInput.sendKeys('3'); + + expect(withoutOffset.getText()).toEqual('3 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.'); + + countInput.clear(); + countInput.sendKeys('4'); + + expect(withoutOffset.getText()).toEqual('4 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.'); + }); + it('should show data-bound names', function() { + var withOffset = element.all(by.css('ng-pluralize')).get(1); + var personCount = element(by.model('personCount')); + var person1 = element(by.model('person1')); + var person2 = element(by.model('person2')); + personCount.clear(); + personCount.sendKeys('4'); + person1.clear(); + person1.sendKeys('Di'); + person2.clear(); + person2.sendKeys('Vojta'); + expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.'); + }); + + + */ +var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale, $interpolate, $log) { + var BRACE = /{}/g, + IS_WHEN = /^when(Minus)?(.+)$/; + + return { + link: function(scope, element, attr) { + var numberExp = attr.count, + whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs + offset = attr.offset || 0, + whens = scope.$eval(whenExp) || {}, + whensExpFns = {}, + startSymbol = $interpolate.startSymbol(), + endSymbol = $interpolate.endSymbol(), + braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol, + watchRemover = angular.noop, + lastCount; + + forEach(attr, function(expression, attributeName) { + var tmpMatch = IS_WHEN.exec(attributeName); + if (tmpMatch) { + var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]); + whens[whenKey] = element.attr(attr.$attr[attributeName]); + } + }); + forEach(whens, function(expression, key) { + whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement)); + + }); + + scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) { + var count = parseFloat(newVal); + var countIsNaN = isNaN(count); + + if (!countIsNaN && !(count in whens)) { + // If an explicit number rule such as 1, 2, 3... is defined, just use it. + // Otherwise, check it against pluralization rules in $locale service. + count = $locale.pluralCat(count - offset); + } + + // If both `count` and `lastCount` are NaN, we don't need to re-register a watch. + // In JS `NaN !== NaN`, so we have to explicitly check. + if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) { + watchRemover(); + var whenExpFn = whensExpFns[count]; + if (isUndefined(whenExpFn)) { + if (newVal != null) { + $log.debug("ngPluralize: no rule defined for '" + count + "' in " + whenExp); + } + watchRemover = noop; + updateElementText(); + } else { + watchRemover = scope.$watch(whenExpFn, updateElementText); + } + lastCount = count; + } + }); + + function updateElementText(newText) { + element.text(newText || ''); + } + } + }; +}]; + +/** + * @ngdoc directive + * @name ngRepeat + * @multiElement + * + * @description + * The `ngRepeat` directive instantiates a template once per item from a collection. Each template + * instance gets its own scope, where the given loop variable is set to the current collection item, + * and `$index` is set to the item index or key. + * + * Special properties are exposed on the local scope of each template instance, including: + * + * | Variable | Type | Details | + * |-----------|-----------------|-----------------------------------------------------------------------------| + * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) | + * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. | + * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. | + * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. | + * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). | + * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). | + * + *
    + * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}. + * This may be useful when, for instance, nesting ngRepeats. + *
    + * + * + * # Iterating over object properties + * + * It is possible to get `ngRepeat` to iterate over the properties of an object using the following + * syntax: + * + * ```js + *
    ...
    + * ``` + * + * However, there are a limitations compared to array iteration: + * + * - The JavaScript specification does not define the order of keys + * returned for an object, so Angular relies on the order returned by the browser + * when running `for key in myObj`. Browsers generally follow the strategy of providing + * keys in the order in which they were defined, although there are exceptions when keys are deleted + * and reinstated. See the + * [MDN page on `delete` for more info](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_notes). + * + * - `ngRepeat` will silently *ignore* object keys starting with `$`, because + * it's a prefix used by Angular for public (`$`) and private (`$$`) properties. + * + * - The built-in filters {@link ng.orderBy orderBy} and {@link ng.filter filter} do not work with + * objects, and will throw an error if used with one. + * + * If you are hitting any of these limitations, the recommended workaround is to convert your object into an array + * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could + * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter) + * or implement a `$watch` on the object yourself. + * + * + * # Tracking and Duplicates + * + * `ngRepeat` uses {@link $rootScope.Scope#$watchCollection $watchCollection} to detect changes in + * the collection. When a change happens, ngRepeat then makes the corresponding changes to the DOM: + * + * * When an item is added, a new instance of the template is added to the DOM. + * * When an item is removed, its template instance is removed from the DOM. + * * When items are reordered, their respective templates are reordered in the DOM. + * + * To minimize creation of DOM elements, `ngRepeat` uses a function + * to "keep track" of all items in the collection and their corresponding DOM elements. + * For example, if an item is added to the collection, ngRepeat will know that all other items + * already have DOM elements, and will not re-render them. + * + * The default tracking function (which tracks items by their identity) does not allow + * duplicate items in arrays. This is because when there are duplicates, it is not possible + * to maintain a one-to-one mapping between collection items and DOM elements. + * + * If you do need to repeat duplicate items, you can substitute the default tracking behavior + * with your own using the `track by` expression. + * + * For example, you may track items by the index of each item in the collection, using the + * special scope property `$index`: + * ```html + *
    + * {{n}} + *
    + * ``` + * + * You may also use arbitrary expressions in `track by`, including references to custom functions + * on the scope: + * ```html + *
    + * {{n}} + *
    + * ``` + * + *
    + * If you are working with objects that have an identifier property, you should track + * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat` + * will not have to rebuild the DOM elements for items it has already rendered, even if the + * JavaScript objects in the collection have been substituted for new ones. For large collections, + * this significantly improves rendering performance. If you don't have a unique identifier, + * `track by $index` can also provide a performance boost. + *
    + * ```html + *
    + * {{model.name}} + *
    + * ``` + * + * When no `track by` expression is provided, it is equivalent to tracking by the built-in + * `$id` function, which tracks items by their identity: + * ```html + *
    + * {{obj.prop}} + *
    + * ``` + * + *
    + * **Note:** `track by` must always be the last expression: + *
    + * ``` + *
    + * {{model.name}} + *
    + * ``` + * + * # Special repeat start and end points + * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending + * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively. + * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on) + * up to and including the ending HTML tag where **ng-repeat-end** is placed. + * + * The example below makes use of this feature: + * ```html + *
    + * Header {{ item }} + *
    + *
    + * Body {{ item }} + *
    + *
    + * Footer {{ item }} + *
    + * ``` + * + * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to: + * ```html + *
    + * Header A + *
    + *
    + * Body A + *
    + *
    + * Footer A + *
    + *
    + * Header B + *
    + *
    + * Body B + *
    + *
    + * Footer B + *
    + * ``` + * + * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such + * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**). + * + * @animations + * | Animation | Occurs | + * |----------------------------------|-------------------------------------| + * | {@link ng.$animate#enter enter} | when a new item is added to the list or when an item is revealed after a filter | + * | {@link ng.$animate#leave leave} | when an item is removed from the list or when an item is filtered out | + * | {@link ng.$animate#move move } | when an adjacent item is filtered out causing a reorder or when the item contents are reordered | + * + * See the example below for defining CSS animations with ngRepeat. + * + * @element ANY + * @scope + * @priority 1000 + * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These + * formats are currently supported: + * + * * `variable in expression` – where variable is the user defined loop variable and `expression` + * is a scope expression giving the collection to enumerate. + * + * For example: `album in artist.albums`. + * + * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers, + * and `expression` is the scope expression giving the collection to enumerate. + * + * For example: `(name, age) in {'adam':10, 'amalie':12}`. + * + * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression + * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression + * is specified, ng-repeat associates elements by identity. It is an error to have + * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are + * mapped to the same DOM element, which is not possible.) + * + * Note that the tracking expression must come last, after any filters, and the alias expression. + * + * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements + * will be associated by item identity in the array. + * + * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique + * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements + * with the corresponding item in the array by identity. Moving the same object in array would move the DOM + * element in the same way in the DOM. + * + * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this + * case the object identity does not matter. Two objects are considered equivalent as long as their `id` + * property is same. + * + * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter + * to items in conjunction with a tracking expression. + * + * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the + * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message + * when a filter is active on the repeater, but the filtered result set is empty. + * + * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after + * the items have been processed through the filter. + * + * Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end + * (and not as operator, inside an expression). + * + * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` . + * + * @example + * This example uses `ngRepeat` to display a list of people. A filter is used to restrict the displayed + * results by name. New (entering) and removed (leaving) items are animated. + + +
    + I have {{friends.length}} friends. They are: + +
      +
    • + [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. +
    • +
    • + No results found... +
    • +
    +
    +
    + + angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) { + $scope.friends = [ + {name:'John', age:25, gender:'boy'}, + {name:'Jessie', age:30, gender:'girl'}, + {name:'Johanna', age:28, gender:'girl'}, + {name:'Joy', age:15, gender:'girl'}, + {name:'Mary', age:28, gender:'girl'}, + {name:'Peter', age:95, gender:'boy'}, + {name:'Sebastian', age:50, gender:'boy'}, + {name:'Erika', age:27, gender:'girl'}, + {name:'Patrick', age:40, gender:'boy'}, + {name:'Samantha', age:60, gender:'girl'} + ]; + }); + + + .example-animate-container { + background:white; + border:1px solid black; + list-style:none; + margin:0; + padding:0 10px; + } + + .animate-repeat { + line-height:30px; + list-style:none; + box-sizing:border-box; + } + + .animate-repeat.ng-move, + .animate-repeat.ng-enter, + .animate-repeat.ng-leave { + transition:all linear 0.5s; + } + + .animate-repeat.ng-leave.ng-leave-active, + .animate-repeat.ng-move, + .animate-repeat.ng-enter { + opacity:0; + max-height:0; + } + + .animate-repeat.ng-leave, + .animate-repeat.ng-move.ng-move-active, + .animate-repeat.ng-enter.ng-enter-active { + opacity:1; + max-height:30px; + } + + + var friends = element.all(by.repeater('friend in friends')); + + it('should render initial data set', function() { + expect(friends.count()).toBe(10); + expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.'); + expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.'); + expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.'); + expect(element(by.binding('friends.length')).getText()) + .toMatch("I have 10 friends. They are:"); + }); + + it('should update repeater when filter predicate changes', function() { + expect(friends.count()).toBe(10); + + element(by.model('q')).sendKeys('ma'); + + expect(friends.count()).toBe(2); + expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.'); + expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.'); + }); + +
    + */ +var ngRepeatDirective = ['$parse', '$animate', '$compile', function($parse, $animate, $compile) { + var NG_REMOVED = '$$NG_REMOVED'; + var ngRepeatMinErr = minErr('ngRepeat'); + + var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) { + // TODO(perf): generate setters to shave off ~40ms or 1-1.5% + scope[valueIdentifier] = value; + if (keyIdentifier) scope[keyIdentifier] = key; + scope.$index = index; + scope.$first = (index === 0); + scope.$last = (index === (arrayLength - 1)); + scope.$middle = !(scope.$first || scope.$last); + // jshint bitwise: false + scope.$odd = !(scope.$even = (index&1) === 0); + // jshint bitwise: true + }; + + var getBlockStart = function(block) { + return block.clone[0]; + }; + + var getBlockEnd = function(block) { + return block.clone[block.clone.length - 1]; + }; + + + return { + restrict: 'A', + multiElement: true, + transclude: 'element', + priority: 1000, + terminal: true, + $$tlb: true, + compile: function ngRepeatCompile($element, $attr) { + var expression = $attr.ngRepeat; + var ngRepeatEndComment = $compile.$$createComment('end ngRepeat', expression); + + var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/); + + if (!match) { + throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.", + expression); + } + + var lhs = match[1]; + var rhs = match[2]; + var aliasAs = match[3]; + var trackByExp = match[4]; + + match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/); + + if (!match) { + throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.", + lhs); + } + var valueIdentifier = match[3] || match[1]; + var keyIdentifier = match[2]; + + if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) || + /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) { + throw ngRepeatMinErr('badident', "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.", + aliasAs); + } + + var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn; + var hashFnLocals = {$id: hashKey}; + + if (trackByExp) { + trackByExpGetter = $parse(trackByExp); + } else { + trackByIdArrayFn = function(key, value) { + return hashKey(value); + }; + trackByIdObjFn = function(key) { + return key; + }; + } + + return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) { + + if (trackByExpGetter) { + trackByIdExpFn = function(key, value, index) { + // assign key, value, and $index to the locals so that they can be used in hash functions + if (keyIdentifier) hashFnLocals[keyIdentifier] = key; + hashFnLocals[valueIdentifier] = value; + hashFnLocals.$index = index; + return trackByExpGetter($scope, hashFnLocals); + }; + } + + // Store a list of elements from previous run. This is a hash where key is the item from the + // iterator, and the value is objects with following properties. + // - scope: bound scope + // - element: previous element. + // - index: position + // + // We are using no-proto object so that we don't need to guard against inherited props via + // hasOwnProperty. + var lastBlockMap = createMap(); + + //watch props + $scope.$watchCollection(rhs, function ngRepeatAction(collection) { + var index, length, + previousNode = $element[0], // node that cloned nodes should be inserted after + // initialized to the comment node anchor + nextNode, + // Same as lastBlockMap but it has the current state. It will become the + // lastBlockMap on the next iteration. + nextBlockMap = createMap(), + collectionLength, + key, value, // key/value of iteration + trackById, + trackByIdFn, + collectionKeys, + block, // last object information {scope, element, id} + nextBlockOrder, + elementsToRemove; + + if (aliasAs) { + $scope[aliasAs] = collection; + } + + if (isArrayLike(collection)) { + collectionKeys = collection; + trackByIdFn = trackByIdExpFn || trackByIdArrayFn; + } else { + trackByIdFn = trackByIdExpFn || trackByIdObjFn; + // if object, extract keys, in enumeration order, unsorted + collectionKeys = []; + for (var itemKey in collection) { + if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') { + collectionKeys.push(itemKey); + } + } + } + + collectionLength = collectionKeys.length; + nextBlockOrder = new Array(collectionLength); + + // locate existing items + for (index = 0; index < collectionLength; index++) { + key = (collection === collectionKeys) ? index : collectionKeys[index]; + value = collection[key]; + trackById = trackByIdFn(key, value, index); + if (lastBlockMap[trackById]) { + // found previously seen block + block = lastBlockMap[trackById]; + delete lastBlockMap[trackById]; + nextBlockMap[trackById] = block; + nextBlockOrder[index] = block; + } else if (nextBlockMap[trackById]) { + // if collision detected. restore lastBlockMap and throw an error + forEach(nextBlockOrder, function(block) { + if (block && block.scope) lastBlockMap[block.id] = block; + }); + throw ngRepeatMinErr('dupes', + "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}", + expression, trackById, value); + } else { + // new never before seen block + nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined}; + nextBlockMap[trackById] = true; + } + } + + // remove leftover items + for (var blockKey in lastBlockMap) { + block = lastBlockMap[blockKey]; + elementsToRemove = getBlockNodes(block.clone); + $animate.leave(elementsToRemove); + if (elementsToRemove[0].parentNode) { + // if the element was not removed yet because of pending animation, mark it as deleted + // so that we can ignore it later + for (index = 0, length = elementsToRemove.length; index < length; index++) { + elementsToRemove[index][NG_REMOVED] = true; + } + } + block.scope.$destroy(); + } + + // we are not using forEach for perf reasons (trying to avoid #call) + for (index = 0; index < collectionLength; index++) { + key = (collection === collectionKeys) ? index : collectionKeys[index]; + value = collection[key]; + block = nextBlockOrder[index]; + + if (block.scope) { + // if we have already seen this object, then we need to reuse the + // associated scope/element + + nextNode = previousNode; + + // skip nodes that are already pending removal via leave animation + do { + nextNode = nextNode.nextSibling; + } while (nextNode && nextNode[NG_REMOVED]); + + if (getBlockStart(block) != nextNode) { + // existing item which got moved + $animate.move(getBlockNodes(block.clone), null, previousNode); + } + previousNode = getBlockEnd(block); + updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); + } else { + // new item which we don't know about + $transclude(function ngRepeatTransclude(clone, scope) { + block.scope = scope; + // http://jsperf.com/clone-vs-createcomment + var endNode = ngRepeatEndComment.cloneNode(false); + clone[clone.length++] = endNode; + + $animate.enter(clone, null, previousNode); + previousNode = endNode; + // Note: We only need the first/last node of the cloned nodes. + // However, we need to keep the reference to the jqlite wrapper as it might be changed later + // by a directive with templateUrl when its template arrives. + block.clone = clone; + nextBlockMap[block.id] = block; + updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); + }); + } + } + lastBlockMap = nextBlockMap; + }); + }; + } + }; +}]; + +var NG_HIDE_CLASS = 'ng-hide'; +var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate'; +/** + * @ngdoc directive + * @name ngShow + * @multiElement + * + * @description + * The `ngShow` directive shows or hides the given HTML element based on the expression + * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding + * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined + * in AngularJS and sets the display style to none (using an !important flag). + * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). + * + * ```html + * + *
    + * + * + *
    + * ``` + * + * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class + * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed + * from the element causing the element not to appear hidden. + * + * ## Why is !important used? + * + * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector + * can be easily overridden by heavier selectors. For example, something as simple + * as changing the display style on a HTML list item would make hidden elements appear visible. + * This also becomes a bigger issue when dealing with CSS frameworks. + * + * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector + * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the + * styling to change how to hide an element then it is just a matter of using !important in their own CSS code. + * + * ### Overriding `.ng-hide` + * + * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change + * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide` + * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope + * with extra animation classes that can be added. + * + * ```css + * .ng-hide:not(.ng-hide-animate) { + * /* this is just another form of hiding an element */ + * display: block!important; + * position: absolute; + * top: -9999px; + * left: -9999px; + * } + * ``` + * + * By default you don't need to override in CSS anything and the animations will work around the display style. + * + * ## A note about animations with `ngShow` + * + * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression + * is true and false. This system works like the animation system present with ngClass except that + * you must also include the !important flag to override the display property + * so that you can perform an animation when the element is hidden during the time of the animation. + * + * ```css + * // + * //a working example can be found at the bottom of this page + * // + * .my-element.ng-hide-add, .my-element.ng-hide-remove { + * /* this is required as of 1.3x to properly + * apply all styling in a show/hide animation */ + * transition: 0s linear all; + * } + * + * .my-element.ng-hide-add-active, + * .my-element.ng-hide-remove-active { + * /* the transition is defined in the active class */ + * transition: 1s linear all; + * } + * + * .my-element.ng-hide-add { ... } + * .my-element.ng-hide-add.ng-hide-add-active { ... } + * .my-element.ng-hide-remove { ... } + * .my-element.ng-hide-remove.ng-hide-remove-active { ... } + * ``` + * + * Keep in mind that, as of AngularJS version 1.3, there is no need to change the display + * property to block during animation states--ngAnimate will handle the style toggling automatically for you. + * + * @animations + * | Animation | Occurs | + * |----------------------------------|-------------------------------------| + * | {@link $animate#addClass addClass} `.ng-hide` | after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden | + * | {@link $animate#removeClass removeClass} `.ng-hide` | after the `ngShow` expression evaluates to a truthy value and just before contents are set to visible | + * + * @element ANY + * @param {expression} ngShow If the {@link guide/expression expression} is truthy + * then the element is shown or hidden respectively. + * + * @example + + + Click me:
    +
    + Show: +
    + I show up when your checkbox is checked. +
    +
    +
    + Hide: +
    + I hide when your checkbox is checked. +
    +
    +
    + + @import url(../../components/bootstrap-3.1.1/css/bootstrap.css); + + + .animate-show { + line-height: 20px; + opacity: 1; + padding: 10px; + border: 1px solid black; + background: white; + } + + .animate-show.ng-hide-add, .animate-show.ng-hide-remove { + transition: all linear 0.5s; + } + + .animate-show.ng-hide { + line-height: 0; + opacity: 0; + padding: 0 10px; + } + + .check-element { + padding: 10px; + border: 1px solid black; + background: white; + } + + + var thumbsUp = element(by.css('span.glyphicon-thumbs-up')); + var thumbsDown = element(by.css('span.glyphicon-thumbs-down')); + + it('should check ng-show / ng-hide', function() { + expect(thumbsUp.isDisplayed()).toBeFalsy(); + expect(thumbsDown.isDisplayed()).toBeTruthy(); + + element(by.model('checked')).click(); + + expect(thumbsUp.isDisplayed()).toBeTruthy(); + expect(thumbsDown.isDisplayed()).toBeFalsy(); + }); + +
    + */ +var ngShowDirective = ['$animate', function($animate) { + return { + restrict: 'A', + multiElement: true, + link: function(scope, element, attr) { + scope.$watch(attr.ngShow, function ngShowWatchAction(value) { + // we're adding a temporary, animation-specific class for ng-hide since this way + // we can control when the element is actually displayed on screen without having + // to have a global/greedy CSS selector that breaks when other animations are run. + // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845 + $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, { + tempClasses: NG_HIDE_IN_PROGRESS_CLASS + }); + }); + } + }; +}]; + + +/** + * @ngdoc directive + * @name ngHide + * @multiElement + * + * @description + * The `ngHide` directive shows or hides the given HTML element based on the expression + * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding + * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined + * in AngularJS and sets the display style to none (using an !important flag). + * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). + * + * ```html + * + *
    + * + * + *
    + * ``` + * + * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class + * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed + * from the element causing the element not to appear hidden. + * + * ## Why is !important used? + * + * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector + * can be easily overridden by heavier selectors. For example, something as simple + * as changing the display style on a HTML list item would make hidden elements appear visible. + * This also becomes a bigger issue when dealing with CSS frameworks. + * + * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector + * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the + * styling to change how to hide an element then it is just a matter of using !important in their own CSS code. + * + * ### Overriding `.ng-hide` + * + * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change + * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide` + * class in CSS: + * + * ```css + * .ng-hide { + * /* this is just another form of hiding an element */ + * display: block!important; + * position: absolute; + * top: -9999px; + * left: -9999px; + * } + * ``` + * + * By default you don't need to override in CSS anything and the animations will work around the display style. + * + * ## A note about animations with `ngHide` + * + * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression + * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide` + * CSS class is added and removed for you instead of your own CSS class. + * + * ```css + * // + * //a working example can be found at the bottom of this page + * // + * .my-element.ng-hide-add, .my-element.ng-hide-remove { + * transition: 0.5s linear all; + * } + * + * .my-element.ng-hide-add { ... } + * .my-element.ng-hide-add.ng-hide-add-active { ... } + * .my-element.ng-hide-remove { ... } + * .my-element.ng-hide-remove.ng-hide-remove-active { ... } + * ``` + * + * Keep in mind that, as of AngularJS version 1.3, there is no need to change the display + * property to block during animation states--ngAnimate will handle the style toggling automatically for you. + * + * @animations + * | Animation | Occurs | + * |----------------------------------|-------------------------------------| + * | {@link $animate#addClass addClass} `.ng-hide` | after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden | + * | {@link $animate#removeClass removeClass} `.ng-hide` | after the `ngHide` expression evaluates to a non truthy value and just before contents are set to visible | + * + * + * @element ANY + * @param {expression} ngHide If the {@link guide/expression expression} is truthy then + * the element is shown or hidden respectively. + * + * @example + + + Click me:
    +
    + Show: +
    + I show up when your checkbox is checked. +
    +
    +
    + Hide: +
    + I hide when your checkbox is checked. +
    +
    +
    + + @import url(../../components/bootstrap-3.1.1/css/bootstrap.css); + + + .animate-hide { + transition: all linear 0.5s; + line-height: 20px; + opacity: 1; + padding: 10px; + border: 1px solid black; + background: white; + } + + .animate-hide.ng-hide { + line-height: 0; + opacity: 0; + padding: 0 10px; + } + + .check-element { + padding: 10px; + border: 1px solid black; + background: white; + } + + + var thumbsUp = element(by.css('span.glyphicon-thumbs-up')); + var thumbsDown = element(by.css('span.glyphicon-thumbs-down')); + + it('should check ng-show / ng-hide', function() { + expect(thumbsUp.isDisplayed()).toBeFalsy(); + expect(thumbsDown.isDisplayed()).toBeTruthy(); + + element(by.model('checked')).click(); + + expect(thumbsUp.isDisplayed()).toBeTruthy(); + expect(thumbsDown.isDisplayed()).toBeFalsy(); + }); + +
    + */ +var ngHideDirective = ['$animate', function($animate) { + return { + restrict: 'A', + multiElement: true, + link: function(scope, element, attr) { + scope.$watch(attr.ngHide, function ngHideWatchAction(value) { + // The comment inside of the ngShowDirective explains why we add and + // remove a temporary class for the show/hide animation + $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, { + tempClasses: NG_HIDE_IN_PROGRESS_CLASS + }); + }); + } + }; +}]; + +/** + * @ngdoc directive + * @name ngStyle + * @restrict AC + * + * @description + * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally. + * + * @knownIssue + * You should not use {@link guide/interpolation interpolation} in the value of the `style` + * attribute, when using the `ngStyle` directive on the same element. + * See {@link guide/interpolation#known-issues here} for more info. + * + * @element ANY + * @param {expression} ngStyle + * + * {@link guide/expression Expression} which evals to an + * object whose keys are CSS style names and values are corresponding values for those CSS + * keys. + * + * Since some CSS style names are not valid keys for an object, they must be quoted. + * See the 'background-color' style in the example below. + * + * @example + + + + + +
    + Sample Text +
    myStyle={{myStyle}}
    +
    + + span { + color: black; + } + + + var colorSpan = element(by.css('span')); + + it('should check ng-style', function() { + expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); + element(by.css('input[value=\'set color\']')).click(); + expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)'); + element(by.css('input[value=clear]')).click(); + expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); + }); + +
    + */ +var ngStyleDirective = ngDirective(function(scope, element, attr) { + scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { + if (oldStyles && (newStyles !== oldStyles)) { + forEach(oldStyles, function(val, style) { element.css(style, '');}); + } + if (newStyles) element.css(newStyles); + }, true); +}); + +/** + * @ngdoc directive + * @name ngSwitch + * @restrict EA + * + * @description + * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression. + * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location + * as specified in the template. + * + * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it + * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element + * matches the value obtained from the evaluated expression. In other words, you define a container element + * (where you place the directive), place an expression on the **`on="..."` attribute** + * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place + * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on + * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default + * attribute is displayed. + * + *
    + * Be aware that the attribute values to match against cannot be expressions. They are interpreted + * as literal string values to match against. + * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the + * value of the expression `$scope.someVal`. + *
    + + * @animations + * | Animation | Occurs | + * |----------------------------------|-------------------------------------| + * | {@link ng.$animate#enter enter} | after the ngSwitch contents change and the matched child element is placed inside the container | + * | {@link ng.$animate#leave leave} | after the ngSwitch contents change and just before the former contents are removed from the DOM | + * + * @usage + * + * ``` + * + * ... + * ... + * ... + * + * ``` + * + * + * @scope + * @priority 1200 + * @param {*} ngSwitch|on expression to match against ng-switch-when. + * On child elements add: + * + * * `ngSwitchWhen`: the case statement to match against. If match then this + * case will be displayed. If the same match appears multiple times, all the + * elements will be displayed. + * * `ngSwitchDefault`: the default case when no other case match. If there + * are multiple default cases, all of them will be displayed when no other + * case match. + * + * + * @example + + +
    + + selection={{selection}} +
    +
    +
    Settings Div
    +
    Home Span
    +
    default
    +
    +
    +
    + + angular.module('switchExample', ['ngAnimate']) + .controller('ExampleController', ['$scope', function($scope) { + $scope.items = ['settings', 'home', 'other']; + $scope.selection = $scope.items[0]; + }]); + + + .animate-switch-container { + position:relative; + background:white; + border:1px solid black; + height:40px; + overflow:hidden; + } + + .animate-switch { + padding:10px; + } + + .animate-switch.ng-animate { + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + } + + .animate-switch.ng-leave.ng-leave-active, + .animate-switch.ng-enter { + top:-50px; + } + .animate-switch.ng-leave, + .animate-switch.ng-enter.ng-enter-active { + top:0; + } + + + var switchElem = element(by.css('[ng-switch]')); + var select = element(by.model('selection')); + + it('should start in settings', function() { + expect(switchElem.getText()).toMatch(/Settings Div/); + }); + it('should change to home', function() { + select.all(by.css('option')).get(1).click(); + expect(switchElem.getText()).toMatch(/Home Span/); + }); + it('should select default', function() { + select.all(by.css('option')).get(2).click(); + expect(switchElem.getText()).toMatch(/default/); + }); + +
    + */ +var ngSwitchDirective = ['$animate', '$compile', function($animate, $compile) { + return { + require: 'ngSwitch', + + // asks for $scope to fool the BC controller module + controller: ['$scope', function ngSwitchController() { + this.cases = {}; + }], + link: function(scope, element, attr, ngSwitchController) { + var watchExpr = attr.ngSwitch || attr.on, + selectedTranscludes = [], + selectedElements = [], + previousLeaveAnimations = [], + selectedScopes = []; + + var spliceFactory = function(array, index) { + return function() { array.splice(index, 1); }; + }; + + scope.$watch(watchExpr, function ngSwitchWatchAction(value) { + var i, ii; + for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) { + $animate.cancel(previousLeaveAnimations[i]); + } + previousLeaveAnimations.length = 0; + + for (i = 0, ii = selectedScopes.length; i < ii; ++i) { + var selected = getBlockNodes(selectedElements[i].clone); + selectedScopes[i].$destroy(); + var promise = previousLeaveAnimations[i] = $animate.leave(selected); + promise.then(spliceFactory(previousLeaveAnimations, i)); + } + + selectedElements.length = 0; + selectedScopes.length = 0; + + if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) { + forEach(selectedTranscludes, function(selectedTransclude) { + selectedTransclude.transclude(function(caseElement, selectedScope) { + selectedScopes.push(selectedScope); + var anchor = selectedTransclude.element; + caseElement[caseElement.length++] = $compile.$$createComment('end ngSwitchWhen'); + var block = { clone: caseElement }; + + selectedElements.push(block); + $animate.enter(caseElement, anchor.parent(), anchor); + }); + }); + } + }); + } + }; +}]; + +var ngSwitchWhenDirective = ngDirective({ + transclude: 'element', + priority: 1200, + require: '^ngSwitch', + multiElement: true, + link: function(scope, element, attrs, ctrl, $transclude) { + ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []); + ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element }); + } +}); + +var ngSwitchDefaultDirective = ngDirective({ + transclude: 'element', + priority: 1200, + require: '^ngSwitch', + multiElement: true, + link: function(scope, element, attr, ctrl, $transclude) { + ctrl.cases['?'] = (ctrl.cases['?'] || []); + ctrl.cases['?'].push({ transclude: $transclude, element: element }); + } +}); + +/** + * @ngdoc directive + * @name ngTransclude + * @restrict EAC + * + * @description + * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion. + * + * You can specify that you want to insert a named transclusion slot, instead of the default slot, by providing the slot name + * as the value of the `ng-transclude` or `ng-transclude-slot` attribute. + * + * If the transcluded content is not empty (i.e. contains one or more DOM nodes, including whitespace text nodes), any existing + * content of this element will be removed before the transcluded content is inserted. + * If the transcluded content is empty, the existing content is left intact. This lets you provide fallback content in the case + * that no transcluded content is provided. + * + * @element ANY + * + * @param {string} ngTransclude|ngTranscludeSlot the name of the slot to insert at this point. If this is not provided, is empty + * or its value is the same as the name of the attribute then the default slot is used. + * + * @example + * ### Basic transclusion + * This example demonstrates basic transclusion of content into a component directive. + * + * + * + *
    + *
    + *
    + * {{text}} + *
    + *
    + * + * it('should have transcluded', function() { + * var titleElement = element(by.model('title')); + * titleElement.clear(); + * titleElement.sendKeys('TITLE'); + * var textElement = element(by.model('text')); + * textElement.clear(); + * textElement.sendKeys('TEXT'); + * expect(element(by.binding('title')).getText()).toEqual('TITLE'); + * expect(element(by.binding('text')).getText()).toEqual('TEXT'); + * }); + * + *
    + * + * @example + * ### Transclude fallback content + * This example shows how to use `NgTransclude` with fallback content, that + * is displayed if no transcluded content is provided. + * + * + * + * + * + * + * + * + * Button2 + * + * + * + * it('should have different transclude element content', function() { + * expect(element(by.id('fallback')).getText()).toBe('Button1'); + * expect(element(by.id('modified')).getText()).toBe('Button2'); + * }); + * + * + * + * @example + * ### Multi-slot transclusion + * This example demonstrates using multi-slot transclusion in a component directive. + * + * + * + *
    + *
    + *
    + * + * {{title}} + *

    {{text}}

    + *
    + *
    + *
    + * + * angular.module('multiSlotTranscludeExample', []) + * .directive('pane', function(){ + * return { + * restrict: 'E', + * transclude: { + * 'title': '?paneTitle', + * 'body': 'paneBody', + * 'footer': '?paneFooter' + * }, + * template: '
    ' + + * '
    Fallback Title
    ' + + * '
    ' + + * '' + + * '
    ' + * }; + * }) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.title = 'Lorem Ipsum'; + * $scope.link = "https://google.com"; + * $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...'; + * }]); + *
    + * + * it('should have transcluded the title and the body', function() { + * var titleElement = element(by.model('title')); + * titleElement.clear(); + * titleElement.sendKeys('TITLE'); + * var textElement = element(by.model('text')); + * textElement.clear(); + * textElement.sendKeys('TEXT'); + * expect(element(by.css('.title')).getText()).toEqual('TITLE'); + * expect(element(by.binding('text')).getText()).toEqual('TEXT'); + * expect(element(by.css('.footer')).getText()).toEqual('Fallback Footer'); + * }); + * + *
    + */ +var ngTranscludeMinErr = minErr('ngTransclude'); +var ngTranscludeDirective = ['$compile', function($compile) { + return { + restrict: 'EAC', + terminal: true, + compile: function ngTranscludeCompile(tElement) { + + // Remove and cache any original content to act as a fallback + var fallbackLinkFn = $compile(tElement.contents()); + tElement.empty(); + + return function ngTranscludePostLink($scope, $element, $attrs, controller, $transclude) { + + if (!$transclude) { + throw ngTranscludeMinErr('orphan', + 'Illegal use of ngTransclude directive in the template! ' + + 'No parent directive that requires a transclusion found. ' + + 'Element: {0}', + startingTag($element)); + } + + + // If the attribute is of the form: `ng-transclude="ng-transclude"` then treat it like the default + if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) { + $attrs.ngTransclude = ''; + } + var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot; + + // If the slot is required and no transclusion content is provided then this call will throw an error + $transclude(ngTranscludeCloneAttachFn, null, slotName); + + // If the slot is optional and no transclusion content is provided then use the fallback content + if (slotName && !$transclude.isSlotFilled(slotName)) { + useFallbackContent(); + } + + function ngTranscludeCloneAttachFn(clone, transcludedScope) { + if (clone.length) { + $element.append(clone); + } else { + useFallbackContent(); + // There is nothing linked against the transcluded scope since no content was available, + // so it should be safe to clean up the generated scope. + transcludedScope.$destroy(); + } + } + + function useFallbackContent() { + // Since this is the fallback content rather than the transcluded content, + // we link against the scope of this directive rather than the transcluded scope + fallbackLinkFn($scope, function(clone) { + $element.append(clone); + }); + } + }; + } + }; +}]; + +/** + * @ngdoc directive + * @name script + * @restrict E + * + * @description + * Load the content of a ` + + Load inlined template +
    + + + it('should load template defined inside script tag', function() { + element(by.css('#tpl-link')).click(); + expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/); + }); + + + */ +var scriptDirective = ['$templateCache', function($templateCache) { + return { + restrict: 'E', + terminal: true, + compile: function(element, attr) { + if (attr.type == 'text/ng-template') { + var templateUrl = attr.id, + text = element[0].text; + + $templateCache.put(templateUrl, text); + } + } + }; +}]; + +var noopNgModelController = { $setViewValue: noop, $render: noop }; + +function chromeHack(optionElement) { + // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459 + // Adding an